Module: sip-router
Branch: carstenbock/ims
Commit: f61056d444ad9d453281d70c70a297b8561ce204
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=f61056d…
Author: Carsten Bock <carsten(a)bock.info>
Committer: Carsten Bock <carsten(a)bock.info>
Date: Thu Jan 20 09:01:29 2011 +0100
- allow setting, editing and removing of variables before the dialog was created.
---
modules_k/dialog/dlg_handlers.c | 5 ++
modules_k/dialog/dlg_var.c | 89 +++++++++++++++++++++++++--------------
modules_k/dialog/dlg_var.h | 6 +++
3 files changed, 68 insertions(+), 32 deletions(-)
diff --git a/modules_k/dialog/dlg_handlers.c b/modules_k/dialog/dlg_handlers.c
index a118a91..67b8160 100644
--- a/modules_k/dialog/dlg_handlers.c
+++ b/modules_k/dialog/dlg_handlers.c
@@ -679,6 +679,8 @@ int dlg_new_dialog(struct sip_msg *msg, struct cell *t)
return -1;
}
+
+
/* save caller's tag, cseq, contact and record route*/
if (populate_leg_info(dlg, msg, t, DLG_CALLER_LEG,
&(get_from(msg)->tag_value)) !=0)
@@ -690,6 +692,9 @@ int dlg_new_dialog(struct sip_msg *msg, struct cell *t)
set_current_dialog(msg, dlg);
_dlg_ctx.dlg = dlg;
+ /* Populate initial varlist: */
+ dlg->vars = getvarlist(msg);
+ deletevarlist();
link_dlg(dlg, 2/* extra ref for the callback and current dlg hook */);
diff --git a/modules_k/dialog/dlg_var.c b/modules_k/dialog/dlg_var.c
index d540099..e9df6a2 100644
--- a/modules_k/dialog/dlg_var.c
+++ b/modules_k/dialog/dlg_var.c
@@ -29,6 +29,11 @@
dlg_ctx_t _dlg_ctx;
+/*! global variable table, in case the dialog does not exist yet */
+struct dlg_var * var_table = 0;
+/*! ID of the current message */
+int msg_id;
+
int dlg_cfg_cb(struct sip_msg *foo, unsigned int flags, void *bar)
{
memset(&_dlg_ctx, 0, sizeof(dlg_ctx_t));
@@ -70,7 +75,7 @@ static inline struct dlg_var *new_dlg_var(str *key, str *val)
}
/* Adds, updates and deletes dialog variables */
-int set_dlg_variable(struct dlg_cell *dlg, str *key, str *val)
+int set_dlg_variable_unsafe(struct dlg_var * var_list, str *key, str *val)
{
struct dlg_var * var = NULL;
struct dlg_var * it;
@@ -81,27 +86,21 @@ int set_dlg_variable(struct dlg_cell *dlg, str *key, str *val)
return -1;
}
- /* lock dialog */
- dlg_lock(d_table, &(d_table->entries[dlg->h_entry]));
-
/* iterate the list */
- for( it_prev=NULL, it=dlg->vars ; it ; it_prev=it,it=it->next) {
+ for( it_prev=NULL, it=var_list ; it ; it_prev=it,it=it->next) {
if (key->len==it->key.len &&
memcmp(key->s,it->key.s,key->len)==0) {
/* found -> replace or delete it */
if (val==NULL) {
/* delete it */
if (it_prev) it_prev->next = it->next;
- else dlg->vars = it->next;
+ else var_list = it->next;
} else {
/* replace the current it with var and free the it */
var->next = it->next;
if (it_prev) it_prev->next = var;
- else dlg->vars = var;
+ else var_list = var;
}
- /* unlock dialog */
- dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
-
/* Free this var: */
shm_free(it->key.s);
shm_free(it->value.s);
@@ -113,34 +112,23 @@ int set_dlg_variable(struct dlg_cell *dlg, str *key, str *val)
/* not found -> simply add a new one */
/* insert at the beginning of the list */
- var->next = dlg->vars;
- dlg->vars = var;
-
- /* unlock dialog */
- dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
+ var->next = var_list;
+ var_list = var;
return 0;
}
-str * get_dlg_variable(struct dlg_cell *dlg, str *key)
+str * get_dlg_variable_unsafe(struct dlg_var * var_list, str *key)
{
struct dlg_var *var;
- /* lock dialog */
- dlg_lock(d_table, &(d_table->entries[dlg->h_entry]));
-
/* iterate the list */
- for(var=dlg->vars ; var ; var=var->next) {
+ for(var=var_list ; var ; var=var->next) {
if (key->len==var->key.len &&
memcmp(key->s,var->key.s,key->len)==0) {
- /* unlock dialog */
- dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
return &var->value;
}
}
- /* unlock dialog */
- dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
-
return NULL;
}
@@ -156,10 +144,30 @@ int pv_parse_dialog_var_name(pv_spec_p sp, str *in)
return 0;
}
+/*! Delete the current var-list */
+void deletevarlist() {
+ struct dlg_var *var;
+ while (var_table) {
+ var = var_table;
+ var_table = var_table->next;
+ shm_free(var->key.s);
+ shm_free(var->key.s);
+ shm_free(var);
+ }
+}
+
+/*! Retrieve the current var-list */
+struct dlg_var * getvarlist(struct sip_msg *msg) {
+ /* New list, delete the old one */
+ if (msg->id != msg_id)
+ deletevarlist();
+ return var_table;
+}
int pv_get_dlg_variable(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
{
struct dlg_cell *dlg;
+ struct dlg_var *varlist;
str * value;
if (param==NULL || param->pvn.type!=PV_NAME_INTSTR ||
param->pvn.u.isname.type!=AVP_NAME_STR || param->pvn.u.isname.name.s.s==NULL) {
@@ -168,9 +176,18 @@ int pv_get_dlg_variable(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
}
if ((dlg=get_current_dlg_pointer())==NULL)
- return pv_get_null(msg, param, res);
+ varlist = getvarlist(msg);
+ else
+ varlist = dlg->vars;
+
+ /* unlock dialog */
+ if (dlg) dlg_lock(d_table, &(d_table->entries[dlg->h_entry]));
+
+ value = get_dlg_variable_unsafe(varlist, ¶m->pvn.u.isname.name.s);
+
+ /* unlock dialog */
+ if (dlg) dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
- value = get_dlg_variable(dlg, ¶m->pvn.u.isname.name.s);
if (value)
return pv_get_strval(msg, param, res, value);
return 0;
@@ -179,9 +196,12 @@ int pv_get_dlg_variable(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
int pv_set_dlg_variable(struct sip_msg* msg, pv_param_t *param, int op, pv_value_t *val)
{
struct dlg_cell *dlg;
+ struct dlg_var *varlist;
- if ( (dlg=get_current_dlg_pointer())==NULL )
- return -1;
+ if ((dlg=get_current_dlg_pointer())==NULL)
+ varlist = getvarlist(msg);
+ else
+ varlist = dlg->vars;
if (param==NULL || param->pvn.type!=PV_NAME_INTSTR ||
param->pvn.u.isname.type!=AVP_NAME_STR || param->pvn.u.isname.name.s.s==NULL ) {
LM_CRIT("BUG - bad parameters\n");
@@ -190,19 +210,25 @@ int pv_set_dlg_variable(struct sip_msg* msg, pv_param_t *param, int
op, pv_value
if (val==NULL || val->flags&(PV_VAL_NONE|PV_VAL_NULL|PV_VAL_EMPTY)) {
/* if NULL, remove the value */
- if (set_dlg_variable(dlg, ¶m->pvn.u.isname.name.s, NULL)!=0) {
+ if (set_dlg_variable_unsafe(varlist, ¶m->pvn.u.isname.name.s, NULL)!=0) {
LM_ERR("failed to delete dialog variable <%.*s>\n",
param->pvn.u.isname.name.s.len,param->pvn.u.isname.name.s.s);
+ /* unlock dialog */
+ if (dlg) dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
return -1;
}
} else {
/* if value, must be string */
if ( !(val->flags&PV_VAL_STR)) {
LM_ERR("non-string values are not supported\n");
+ /* unlock dialog */
+ if (dlg) dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
return -1;
}
- if (set_dlg_variable(dlg, ¶m->pvn.u.isname.name.s, &val->rs)!=0) {
+ if (set_dlg_variable_unsafe(varlist, ¶m->pvn.u.isname.name.s,
&val->rs)!=0) {
LM_ERR("failed to store dialog values
<%.*s>\n",param->pvn.u.isname.name.s.len,param->pvn.u.isname.name.s.s);
+ /* unlock dialog */
+ if (dlg) dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
return -1;
}
}
@@ -210,7 +236,6 @@ int pv_set_dlg_variable(struct sip_msg* msg, pv_param_t *param, int
op, pv_value
return 0;
}
-
int pv_get_dlg_ctx(struct sip_msg *msg, pv_param_t *param,
pv_value_t *res)
{
diff --git a/modules_k/dialog/dlg_var.h b/modules_k/dialog/dlg_var.h
index c56e074..f166606 100644
--- a/modules_k/dialog/dlg_var.h
+++ b/modules_k/dialog/dlg_var.h
@@ -57,6 +57,12 @@ int pv_get_dialog_var(struct sip_msg *msg, pv_param_t *param,
int pv_set_dialog_var(struct sip_msg* msg, pv_param_t *param,
int op, pv_value_t *val);
+/*! Delete the current var-list */
+void deletevarlist();
+
+/*! Retrieve the current var-list */
+struct dlg_var * getvarlist(struct sip_msg *msg);
+
extern dlg_ctx_t _dlg_ctx;
int pv_get_dlg_ctx(struct sip_msg *msg, pv_param_t *param,