Module: sip-router Branch: master Commit: 7f50e172c26259ebf023d414fb97b295958de370 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=7f50e172...
Author: Jason Penton jason.penton@gmail.com Committer: Jason Penton jason.penton@gmail.com Date: Fri Oct 10 10:44:49 2014 +0200
modules/tm: new function t_is_retr_async_reply to check if a reply being processed is part of a transaction currently suspended
---
modules/tm/doc/functions.xml | 28 ++++++++++++++++++++++++++-- modules/tm/h_table.h | 1 + modules/tm/t_suspend.c | 1 + modules/tm/tm.c | 26 ++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 2 deletions(-)
diff --git a/modules/tm/doc/functions.xml b/modules/tm/doc/functions.xml index af7d11d..9d42cf3 100644 --- a/modules/tm/doc/functions.xml +++ b/modules/tm/doc/functions.xml @@ -1723,5 +1723,29 @@ t_use_uac_headers(); </programlisting> </example> </section> - -</section> + <section id="tm.f.t_is_retr_async_reply"> + <title> </section> + <function>t_is_retr_async_reply()</function> + </title> + <para> + Check to see if the reply is a retransmitted reply on a transaction that is + currently suspended asynchronously (suspended during reply processing). Right now the check is only on the + transaction, we don't actually check to see if the reply message is an actual + retransmission of the suspended reply. This is expected as you should not process + another reply until the suspended reply processing has been completed. The trick here + is to make sure you don't suspend for too long or even worse, indefinitely. + </para> + <para>returns true if the transaction is currently reply suspended or false if not.</para> + <example> + <title><function>t_is_retr_async_reply</function> usage</title> + <programlisting> +... +if (t_is_retr_async_reply()) { + xlog("L_DBG", "Dropping retransmitted reply which is still currently suspended\n"); + drop(); +} +... + </programlisting> + </example> + </section> + </section> diff --git a/modules/tm/h_table.h b/modules/tm/h_table.h index 50a711d..42551bb 100644 --- a/modules/tm/h_table.h +++ b/modules/tm/h_table.h @@ -322,6 +322,7 @@ typedef struct async_state {
#define T_DISABLE_INTERNAL_REPLY (1<<13) /* don't send internal negative reply */ #define T_ADMIN_REPLY (1<<14) /* t reply sent by admin (e.g., from cfg script) */ +#define T_ASYNC_SUSPENDED (1<<15)
/* unsigned short should be enough for a retr. timer: max. 65535 ms => * max retr. = 65 s which should be enough and saves us 2*2 bytes */ diff --git a/modules/tm/t_suspend.c b/modules/tm/t_suspend.c index 435686a..1d7e3ca 100644 --- a/modules/tm/t_suspend.c +++ b/modules/tm/t_suspend.c @@ -108,6 +108,7 @@ int t_suspend(struct sip_msg *msg, } else { LM_DBG("this is a suspend on reply - setting msg flag to SUSPEND\n"); msg->msg_flags |= FL_RPL_SUSPENDED; + t->flags |= T_ASYNC_SUSPENDED; /* this is a reply suspend find which branch */
if (t_check( msg , &branch )==-1){ diff --git a/modules/tm/tm.c b/modules/tm/tm.c index 5b92055..54bcc78 100644 --- a/modules/tm/tm.c +++ b/modules/tm/tm.c @@ -298,6 +298,7 @@ static int t_any_timeout(struct sip_msg* msg, char*, char*); static int t_any_replied(struct sip_msg* msg, char*, char*); static int w_t_is_canceled(struct sip_msg* msg, char*, char*); static int t_is_expired(struct sip_msg* msg, char*, char*); +static int w_t_is_retr_async_reply(struct sip_msg* msg, char*, char*); static int t_grep_status(struct sip_msg* msg, char*, char*); static int w_t_drop_replies(struct sip_msg* msg, char* foo, char* bar); static int w_t_save_lumps(struct sip_msg* msg, char* foo, char* bar); @@ -472,6 +473,8 @@ static cmd_export_t cmds[]={ REQUEST_ROUTE|TM_ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE }, {"t_is_canceled", w_t_is_canceled, 0, 0, REQUEST_ROUTE|TM_ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE }, + {"t_is_retr_async_reply", w_t_is_retr_async_reply, 0, 0, + TM_ONREPLY_ROUTE}, {"t_is_expired", t_is_expired, 0, 0, REQUEST_ROUTE|TM_ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE }, {"t_grep_status", t_grep_status, 1, fixup_var_int_1, @@ -1950,6 +1953,29 @@ static int w_t_is_canceled(struct sip_msg* msg, char* foo, char* bar) return t_is_canceled(msg); }
+/* script function, returns: 1 if the transaction is currently suspended, -1 if not */ +int t_is_retr_async_reply(struct sip_msg* msg) +{ + struct cell *t; + int ret; + + if (t_check( msg , 0 )==-1) return -1; + t=get_t(); + if ((t==0) || (t==T_UNDEFINED)){ + LOG(L_ERR, "ERROR: t_is_retr_async_reply: cannot check a message " + "for which no T-state has been established\n"); + ret=-1; + }else{ + LOG(L_DBG, "TRANSACTION FLAGS IS %d\n", t->flags); + ret=(t->flags & T_ASYNC_SUSPENDED)?1:-1; + } + return ret; +} +static int w_t_is_retr_async_reply(struct sip_msg* msg, char* foo, char* bar) +{ + return t_is_retr_async_reply(msg); +} + /* script function, returns: 1 if the transaction lifetime interval has already elapsed, -1 if not */ int t_is_expired(struct sip_msg* msg, char* foo, char* bar) {