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=03a8a003...
Author: Jason Penton jason.penton@smilecoms.com Committer: Jason Penton jason.penton@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 */