Module: sip-router Branch: carstenbock/ims Commit: f61056d444ad9d453281d70c70a297b8561ce204 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=f61056d4...
Author: Carsten Bock carsten@bock.info Committer: Carsten Bock carsten@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,