Module: sip-router
Branch: master
Commit: 7f50e172c26259ebf023d414fb97b295958de370
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=7f50e17…
Author: Jason Penton <jason.penton(a)gmail.com>
Committer: Jason Penton <jason.penton(a)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)
{