Module: sip-router
Branch: tmp/tm_async_reply_support
Commit: a23a131e5e6b0751c9d18bca3e6fe695c6cdbe30
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=a23a131…
Author: Richard Good <richard.good(a)smilecoms.com>
Committer: Richard Good <richard.good(a)smilecoms.com>
Date: Mon Jul 15 12:51:23 2013 +0200
modules/tm: removed branch parameter from t_continue_reply
- With improved suspend functionality now saving the branch the calling application does not need to store the reply branch when suspending on a reply
---
modules/tm/t_suspend.c | 23 ++++++++++++++++++-----
modules/tm/t_suspend.h | 8 ++++----
2 files changed, 22 insertions(+), 9 deletions(-)
diff --git a/modules/tm/t_suspend.c b/modules/tm/t_suspend.c
index eb5b1a5..8d5f0aa 100644
--- a/modules/tm/t_suspend.c
+++ b/modules/tm/t_suspend.c
@@ -162,8 +162,13 @@ int t_suspend_reply(struct sip_msg *msg,
LOG(L_ERR, "ERROR: t_suspend_reply: can't alloc' clone memory\n");
return -1;
}
-
- LOG(L_DBG,"DEBUG: t_suspend_reply: Saving transaction hash and label\n");
+
+ LOG(L_DBG,"DEBUG: t_suspend_reply: Saving transaction data\n");
+ t->uac[branch].reply->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;
@@ -293,6 +298,7 @@ int t_continue(unsigned int hash_index, unsigned int label,
}
}
+ t->flags &= ~T_ASYNC_CONTINUE; //we can now know anywhere in kamailio that we are executing post a suspend.
UNLOCK_ASYNC_CONTINUE(t);
/* unref the transaction */
@@ -332,11 +338,12 @@ kill_trans:
* <0 - failure
*/
int t_continue_reply(unsigned int hash_index, unsigned int label,
- struct action *route, int branch)
+ struct action *route)
{
struct cell *t;
struct sip_msg faked_resp;
struct cancel_info cancel_data;
+ int branch;
if (t_lookup_ident(&t, hash_index, label) < 0) {
LOG(L_ERR, "ERROR: t_continue_reply: transaction not found\n");
@@ -352,11 +359,14 @@ int t_continue_reply(unsigned int hash_index, unsigned int label,
return 1;
}
+ branch = t->async_backup.backup_branch;
+
init_cancel_info(&cancel_data);
/* The transaction has to be locked to protect it
* form calling t_continue() multiple times simultaneously */
LOCK_ASYNC_CONTINUE(t);
+ t->flags |= T_ASYNC_CONTINUE; //we can now know anywhere in kamailio that we are executing post a suspend.
LOG(L_DBG,"DEBUG: t_continue_reply: This a continue from a reply suspend\n");
/* this is a continue from a reply suspend */
@@ -457,7 +467,7 @@ int t_continue_reply(unsigned int hash_index, unsigned int label,
done:
-
+ t->flags &= ~T_ASYNC_CONTINUE; //we can now know anywhere in kamailio that we are executing post a suspend.
UNLOCK_ASYNC_CONTINUE(t);
tm_ctx_set_branch_index(T_BR_UNDEFINED);
@@ -546,9 +556,10 @@ int t_cancel_suspend(unsigned int hash_index, unsigned int label)
* 0 - success
* <0 - failure
*/
-int t_cancel_suspend_reply(unsigned int hash_index, unsigned int label, int branch)
+int t_cancel_suspend_reply(unsigned int hash_index, unsigned int label)
{
struct cell *t;
+ int branch;
t = get_t();
if (!t || t == T_UNDEFINED) {
@@ -564,6 +575,8 @@ int t_cancel_suspend_reply(unsigned int hash_index, unsigned int label, int bran
"transaction id mismatch\n");
return -1;
}
+
+ branch = t->async_backup.backup_branch;
LOG(L_DBG,"DEBUG: t_cancel_suspend_reply: This is a cancel suspend for a response\n");
diff --git a/modules/tm/t_suspend.h b/modules/tm/t_suspend.h
index f50fc5d..b898dba 100644
--- a/modules/tm/t_suspend.h
+++ b/modules/tm/t_suspend.h
@@ -46,16 +46,16 @@ typedef int (*t_continue_f)(unsigned int hash_index, unsigned int label,
struct action *route);
int t_continue_reply(unsigned int hash_index, unsigned int label,
- struct action *route, int branch);
+ struct action *route);
typedef int (*t_continue_reply_f)(unsigned int hash_index, unsigned int label,
- struct action *route, int branch);
+ struct action *route);
int t_cancel_suspend(unsigned int hash_index, unsigned int label);
typedef int (*t_cancel_suspend_f)(unsigned int hash_index, unsigned int label);
-int t_cancel_suspend_reply(unsigned int hash_index, unsigned int label, int branch);
-typedef int (*t_cancel_suspend_reply_f)(unsigned int hash_index, unsigned int label, int branch);
+int t_cancel_suspend_reply(unsigned int hash_index, unsigned int label);
+typedef int (*t_cancel_suspend_reply_f)(unsigned int hash_index, unsigned int label);
#endif /* _T_SUSPEND_H */
Module: sip-router
Branch: master
Commit: 9ac9b5c35858efd7c71163c604d18a1fa35e3a02
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=9ac9b5c…
Author: Daniel-Constantin Mierla <miconda(a)gmail.com>
Committer: Daniel-Constantin Mierla <miconda(a)gmail.com>
Date: Fri Jul 12 18:09:09 2013 +0200
ipops: added dsn_int_match_ip(hostname, ipaddr)
- function that uses the internal resolver to match a hostname with an
ip (similar operation like 'scr_ip=="hostname"')
- rename dns_nc_match_ip() to dns_sys_match_ip() to be more suggestive
about what kind of resolver is used
---
modules/ipops/README | 51 +++++++++++++++++++++++------
modules/ipops/doc/ipops_admin.xml | 64 +++++++++++++++++++++++++++++++++---
modules/ipops/ipops_mod.c | 60 ++++++++++++++++++++++++++++++++--
3 files changed, 155 insertions(+), 20 deletions(-)
diff --git a/modules/ipops/README b/modules/ipops/README
index 901535a..cd6118e 100644
--- a/modules/ipops/README
+++ b/modules/ipops/README
@@ -36,7 +36,8 @@ I
4.8. compare_pure_ips (ip1, ip2)
4.9. is_ip_rfc1918 (ip)
4.10. is_in_subnet (ip, subnet)
- 4.11. dns_nc_match_ip(hostname, ipaddr)
+ 4.11. dns_sys_match_ip(hostname, ipaddr)
+ 4.12. dns_int_match_ip(hostname, ipaddr)
List of Examples
@@ -50,7 +51,8 @@ I
1.8. compare_pure_ips usage
1.9. is_ip_rfc1918 usage
1.10. is_in_subnet usage
- 1.11. dns_nc_match_ip usage
+ 1.11. dns_sys_match_ip usage
+ 1.12. dns_int_match_ip usage
Chapter 1. Admin Guide
@@ -75,7 +77,8 @@ Chapter 1. Admin Guide
4.8. compare_pure_ips (ip1, ip2)
4.9. is_ip_rfc1918 (ip)
4.10. is_in_subnet (ip, subnet)
- 4.11. dns_nc_match_ip(hostname, ipaddr)
+ 4.11. dns_sys_match_ip(hostname, ipaddr)
+ 4.12. dns_int_match_ip(hostname, ipaddr)
1. Overview
@@ -127,7 +130,8 @@ Chapter 1. Admin Guide
4.8. compare_pure_ips (ip1, ip2)
4.9. is_ip_rfc1918 (ip)
4.10. is_in_subnet (ip, subnet)
- 4.11. dns_nc_match_ip(hostname, ipaddr)
+ 4.11. dns_sys_match_ip(hostname, ipaddr)
+ 4.12. dns_int_match_ip(hostname, ipaddr)
4.1. is_ip (ip)
@@ -334,22 +338,49 @@ if (is_in_subnet("10.0.123.123", "10.0.123.1/24")) {
}
...
-4.11. dns_nc_match_ip(hostname, ipaddr)
+4.11. dns_sys_match_ip(hostname, ipaddr)
Returns TRUE if ipaddr is associated by DNS to hostname. FALSE
- otherwise. It does not use the internal DNS cache, but directly
- getaddrinfo(...).
+ otherwise. It does not use the internal DNS resolver, but directly
+ getaddrinfo(...). All addresses returned for the hostname are checked.
+ Note that some hosts may return different lists of IP addresses for
+ each query, if the DNS server is configured in that way (e.g., for
+ providing load balancing through DNS).
Parameters:
* ipaddr - string or pseudo-variable containing the ip address.
* hostname - string or pseudo-variable containing the hostname. The
- resulting IP addresses from DNS query are compared with ipaddress.
+ resulting IP addresses from DNS query are compared with ipaddr.
This function can be used from ANY_ROUTE.
- Example 1.11. dns_nc_match_ip usage
+ Example 1.11. dns_sys_match_ip usage
...
-if (!dns_nc_match_ip("myhost.com", "1.2.3.4")) {
+if (!dns_sys_match_ip("myhost.com", "1.2.3.4")) {
+ xdbg("ip address not associated with hostname\n");
+}
+...
+
+4.12. dns_int_match_ip(hostname, ipaddr)
+
+ Returns TRUE if ipaddr is associated by DNS to hostname. FALSE
+ otherwise. It uses internal DNS resolver. At this moment, the function
+ might not check all the IP addresses as returned by dns_sys_match_ip(),
+ because the internal resolver targets to discover the first address to
+ be used for relaying SIP traffic. Thus is better to use
+ dns_sys_match_ip() if the host you want to check has many IP addresses,
+ in different address famililies (IPv4/6).
+
+ Parameters:
+ * ipaddr - string or pseudo-variable containing the ip address.
+ * hostname - string or pseudo-variable containing the hostname. The
+ resulting IP addresses from DNS query are compared with ipaddr.
+
+ This function can be used from ANY_ROUTE.
+
+ Example 1.12. dns_int_match_ip usage
+...
+if (!dns_int_match_ip("myhost.com", "1.2.3.4")) {
xdbg("ip address not associated with hostname\n");
}
...
diff --git a/modules/ipops/doc/ipops_admin.xml b/modules/ipops/doc/ipops_admin.xml
index afb03d8..9f3528d 100644
--- a/modules/ipops/doc/ipops_admin.xml
+++ b/modules/ipops/doc/ipops_admin.xml
@@ -529,14 +529,17 @@ if (is_in_subnet("10.0.123.123", "10.0.123.1/24")) {
</section>
- <section id="ipops.f.dns_nc_match_ip">
+ <section id="ipops.f.dns_sys_match_ip">
<title>
- <function moreinfo="none">dns_nc_match_ip(hostname, ipaddr)</function>
+ <function moreinfo="none">dns_sys_match_ip(hostname, ipaddr)</function>
</title>
<para>
Returns TRUE if ipaddr is associated by DNS to hostname. FALSE otherwise. It
- does not use the internal DNS cache, but directly getaddrinfo(...).
+ does not use the internal DNS resolver, but directly getaddrinfo(...). All
+ addresses returned for the hostname are checked. Note that some hosts may
+ return different lists of IP addresses for each query, if the DNS server
+ is configured in that way (e.g., for providing load balancing through DNS).
</para>
<para>Parameters:</para>
@@ -550,7 +553,7 @@ if (is_in_subnet("10.0.123.123", "10.0.123.1/24")) {
<listitem>
<para>
<emphasis>hostname</emphasis> - string or pseudo-variable containing the hostname.
- The resulting IP addresses from DNS query are compared with ipaddress.
+ The resulting IP addresses from DNS query are compared with ipaddr.
</para>
</listitem>
</itemizedlist>
@@ -561,11 +564,60 @@ if (is_in_subnet("10.0.123.123", "10.0.123.1/24")) {
<example>
<title>
- <function>dns_nc_match_ip</function> usage
+ <function>dns_sys_match_ip</function> usage
</title>
<programlisting format="linespecific">
...
-if (!dns_nc_match_ip("myhost.com", "1.2.3.4")) {
+if (!dns_sys_match_ip("myhost.com", "1.2.3.4")) {
+ xdbg("ip address not associated with hostname\n");
+}
+...
+ </programlisting>
+ </example>
+
+ </section>
+
+ <section id="ipops.f.dns_int_match_ip">
+ <title>
+ <function moreinfo="none">dns_int_match_ip(hostname, ipaddr)</function>
+ </title>
+
+ <para>
+ Returns TRUE if ipaddr is associated by DNS to hostname. FALSE otherwise. It
+ uses internal DNS resolver. At this moment, the function might not check all
+ the IP addresses as returned by dns_sys_match_ip(), because the internal
+ resolver targets to discover the first address to be used for relaying
+ SIP traffic. Thus is better to use dns_sys_match_ip() if the host you want
+ to check has many IP addresses, in different address famililies (IPv4/6).
+ </para>
+
+ <para>Parameters:</para>
+
+ <itemizedlist>
+ <listitem>
+ <para>
+ <emphasis>ipaddr</emphasis> - string or pseudo-variable containing the ip address.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <emphasis>hostname</emphasis> - string or pseudo-variable containing the hostname.
+ The resulting IP addresses from DNS query are compared with ipaddr.
+ </para>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ This function can be used from ANY_ROUTE.
+ </para>
+
+ <example>
+ <title>
+ <function>dns_int_match_ip</function> usage
+ </title>
+ <programlisting format="linespecific">
+...
+if (!dns_int_match_ip("myhost.com", "1.2.3.4")) {
xdbg("ip address not associated with hostname\n");
}
...
diff --git a/modules/ipops/ipops_mod.c b/modules/ipops/ipops_mod.c
index d21546c..dc58fc8 100644
--- a/modules/ipops/ipops_mod.c
+++ b/modules/ipops/ipops_mod.c
@@ -87,7 +87,8 @@ static int w_compare_ips(struct sip_msg*, char*, char*);
static int w_compare_pure_ips(struct sip_msg*, char*, char*);
static int w_is_ip_rfc1918(struct sip_msg*, char*);
static int w_ip_is_in_subnet(struct sip_msg*, char*, char*);
-static int w_dns_nc_match_ip(sip_msg_t*, char*, char*);
+static int w_dns_sys_match_ip(sip_msg_t*, char*, char*);
+static int w_dns_int_match_ip(sip_msg_t*, char*, char*);
/*
@@ -115,7 +116,9 @@ static cmd_export_t cmds[] =
REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
{ "is_in_subnet", (cmd_function)w_ip_is_in_subnet, 2, fixup_spve_spve, 0,
REQUEST_ROUTE|FAILURE_ROUTE|ONREPLY_ROUTE|BRANCH_ROUTE|LOCAL_ROUTE },
- { "dns_nc_match_ip", (cmd_function)w_dns_nc_match_ip, 2, fixup_spve_spve, 0,
+ { "dns_sys_match_ip", (cmd_function)w_dns_sys_match_ip, 2, fixup_spve_spve, 0,
+ ANY_ROUTE },
+ { "dns_int_match_ip", (cmd_function)w_dns_int_match_ip, 2, fixup_spve_spve, 0,
ANY_ROUTE },
{ "bind_ipops", (cmd_function)bind_ipops, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0 }
@@ -617,7 +620,7 @@ static inline ip_addr_t *strtoipX(str *ips)
}
}
-static int w_dns_nc_match_ip(sip_msg_t *msg, char *hnp, char *ipp)
+static int w_dns_sys_match_ip(sip_msg_t *msg, char *hnp, char *ipp)
{
struct addrinfo hints, *res, *p;
int status;
@@ -653,7 +656,7 @@ static int w_dns_nc_match_ip(sip_msg_t *msg, char *hnp, char *ipp)
if ((status = getaddrinfo(hns.s, NULL, &hints, &res)) != 0)
{
LM_ERR("getaddrinfo: %s\n", gai_strerror(status));
- return -2;
+ return -4;
}
for(p = res;p != NULL; p = p->ai_next)
@@ -680,3 +683,52 @@ static int w_dns_nc_match_ip(sip_msg_t *msg, char *hnp, char *ipp)
return -1;
}
+
+static int w_dns_int_match_ip(sip_msg_t *msg, char *hnp, char *ipp)
+{
+ ip_addr_t *ipa;
+ str hns;
+ str ips;
+ struct hostent* he;
+ char ** h;
+ int ret;
+
+ if (fixup_get_svalue(msg, (gparam_p)hnp, &hns))
+ {
+ LM_ERR("cannot evaluate hostname parameter\n");
+ return -2;
+ }
+
+ if (fixup_get_svalue(msg, (gparam_p)ipp, &ips))
+ {
+ LM_ERR("cannot evaluate ip address parameter\n");
+ return -2;
+ }
+
+ ipa = strtoipX(&ips);
+ if(ipa==NULL)
+ {
+ LM_ERR("invalid ip address: %.*s\n", ips.len, ips.s);
+ return -3;
+ }
+
+ he=resolvehost(hns.s);
+ if (he==0) {
+ DBG("could not resolve %s\n", hns.s);
+ return -4;
+ }
+ ret = 0;
+ if (he->h_addrtype==ipa->af)
+ {
+ for(h=he->h_addr_list; (*h); h++)
+ {
+ if(memcmp(ipa->u.addr, *h, ipa->len)==0)
+ {
+ /* match */
+ return 1;
+ }
+ }
+ }
+ /* no match */
+ return -1;
+}
Module: sip-router
Branch: tmp/tm_async_reply_support
Commit: 997feed460ea53c926f8e42d5b46d304cba7dce5
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=997feed…
Author: Richard Good <richard.good(a)smilecoms.com>
Committer: Richard Good <richard.good(a)smilecoms.com>
Date: Fri Jul 12 17:46:58 2013 +0200
modules/tm: Cleaned up async_response code to use new faked async env
-Use new faked_env_async method -instead of duplicating with faked_env_resp
-Also use new async lock on continue
---
modules/tm/t_reply.c | 92 ------------------------------------------------
modules/tm/t_reply.h | 1 -
modules/tm/t_suspend.c | 13 +++++--
3 files changed, 9 insertions(+), 97 deletions(-)
diff --git a/modules/tm/t_reply.c b/modules/tm/t_reply.c
index 2a45188..8542340 100644
--- a/modules/tm/t_reply.c
+++ b/modules/tm/t_reply.c
@@ -859,98 +859,6 @@ void free_faked_resp(struct sip_msg *faked_resp, struct cell *t, int branch)
}
}
-/** create or restore a "fake environment" for running a TM_ONREPLY_ROUTE.
- * This used for suspending and continuing on SIP replies
- *if msg is set -> it will fake the env. vars conforming with the msg; if NULL
- * the env. will be restore to original.
- * Side-effect: mark_ruri_consumed().
- */
-void faked_env_resp( 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 reply processing, but process
- * a shmem-ed replica of the reply; advertise it in route type;
- * for example t_reply needs to know that
- */
- backup_route_type=get_route_type();
-
- /*This is response so route type is TM_ONREPLY_ROUTE*/
- set_route_type(TM_ONREPLY_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_BR_UNDEFINED);
- /* 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;
- }
-}
-
void faked_env_async( struct cell *t, struct sip_msg *msg) {
if (msg) {
diff --git a/modules/tm/t_reply.h b/modules/tm/t_reply.h
index d2f1370..51e4634 100644
--- a/modules/tm/t_reply.h
+++ b/modules/tm/t_reply.h
@@ -239,7 +239,6 @@ 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,
struct sip_msg *shmem_msg, int extra_flags, struct ua_client *uac);
diff --git a/modules/tm/t_suspend.c b/modules/tm/t_suspend.c
index b9c92e6..eb5b1a5 100644
--- a/modules/tm/t_suspend.c
+++ b/modules/tm/t_suspend.c
@@ -355,8 +355,8 @@ int t_continue_reply(unsigned int hash_index, unsigned int label,
init_cancel_info(&cancel_data);
/* The transaction has to be locked to protect it
- * form calling t_continue_reply() multiple times simultaneously */
- LOCK_REPLIES(t);
+ * form calling t_continue() multiple times simultaneously */
+ LOCK_ASYNC_CONTINUE(t);
LOG(L_DBG,"DEBUG: t_continue_reply: This a continue from a reply suspend\n");
/* this is a continue from a reply suspend */
@@ -371,7 +371,7 @@ int t_continue_reply(unsigned int hash_index, unsigned int label,
return 0;
}
- faked_env_resp( t, &faked_resp);
+ faked_env_async( t, &faked_resp);
LOG(L_DBG,"DEBUG: Running pre script\n");
if (exec_pre_script_cb(&faked_resp, ONREPLY_CB_TYPE)>0) {
@@ -383,10 +383,13 @@ int t_continue_reply(unsigned int hash_index, unsigned int label,
}
LOG(L_DBG,"DEBUG: t_continue_reply: Restoring previous environment");
- faked_env_resp( t, 0);
+ faked_env_async( t, 0);
free_faked_resp(&faked_resp, t, branch);
int reply_status;
+
+ /*lock transaction replies - will be unlocked when reply is relayed*/
+ LOCK_REPLIES( t );
if ( is_local(t) ) {
LOG(L_DBG,"DEBUG: t_continue_reply: t is local sending local reply with status code: [%d]\n", t->uac[branch].reply->first_line.u.reply.statuscode);
reply_status = local_reply( t, t->uac[branch].reply, branch, t->uac[branch].reply->first_line.u.reply.statuscode, &cancel_data );
@@ -455,6 +458,8 @@ int t_continue_reply(unsigned int hash_index, unsigned int label,
done:
+ UNLOCK_ASYNC_CONTINUE(t);
+
tm_ctx_set_branch_index(T_BR_UNDEFINED);
/* unref the transaction */
t_unref(t->uac[branch].reply);
Hi
We are using the t_suspend and t_continue functionality to asynchronously
send Diameter messages.
This works nicely when we suspend and resume on a SIP request. However in
some circumstances we want to send a Diameter message on a SIP response.
I have found that the SIP responses continue to be relayed despite being
suspended and returning 0 to the cfg file.
I am investigating the cause but before I get any deeper does anyone know
if the t_suspend and t_continue functionality in the tm module can be used
on a SIP response?
Regards
Richard.
This email is subject to the disclaimer of Smile Communications (PTY) Ltd. at http://www.smilecoms.com/disclaimer
THIS IS AN AUTOMATED MESSAGE, DO NOT REPLY.
The following task has a new comment added:
FS#324 - Entity URI in NOTIFY XML body
User who did this - Daniel-Constantin Mierla (miconda)
----------
OK. It may make no sense to have a module parameter if using uri schema is the correct mode. Also will be all with or without schema, so won't work in mixed environment.
If proved not to work with some UA, then we'll have to add some flags to mark each subscription. The condition will be in config file based on UA or what so ever test. Hopefully will not be the case. I'll ping the author of the module for an opinion as well.
----------
More information can be found at the following URL:
http://sip-router.org/tracker/index.php?do=details&task_id=324#comment999
You are receiving this message because you have requested it from the Flyspray bugtracking system. If you did not expect this message or don't want to receive mails in future, you can change your notification settings at the URL shown above.
Module: sip-router
Branch: tmp/tm_async_reply_support
Commit: 749ce7e29901f79597c461c4cd161d3c3e24dda2
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=749ce7e…
Author: Jason Penton <jason.penton(a)smilecoms.com>
Committer: Jason Penton <jason.penton(a)smilecoms.com>
Date: Fri Jul 12 16:14:08 2013 +0200
modules/tm: more async improvements
---
modules/tm/h_table.h | 2 ++
modules/tm/t_fwd.c | 2 ++
modules/tm/t_reply.c | 4 ++--
modules/tm/t_suspend.c | 17 +++++++----------
4 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/modules/tm/h_table.h b/modules/tm/h_table.h
index e4f2fa1..48027c4 100644
--- a/modules/tm/h_table.h
+++ b/modules/tm/h_table.h
@@ -270,6 +270,7 @@ typedef struct async_state
{
unsigned int backup_route;
unsigned int backup_branch;
+ unsigned int blind_uac;
unsigned int ruri_new;
}async_state_type;
@@ -317,6 +318,7 @@ struct totag_elem {
# define T_PASS_PROVISIONAL_FLAG (1<<11)
# define pass_provisional(_t_) ((_t_)->flags&T_PASS_PROVISIONAL_FLAG)
#endif
+#define T_ASYNC_CONTINUE (1<<9) /* Is this transaction in a continuation after being suspended */
/* 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_fwd.c b/modules/tm/t_fwd.c
index 55d45f4..d4b967d 100644
--- a/modules/tm/t_fwd.c
+++ b/modules/tm/t_fwd.c
@@ -755,6 +755,8 @@ int add_blind_uac( /*struct cell *t*/ )
membar_write(); /* to allow lockless prepare_to_cancel() we want to be sure
all the writes finished before updating branch number*/
t->nr_of_outgoings=(branch+1);
+ t->async_backup.blind_uac = branch;
+
/* start FR timer -- protocol set by default to PROTO_NONE,
which means retransmission timer will not be started
*/
diff --git a/modules/tm/t_reply.c b/modules/tm/t_reply.c
index c009a18..2a45188 100644
--- a/modules/tm/t_reply.c
+++ b/modules/tm/t_reply.c
@@ -1379,8 +1379,8 @@ int t_pick_branch(int inc_branch, int inc_code, struct cell *t, int *res_code)
* to be a pending, incomplete branch. */
if ((!t->uac[b].request.buffer) && (t->uac[b].last_received>=200))
continue;
- /* there is still an unfinished UAC transaction; wait now! */
- if ( t->uac[b].last_received<200 )
+ /* there is still an unfinished UAC transaction (we ignore unfinished blind UACs) wait now! */
+ if ( t->uac[b].last_received<200 && !((t->flags&T_ASYNC_CONTINUE) && b==t->async_backup.blind_uac))
return -2;
/* if reply is null => t_send_branch "faked" reply, skip over it */
if ( rpl &&
diff --git a/modules/tm/t_suspend.c b/modules/tm/t_suspend.c
index 3b03f97..b9c92e6 100644
--- a/modules/tm/t_suspend.c
+++ b/modules/tm/t_suspend.c
@@ -103,7 +103,7 @@ int t_suspend(struct sip_msg *msg,
*hash_index = t->hash_index;
*label = t->label;
- /* add a bling UAC to let the fr timer running */
+ /* add a blind UAC to let the fr timer running */
if (add_blind_uac() < 0) {
LOG(L_ERR, "ERROR: t_suspend: " \
"failed to add the blind UAC\n");
@@ -205,15 +205,12 @@ int t_continue(unsigned int hash_index, unsigned int label,
* form calling t_continue() multiple times simultaneously */
LOCK_ASYNC_CONTINUE(t);
- /* Try to find the blind UAC, and cancel its fr timer.
- * We assume that the last blind uac called t_continue(). */
- for ( branch = t->nr_of_outgoings-1;
- branch >= 0 && t->uac[branch].request.buffer;
- branch--);
-
- if (branch >= 0) {
+ t->flags |= T_ASYNC_CONTINUE; //we can now know anywhere in kamailio that we are executing post a suspend.
+
+
+ branch = t->async_backup.blind_uac;
+ if (branch >= 0) {
stop_rb_timers(&t->uac[branch].request);
-
if (t->uac[branch].last_received != 0) {
/* Either t_continue() has already been
* called or the branch has already timed out.
@@ -231,7 +228,7 @@ int t_continue(unsigned int hash_index, unsigned int label,
* for example when t_reply() is called from
* a failure route => deadlock, because both
* of them need the reply lock to be held. */
- t->uac[branch].last_received=500;
+ //t->uac[branch].last_received=500; we dont need this anymore, we are not locking replies
uac = &t->uac[branch];
}
/* else