Author: mikej Date: Thu Aug 14 11:37:53 2008 New Revision: 9290 Modified: freeswitch/trunk/libs/sofia-sip/.update freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c Log: Wed Aug 13 13:03:33 EDT 2008 Pekka Pessi <first.last@nokia.com> * nua_session.c: destroying invite transaction only after nua_i_invite is sent Added nua_client_request_clean(), nua_invite_client_should_ack(). Modified: freeswitch/trunk/libs/sofia-sip/.update ============================================================================== --- freeswitch/trunk/libs/sofia-sip/.update (original) +++ freeswitch/trunk/libs/sofia-sip/.update Thu Aug 14 11:37:53 2008 @@ -1 +1 @@ -Thu Aug 14 11:37:00 EDT 2008 +Thu Aug 14 11:37:23 EDT 2008 Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h ============================================================================== --- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h (original) +++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h Thu Aug 14 11:37:53 2008 @@ -296,6 +296,7 @@ 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_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 @@ 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) 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 Thu Aug 14 11:37:53 2008 @@ -197,6 +197,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ 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 @@ next_state = nua_callstate_ready; else next_state = nua_callstate_terminating; + nua_client_request_clean(du->du_cr); } } @@ -3300,7 +3312,7 @@ 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 @@ next_state = nua_callstate_ready; else next_state = nua_callstate_terminating; + nua_client_request_clean(du->du_cr); } } Modified: freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c ============================================================================== --- freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c (original) +++ freeswitch/trunk/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c Thu Aug 14 11:37:53 2008 @@ -2092,13 +2092,17 @@ 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 @@ 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;