diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update index 1c24f9eb45..37ad46c796 100644 --- a/libs/sofia-sip/.update +++ b/libs/sofia-sip/.update @@ -1 +1 @@ -Wed Feb 11 11:05:49 CST 2009 +Wed Feb 11 11:06:56 CST 2009 diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/check_session.c b/libs/sofia-sip/libsofia-sip-ua/nua/check_session.c index e8ce93530d..06e1bdba77 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/check_session.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/check_session.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -1007,8 +1008,10 @@ TCase *cancel_tcase(void) /* 2.3 - Session timers */ /* Wait for invite from NUA */ -static void invite_timer_round(nua_handle_t *nh, - char const *session_expires) +static struct message * +invite_timer_round(nua_handle_t *nh, + char const *session_expires, + sip_record_route_t *rr) { struct message *invite, *ack; @@ -1019,17 +1022,27 @@ static void invite_timer_round(nua_handle_t *nh, invite, dialog, SIP_200_OK, SIPTAG_SESSION_EXPIRES_STR(session_expires), SIPTAG_REQUIRE_STR("timer"), + SIPTAG_RECORD_ROUTE(rr), TAG_END()); s2_free_message(invite); fail_unless(s2_check_event(nua_r_invite, 200)); fail_unless(s2_check_callstate(nua_callstate_ready)); ack = s2_wait_for_request(SIP_METHOD_ACK); - s2_free_message(ack); + if (rr == NULL) + s2_free_message(ack); + return ack; } START_TEST(call_2_3_1) { nua_handle_t *nh; + sip_record_route_t rr[1]; + struct message *ack; + + sip_record_route_init(rr); + *rr->r_url = *s2->contact->m_url; + rr->r_url->url_user = "record"; + rr->r_url->url_params = "lr"; s2_case("2.3.1", "Incoming call with call timers", "NUA receives INVITE, " @@ -1043,9 +1056,11 @@ START_TEST(call_2_3_1) TAG_END()); s2_fast_forward(300); - invite_timer_round(nh, "300;refresher=uac"); + ack = invite_timer_round(nh, "300;refresher=uac", rr); + fail_if(ack->sip->sip_route && + su_strmatch(ack->sip->sip_route->r_url->url_user, "record")); s2_fast_forward(300); - invite_timer_round(nh, "300;refresher=uac"); + invite_timer_round(nh, "300;refresher=uac", NULL); bye_by_nua(nh, TAG_END()); @@ -1069,9 +1084,9 @@ START_TEST(call_2_3_2) TAG_END()); s2_fast_forward(300); - invite_timer_round(nh, "300"); + invite_timer_round(nh, "300", NULL); s2_fast_forward(300); - invite_timer_round(nh, "300"); + invite_timer_round(nh, "300", NULL); bye_by_nua(nh, TAG_END()); @@ -1098,8 +1113,9 @@ TCase *session_timer_tcase(void) START_TEST(call_2_4_1) { nua_handle_t *nh; - struct message *invite, *prack; + struct message *invite, *prack, *ack; int with_sdp; + sip_record_route_t rr[1]; s2_case("2.4.1", "Call with 100rel", "NUA sends INVITE, " @@ -1107,6 +1123,11 @@ START_TEST(call_2_4_1) "receives 180, sends PRACK, receives 200 for it, " "receives 200, send ACK."); + sip_record_route_init(rr); + *rr->r_url = *s2->contact->m_url; + rr->r_url->url_user = "record"; + rr->r_url->url_params = "lr"; + nh = nua_handle(nua, NULL, SIPTAG_TO(s2->local), TAG_END()); invite = invite_sent_by_nua( @@ -1116,6 +1137,7 @@ START_TEST(call_2_4_1) prack = respond_with_100rel(invite, dialog, with_sdp = 1, SIP_183_SESSION_PROGRESS, + SIPTAG_RECORD_ROUTE(rr), TAG_END()); s2_respond_to(prack, dialog, SIP_200_OK, TAG_END()); s2_free_message(prack), prack = NULL; @@ -1125,16 +1147,26 @@ START_TEST(call_2_4_1) prack = respond_with_100rel(invite, dialog, with_sdp = 0, SIP_180_RINGING, TAG_END()); + fail_unless(prack->sip->sip_route != NULL); + fail_unless(su_strmatch(prack->sip->sip_route->r_url->url_user, "record")); + s2_respond_to(prack, dialog, SIP_200_OK, TAG_END()); s2_free_message(prack), prack = NULL; fail_unless(s2_check_callstate(nua_callstate_proceeding)); fail_unless(s2_check_event(nua_r_prack, 200)); - s2_respond_to(invite, dialog, SIP_200_OK, TAG_END()); + /* Change the record-route */ + rr->r_url->url_user = "record2"; + s2_respond_to(invite, dialog, SIP_200_OK, + SIPTAG_RECORD_ROUTE(rr), + TAG_END()); s2_free_message(invite); fail_unless(s2_check_event(nua_r_invite, 200)); fail_unless(s2_check_callstate(nua_callstate_ready)); - fail_unless(s2_check_request(SIP_METHOD_ACK)); + ack = s2_wait_for_request(SIP_METHOD_ACK); + fail_if(!ack); + fail_unless(su_strmatch(ack->sip->sip_route->r_url->url_user, "record2")); + s2_free_message(ack); bye_to_nua(nh, TAG_END()); @@ -2314,7 +2346,7 @@ START_TEST(bye_4_2_1) TAG_END()); s2_fast_forward(300); - invite_timer_round(nh, "300"); + invite_timer_round(nh, "300", NULL); nua_bye(nh, TAG_END()); @@ -2358,7 +2390,7 @@ START_TEST(bye_4_2_2) TAG_END()); s2_fast_forward(300); - invite_timer_round(nh, "300"); + invite_timer_round(nh, "300", NULL); s2_fast_forward(300); diff --git a/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c b/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c index 2b70646fec..b7c7916e9e 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.c @@ -104,13 +104,16 @@ void nua_dialog_uas_route(nua_owner_t *own, * @param ds dialog state * @param sip SIP message containing response used to update dialog * @param rtag if true, set remote tag within the leg + * @param initial if true, @a sip is response to initial transaction */ void nua_dialog_uac_route(nua_owner_t *own, nua_dialog_state_t *ds, sip_t const *sip, - int rtag) + int rtag, + int initial) { int established = nua_dialog_is_established(ds); + int status = sip->sip_status->st_status; if (!established && sip->sip_to->a_tag) ds->ds_remote_tag = su_strdup(own, sip->sip_to->a_tag); @@ -118,7 +121,11 @@ void nua_dialog_uac_route(nua_owner_t *own, if (ds->ds_leg == NULL) return; - nta_leg_client_route(ds->ds_leg, sip->sip_record_route, sip->sip_contact); + if (initial && status >= 200) + nta_leg_client_reroute(ds->ds_leg, sip->sip_record_route, sip->sip_contact, 1); + else + nta_leg_client_reroute(ds->ds_leg, sip->sip_record_route, sip->sip_contact, 0); + ds->ds_route = ds->ds_route || sip->sip_record_route || sip->sip_contact; if (rtag && !established && sip->sip_to->a_tag) 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 25dde0a5ff..a4c049be9d 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_dialog.h @@ -299,6 +299,7 @@ struct nua_client_request unsigned cr_dialog:1; /**< Request can initiate dialog */ /* Current state */ + unsigned cr_initial:1; /**< Initial request of a dialog */ 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 */ @@ -411,7 +412,7 @@ struct nua_dialog_usage { }; void nua_dialog_uac_route(nua_owner_t *, nua_dialog_state_t *ds, - sip_t const *sip, int rtag); + sip_t const *sip, int rtag, int initial); void nua_dialog_uas_route(nua_owner_t *, nua_dialog_state_t *ds, sip_t const *sip, int rtag); void nua_dialog_store_peer_info(nua_owner_t *, nua_dialog_state_t *ds, 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 a52ebca5a6..60d45c101f 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_session.c @@ -732,9 +732,12 @@ static int nua_invite_client_init(nua_client_request_t *cr, if (sr->sr_usage == du && sr->sr_method == sip_method_invite && nua_server_request_is_pending(sr)) return nua_client_return(cr, SIP_491_REQUEST_PENDING, msg); + cr->cr_initial = 0; } - else + else { du = nua_dialog_usage_add(nh, nh->nh_ds, nua_session_usage, NULL); + cr->cr_initial = 1; + } if (!du) return -1; @@ -884,7 +887,7 @@ static int nua_invite_client_preliminary(nua_client_request_t *cr, if (!nua_dialog_is_established(nh->nh_ds)) { nta_outgoing_t *tagged; - nua_dialog_uac_route(nh, nh->nh_ds, sip, 1); + nua_dialog_uac_route(nh, nh->nh_ds, sip, 1, 1); nua_dialog_store_peer_info(nh, nh->nh_ds, sip); /* Tag the INVITE request */ @@ -1188,7 +1191,6 @@ int nua_stack_ack(nua_t *nua, nua_handle_t *nh, nua_event_t e, } nua_client_request_ref(cr); - error = nua_invite_client_ack(cr, tags); if (error < 0) { @@ -1238,6 +1240,8 @@ 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); + cr->cr_initial = 0; + if (!ds->ds_leg) { /* XXX - fix nua_dialog_usage_remove_at() instead! */ nua_client_request_clean(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 ccf9a8f4e8..53ee3726f5 100644 --- a/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c +++ b/libs/sofia-sip/libsofia-sip-ua/nua/nua_stack.c @@ -2876,7 +2876,7 @@ int nua_client_response(nua_client_request_t *cr, else { if (sip) { if (cr->cr_contactize) - nua_dialog_uac_route(nh, nh->nh_ds, sip, 1); + nua_dialog_uac_route(nh, nh->nh_ds, sip, 1, cr->cr_initial); nua_dialog_store_peer_info(nh, nh->nh_ds, sip); }