diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update index fe223acfa3..a8ec3b3306 100644 --- a/libs/sofia-sip/.update +++ b/libs/sofia-sip/.update @@ -1 +1 @@ -Fri Jun 26 14:54:58 CDT 2009 +Thu Jul 9 10:56:15 CDT 2009 diff --git a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c index 89f5b359d0..6a5abbef01 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nta/nta.c +++ b/libs/sofia-sip/libsofia-sip-ua/nta/nta.c @@ -519,14 +519,15 @@ struct nta_outgoing_s unsigned orq_destroyed:1; unsigned orq_completed:1; unsigned orq_delayed:1; - unsigned orq_stripped_uri:1; unsigned orq_user_tport:1; /**< Application provided tport - don't retry */ unsigned orq_try_tcp_instead:1; unsigned orq_try_udp_instead:1; unsigned orq_reliable:1; /**< Transport is reliable */ - unsigned orq_ack_error:1; /**< ACK is sent by NTA */ + + unsigned orq_forked:1; /**< Tagged fork */ /* Attributes */ + unsigned orq_uas:1; /**< Running this transaction as UAS */ unsigned orq_user_via:1; unsigned orq_stateless:1; unsigned orq_pass_100:1; @@ -701,7 +702,7 @@ 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 *); -static void incoming_timer(nta_agent_t *); +static void _nta_incoming_timer(nta_agent_t *); static nta_reliable_t *reliable_mreply(nta_incoming_t *, nta_prack_f *, nta_reliable_magic_t *, @@ -736,7 +737,7 @@ static nta_outgoing_t *outgoing_find(nta_agent_t const *sa, 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 *); -static void outgoing_timer(nta_agent_t *); +static void _nta_outgoing_timer(nta_agent_t *); static int outgoing_recv_reliable(nta_outgoing_t *orq, msg_t *msg, sip_t *sip); /* Internal message passing */ @@ -1234,8 +1235,8 @@ void agent_timer(su_root_magic_t *rm, su_timer_t *timer, nta_agent_t *agent) agent->sa_millisec = now; agent->sa_in_timer = 1; - outgoing_timer(agent); - incoming_timer(agent); + _nta_outgoing_timer(agent); + _nta_incoming_timer(agent); /* agent->sa_now is used only if sa_millisec != 0 */ agent->sa_millisec = 0; @@ -6792,7 +6793,8 @@ enum { }; /** @internal Timer routine for the incoming request. */ -static void incoming_timer(nta_agent_t *sa) +static void +_nta_incoming_timer(nta_agent_t *sa) { uint32_t now = sa->sa_millisec; nta_incoming_t *irq, *irq_next; @@ -7083,6 +7085,7 @@ static void outgoing_trying(nta_outgoing_t *orq); static void outgoing_timeout(nta_outgoing_t *orq, uint32_t now); static int outgoing_complete(nta_outgoing_t *orq); static void outgoing_terminate_invite(nta_outgoing_t *); +static void outgoing_remove_fork(nta_outgoing_t *orq); static int outgoing_terminate(nta_outgoing_t *orq); static size_t outgoing_mass_destroy(nta_agent_t *sa, outgoing_queue_t *q); static void outgoing_estimate_delay(nta_outgoing_t *orq, sip_t *sip); @@ -7360,6 +7363,10 @@ nta_outgoing_t *nta_outgoing_tcancel(nta_outgoing_t *orq, SU_DEBUG_3(("%s: trying to cancel non-INVITE request\n", __func__)); return NULL; } + + if (orq->orq_forking) + orq = orq->orq_forking; + if (orq->orq_status >= 200 /* && orq->orq_method != sip_method_invite ... !multicast */) { SU_DEBUG_3(("%s: trying to cancel completed request\n", __func__)); @@ -7735,6 +7742,7 @@ nta_outgoing_t *outgoing_create(nta_agent_t *agent, orq->orq_stateless = stateless != 0; orq->orq_user_via = user_via != 0 && sip->sip_via; orq->orq_100rel = invite_100rel; + orq->orq_uas = !stateless && agent->sa_is_a_uas; if (cc) orq->orq_cc = nta_compartment_ref(cc); @@ -7822,9 +7830,9 @@ nta_outgoing_t *outgoing_create(nta_agent_t *agent, else orq->orq_branch = su_sprintf(home, "branch=%s", ack_branch); } - else if (!stateless && agent->sa_is_a_uas) { + else if (orq->orq_uas) { /* - * ACK redirect further 2XX messages to it. + * ACK redirects further 2XX messages to it. * * Use orq_branch from INVITE, but put a different branch in topmost Via. */ @@ -8414,12 +8422,11 @@ outgoing_queue(outgoing_queue_t *queue, return; } + assert(!orq->orq_forked); + if (outgoing_is_queued(orq)) outgoing_remove(orq); - assert(orq->orq_next == NULL); - assert(*queue->q_tail == NULL); - orq->orq_timeout = set_timeout(orq->orq_agent, queue->q_timeout); orq->orq_queue = queue; @@ -8525,8 +8532,8 @@ void outgoing_free(nta_outgoing_t *orq) } /** Remove outgoing request from hash tables */ -su_inline -void outgoing_cut_off(nta_outgoing_t *orq) +su_inline void +outgoing_cut_off(nta_outgoing_t *orq) { nta_agent_t *agent = orq->orq_agent; @@ -8539,6 +8546,11 @@ void outgoing_cut_off(nta_outgoing_t *orq) if (outgoing_is_queued(orq)) outgoing_remove(orq); +#if 0 + if (orq->orq_forked) + outgoing_remove_fork(orq); +#endif + outgoing_reset_timer(orq); if (orq->orq_pending) { @@ -8637,7 +8649,8 @@ void outgoing_destroy(nta_outgoing_t *orq) /** @internal Outgoing transaction timer routine. * */ -static void outgoing_timer(nta_agent_t *sa) +static void +_nta_outgoing_timer(nta_agent_t *sa) { uint32_t now = sa->sa_millisec; nta_outgoing_t *orq; @@ -8742,7 +8755,9 @@ void outgoing_retransmit(nta_outgoing_t *orq) static void outgoing_trying(nta_outgoing_t *orq) { - if (orq->orq_method == sip_method_invite) + if (orq->orq_forked) + ; + else if (orq->orq_method == sip_method_invite) outgoing_queue(orq->orq_agent->sa_out.inv_calling, orq); else outgoing_queue(orq->orq_agent->sa_out.trying, orq); @@ -8847,8 +8862,14 @@ outgoing_complete(nta_outgoing_t *orq) if (orq->orq_stateless) return outgoing_terminate(orq); + + if (orq->orq_forked) { + outgoing_remove_fork(orq); + return outgoing_terminate(orq); + } + if (orq->orq_reliable) { - if (orq->orq_method != sip_method_invite || !orq->orq_agent->sa_is_a_uas) + if (orq->orq_method != sip_method_invite || !orq->orq_uas) return outgoing_terminate(orq); } @@ -8908,7 +8929,7 @@ outgoing_terminate_invite(nta_outgoing_t *original) "terminate", orq->orq_method_name, orq->orq_cseq->cs_seq, orq->orq_tag)); - orq->orq_forking = NULL; + orq->orq_forking = NULL, orq->orq_forks = NULL, orq->orq_forked = 0; if (outgoing_terminate(orq)) continue; @@ -8930,6 +8951,25 @@ outgoing_terminate_invite(nta_outgoing_t *original) } } +static void +outgoing_remove_fork(nta_outgoing_t *orq) +{ + nta_outgoing_t **slot; + + for (slot = &orq->orq_forking->orq_forks; + *slot; + slot = &(*slot)->orq_forks) { + if (orq == *slot) { + *slot = orq->orq_forks; + orq->orq_forks = NULL; + orq->orq_forking = NULL; + orq->orq_forked = 0; + } + } + + assert(orq == NULL); +} + /** Terminate a client transaction. */ static int outgoing_terminate(nta_outgoing_t *orq) @@ -9031,7 +9071,7 @@ nta_outgoing_t *outgoing_find(nta_agent_t const *sa, /* Get original invite when ACKing */ if (sip->sip_request && method == sip_method_ack && v == NULL) method = sip_method_invite, method2 = sip_method_invalid; - else if (sa->sa_is_a_uas && status >= 200 && method == sip_method_invite) + else if (sa->sa_is_a_uas && 200 <= status && status < 300 && method == sip_method_invite) method2 = sip_method_ack; else method2 = method; @@ -9062,10 +9102,8 @@ nta_outgoing_t *outgoing_find(nta_agent_t const *sa, su_strcasecmp(orq->orq_to->a_tag, sip->sip_to->a_tag)) continue; - if (orq->orq_method == sip_method_ack) { - if (orq->orq_ack_error ? status < 300 : status >= 300) - continue; - } + if (orq->orq_method == sip_method_ack && 300 <= status) + continue; if (v && !su_casematch(orq->orq_branch + strlen("branch="), v->v_branch)) continue; @@ -9085,7 +9123,6 @@ int outgoing_recv(nta_outgoing_t *_orq, nta_outgoing_t *orq = _orq->orq_forking ? _orq->orq_forking : _orq; nta_agent_t *sa = orq->orq_agent; int internal = sip == NULL || (sip->sip_flags & NTA_INTERNAL_MSG) != 0; - int uas = sa->sa_is_a_uas; assert(!internal || status >= 300); assert(orq == _orq || orq->orq_method == sip_method_invite); @@ -9126,7 +9163,7 @@ int outgoing_recv(nta_outgoing_t *_orq, orq = _orq; if (orq->orq_destroyed && 200 <= status && status < 300) { - if (uas && su_strcasecmp(sip->sip_to->a_tag, orq->orq_tag) != 0) { + if (orq->orq_uas && su_strcasecmp(sip->sip_to->a_tag, orq->orq_tag) != 0) { /* Orphan 200 Ok to INVITE. ACK and BYE it */ SU_DEBUG_5(("nta: Orphan 200 Ok send ACK&BYE\n")); return nta_msg_ackbye(sa, msg); @@ -9134,11 +9171,14 @@ int outgoing_recv(nta_outgoing_t *_orq, return -1; /* Proxy statelessly (RFC3261 section 16.11) */ } - outgoing_reset_timer(original); + outgoing_reset_timer(original); /* Retransmission */ if (status < 200) { - original->orq_status = status; - orq->orq_status = status; + if (original->orq_status < 200) + original->orq_status = status; + if (orq->orq_status < 200) + orq->orq_status = status; + if (original->orq_queue == sa->sa_out.inv_calling) { outgoing_queue(sa->sa_out.inv_proceeding, original); } @@ -9148,9 +9188,7 @@ int outgoing_recv(nta_outgoing_t *_orq, outgoing_queue(sa->sa_out.inv_proceeding, original); } } - } - if (status < 200) { /* Handle 100rel */ if (sip && sip->sip_rseq) { if (outgoing_recv_reliable(orq, msg, sip) < 0) { @@ -9168,7 +9206,7 @@ int outgoing_recv(nta_outgoing_t *_orq, if (outgoing_complete(original)) return 0; - if (uas && sip && orq == original) { + if (orq->orq_uas && sip && orq == original) { /* * We silently discard duplicate final responses to INVITE below * with outgoing_duplicate() @@ -9183,7 +9221,7 @@ int outgoing_recv(nta_outgoing_t *_orq, if (status >= 300) return outgoing_duplicate(orq, msg, sip); - if (uas) { + if (orq->orq_uas) { if (su_strcasecmp(sip->sip_to->a_tag, orq->orq_tag) == 0) /* Catch retransmission */ return outgoing_duplicate(orq, msg, sip); @@ -9243,16 +9281,21 @@ int outgoing_recv(nta_outgoing_t *_orq, return 0; } - if (status + orq->orq_pass_100 > 100 && !orq->orq_destroyed) { - if (orq->orq_response) - msg_destroy(orq->orq_response); - orq->orq_response = msg; - /* Call callback */ - orq->orq_callback(orq->orq_magic, orq, sip); - } - else + if (100 >= status + orq->orq_pass_100) { msg_destroy(msg); + return 0; + } + if (orq->orq_destroyed) { + msg_destroy(msg); + return 0; + } + + if (orq->orq_response) + msg_destroy(orq->orq_response); + orq->orq_response = msg; + /* Call callback */ + orq->orq_callback(orq->orq_magic, orq, sip); return 0; } @@ -11233,13 +11276,18 @@ nta_outgoing_t *nta_outgoing_tagged(nta_outgoing_t *orq, sip_to_tag(home, to = sip_to_copy(home, orq->orq_to), to_tag); tagged->orq_to = to; + tagged->orq_tag = to->a_tag; tagged->orq_tport = tport_ref(orq->orq_tport); tagged->orq_request = msg_ref_create(orq->orq_request); tagged->orq_response = msg_ref_create(orq->orq_response); tagged->orq_cancel = NULL; - tagged->orq_forking = orq; - tagged->orq_forks = orq->orq_forks; - orq->orq_forks = tagged; + + if ((tagged->orq_uas = orq->orq_uas)) { + tagged->orq_forking = orq; + tagged->orq_forks = orq->orq_forks; + tagged->orq_forked = 1; + orq->orq_forks = tagged; + } tagged->orq_rseq = 0;