[sr-dev] git:carstenbock/ims: - allow setting, editing and removing of variables before the dialog was created.

Carsten Bock carsten at bock.info
Fri Jan 21 15:48:29 CET 2011


Module: sip-router
Branch: carstenbock/ims
Commit: f61056d444ad9d453281d70c70a297b8561ce204
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=f61056d444ad9d453281d70c70a297b8561ce204

Author: Carsten Bock <carsten at bock.info>
Committer: Carsten Bock <carsten at 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, &param->pvn.u.isname.name.s);
+
+	/* unlock dialog */
+	if (dlg) dlg_unlock(d_table, &(d_table->entries[dlg->h_entry]));
 
-	value = get_dlg_variable(dlg, &param->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, &param->pvn.u.isname.name.s, NULL)!=0) {
+		if (set_dlg_variable_unsafe(varlist, &param->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, &param->pvn.u.isname.name.s, &val->rs)!=0) {
+		if (set_dlg_variable_unsafe(varlist, &param->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,




More information about the sr-dev mailing list