forked from Mirrors/freeswitch
Fri Jan 16 07:42:29 CST 2009 Pekka Pessi <first.last@nokia.com>
* nua: fixed problems with route set handling RFC 3261 allows the route set changes while dialog is in early state. git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@11834 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
293a9b1483
commit
5baf8d20b6
@ -1 +1 @@
|
||||
Wed Feb 11 11:05:49 CST 2009
|
||||
Wed Feb 11 11:06:56 CST 2009
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include <sofia-sip/sip_header.h>
|
||||
#include <sofia-sip/soa.h>
|
||||
#include <sofia-sip/su_tagarg.h>
|
||||
#include <sofia-sip/su_string.h>
|
||||
#include <sofia-sip/su_tag_io.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user