From 961c78c3b9b6216205c29b34d5c484b6dd4ceb8f Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Thu, 14 Aug 2008 15:37:53 +0000 Subject: [PATCH] Wed Aug 13 13:03:33 EDT 2008 Pekka Pessi * nua_session.c: destroying invite transaction only after nua_i_invite is sent Added nua_client_request_clean(), nua_invite_client_should_ack(). git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@9290 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- libs/sofia-sip/.update | 2 +- .../libsofia-sip-ua/nua/nua_dialog.h | 6 +-- .../libsofia-sip-ua/nua/nua_session.c | 45 ++++++++++++------- .../sofia-sip/libsofia-sip-ua/nua/nua_stack.c | 12 +++-- 4 files changed, 41 insertions(+), 24 deletions(-) diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update index 1630464101..8cee7c8ca0 100644 --- a/libs/sofia-sip/.update +++ b/libs/sofia-sip/.update @@ -1 +1 @@ -Thu Aug 14 11:37:00 EDT 2008 +Thu Aug 14 11:37:23 EDT 2008 diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h b/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h index ed9ff66707..6c28f55257 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h @@ -296,6 +296,7 @@ struct nua_client_request unsigned cr_dialog:1; /**< Request can initiate dialog */ /* Current state */ + unsigned cr_acked:1; /**< Final response to the request has been ACKed */ unsigned cr_waiting:1; /**< Request is waiting */ unsigned cr_challenged:1; /**< Request was challenged */ unsigned cr_wait_for_cred:1; /**< Request is pending authentication */ @@ -523,7 +524,6 @@ void *nua_private_client_request(nua_client_request_t const *cr) } void nua_client_request_complete(nua_client_request_t *); - void nua_client_request_destroy(nua_client_request_t *); int nua_client_request_queue(nua_client_request_t *cr); @@ -533,8 +533,8 @@ su_inline int nua_client_is_queued(nua_client_request_t const *cr) return cr && cr->cr_prev; } -nua_client_request_t *nua_client_request_remove(nua_client_request_t *cr); - +void nua_client_request_remove(nua_client_request_t *cr); +void nua_client_request_clean(nua_client_request_t *cr); int nua_client_bind(nua_client_request_t *cr, nua_dialog_usage_t *du); su_inline int nua_client_is_bound(nua_client_request_t const *cr) diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c index f951531e85..a6ff8488b6 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c @@ -197,6 +197,7 @@ static void signal_call_state_change(nua_handle_t *nh, int status, char const *phrase, enum nua_callstate next_state); +static int nua_invite_client_should_ack(nua_client_request_t const *cr); static int nua_invite_client_ack(nua_client_request_t *cr, tagi_t const *tags); static int nua_invite_client_complete(nua_client_request_t *cr); @@ -247,15 +248,6 @@ void nua_session_usage_remove(nua_handle_t *nh, nua_client_request_t *cr, *cr_next; nua_server_request_t *sr; - cr = du->du_cr; - - if (cr != cr0 && cr && cr->cr_orq && cr->cr_status >= 200 && - cr->cr_method == sip_method_invite) { - ss->ss_reporting = 1; - nua_invite_client_ack(cr, NULL); - ss->ss_reporting = 0; - } - /* Destroy queued INVITE transactions */ for (cr = ds->ds_cr; cr; cr = cr_next) { cr_next = cr->cr_next; @@ -266,6 +258,13 @@ void nua_session_usage_remove(nua_handle_t *nh, if (cr == cr0) continue; + if (nua_invite_client_should_ack(cr)) { + ss->ss_reporting = 1; + nua_invite_client_ack(cr, NULL); + ss->ss_reporting = 0; + nua_client_request_clean(cr); + } + if (cr == du->du_cr && cr->cr_orq) continue; @@ -1180,6 +1179,8 @@ int nua_stack_ack(nua_t *nua, nua_handle_t *nh, nua_event_t e, error = nua_invite_client_ack(cr, tags); + nua_client_request_clean(cr); + if (error < 0) { if (ss->ss_reason == NULL) ss->ss_reason = "SIP;cause=500;text=\"Internal Error\""; @@ -1230,7 +1231,6 @@ int nua_invite_client_ack(nua_client_request_t *cr, tagi_t const *tags) assert(cr->cr_orq); assert(cr->cr_method == sip_method_invite); - if (!ds->ds_leg) { /* XXX - fix nua_dialog_usage_remove_at() instead! */ nta_outgoing_destroy(cr->cr_orq); @@ -1366,12 +1366,20 @@ int nua_invite_client_ack(nua_client_request_t *cr, tagi_t const *tags) if (error == -1) msg_destroy(msg); - nta_outgoing_destroy(cr->cr_orq), cr->cr_orq = NULL; nua_client_request_remove(cr); + cr->cr_acked = 1; /* ... or we have at least tried */ return error; } +static int +nua_invite_client_should_ack(nua_client_request_t const *cr) +{ + return + cr && cr->cr_orq && !cr->cr_acked && + 200 <= cr->cr_status && cr->cr_status < 300; +} + /** Complete client request */ static int nua_invite_client_complete(nua_client_request_t *cr) { @@ -1379,7 +1387,7 @@ static int nua_invite_client_complete(nua_client_request_t *cr) /* Xyzzy */; else if (cr->cr_status < 200) nta_outgoing_cancel(cr->cr_orq); - else + else if (cr->cr_status < 300 && !cr->cr_acked) nua_invite_client_ack(cr, NULL); return 0; @@ -1560,10 +1568,13 @@ static int nua_session_usage_shutdown(nua_handle_t *nh, case nua_callstate_completed: case nua_callstate_ready: if (cri && cri->cr_orq) { - if (cri->cr_status < 200) + if (cri->cr_status < 200) { nua_client_create(nh, nua_r_cancel, &nua_cancel_client_methods, NULL); - else if (cri->cr_status < 300) + } + else if (cri->cr_status < 300 && !cri->cr_acked) { nua_invite_client_ack(cri, NULL); + nua_client_request_clean(cri); + } } if (nua_client_create(nh, nua_r_bye, &nua_bye_client_methods, NULL) != 0) break; @@ -1796,7 +1807,7 @@ static int nua_prack_client_report(nua_client_request_t *cr, if (status < 200) ; - else if (du->du_cr && du->du_cr->cr_orq && du->du_cr->cr_status >= 200) { + else if (nua_invite_client_should_ack(du->du_cr)) { /* There is an un-ACK-ed INVITE there */ assert(du->du_cr->cr_method == sip_method_invite); if (NH_PGET(nh, auto_ack) || @@ -1807,6 +1818,7 @@ static int nua_prack_client_report(nua_client_request_t *cr, next_state = nua_callstate_ready; else next_state = nua_callstate_terminating; + nua_client_request_clean(du->du_cr); } } @@ -3300,7 +3312,7 @@ static int nua_update_client_report(nua_client_request_t *cr, if (status < 200) ; - else if (du->du_cr && du->du_cr->cr_orq && du->du_cr->cr_status >= 200) { + else if (nua_invite_client_should_ack(du->du_cr)) { /* There is an un-ACK-ed INVITE there */ assert(du->du_cr->cr_method == sip_method_invite); @@ -3311,6 +3323,7 @@ static int nua_update_client_report(nua_client_request_t *cr, next_state = nua_callstate_ready; else next_state = nua_callstate_terminating; + nua_client_request_clean(du->du_cr); } } diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c index 4e799a2965..23c12f8f37 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c @@ -2092,13 +2092,17 @@ int nua_client_request_queue(nua_client_request_t *cr) return queued; } -nua_client_request_t *nua_client_request_remove(nua_client_request_t *cr) +void nua_client_request_remove(nua_client_request_t *cr) { if (cr->cr_prev) if ((*cr->cr_prev = cr->cr_next)) cr->cr_next->cr_prev = cr->cr_prev; cr->cr_prev = NULL, cr->cr_next = NULL; - return cr; +} + +void nua_client_request_clean(nua_client_request_t *cr) +{ + nta_outgoing_destroy(cr->cr_orq), cr->cr_orq = NULL, cr->cr_acked = 0; } void nua_client_request_complete(nua_client_request_t *cr) @@ -3106,13 +3110,13 @@ int nua_base_client_response(nua_client_request_t *cr, if (status < 200 || /* Un-ACKed 2XX response to INVITE */ - (method == sip_method_invite && status < 300 && cr->cr_orq)) { + (method == sip_method_invite && status < 300 && !cr->cr_acked)) { cr->cr_reporting = 0, nh->nh_ds->ds_reporting = 0; return 1; } if (cr->cr_orq) - nta_outgoing_destroy(cr->cr_orq), cr->cr_orq = NULL; + nta_outgoing_destroy(cr->cr_orq), cr->cr_orq = NULL, cr->cr_acked = 0; du = cr->cr_usage;