[Freeswitch-svn] [commit] r7109 - in freeswitch/trunk/libs/sofia-sip: . libsofia-sip-ua libsofia-sip-ua-glib libsofia-sip-ua/docs libsofia-sip-ua/nta libsofia-sip-ua/nua libsofia-sip-ua/stun libsofia-sip-ua/tport m4 scripts tests
Freeswitch SVN
mikej at freeswitch.org
Sun Jan 6 15:15:11 EST 2008
Author: mikej
Date: Sun Jan 6 15:15:11 2008
New Revision: 7109
Added:
freeswitch/trunk/libs/sofia-sip/scripts/hide_emails.sh
Removed:
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/docs/hide_emails.sh
Modified:
freeswitch/trunk/libs/sofia-sip/.update
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua-glib/Makefile.am
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/Makefile.am
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nta/nta.c
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nta/test_nta.c
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_subnotref.c
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/outbound.c
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/stun/stun.c
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport_tag.c
freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_udp.c
freeswitch/trunk/libs/sofia-sip/m4/sac-su2.m4
freeswitch/trunk/libs/sofia-sip/tests/check_sofia.c
Log:
Merge current sofia-sip darcs tree:
Thu Dec 13 09:15:04 EST 2007 Pekka.Pessi at nokia.com
* libsofia-sip-ua/docs/hide_emails.sh: moved to scripts/ subdir
Thu Dec 13 09:15:34 EST 2007 Pekka.Pessi at nokia.com
* check_sofia.c: pass xml result file as optional parameter to check_sofia
Thu Dec 20 08:13:37 EST 2007 Pekka.Pessi at nokia.com
* stun.c: try to avoid using stun handle after returning from discovery callback
Crash reported and partial patch by Daniele Rondina.
Thu Jan 3 07:11:27 EST 2008 Pekka.Pessi at nokia.com
* tport_type_udp.c: using SO_RCVBUFFORCE and SO_SNDBUFFORCE to set rmem/wmem on udp sockets
Referring reader to Linux sysctls to TPTAG_UDP_RMEM and TPTAG_UDP_WMEM
documentation.
Thu Jan 3 07:11:47 EST 2008 Pekka.Pessi at nokia.com
* m4/sac-su2.m4: checks for SO_RCVBUFFORCE and SO_SNDBUFFORCE
Thu Jan 3 08:19:04 EST 2008 Pekka.Pessi at nokia.com
* nta.c: calculate next timeout only after completing current timeout
Thanks to Mike Jerris for reporting this problem.
Thu Jan 3 11:02:11 EST 2008 Pekka.Pessi at nokia.com
* sac-su2.m4: checking for IP_ADD_MEMBERSHIP and IP_MULTICAST_LOOP
Thu Jan 3 12:08:39 EST 2008 Pekka.Pessi at nokia.com
* tport_type_udp.c: when binding to multicast address, join to the group, too.
Use "canonic" IP address (from host-part of the SIP URI) to specify
interface.
Mon Nov 19 15:01:09 EST 2007 Pekka Pessi <first.lastname at nokia.com>
* tport_type_udp.c: made IP_ADD_MEMBERSHIP as portable
Fri Jan 4 13:19:01 EST 2008 Pekka.Pessi at nokia.com
* test_nta.c: added check for request merging (with both 3261 and 2543 proxies)
Fri Jan 4 13:20:35 EST 2008 Pekka.Pessi at nokia.com
* nta.c: fixed request merging with RFC 2543 proxies
Updated matching of PRACKs with outstanding 100rel, too.
Fri Jan 4 15:27:01 EST 2008 Pekka.Pessi at nokia.com
* nta.c: follow more closely RFC 3261 request matching rules
Fri Jan 4 15:31:22 EST 2008 Pekka.Pessi at nokia.com
* nua_session.c: do not clear soa when an overlapping INVITE is received
Fri Jan 4 15:32:58 EST 2008 Pekka.Pessi at nokia.com
* nua/outbound.c: reduce logging
Fri Jan 4 16:51:00 EST 2008 Pekka.Pessi at nokia.com
* nua_subnotref.c: accept NOTIFY without Event header
Fri Jan 4 16:53:20 EST 2008 Pekka.Pessi at nokia.com
* nua_notifier.c: fix problem handing expiration time if NOTIFY is sent before SUBSCRIBE has been responded
Fri Jan 4 16:54:08 EST 2008 Pekka.Pessi at nokia.com
* nua_notifier.c: allow notifier handle to be shut down if SUBSCRIBE has been accpeted but no NOTIFY has been sent
Modified: freeswitch/trunk/libs/sofia-sip/.update
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/.update (original)
+++ freeswitch/trunk/libs/sofia-sip/.update Sun Jan 6 15:15:11 2008
@@ -1 +1 @@
-Thu Oct 11 15:56:47 EDT 2007
+Sun Jan 6 15:11:42 EST 2008
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua-glib/Makefile.am
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua-glib/Makefile.am (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua-glib/Makefile.am Sun Jan 6 15:15:11 2008
@@ -40,7 +40,7 @@
&& ${DOXYGEN} \
&& popd > /dev/null ; \
done
- ${top_srcdir}/libsofia-sip-ua/docs/hide_emails.sh docs/html
+ ${top_srcdir}/scripts/hide_emails.sh docs/html
PHONY = doxygen
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/Makefile.am
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/Makefile.am (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/Makefile.am Sun Jan 6 15:15:11 2008
@@ -101,7 +101,7 @@
docs/$$d.doxytags > docs/$$d.doxytags.tmp && \
mv -f docs/$$d.doxytags.tmp docs/$$d.doxytags ; \
done
- ${srcdir}/docs/hide_emails.sh docs/html
+ ${top_srcdir}/scripts/hide_emails.sh docs/html
if HAVE_LCOV
include $(top_srcdir)/rules/lcov.am
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nta/nta.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nta/nta.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nta/nta.c Sun Jan 6 15:15:11 2008
@@ -202,11 +202,12 @@
incoming_queue_t *queue,
unsigned timeout);
-su_inline
-nta_incoming_t *incoming_find(nta_agent_t const *agent, sip_t const *sip,
- sip_via_t const *v,
- nta_incoming_t **merge,
- nta_incoming_t **ack);
+static nta_incoming_t *incoming_find(nta_agent_t const *agent,
+ sip_t const *sip,
+ sip_via_t const *v,
+ nta_incoming_t **merge,
+ nta_incoming_t **ack,
+ nta_incoming_t **cancel);
static int incoming_reply(nta_incoming_t *irq, msg_t *msg, sip_t *sip);
su_inline int incoming_recv(nta_incoming_t *irq, msg_t *msg, sip_t *sip,
tport_t *tport);
@@ -214,10 +215,11 @@
tport_t *tport);
su_inline int incoming_cancel(nta_incoming_t *irq, msg_t *msg, sip_t *sip,
tport_t *tport);
-su_inline int incoming_merge(nta_incoming_t *irq, msg_t *msg, sip_t *sip,
- tport_t *tport);
+static void request_merge(nta_agent_t *,
+ msg_t *msg, sip_t *sip, tport_t *tport,
+ char const *to_tag);
su_inline int incoming_timestamp(nta_incoming_t *, msg_t *, sip_t *);
-su_inline su_duration_t incoming_timer(nta_agent_t *, su_duration_t);
+static void incoming_timer(nta_agent_t *);
static nta_reliable_t *reliable_mreply(nta_incoming_t *,
nta_prack_f *, nta_reliable_magic_t *,
@@ -225,7 +227,8 @@
static int reliable_send(nta_incoming_t *, nta_reliable_t *, msg_t *, sip_t *);
static int reliable_final(nta_incoming_t *irq, msg_t *msg, sip_t *sip);
static msg_t *reliable_response(nta_incoming_t *irq);
-static int reliable_recv(nta_incoming_t *, msg_t *, sip_t *, tport_t *);
+static nta_reliable_t *reliable_find(nta_agent_t const *, sip_t const *);
+static int reliable_recv(nta_reliable_t *rel, msg_t *, sip_t *, tport_t *);
static void reliable_flush(nta_incoming_t *irq);
static void reliable_timeout(nta_incoming_t *irq, int timeout);
@@ -251,7 +254,7 @@
sip_via_t const *v);
static int outgoing_recv(nta_outgoing_t *orq, int status, msg_t *, sip_t *);
static void outgoing_default_recv(nta_outgoing_t *, int, msg_t *, sip_t *);
-su_inline su_duration_t outgoing_timer(nta_agent_t *, su_duration_t);
+static void outgoing_timer(nta_agent_t *);
static int outgoing_recv_reliable(nta_outgoing_t *orq, msg_t *msg, sip_t *sip);
/* Internal message passing */
@@ -725,9 +728,6 @@
return -(agent->sa_timer == NULL);
}
-#define NEXT_TIMEOUT(next, p, f, now) \
- (p && p->f - (next) < 0 ? (p->f - (now) > 0 ? p->f : (now)) : (next))
-
/**
* Agent timer routine.
*/
@@ -739,20 +739,43 @@
now += now == 0;
+ agent->sa_next = 0;
+
agent->sa_now = stamp;
agent->sa_millisec = now;
- agent->sa_next = 0;
agent->sa_in_timer = 1;
- next = now + SU_DURATION_MAX;
- next = outgoing_timer(agent, next);
- next = incoming_timer(agent, next);
+ outgoing_timer(agent);
+ incoming_timer(agent);
+ /* agent->sa_now is used only if sa_millisec != 0 */
agent->sa_millisec = 0;
agent->sa_in_timer = 0;
+ /* Calculate next timeout */
+ next = now + SU_DURATION_MAX;
+
+#define NEXT_TIMEOUT(next, p, f, now) \
+ (void)(p && p->f - (next) < 0 && ((next) = (p->f - (now) > 0 ? p->f : (now))))
+
+ NEXT_TIMEOUT(next, agent->sa_out.re_list, orq_retry, now);
+ NEXT_TIMEOUT(next, agent->sa_out.inv_completed->q_head, orq_timeout, now);
+ NEXT_TIMEOUT(next, agent->sa_out.completed->q_head, orq_timeout, now);
+ NEXT_TIMEOUT(next, agent->sa_out.inv_calling->q_head, orq_timeout, now);
+ if (agent->sa_out.inv_proceeding->q_timeout)
+ NEXT_TIMEOUT(next, agent->sa_out.inv_proceeding->q_head, orq_timeout, now);
+ NEXT_TIMEOUT(next, agent->sa_out.trying->q_head, orq_timeout, now);
+
+ NEXT_TIMEOUT(next, agent->sa_in.preliminary->q_head, irq_timeout, now);
+ NEXT_TIMEOUT(next, agent->sa_in.inv_completed->q_head, irq_timeout, now);
+ NEXT_TIMEOUT(next, agent->sa_in.inv_confirmed->q_head, irq_timeout, now);
+ NEXT_TIMEOUT(next, agent->sa_in.completed->q_head, irq_timeout, now);
+ NEXT_TIMEOUT(next, agent->sa_in.re_list, irq_retry, now);
+
if (agent->sa_next)
- next = NEXT_TIMEOUT(next, agent, sa_next, now);
+ NEXT_TIMEOUT(next, agent, sa_next, now);
+
+#undef NEXT_TIMEOUT
if (next == now + SU_DURATION_MAX) {
/* Do not set timer */
@@ -2199,7 +2222,7 @@
tport_t *tport)
{
nta_leg_t *leg;
- nta_incoming_t *irq, *merge = NULL, *ack = NULL;
+ nta_incoming_t *irq, *merge = NULL, *ack = NULL, *cancel = NULL;
sip_method_t method = sip->sip_request->rq_method;
char const *method_name = sip->sip_request->rq_method_name;
url_t url[1];
@@ -2337,7 +2360,15 @@
}
/* First, try existing incoming requests */
- irq = incoming_find(agent, sip, sip->sip_via, &merge, &ack);
+ irq = incoming_find(agent, sip, sip->sip_via,
+ agent->sa_merge_482 &&
+ !sip->sip_to->a_tag &&
+ method != sip_method_ack
+ ? &merge
+ : NULL,
+ method == sip_method_ack ? &ack : NULL,
+ method == sip_method_cancel ? &cancel : NULL);
+
if (irq) {
/* Match - this is a retransmission */
SU_DEBUG_5(("nta: %s (%u) going to existing %s transaction\n",
@@ -2346,31 +2377,36 @@
return;
}
else if (ack) {
- /* Match - this is an ACK or CANCEL or PRACK */
SU_DEBUG_5(("nta: %s (%u) is going to %s (%u)\n",
method_name, cseq,
- ack->irq_rq->rq_method_name, ack->irq_cseq->cs_seq));
- if (method == sip_method_ack) {
- if (incoming_ack(ack, msg, sip, tport) >= 0)
- return;
- }
- else if (method == sip_method_cancel) {
- if (incoming_cancel(ack, msg, sip, tport) >= 0)
- return;
- }
- else if (method == sip_method_prack) {
- if (reliable_recv(ack, msg, sip, tport) >= 0)
- return;
- }
- else {
- assert(!method);
- }
+ ack->irq_cseq->cs_method_name, ack->irq_cseq->cs_seq));
+ if (incoming_ack(ack, msg, sip, tport) >= 0)
+ return;
+ }
+ else if (cancel) {
+ SU_DEBUG_5(("nta: %s (%u) is going to %s (%u)\n",
+ method_name, cseq,
+ cancel->irq_cseq->cs_method_name, cancel->irq_cseq->cs_seq));
+ if (incoming_cancel(cancel, msg, sip, tport) >= 0)
+ return;
}
else if (merge) {
SU_DEBUG_5(("nta: %s (%u) %s\n",
method_name, cseq, "is a merged request"));
- if (incoming_merge(merge, msg, sip, tport) >= 0)
+ request_merge(agent, msg, sip, tport, merge->irq_tag);
+ return;
+ }
+
+ if (method == sip_method_prack && sip->sip_rack) {
+ nta_reliable_t *rel = reliable_find(agent, sip);
+ if (rel) {
+ SU_DEBUG_5(("nta: %s (%u) is going to %s (%u)\n",
+ method_name, cseq,
+ rel->rel_irq->irq_cseq->cs_method_name,
+ rel->rel_irq->irq_cseq->cs_seq));
+ reliable_recv(rel, msg, sip, tport);
return;
+ }
}
*url = *sip->sip_request->rq_url;
@@ -5176,48 +5212,41 @@
sip_via_t const *v)
{
if (agent && sip && v)
- return incoming_find(agent, sip, v, NULL, NULL);
+ return incoming_find(agent, sip, v, NULL, NULL, NULL);
else
return NULL;
}
-su_inline
-int addr_match(sip_addr_t const *a, char const *a_tag, sip_addr_t const *b)
-{
- if (a_tag && b->a_tag)
- return strcasecmp(a_tag, b->a_tag) == 0;
- else if (a->a_tag && b->a_tag)
- return strcasecmp(a->a_tag, b->a_tag) == 0;
- else
- return
- str0casecmp(a->a_host, b->a_host) == 0 &&
- str0cmp(a->a_user, b->a_user) == 0;
-}
-
/** Find a matching server transaction object.
*
- *
+ * Check also for requests to merge, to ACK, or to CANCEL.
*/
-su_inline
-nta_incoming_t *incoming_find(nta_agent_t const *agent,
- sip_t const *sip,
- sip_via_t const *v,
- nta_incoming_t **return_merge,
- nta_incoming_t **return_ack)
+static nta_incoming_t *incoming_find(nta_agent_t const *agent,
+ sip_t const *sip,
+ sip_via_t const *v,
+ nta_incoming_t **return_merge,
+ nta_incoming_t **return_ack,
+ nta_incoming_t **return_cancel)
{
sip_cseq_t const *cseq = sip->sip_cseq;
sip_call_id_t const *i = sip->sip_call_id;
sip_to_t const *to = sip->sip_to;
sip_from_t const *from = sip->sip_from;
sip_request_t *rq = sip->sip_request;
- int is_uas_ack = return_ack &&
- agent->sa_is_a_uas && rq->rq_method == sip_method_ack;
incoming_htable_t const *iht = agent->sa_incoming;
hash_value_t hash = NTA_HASH(i, cseq->cs_seq);
+ char const *magic_branch;
+
+ nta_incoming_t **ii, *irq;
- nta_incoming_t **ii, *irq, *maybe;
+ int is_uas_ack = return_ack && agent->sa_is_a_uas;
- for (ii = incoming_htable_hash(iht, hash), maybe = NULL;
+ if (v->v_branch && strncasecmp(v->v_branch, "z9hG4bK", 7) == 0)
+ magic_branch = v->v_branch + 7;
+ else
+ magic_branch = NULL;
+
+ for (ii = incoming_htable_hash(iht, hash);
(irq = *ii);
ii = incoming_htable_next(iht, ii)) {
if (hash != irq->irq_hash ||
@@ -5229,96 +5258,84 @@
if (str0casecmp(irq->irq_from->a_tag, from->a_tag))
continue;
- if (str0casecmp(irq->irq_via->v_branch, v->v_branch) != 0 ||
- strcasecmp(irq->irq_via->v_host, v->v_host) != 0) {
- if (!agent->sa_is_a_uas)
- continue;
-
- if (is_uas_ack &&
- irq->irq_method == sip_method_invite &&
- 200 <= irq->irq_status && irq->irq_status < 300 &&
- addr_match(irq->irq_to, irq->irq_tag, to))
- *return_ack = irq;
- /* RFC3261 - section 8.2.2.2 Merged Requests */
- else if (return_merge && agent->sa_merge_482 &&
- irq->irq_cseq->cs_method == cseq->cs_method &&
- (irq->irq_cseq->cs_method != sip_method_unknown ||
- strcmp(irq->irq_cseq->cs_method_name,
- cseq->cs_method_name) == 0)) {
- *return_merge = irq;
- continue;
- }
- else
- continue;
- }
-
- if (is_uas_ack) {
- if (!addr_match(irq->irq_to, irq->irq_tag, to))
- continue;
- }
- else if (irq->irq_tag_set || !irq->irq_tag) {
- if (str0casecmp(irq->irq_to->a_host, to->a_host) != 0 ||
- str0cmp(irq->irq_to->a_user, to->a_user) != 0)
- continue;
+ if (is_uas_ack &&
+ irq->irq_method == sip_method_invite &&
+ 200 <= irq->irq_status && irq->irq_status < 300 &&
+ str0casecmp(irq->irq_tag, to->a_tag) == 0) {
+ *return_ack = irq;
+ return NULL;
}
- else if (str0casecmp(irq->irq_to->a_tag, to->a_tag))
- continue;
-
- if (!is_uas_ack && url_cmp(irq->irq_rq->rq_url, rq->rq_url))
- continue;
-
-#if 0
- if (irq->irq_terminated)
- continue;
-#endif
- if (irq->irq_method == rq->rq_method)
- break; /* found */
-
- if (!return_ack)
- continue;
+ if (magic_branch) {
+ /* RFC3261 17.2.3:
+ *
+ * The request matches a transaction if branch and sent-by in topmost
+ * the method of the request matches the one that created the
+ * transaction, except for ACK, where the method of the request
+ * that created the transaction is INVITE.
+ */
- if (irq->irq_method == sip_method_invite) {
- if (rq->rq_method == sip_method_cancel)
- *return_ack = irq;
- else if (rq->rq_method == sip_method_ack)
- *return_ack = irq;
+ if (irq->irq_via->v_branch &&
+ strcasecmp(irq->irq_via->v_branch + 7, magic_branch) == 0 &&
+ strcasecmp(irq->irq_via->v_host, v->v_host) == 0 &&
+ str0cmp(irq->irq_via->v_port, v->v_port) == 0) {
+ if (irq->irq_method == cseq->cs_method &&
+ strcmp(irq->irq_cseq->cs_method_name,
+ cseq->cs_method_name) == 0)
+ return irq;
+ if (return_ack && irq->irq_method == sip_method_invite)
+ return *return_ack = irq, NULL;
+ if (return_cancel && irq->irq_method != sip_method_ack)
+ return *return_cancel = irq, NULL;
+ }
}
- else if (rq->rq_method == sip_method_cancel && !irq->irq_terminated)
- *return_ack = irq;
- }
-
- if (irq)
- return irq;
+ else {
+ /* No magic branch */
- /* Check PRACKed requests */
- if (return_ack && rq->rq_method == sip_method_prack && sip->sip_rack) {
- sip_rack_t const *rack = sip->sip_rack;
- hash = NTA_HASH(i, rack->ra_cseq);
-
- for (ii = incoming_htable_hash(iht, hash);
- (irq = *ii);
- ii = incoming_htable_next(iht, ii)) {
- if (hash != irq->irq_hash)
- continue;
- if (irq->irq_call_id->i_hash != i->i_hash)
- continue;
- if (strcmp(irq->irq_call_id->i_id, i->i_id))
- continue;
- if (irq->irq_cseq->cs_seq != rack->ra_cseq)
- continue;
- if (!addr_match(irq->irq_to, NULL, to) ||
- !addr_match(irq->irq_from, NULL, from))
- continue;
- if (!irq->irq_from->a_tag != !from->a_tag)
- continue;
- *return_ack = irq;
+ /* INVITE request matches a transaction if
+ the Request-URI, To tag, From tag, Call-ID, CSeq, and
+ top Via header match */
+
+ /* From tag, Call-ID, and CSeq number has been matched above */
+
+ /* Match To tag */
+ if (str0casecmp(irq->irq_to->a_tag, to->a_tag) &&
+ /* Ignore failing match if tag has been set */
+ /* and retransmitted request had no to tag */
+ !(irq->irq_tag_set && to->a_tag == NULL))
+ ;
+ /* Match top Via header field */
+ else if (str0casecmp(irq->irq_via->v_branch, v->v_branch) == 0 &&
+ strcasecmp(irq->irq_via->v_host, v->v_host) == 0 &&
+ str0cmp(irq->irq_via->v_port, v->v_port) == 0)
+ ;
+ /* Match Request-URI */
+ else if (url_cmp(irq->irq_rq->rq_url, rq->rq_url))
+ ;
+ else {
+ /* Match CSeq */
+ if (irq->irq_method == cseq->cs_method &&
+ strcmp(irq->irq_cseq->cs_method_name,
+ cseq->cs_method_name) == 0)
+ return irq; /* found */
+
+ if (return_ack && irq->irq_method == sip_method_invite)
+ *return_ack = irq;
+ else if (return_cancel && irq->irq_method != sip_method_ack)
+ *return_cancel = irq;
+ }
+ }
- return NULL;
+ /* RFC3261 - section 8.2.2.2 Merged Requests */
+ if (return_merge) {
+ if (irq->irq_cseq->cs_method == cseq->cs_method &&
+ strcmp(irq->irq_cseq->cs_method_name,
+ cseq->cs_method_name) == 0)
+ *return_merge = irq, return_merge = NULL;
}
}
- return irq;
+ return NULL;
}
/** Process retransmitted requests. */
@@ -5397,23 +5414,26 @@
return 0;
}
+/** Respond to the CANCEL. */
su_inline
int incoming_cancel(nta_incoming_t *irq, msg_t *msg, sip_t *sip,
tport_t *tport)
{
nta_agent_t *agent = irq->irq_agent;
- /* Respond to the CANCEL */
-
- if (200 <= irq->irq_status && irq->irq_status < 300) {
- nta_msg_treply(agent, msg_ref_create(msg), SIP_481_NO_TRANSACTION,
+ /* According to the spec, this INVITE has been destroyed */
+ if (irq->irq_method == sip_method_invite &&
+ 200 <= irq->irq_status && irq->irq_status < 300) {
+ nta_msg_treply(agent, msg, SIP_481_NO_TRANSACTION,
NTATAG_TPORT(tport),
TAG_END());
+ return 0;
}
- else
- nta_msg_treply(agent, msg_ref_create(msg), SIP_200_OK,
- NTATAG_TPORT(tport),
- TAG_END());
+
+ nta_msg_treply(agent, msg_ref_create(msg), SIP_200_OK,
+ NTATAG_TPORT(tport),
+ SIPTAG_TO(irq->irq_to),
+ TAG_END());
/* We have already sent final response */
if (irq->irq_completed || irq->irq_method != sip_method_invite) {
@@ -5436,29 +5456,28 @@
return 0;
}
-/** Process merged requests */
-su_inline
-int incoming_merge(nta_incoming_t *irq, msg_t *msg, sip_t *sip, tport_t *tport)
+/** Merge request */
+static
+void request_merge(nta_agent_t *agent,
+ msg_t *msg, sip_t *sip, tport_t *tport,
+ char const *to_tag)
{
- nta_agent_t *agent = irq->irq_agent;
+ nta_incoming_t *irq;
agent->sa_stats->as_merged_request++;
- irq = incoming_create(irq->irq_agent, msg, sip, tport, irq->irq_tag);
+ irq = incoming_create(agent, msg, sip, tport, to_tag);
- if (!irq) {
- SU_DEBUG_3(("nta: incoming_merge(): cannot create transaction for %s\n",
+ if (irq) {
+ nta_incoming_treply(irq, 482, "Request merged", TAG_END());
+ nta_incoming_destroy(irq);
+ } else {
+ SU_DEBUG_3(("nta: request_merge(): cannot create transaction for %s\n",
sip->sip_request->rq_method_name));
nta_msg_treply(agent, msg, 482, "Request merged",
NTATAG_TPORT(tport),
TAG_END());
- return 0;
}
-
- nta_incoming_treply(irq, 482, "Request merged", TAG_END());
- nta_incoming_destroy(irq);
-
- return 0;
}
/**@typedef nta_ack_cancel_f
@@ -6097,8 +6116,7 @@
};
/** @internal Timer routine for the incoming request. */
-su_inline
-su_duration_t incoming_timer(nta_agent_t *sa, su_duration_t next)
+static void incoming_timer(nta_agent_t *sa)
{
su_duration_t now = sa->sa_millisec;
nta_incoming_t *irq, *irq_next;
@@ -6166,8 +6184,6 @@
}
}
- next = NEXT_TIMEOUT(next, irq, irq_retry, now);
-
while ((irq = sa->sa_in.final_failed->q_head)) {
incoming_remove(irq);
irq->irq_final_failed = 0;
@@ -6215,8 +6231,6 @@
reliable_timeout(irq, 1);
}
- next = NEXT_TIMEOUT(next, irq, irq_timeout, now);
-
while ((irq = sa->sa_in.inv_completed->q_head)) {
assert(irq->irq_status >= 200);
assert(irq->irq_timeout);
@@ -6245,8 +6259,6 @@
}
}
- next = NEXT_TIMEOUT(next, irq, irq_timeout, now);
-
while ((irq = sa->sa_in.inv_confirmed->q_head)) {
assert(irq->irq_timeout);
assert(irq->irq_status >= 200);
@@ -6268,8 +6280,6 @@
incoming_free_queue(rq, irq);
}
- next = NEXT_TIMEOUT(next, irq, irq_timeout, now);
-
while ((irq = sa->sa_in.completed->q_head)) {
assert(irq->irq_status >= 200);
assert(irq->irq_timeout);
@@ -6292,8 +6302,6 @@
incoming_free_queue(rq, irq);
}
- next = NEXT_TIMEOUT(next, irq, irq_timeout, now);
-
for (irq = sa->sa_in.terminated->q_head; irq; irq = irq_next) {
irq_next = irq->irq_next;
if (irq->irq_destroyed)
@@ -6312,8 +6320,6 @@
timeout, unconfirmed,
terminated, unterminated,
destroyed, total));
-
- return next;
}
/** Mass destroy server transactions */
@@ -7864,8 +7870,7 @@
/** @internal Outgoing transaction timer routine.
*
*/
-su_inline
-su_duration_t outgoing_timer(nta_agent_t *sa, su_duration_t next)
+static void outgoing_timer(nta_agent_t *sa)
{
su_duration_t now = sa->sa_millisec;
nta_outgoing_t *orq;
@@ -7877,7 +7882,6 @@
sa->sa_out.inv_calling->q_length;
size_t completed = sa->sa_out.completed->q_length +
sa->sa_out.inv_completed->q_length;
- outgoing_queue_t *proceeding = sa->sa_out.inv_proceeding;
outgoing_queue_init(sa->sa_out.free = rq, 0);
@@ -7920,25 +7924,15 @@
su_root_yield(sa->sa_root); /* Handle received packets */
}
- next = NEXT_TIMEOUT(next, orq, orq_retry, now);
-
terminated
= outgoing_timer_dk(sa->sa_out.inv_completed, "D", now)
+ outgoing_timer_dk(sa->sa_out.completed, "K", now);
- next = NEXT_TIMEOUT(next, sa->sa_out.inv_completed->q_head, orq_timeout, now);
- next = NEXT_TIMEOUT(next, sa->sa_out.completed->q_head, orq_timeout, now);
-
timeout
= outgoing_timer_bf(sa->sa_out.inv_calling, "B", now)
- + outgoing_timer_c(proceeding, "C", now)
+ + outgoing_timer_c(sa->sa_out.inv_proceeding, "C", now)
+ outgoing_timer_bf(sa->sa_out.trying, "F", now);
- next = NEXT_TIMEOUT(next, sa->sa_out.inv_calling->q_head, orq_timeout, now);
- if (proceeding->q_timeout)
- next = NEXT_TIMEOUT(next, proceeding->q_head, orq_timeout, now);
- next = NEXT_TIMEOUT(next, sa->sa_out.trying->q_head, orq_timeout, now);
-
destroyed = outgoing_mass_destroy(sa, rq);
sa->sa_out.free = NULL;
@@ -7954,8 +7948,6 @@
terminated, completed,
destroyed, total));
}
-
- return next;
}
/** @internal Retransmit the outgoing request. */
@@ -8246,13 +8238,8 @@
continue;
if (str0casecmp(orq->orq_from->a_tag, sip->sip_from->a_tag))
continue;
- if (!addr_match(orq->orq_to, NULL, sip->sip_to))
- continue;
- if (orq->orq_method == method ?
- /* Don't match if request To has a tag and response has no To tag */
- orq->orq_to->a_tag && !sip->sip_to->a_tag :
- /* Don't (with ACK) if request/response tag mismatch */
- !orq->orq_to->a_tag != !sip->sip_to->a_tag)
+ if (orq->orq_to->a_tag &&
+ str0casecmp(orq->orq_to->a_tag, sip->sip_to->a_tag))
continue;
if (orq->orq_method == sip_method_ack) {
@@ -9851,7 +9838,7 @@
nta_agent_t *agent;
agent = irq->irq_agent;
-
+
if (callback == NULL)
callback = nta_reliable_destroyed;
@@ -9976,24 +9963,54 @@
return rel->rel_unsent;
}
+/* Find un-PRACKed responses */
+static
+nta_reliable_t *reliable_find(nta_agent_t const *agent,
+ sip_t const *sip)
+{
+ incoming_htable_t const *iht = agent->sa_incoming;
+ nta_incoming_t *irq, **ii;
+ sip_call_id_t const *i = sip->sip_call_id;
+ sip_rack_t const *rack = sip->sip_rack;
+ hash_value_t hash = NTA_HASH(i, rack->ra_cseq);
+
+ /* XXX - add own hash table for 100rel */
+
+ for (ii = incoming_htable_hash(iht, hash);
+ (irq = *ii);
+ ii = incoming_htable_next(iht, ii)) {
+
+ if (hash == irq->irq_hash &&
+ irq->irq_call_id->i_hash == i->i_hash &&
+ irq->irq_cseq->cs_seq == rack->ra_cseq &&
+ irq->irq_method == sip_method_invite &&
+ strcmp(irq->irq_call_id->i_id, i->i_id) == 0 &&
+ (irq->irq_to->a_tag == NULL ||
+ str0casecmp(irq->irq_to->a_tag, sip->sip_to->a_tag) == 0) &&
+ str0casecmp(irq->irq_from->a_tag, sip->sip_from->a_tag) == 0) {
+
+ nta_reliable_t const *rel;
+
+ /* Found matching INVITE */
+ for (rel = irq->irq_reliable; rel; rel = rel->rel_next)
+ if (rel->rel_rseq == rack->ra_response)
+ return (nta_reliable_t *)rel;
+
+ return NULL;
+ }
+ }
+
+ return NULL;
+}
+
/** Process incoming PRACK with matching @RAck field */
static
-int reliable_recv(nta_incoming_t *irq, msg_t *msg, sip_t *sip, tport_t *tp)
+int reliable_recv(nta_reliable_t *rel, msg_t *msg, sip_t *sip, tport_t *tp)
{
- sip_rack_t *rack = sip->sip_rack;
- nta_reliable_t *rel;
+ nta_incoming_t *irq = rel->rel_irq;
nta_incoming_t *pr_irq;
int status;
- for (rel = irq->irq_reliable; rel; rel = rel->rel_next)
- if (rel->rel_pracked)
- return -1;
- else if (rel->rel_rseq == rack->ra_response)
- break;
-
- if (!rel)
- return -1; /* Process normally */
-
rel->rel_pracked = 1;
msg_ref_destroy(rel->rel_unsent), rel->rel_unsent = NULL;
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nta/test_nta.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nta/test_nta.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nta/test_nta.c Sun Jan 6 15:15:11 2008
@@ -176,10 +176,13 @@
msg_t *ag_probe_msg;
+ su_sockaddr_t ag_su_nta[1];
+ socklen_t ag_su_nta_len;
/* Dummy servers */
char const *ag_sink_port;
su_socket_t ag_sink_socket, ag_down_socket;
+ su_wait_t ag_sink_wait[1];
};
static int test_init(agent_t *ag, char const *resolv_conf);
@@ -558,8 +561,11 @@
TEST_1(bind(s, &su.su_sa, sulen) < 0 ? (perror("bind"), 0) : 1);
TEST_1(getsockname(s, &su.su_sa, &sulen) == 0);
- ag->ag_sink_port = su_sprintf(ag->ag_home, "%u", ntohs(su.su_sin.sin_port));
ag->ag_sink_socket = s;
+ su_wait_init(ag->ag_sink_wait);
+ su_wait_create(ag->ag_sink_wait, ag->ag_sink_socket, SU_WAIT_IN);
+
+ ag->ag_sink_port = su_sprintf(ag->ag_home, "%u", ntohs(su.su_sin.sin_port));
/* Down server */
s = su_socket(af, SOCK_STREAM, 0); TEST_1(s != INVALID_SOCKET);
@@ -591,13 +597,38 @@
sip_to_t to[1];
sip_contact_t m[1];
+ su_sockaddr_t *su = ag->ag_su_nta;
+
sip_from_init(from);
sip_to_init(to);
sip_contact_init(m);
+
TEST_1(ag->ag_contact = nta_agent_contact(ag->ag_agent));
*m->m_url = *ag->ag_contact->m_url;
+
+ if (host_is_ip4_address(m->m_url->url_host)) {
+ inet_pton(su->su_family = AF_INET,
+ m->m_url->url_host,
+ &su->su_sin.sin_addr);
+ ag->ag_su_nta_len = (sizeof su->su_sin);
+ }
+ else {
+ TEST_1(host_is_ip_address(m->m_url->url_host));
+ inet_pton(su->su_family = AF_INET6,
+ m->m_url->url_host,
+ &su->su_sin6.sin6_addr);
+ ag->ag_su_nta_len = (sizeof su->su_sin6);
+ }
+
+ su->su_port = htons(5060);
+ if (m->m_url->url_port && strlen(m->m_url->url_port)) {
+ unsigned long port = strtoul(m->m_url->url_port, NULL, 10);
+ su->su_port = htons(port);
+ }
+ TEST_1(su->su_port != 0);
+
m->m_url->url_user = "bob";
TEST_1(ag->ag_m_bob = sip_contact_dup(ag->ag_home, m));
@@ -651,11 +682,12 @@
NTATAG_ALIASES(ag->ag_aliases),
NTATAG_REL100(1),
NTATAG_UA(1),
+ NTATAG_MERGE_482(1),
NTATAG_USE_NAPTR(1),
NTATAG_USE_SRV(1),
NTATAG_MAX_FORWARDS(20),
TAG_END());
- TEST(err, 6);
+ TEST(err, 7);
err = nta_agent_set_params(ag->ag_agent,
NTATAG_ALIASES(ag->ag_aliases),
@@ -723,7 +755,11 @@
nta_agent_destroy(ag->ag_agent);
su_root_destroy(ag->ag_root);
- su_free(ag->ag_home, (void *)ag->ag_sink_port), ag->ag_sink_port = NULL;
+ if (ag->ag_sink_port) {
+ su_free(ag->ag_home, (void *)ag->ag_sink_port), ag->ag_sink_port = NULL;
+ su_wait_destroy(ag->ag_sink_wait);
+ su_close(ag->ag_sink_socket);
+ }
free(ag->ag_mclass), ag->ag_mclass = NULL;
@@ -1206,6 +1242,9 @@
ctx->c_extra = &used_tport;
+ *url = *ag->ag_aliases->m_url;
+ url->url_user = "alice";
+
TEST(tport_shutdown(tcp_tport, 1), 0); /* Not going to send anymore */
TEST_1(pl = test_payload(ag->ag_home, 512));
@@ -2217,6 +2256,302 @@
END();
}
+/* Test merging */
+
+int test_merging(agent_t *ag)
+{
+ BEGIN();
+
+ /*
+ * Test merging: send two messages with same
+ * from tag/call-id/cseq number to nta,
+ * expect 200 and 408.
+ */
+
+ char const rfc3261prefix[] = "z9hG4bK";
+
+ char const template[] =
+ "%s " URL_PRINT_FORMAT " SIP/2.0\r\n"
+ "Via: SIP/2.0/UDP 127.0.0.1:%s;branch=%s.%p\r\n"
+ "Via: SIP/2.0/TCP fake.address.for.via.example.net;branch=z9hG4bK.%p\r\n"
+ "CSeq: %u %s\r\n"
+ "Call-ID: dfsjfhsduifhsjfsfjkfsd.%p at dfsdhfsjkhsdjk\r\n"
+ "From: Evil Forker <sip:evel at forker.com>;tag=test_nta-%s\r\n"
+ "To: Bob the Builder <sip:bob at example.net>%s\r\n"
+ "Content-Length: 0\r\n"
+ "\r\n";
+
+ url_t u1[1], u2[2];
+
+ char m1[1024], m2[1024];
+ char r1[1024], r2[1024];
+
+ size_t len, l1, l2;
+ su_sockaddr_t *su = ag->ag_su_nta;
+ socklen_t sulen = ag->ag_su_nta_len;
+ int n;
+
+ /* Empty sink socket */
+ while (su_wait(ag->ag_sink_wait, 1, 0) == 0)
+ su_recv(ag->ag_sink_socket, m1, sizeof m1, MSG_TRUNC);
+
+ {
+ /* RFC 3261 8.2.2.2 Merged Requests:
+
+ If the request has no tag in the To header field, the UAS core MUST
+ check the request against ongoing transactions. If the From tag,
+ Call-ID, and CSeq exactly match those associated with an ongoing
+ transaction, but the request does not match that transaction (based
+ on the matching rules in Section 17.2.3), the UAS core SHOULD
+ generate a 482 (Loop Detected) response and pass it to the server
+ transaction.
+ */
+ nta_leg_bind(ag->ag_server_leg, leg_callback_200, ag);
+ ag->ag_expect_leg = ag->ag_server_leg;
+ ag->ag_latest_leg = NULL;
+
+ *u1 = *ag->ag_m_bob->m_url;
+ snprintf(m1, sizeof m1,
+ template,
+ "MESSAGE", URL_PRINT_ARGS(u1),
+ /* Via */ ag->ag_sink_port, rfc3261prefix, (void *)m1,
+ /* 2nd Via */ (void *)ag,
+ /* CSeq */ 13, "MESSAGE",
+ /* Call-ID */ (void *)ag,
+ /* From tag */ "2.5.1",
+ /* To tag */ "");
+ l1 = strlen(m1);
+
+ *u2 = *ag->ag_m_bob->m_url;
+
+ snprintf(m2, sizeof m2,
+ template,
+ "MESSAGE", URL_PRINT_ARGS(u2),
+ /* Via */ ag->ag_sink_port, rfc3261prefix, (void *)m2,
+ /* 2nd Via */ (void *)ag,
+ /* CSeq */ 13, "MESSAGE",
+ /* Call-ID */ (void *)ag,
+ /* From tag */ "2.5.1",
+ /* To tag */ "");
+ l2 = strlen(m2);
+
+ TEST_1((size_t)su_sendto(ag->ag_sink_socket, m1, l1, 0, su, sulen) == l1);
+ TEST_1((size_t)su_sendto(ag->ag_sink_socket, m2, l2, 0, su, sulen) == l2);
+
+ for (n = 0; n < 2; ) {
+ su_root_step(ag->ag_root, 10L);
+ if (su_wait(ag->ag_sink_wait, 1, 0) == 0) {
+ if (n == 0)
+ su_recv(ag->ag_sink_socket, r1, sizeof r1, MSG_TRUNC);
+ else
+ su_recv(ag->ag_sink_socket, r2, sizeof r2, MSG_TRUNC);
+ n++;
+ }
+ }
+ len = strlen("SIP/2.0 200 ");
+ TEST_1(memcmp(r1, "SIP/2.0 200 ", len) == 0);
+ TEST_1(memcmp(r2, "SIP/2.0 482 ", len) == 0);
+
+ TEST_P(ag->ag_latest_leg, ag->ag_server_leg);
+ }
+
+ {
+ /*
+ * Check that request with same call-id, cseq and from-tag
+ * are not merged if the method is different.
+ */
+ nta_leg_bind(ag->ag_server_leg, leg_callback_200, ag);
+ ag->ag_expect_leg = ag->ag_server_leg;
+ ag->ag_latest_leg = NULL;
+
+ *u1 = *ag->ag_m_bob->m_url;
+ snprintf(m1, sizeof m1,
+ template,
+ "MESSAGE", URL_PRINT_ARGS(u1),
+ /* Via */ ag->ag_sink_port, rfc3261prefix, (void *)m1,
+ /* 2nd Via */ (void *)ag,
+ /* CSeq */ 14, "MESSAGE",
+ /* Call-ID */ (void *)ag,
+ /* From tag */ "2.5.2",
+ /* To tag */ "");
+ l1 = strlen(m1);
+
+ *u2 = *ag->ag_m_bob->m_url;
+
+ snprintf(m2, sizeof m2,
+ template,
+ "OPTIONS", URL_PRINT_ARGS(u2),
+ /* Via */ ag->ag_sink_port, rfc3261prefix, (void *)m2,
+ /* 2nd Via */ (void *)ag,
+ /* CSeq */ 14, "OPTIONS",
+ /* Call-ID */ (void *)ag,
+ /* From tag */ "2.5.2",
+ /* To tag */ "");
+ l2 = strlen(m2);
+
+ TEST_1((size_t)su_sendto(ag->ag_sink_socket, m1, l1, 0, su, sulen) == l1);
+ TEST_1((size_t)su_sendto(ag->ag_sink_socket, m2, l2, 0, su, sulen) == l2);
+
+ for (n = 0; n < 2; ) {
+ su_root_step(ag->ag_root, 10L);
+ if (su_wait(ag->ag_sink_wait, 1, 0) == 0) {
+ if (n == 0)
+ su_recv(ag->ag_sink_socket, r1, sizeof r1, MSG_TRUNC);
+ else
+ su_recv(ag->ag_sink_socket, r2, sizeof r2, MSG_TRUNC);
+ n++;
+ }
+ }
+
+ len = strlen("SIP/2.0 200 ");
+ TEST_1(memcmp(r1, "SIP/2.0 200 ", len) == 0);
+ TEST_1(memcmp(r2, "SIP/2.0 482 ", len) != 0);
+
+ TEST_P(ag->ag_latest_leg, ag->ag_server_leg);
+ }
+
+ {
+ /* test with rfc2543 */
+
+ snprintf(m1, sizeof m1,
+ template,
+ "MASSAGE", URL_PRINT_ARGS(u1),
+ /* Via */ ag->ag_sink_port, "0.", (void *)0,
+ /* 2nd Via */ (void *)ag,
+ /* CSeq */ 14, "MASSAGE",
+ /* Call-ID */ (void *)(ag + 1),
+ /* From tag */ "2.5.3",
+ /* To tag */ "");
+ l1 = strlen(m1);
+
+ u2->url_user = "bob+2";
+
+ snprintf(m2, sizeof m2,
+ template,
+ "MASSAGE", URL_PRINT_ARGS(u2),
+ /* Via */ ag->ag_sink_port, "0.", (void *)0,
+ /* 2nd Via */ (void *)ag,
+ /* CSeq */ 14, "MASSAGE",
+ /* Call-ID */ (void *)(ag + 1),
+ /* From tag */ "2.5.3",
+ /* To tag */ "");
+ l2 = strlen(m2);
+
+ TEST_1((size_t)su_sendto(ag->ag_sink_socket, m1, l1, 0, su, sulen) == l1);
+ TEST_1((size_t)su_sendto(ag->ag_sink_socket, m2, l2, 0, su, sulen) == l2);
+
+ for (n = 0; n < 2; ) {
+ su_root_step(ag->ag_root, 10L);
+ if (su_wait(ag->ag_sink_wait, 1, 0) == 0) {
+ if (n == 0)
+ su_recv(ag->ag_sink_socket, r1, sizeof r1, MSG_TRUNC);
+ else
+ su_recv(ag->ag_sink_socket, r2, sizeof r2, MSG_TRUNC);
+ n++;
+ }
+ }
+ l1 = strlen("SIP/2.0 200 ");
+ TEST_1(memcmp(r1, "SIP/2.0 200 ", l1) == 0);
+ TEST_1(memcmp(r2, "SIP/2.0 482 ", l1) == 0);
+
+ TEST_P(ag->ag_latest_leg, ag->ag_server_leg);
+ }
+
+ {
+ /* test with to-tag */
+
+ snprintf(m1, sizeof m1,
+ template,
+ "MESSAGE", URL_PRINT_ARGS(u1),
+ /* Via */ ag->ag_sink_port, rfc3261prefix, (void *)m1,
+ /* 2nd Via */ (void *)ag,
+ /* CSeq */ 15, "MESSAGE",
+ /* Call-ID */ (void *)(ag + 2),
+ /* From tag */ "2.5.4",
+ /* To tag */ ";tag=in-dialog");
+ l1 = strlen(m1);
+
+ u2->url_user = "bob+2";
+
+ snprintf(m2, sizeof m2,
+ template,
+ "MESSAGE", URL_PRINT_ARGS(u2),
+ /* Via */ ag->ag_sink_port, rfc3261prefix, (void *)m2,
+ /* 2nd Via */ (void *)ag,
+ /* CSeq */ 15, "MESSAGE",
+ /* Call-ID */ (void *)(ag + 2),
+ /* From tag */ "2.5.4",
+ /* To tag */ ";tag=in-dialog");
+ l2 = strlen(m2);
+
+ TEST_1((size_t)su_sendto(ag->ag_sink_socket, m1, l1, 0, su, sulen) == l1);
+ TEST_1((size_t)su_sendto(ag->ag_sink_socket, m2, l2, 0, su, sulen) == l2);
+
+ for (n = 0; n < 2; ) {
+ su_root_step(ag->ag_root, 10L);
+ if (su_wait(ag->ag_sink_wait, 1, 0) == 0) {
+ if (n == 0)
+ su_recv(ag->ag_sink_socket, r1, sizeof r1, MSG_TRUNC);
+ else
+ su_recv(ag->ag_sink_socket, r2, sizeof r2, MSG_TRUNC);
+ n++;
+ }
+ }
+ l1 = strlen("SIP/2.0 200 ");
+ TEST_1(memcmp(r1, "SIP/2.0 200 ", l1) == 0);
+ TEST_1(memcmp(r2, "SIP/2.0 482 ", l1) != 0);
+
+ TEST_P(ag->ag_latest_leg, ag->ag_server_leg);
+ }
+
+ {
+ /* test with rfc2543 and to-tag */
+
+ snprintf(m1, sizeof m1,
+ template,
+ "MESSAGE", URL_PRINT_ARGS(u1),
+ /* Via */ ag->ag_sink_port, "0.", (void *)0,
+ /* 2nd Via */ (void *)ag,
+ /* CSeq */ 15, "MESSAGE",
+ /* Call-ID */ (void *)(ag + 2),
+ /* From tag */ "2.5.5",
+ /* To tag */ ";tag=in-dialog");
+ l1 = strlen(m1);
+
+ snprintf(m2, sizeof m2,
+ template,
+ "MESSAGE", URL_PRINT_ARGS(u2),
+ /* Via */ ag->ag_sink_port, "0.", (void *)0,
+ /* 2nd Via */ (void *)ag,
+ /* CSeq */ 15, "MESSAGE",
+ /* Call-ID */ (void *)(ag + 2),
+ /* From tag */ "2.5.5",
+ /* To tag */ ";tag=in-dialog");
+ l2 = strlen(m2);
+
+ TEST_1((size_t)su_sendto(ag->ag_sink_socket, m1, l1, 0, su, sulen) == l1);
+ TEST_1((size_t)su_sendto(ag->ag_sink_socket, m2, l2, 0, su, sulen) == l2);
+
+ for (n = 0; n < 2; ) {
+ su_root_step(ag->ag_root, 10L);
+ if (su_wait(ag->ag_sink_wait, 1, 0) == 0) {
+ if (n == 0)
+ su_recv(ag->ag_sink_socket, r1, sizeof r1, MSG_TRUNC);
+ else
+ su_recv(ag->ag_sink_socket, r2, sizeof r2, MSG_TRUNC);
+ n++;
+ }
+ }
+ l1 = strlen("SIP/2.0 200 ");
+ TEST_1(memcmp(r1, "SIP/2.0 200 ", l1) == 0);
+ TEST_1(memcmp(r2, "SIP/2.0 482 ", l1) != 0);
+
+ TEST_P(ag->ag_latest_leg, ag->ag_server_leg);
+ }
+
+ END();
+}
+
/* ---------------------------------------------------------------------- */
/* Test INVITE, dialogs */
@@ -3485,6 +3820,7 @@
if (retval == 0) {
retval |= test_bad_messages(ag); SINGLE_FAILURE_CHECK();
retval |= test_reinit(ag); SINGLE_FAILURE_CHECK();
+ retval |= test_merging(ag); SINGLE_FAILURE_CHECK();
retval |= test_tports(ag); SINGLE_FAILURE_CHECK();
retval |= test_destroy_incoming(ag); SINGLE_FAILURE_CHECK();
retval |= test_resolv(ag, argv[i]); SINGLE_FAILURE_CHECK();
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_notifier.c Sun Jan 6 15:15:11 2008
@@ -498,10 +498,18 @@
else if (nu->nu_requested >= now + expires)
nu->nu_expires = nu->nu_requested = now + expires;
}
+ else {
+ if (nu->nu_requested >= nu->nu_expires)
+ nu->nu_expires = nu->nu_requested;
+ }
+
}
else {
enum nua_substate substate = nu->nu_substate;
+ if (nu->nu_requested >= nu->nu_expires)
+ nu->nu_expires = nu->nu_requested;
+
if (nu->nu_expires > now) {
tagi_t const *t = tl_find_last(tags, nutag_substate);
if (t)
@@ -794,8 +802,11 @@
return 0;
}
else {
- if (nua_client_create(nh, nua_r_notify,
- &nua_notify_client_methods, NULL) >= 0)
+ if (nua_client_tcreate(nh, nua_r_notify,
+ &nua_notify_client_methods,
+ SIPTAG_EVENT(du->du_event),
+ NUTAG_SUBSTATE(nua_substate_terminated),
+ TAG_END()) >= 0)
return 0;
}
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c Sun Jan 6 15:15:11 2008
@@ -2023,7 +2023,8 @@
reliable = 1, early_answer = 1;
}
else if (!nh->nh_soa || sr->sr_status >= 300) {
-
+ if (sr->sr_neutral)
+ return nua_base_server_respond(sr, tags);
}
else if (tags && 100 < sr->sr_status && sr->sr_status < 200 &&
!NHP_ISSET(nh->nh_prefs, early_answer)) {
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_subnotref.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_subnotref.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_subnotref.c Sun Jan 6 15:15:11 2008
@@ -581,7 +581,7 @@
sr->sr_usage = du;
eu = nua_dialog_usage_private(du); assert(eu);
eu->eu_notified++;
- if (!o->o_id)
+ if (!o || !o->o_id)
eu->eu_no_id = 1;
if (subs == NULL) {
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/outbound.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/outbound.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/outbound.c Sun Jan 6 15:15:11 2008
@@ -503,13 +503,13 @@
}
if (!nat_detected) {
- SU_DEBUG_1(("outbound(%p): detected NAT: %s != %s\n",
+ SU_DEBUG_5(("outbound(%p): detected NAT: %s != %s\n",
(void *)ob->ob_owner, v->v_host, received));
if (ob->ob_oo && ob->ob_oo->oo_status)
ob->ob_oo->oo_status(ob->ob_owner, ob, 101, "NAT detected", TAG_END());
}
else {
- SU_DEBUG_1(("outbound(%p): NAT binding changed: "
+ SU_DEBUG_5(("outbound(%p): NAT binding changed: "
"[%s]:%s != [%s]:%s\n",
(void *)ob->ob_owner, nat_detected, nat_port, received, rport));
if (ob->ob_oo && ob->ob_oo->oo_status)
@@ -860,8 +860,6 @@
else
loglevel = 3, failed = 1;
- loglevel = 1; /* XXX ... for now */
-
if (loglevel >= SU_LOG->log_level) {
sip_contact_t const *m = ob->ob_rcontact;
@@ -886,7 +884,7 @@
ob->ob_oo->oo_probe_error(ob->ob_owner, ob, status, phrase, TAG_END());
}
else if (status == 408) {
- SU_DEBUG_1(("outbound(%p): keepalive timeout\n", (void *)ob->ob_owner));
+ SU_DEBUG_3(("outbound(%p): keepalive timeout\n", (void *)ob->ob_owner));
ob->ob_oo->oo_keepalive_error(ob->ob_owner, ob, status, phrase, TAG_END());
return 0;
}
@@ -979,7 +977,7 @@
return 0;
if (ob->ob_keepalive.validating) {
- SU_DEBUG_1(("outbound(%p): registration check OPTIONS received\n",
+ SU_DEBUG_5(("outbound(%p): registration check OPTIONS received\n",
(void *)ob->ob_owner));
ob->ob_keepalive.validated = 1;
}
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/stun/stun.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/stun/stun.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/stun/stun.c Sun Jan 6 15:15:11 2008
@@ -1895,23 +1895,23 @@
if ((req->sr_state == stun_req_timeout) && (req->sr_from_y == -1)) {
SU_DEBUG_0(("%s: lifetime determination failed.\n", __func__));
sd->sd_state = stun_discovery_timeout;
+ req->sr_state = stun_req_dispose_me;
/* Use per discovery specific callback */
if (sd->sd_callback)
sd->sd_callback(sd->sd_magic, sh, sd, action, sd->sd_state);
- req->sr_state = stun_req_dispose_me;
return 0;
}
if (abs(sd->sd_lt_cur - sd->sd_lt) <= STUN_LIFETIME_CI) {
sd->sd_state = stun_discovery_done;
+ req->sr_state = stun_req_dispose_me;
/* Use per discovery specific callback */
if (sd->sd_callback)
sd->sd_callback(sd->sd_magic, sh, sd, action, sd->sd_state);
- req->sr_state = stun_req_dispose_me;
return 0;
}
@@ -1998,12 +1998,11 @@
memcpy(sd->sd_addr_seen_outside, sa, sizeof(su_sockaddr_t));
sd->sd_state = stun_discovery_done;
+ req->sr_state = stun_req_dispose_me;
if (sd->sd_callback)
sd->sd_callback(sd->sd_magic, sh, sd, action, sd->sd_state);
- req->sr_state = stun_req_dispose_me;
-
return 0;
}
@@ -2053,9 +2052,9 @@
stun_request_t *req)
{
sd->sd_state = stun_discovery_done;
+ req->sr_state = stun_req_dispose_me;
if (sd->sd_callback)
sd->sd_callback(sd->sd_magic, sh, sd, action, sd->sd_state);
- req->sr_state = stun_req_dispose_me;
}
/**
@@ -2290,12 +2289,12 @@
switch (action) {
case stun_action_binding_request:
sd->sd_state = stun_discovery_timeout;
+ req->sr_state = stun_req_dispose_me;
/* Use per discovery specific callback */
if (sd->sd_callback)
sd->sd_callback(sd->sd_magic, sh, sd, action, sd->sd_state);
- req->sr_state = stun_req_dispose_me;
break;
case stun_action_test_nattype:
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport_tag.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport_tag.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport_tag.c Sun Jan 6 15:15:11 2008
@@ -311,6 +311,10 @@
*
* This is a parameter suitable for tuning.
*
+ * On Linux systems, the default value for receive buffer is set with
+ * the sysctl "net.core.rmem_default", and the maximum value is set with
+ * the sysctl "net.core.rmem_max".
+ *
* Use with tport_tbind(), nua_create(), nta_agent_create(),
* nta_agent_add_tport(), nth_engine_create(), or initial nth_site_create().
*/
@@ -322,6 +326,10 @@
*
* This is a parameter suitable for tuning.
*
+ * On Linux systems, the default value for receive buffer is set with
+ * the sysctl "net.core.wmem_default", and the maximum value is set with
+ * the sysctl "net.core.wmem_max".
+ *
* Use with tport_tbind(), nua_create(), nta_agent_create(),
* nta_agent_add_tport(), nth_engine_create(), or initial nth_site_create().
*/
Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_udp.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_udp.c (original)
+++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/tport/tport_type_udp.c Sun Jan 6 15:15:11 2008
@@ -35,6 +35,7 @@
#include "config.h"
#include "tport_internal.h"
+#include "sofia-sip/hostdomain.h"
#if HAVE_IP_RECVERR || HAVE_IPV6_RECVERR
#include <linux/types.h>
@@ -113,6 +114,8 @@
unsigned rmem = 0, wmem = 0;
int events = SU_WAIT_IN;
int s;
+ su_sockaddr_t *su = (su_sockaddr_t *)ai->ai_addr;
+ int const one = 1; (void)one;
s = su_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (s == INVALID_SOCKET)
@@ -125,20 +128,51 @@
tport_set_tos(s, ai, pri->pri_params->tpp_tos);
+#if HAVE_IP_ADD_MEMBERSHIP
+ if (ai->ai_family == AF_INET &&
+ IN_MULTICAST(ntohl(su->su_sin.sin_addr.s_addr))) {
+ /* Try to join to the multicast group */
+ /* Bind to the SIP address like
+ <sip:88.77.66.55:5060;maddr=224.0.1.75;transport=udp> */
+ struct ip_mreq imr[1];
+ struct in_addr iface;
+
+ memset(imr, 0, sizeof imr);
+
+ imr->imr_multiaddr = su->su_sin.sin_addr;
+
+ if (host_is_ip4_address(tpn->tpn_canon) &&
+ inet_pton(AF_INET, tpn->tpn_canon, &iface) > 0) {
+ imr->imr_interface = iface;
+ }
+
+ if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, imr, (sizeof imr)) < 0) {
+ SU_DEBUG_3(("setsockopt(%s): %s\n",
+ "IP_ADD_MEMBERSHIP", su_strerror(su_errno())));
+ }
+#if HAVE_IP_MULTICAST_LOOP
+ else
+ if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &one, sizeof one) < 0) {
+ SU_DEBUG_3(("setsockopt(%s): %s\n",
+ "IP_MULTICAST_LOOP", su_strerror(su_errno())));
+ }
+#endif
+ }
+#endif
+
#if HAVE_IP_RECVERR
if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) {
- int const one = 1;
- if (setsockopt(s, SOL_IP, IP_RECVERR, &one, sizeof(one)) < 0) {
+ if (setsockopt(s, IPPROTO_IP, IP_RECVERR, &one, sizeof(one)) < 0) {
if (ai->ai_family == AF_INET)
- SU_DEBUG_3(("setsockopt(IPVRECVERR): %s\n", su_strerror(su_errno())));
+ SU_DEBUG_3(("setsockopt(%s): %s\n",
+ "IPVRECVERR", su_strerror(su_errno())));
}
events |= SU_WAIT_ERR;
}
#endif
#if HAVE_IPV6_RECVERR
if (ai->ai_family == AF_INET6) {
- int const one = 1;
- if (setsockopt(s, SOL_IPV6, IPV6_RECVERR, &one, sizeof(one)) < 0)
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVERR, &one, sizeof(one)) < 0)
SU_DEBUG_3(("setsockopt(IPV6_RECVERR): %s\n", su_strerror(su_errno())));
events |= SU_WAIT_ERR;
}
@@ -150,12 +184,18 @@
TAG_END());
if (rmem != 0 &&
+#if HAVE_SO_RCVBUFFORCE
+ setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, (void *)&rmem, sizeof rmem) < 0 &&
+#endif
setsockopt(s, SOL_SOCKET, SO_RCVBUF, (void *)&rmem, sizeof rmem) < 0) {
SU_DEBUG_3(("setsockopt(SO_RCVBUF): %s\n",
su_strerror(su_errno())));
}
if (wmem != 0 &&
+#if HAVE_SO_SNDBUFFORCE
+ setsockopt(s, SOL_SOCKET, SO_SNDBUFFORCE, (void *)&wmem, sizeof wmem) < 0 &&
+#endif
setsockopt(s, SOL_SOCKET, SO_SNDBUF, (void *)&wmem, sizeof wmem) < 0) {
SU_DEBUG_3(("setsockopt(SO_SNDBUF): %s\n",
su_strerror(su_errno())));
@@ -409,10 +449,10 @@
for (c = CMSG_FIRSTHDR(msg); c; c = CMSG_NXTHDR(msg, c)) {
if (0
#if HAVE_IP_RECVERR
- || (c->cmsg_level == SOL_IP && c->cmsg_type == IP_RECVERR)
+ || (c->cmsg_level == IPPROTO_IP && c->cmsg_type == IP_RECVERR)
#endif
#if HAVE_IPV6_RECVERR
- || (c->cmsg_level == SOL_IPV6 && c->cmsg_type == IPV6_RECVERR)
+ || (c->cmsg_level == IPPROTO_IPV6 && c->cmsg_type == IPV6_RECVERR)
#endif
) {
char info[128];
Modified: freeswitch/trunk/libs/sofia-sip/m4/sac-su2.m4
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/m4/sac-su2.m4 (original)
+++ freeswitch/trunk/libs/sofia-sip/m4/sac-su2.m4 Sun Jan 6 15:15:11 2008
@@ -273,6 +273,28 @@
#include <sys/types.h>
#include <sys/socket.h>])
+AC_CHECK_DECL([SO_RCVBUFFORCE],
+AC_DEFINE([HAVE_SO_RCVBUFFORCE],1,[Define to 1 if you have socket option SO_RCVBUFFORCE]),,[
+#include <sys/types.h>
+#include <sys/socket.h>])
+
+AC_CHECK_DECL([SO_SNDBUFFORCE],
+AC_DEFINE([HAVE_SO_SNDBUFFORCE],1,[Define to 1 if you have socket option SO_SNDBUFFORCE]),,[
+#include <sys/types.h>
+#include <sys/socket.h>])
+
+AC_CHECK_DECL([IP_ADD_MEMBERSHIP],
+AC_DEFINE([HAVE_IP_ADD_MEMBERSHIP],1,[Define to 1 if you have IP_ADD_MEMBERSHIP]),,[
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>])
+
+AC_CHECK_DECL([IP_MULTICAST_LOOP],
+AC_DEFINE([HAVE_IP_MULTICAST_LOOP],1,[Define to 1 if you have IP_MULTICAST_LOOP]),,[
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>])
+
AC_CACHE_CHECK([for struct addrinfo],
[ac_cv_struct_addrinfo],[
ac_cv_struct_addrinfo=no
Added: freeswitch/trunk/libs/sofia-sip/scripts/hide_emails.sh
==============================================================================
--- (empty file)
+++ freeswitch/trunk/libs/sofia-sip/scripts/hide_emails.sh Sun Jan 6 15:15:11 2008
@@ -0,0 +1,41 @@
+#!/bin/sh
+#
+# description: Mangle email addresses in the HTML documentation
+# author: Kai Vehmanen <kai.vehmanen at nokia.com>
+# version: 20050908-3
+#
+# --------------------------------------------------------------------
+#
+# This file is part of the Sofia-SIP package
+#
+# Copyright (C) 2005 Nokia Corporation.
+#
+# Contact: Pekka Pessi <pekka.pessi at nokia.com>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public License
+# as published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+#
+# --------------------------------------------------------------------
+
+echo "Postprocessing HTML in ${1:-.}: hiding email addresses, fixing links"
+
+find ${1:-.} -name '*.html' -print0 |
+xargs -0 \
+sed -r -i '
+# Hide e-mail addresses
+s/([:>;][a-z][-a-z.]*)(@[a-z][a-z]*)\.[a-z][a-z]*(["<\&])/\1\2-email.address.hidden\3/gi;
+# Fix cross-module links
+s!doxygen="([a-z]*).doxytags:../\1/" href="../\1/\1_index.html"!doxygen="\1.doxytags:../\1/" href="../\1/index.html"!g;
+'
Modified: freeswitch/trunk/libs/sofia-sip/tests/check_sofia.c
==============================================================================
--- freeswitch/trunk/libs/sofia-sip/tests/check_sofia.c (original)
+++ freeswitch/trunk/libs/sofia-sip/tests/check_sofia.c Sun Jan 6 15:15:11 2008
@@ -51,7 +51,9 @@
suite = suite_for_nua();
runner = srunner_create(suite);
- srunner_set_xml(runner, "/tmp/result.xml");
+ if (argv[1]) {
+ srunner_set_xml(runner, argv[1]);
+ }
srunner_run_all(runner, CK_NORMAL);
failed = srunner_ntests_failed(runner);
More information about the Freeswitch-svn
mailing list