[sr-dev] git:tmp/tm_async_reply_support: modules/tm: improved functionality for async transaction framework

Jason Penton jason.penton at gmail.com
Tue Jul 9 17:09:00 CEST 2013


Module: sip-router
Branch: tmp/tm_async_reply_support
Commit: 03a8a0030644146a920f03c2d5186eb72806d3f3
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=03a8a0030644146a920f03c2d5186eb72806d3f3

Author: Jason Penton <jason.penton at smilecoms.com>
Committer: Jason Penton <jason.penton at smilecoms.com>
Date:   Tue Jul  9 17:05:38 2013 +0200

modules/tm: improved functionality for async transaction framework

---

 modules/tm/h_table.h   |   12 ++++++-
 modules/tm/t_reply.c   |   90 ++++++++++++++++++++++++++++++++++++++++++++++++
 modules/tm/t_reply.h   |    1 +
 modules/tm/t_suspend.c |   28 +++++++++++++--
 4 files changed, 126 insertions(+), 5 deletions(-)

diff --git a/modules/tm/h_table.h b/modules/tm/h_table.h
index e260d7e..966f374 100644
--- a/modules/tm/h_table.h
+++ b/modules/tm/h_table.h
@@ -91,6 +91,7 @@ struct cell;
 struct timer;
 struct retr_buf;
 struct ua_client;
+struct async_state;
 
 #include "../../mem/shm_mem.h"
 #include "lock.h"
@@ -264,6 +265,13 @@ typedef struct ua_client
 	unsigned short on_unused;
 }ua_client_type;
 
+/* structure for storing trnasaction state prior to suspending for async transactions */
+typedef struct async_state
+{        
+        unsigned int backup_route;
+        unsigned int backup_branch;
+        unsigned int ruri_new;
+}async_state_type;
 
 struct totag_elem {
 	struct totag_elem *next;
@@ -403,6 +411,9 @@ typedef struct cell
 	   outbound buffer, for proxies transactions pointer to
 	   original message; needed for reply matching */
 	str method;
+        
+        /* store transaction state to be used with async transactions */
+        struct async_state async_backup;
 
 	/* head of callback list */
 	struct tmcb_head_list tmcb_hl;
@@ -460,7 +471,6 @@ typedef struct cell
 
 } tm_cell_t;
 
-
 #if 0
 /* warning: padding too much => big size increase */
 #define ENTRY_PAD_TO  128 /* should be a multiple of cacheline size for 
diff --git a/modules/tm/t_reply.c b/modules/tm/t_reply.c
index 359fd90..d6f6030 100644
--- a/modules/tm/t_reply.c
+++ b/modules/tm/t_reply.c
@@ -951,6 +951,96 @@ void faked_env_resp( struct cell *t, struct sip_msg *msg)
 	}
 }
 
+void faked_env_async( struct cell *t, struct sip_msg *msg) {
+       	static int backup_route_type;
+	static struct cell *backup_t;
+	static int backup_branch;
+	static unsigned int backup_msgid;
+	static avp_list_t* backup_user_from, *backup_user_to;
+	static avp_list_t* backup_domain_from, *backup_domain_to;
+	static avp_list_t* backup_uri_from, *backup_uri_to;
+#ifdef WITH_XAVP
+	static sr_xavp_t **backup_xavps;
+#endif
+	static struct socket_info* backup_si;
+
+	static struct lump *backup_add_rm;
+	static struct lump *backup_body_lumps;
+	static struct lump_rpl *backup_reply_lump;
+
+
+	if (msg) {
+		/* remember we are back in request processing, but process
+		 * a shmem-ed replica of the request; advertise it in route type;
+		 * for example t_reply needs to know that
+		 */
+		backup_route_type=get_route_type();
+		set_route_type(t->async_backup.backup_route);
+                if (t->async_backup.ruri_new) {
+                    ruri_mark_new();
+                }
+                
+                if (!is_route_type(REQUEST_ROUTE)) {
+                    /* don't bother backing up ruri state, since failure route
+                       is called either on reply or on timer and in both cases
+                       the ruri should not be used again for forking */
+                    ruri_mark_consumed(); /* in failure route we assume ruri
+                                             should not be used again for forking */
+                }
+		/* also, tm actions look in beginning whether transaction is
+		 * set -- whether we are called from a reply-processing
+		 * or a timer process, we need to set current transaction;
+		 * otherwise the actions would attempt to look the transaction
+		 * up (unnecessary overhead, refcounting)
+		 */
+		/* backup */
+		backup_t=get_t();
+		backup_branch=get_t_branch();
+		backup_msgid=global_msg_id;
+		/* fake transaction and message id */
+		global_msg_id=msg->id;
+		set_t(t, t->async_backup.backup_branch);
+		/* make available the avp list from transaction */
+
+		backup_uri_from = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from );
+		backup_uri_to = set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to );
+		backup_user_from = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from );
+		backup_user_to = set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to );
+		backup_domain_from = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from );
+		backup_domain_to = set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to );
+#ifdef WITH_XAVP
+		backup_xavps = xavp_set_list(&t->xavps_list);
+#endif
+		/* set default send address to the saved value */
+		backup_si=bind_address;
+		bind_address=t->uac[0].request.dst.send_sock;
+		/* backup lump lists */
+		backup_add_rm = t->uas.request->add_rm;
+		backup_body_lumps = t->uas.request->body_lumps;
+		backup_reply_lump = t->uas.request->reply_lump;
+	} else {
+		/* restore original environment */
+		set_t(backup_t, backup_branch);
+		global_msg_id=backup_msgid;
+		set_route_type(backup_route_type);
+		/* restore original avp list */
+		set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, backup_user_from );
+		set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, backup_user_to );
+		set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, backup_domain_from );
+		set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, backup_domain_to );
+		set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, backup_uri_from );
+		set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, backup_uri_to );
+#ifdef WITH_XAVP
+		xavp_set_list(backup_xavps);
+#endif
+		bind_address=backup_si;
+		/* restore lump lists */
+		t->uas.request->add_rm = backup_add_rm;
+		t->uas.request->body_lumps = backup_body_lumps;
+		t->uas.request->reply_lump = backup_reply_lump;
+	}
+}
+
 /** create or restore a "fake environment" for running a failure_route.
  *if msg is set -> it will fake the env. vars conforming with the msg; if NULL
  * the env. will be restore to original.
diff --git a/modules/tm/t_reply.h b/modules/tm/t_reply.h
index 17f046b..6ac7928 100644
--- a/modules/tm/t_reply.h
+++ b/modules/tm/t_reply.h
@@ -236,6 +236,7 @@ void t_drop_replies(int v);
 void rpc_reply(rpc_t* rpc, void* c);
 
 void faked_env( struct cell *t,struct sip_msg *msg);
+void faked_env_async( struct cell *t, struct sip_msg *msg);
 void faked_env_resp( struct cell *t,struct sip_msg *msg);
 
 int fake_req(struct sip_msg *faked_req,
diff --git a/modules/tm/t_suspend.c b/modules/tm/t_suspend.c
index ad51ef0..b9806a0 100644
--- a/modules/tm/t_suspend.c
+++ b/modules/tm/t_suspend.c
@@ -33,6 +33,7 @@
 
 #include "../../action.h"
 #include "../../script_cb.h"
+#include "../../dset.h"
 
 #include "config.h"
 #include "sip_msg.h"
@@ -95,7 +96,10 @@ int t_suspend(struct sip_msg *msg,
 	}
 	/* save the message flags */
 	t->uas.request->flags = msg->flags;
-
+        t->async_backup.backup_route = get_route_type();
+        t->async_backup.backup_branch = get_t_branch();
+        t->async_backup.ruri_new = ruri_get_forking_state();
+        
 	*hash_index = t->hash_index;
 	*label = t->label;
 
@@ -242,16 +246,32 @@ int t_continue(unsigned int hash_index, unsigned int label,
 		ret = -1;
 		goto kill_trans;
 	}
-	faked_env( t, &faked_req);
+	faked_env_async( t, &faked_req);
 
 	/* The sip msg is a faked msg just like in failure route
 	 * therefore execute the pre- and post-script callbacks
 	 * of failure route (Miklos)
 	 */
-	if (exec_pre_script_cb(&faked_req, FAILURE_CB_TYPE)>0) {
+        
+        int cb_type = REQUEST_CB_TYPE;
+        switch (t->async_backup.backup_route) {
+            case REQUEST_ROUTE:
+                cb_type = REQUEST_CB_TYPE;
+                break;
+            case FAILURE_ROUTE:
+                cb_type = FAILURE_CB_TYPE;
+                break;
+            case TM_ONREPLY_ROUTE:
+                 cb_type = ONREPLY_CB_TYPE;
+                break;
+            case BRANCH_ROUTE:
+                cb_type = BRANCH_CB_TYPE;
+                break;
+        }
+	if (exec_pre_script_cb(&faked_req, cb_type)>0) {
 		if (run_top_route(route, &faked_req, 0)<0)
 			LOG(L_ERR, "ERROR: t_continue: Error in run_top_route\n");
-		exec_post_script_cb(&faked_req, FAILURE_CB_TYPE);
+		exec_post_script_cb(&faked_req, cb_type);
 	}
 
 	/* TODO: save_msg_lumps should clone the lumps to shm mem */




More information about the sr-dev mailing list