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=03a8a00…
Author: Jason Penton <jason.penton(a)smilecoms.com>
Committer: Jason Penton <jason.penton(a)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 */