From e8e922f0bffe76eea173ac4604e085ec95c634e5 Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Wed, 28 Sep 2016 11:24:13 +0200 Subject: [PATCH] fix header replaces usage according to rfc3891 --- coreapi/bellesip_sal/sal_op_call_transfer.c | 44 ++++++++++++++++----- tester/call_multi_tester.c | 27 ++++++++++--- 2 files changed, 55 insertions(+), 16 deletions(-) diff --git a/coreapi/bellesip_sal/sal_op_call_transfer.c b/coreapi/bellesip_sal/sal_op_call_transfer.c index 177a23602..a0aac3c20 100644 --- a/coreapi/bellesip_sal/sal_op_call_transfer.c +++ b/coreapi/bellesip_sal/sal_op_call_transfer.c @@ -88,14 +88,19 @@ int sal_call_refer_with_replaces(SalOp *op, SalOp *other_call_op){ refer_to=belle_sip_header_refer_to_create(belle_sip_dialog_get_remote_party(other_call_op->dialog)); belle_sip_parameters_clean(BELLE_SIP_PARAMETERS(refer_to)); - if (belle_sip_dialog_is_server(other_call_op->dialog)) { - to_tag=belle_sip_dialog_get_local_tag(other_call_op->dialog); - from_tag=belle_sip_dialog_get_remote_tag(other_call_op->dialog); - - } else { - from_tag=belle_sip_dialog_get_local_tag(other_call_op->dialog); - to_tag=belle_sip_dialog_get_remote_tag(other_call_op->dialog); - } + /*rfc3891 + ... + 4. User Agent Client Behavior: Sending a Replaces Header + + A User Agent that wishes to replace a single existing early or + confirmed dialog with a new dialog of its own, MAY send the target + User Agent an INVITE request containing a Replaces header field. The + User Agent Client (UAC) places the Call-ID, to-tag, and from-tag + information for the target dialog in a single Replaces header field + and sends the new INVITE to the target.*/ + from_tag=belle_sip_dialog_get_local_tag(other_call_op->dialog); + to_tag=belle_sip_dialog_get_remote_tag(other_call_op->dialog); + replaces=belle_sip_header_replaces_create(belle_sip_header_call_id_get_call_id(belle_sip_dialog_get_call_id(other_call_op->dialog)) ,from_tag,to_tag); escaped_replaces=belle_sip_header_replaces_value_to_escaped_string(replaces); @@ -121,11 +126,30 @@ int sal_call_set_referer(SalOp *h, SalOp *refered_call){ /* returns the SalOp of a call that should be replaced by h, if any */ SalOp *sal_call_get_replaces(SalOp *op){ if (op && op->replaces){ + /*rfc3891 + 3. User Agent Server Behavior: Receiving a Replaces Header + + The Replaces header contains information used to match an existing + SIP dialog (call-id, to-tag, and from-tag). Upon receiving an INVITE + with a Replaces header, the User Agent (UA) attempts to match this + information with a confirmed or early dialog. The User Agent Server + (UAS) matches the to-tag and from-tag parameters as if they were tags + present in an incoming request. In other words, the to-tag parameter + is compared to the local tag, and the from-tag parameter is compared + to the remote tag. + */ belle_sip_dialog_t* dialog=belle_sip_provider_find_dialog(op->base.root->prov ,belle_sip_header_replaces_get_call_id(op->replaces) - ,belle_sip_header_replaces_get_from_tag(op->replaces) - ,belle_sip_header_replaces_get_to_tag(op->replaces)); + ,belle_sip_header_replaces_get_to_tag(op->replaces) + ,belle_sip_header_replaces_get_from_tag(op->replaces)); + if (!dialog) { + /*for backward compatibility with liblinphone <= 3.10.2-243 */ + dialog=belle_sip_provider_find_dialog(op->base.root->prov + ,belle_sip_header_replaces_get_call_id(op->replaces) + ,belle_sip_header_replaces_get_from_tag(op->replaces) + ,belle_sip_header_replaces_get_to_tag(op->replaces)); + } if (dialog) { return (SalOp*)belle_sip_dialog_get_application_data(dialog); } diff --git a/tester/call_multi_tester.c b/tester/call_multi_tester.c index 2ea1fc17d..9a23a3205 100644 --- a/tester/call_multi_tester.c +++ b/tester/call_multi_tester.c @@ -559,7 +559,7 @@ static void unattended_call_transfer_with_error(void) { } -static void call_transfer_existing_call_outgoing_call(void) { +static void call_transfer_existing_call(bool_t outgoing_call) { LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_tcp_rc"); LinphoneCoreManager* laure = linphone_core_manager_new( "laure_rc_udp"); @@ -584,11 +584,20 @@ static void call_transfer_existing_call_outgoing_call(void) { goto end; } - /*marie call laure*/ - if (!BC_ASSERT_TRUE(call(marie,laure))) { - end_call(marie, pauline); - goto end; + if (outgoing_call) { + /*marie call laure*/ + if (!BC_ASSERT_TRUE(call(marie,laure))) { + end_call(marie, pauline); + goto end; + } + } else { + /*laure call pauline*/ + if (!BC_ASSERT_TRUE(call(laure,marie))) { + end_call(marie,pauline); + goto end; + } } + marie_call_laure=linphone_core_get_current_call(marie->lc); laure_called_by_marie=linphone_core_get_current_call(laure->lc); @@ -641,7 +650,12 @@ end: linphone_core_manager_destroy(pauline); bctbx_list_free(lcs); } - +static void call_transfer_existing_call_outgoing_call(void) { + call_transfer_existing_call(TRUE); +} +static void call_transfer_existing_call_incoming_call(void) { + call_transfer_existing_call(FALSE); +} static void eject_from_3_participants_conference(LinphoneCoreManager *marie, LinphoneCoreManager *pauline, LinphoneCoreManager *laure, LinphoneCoreManager *focus) { stats initial_marie_stat; stats initial_pauline_stat; @@ -953,6 +967,7 @@ test_t multi_call_tests[] = { TEST_NO_TAG("Unattended call transfer", unattended_call_transfer), TEST_NO_TAG("Unattended call transfer with error", unattended_call_transfer_with_error), TEST_NO_TAG("Call transfer existing call outgoing call", call_transfer_existing_call_outgoing_call), + TEST_NO_TAG("Call transfer existing call incoming call", call_transfer_existing_call_incoming_call), TEST_NO_TAG("Simple remote conference", simple_remote_conference), TEST_NO_TAG("Simple remote conference with shut down focus", simple_remote_conference_shut_down_focus), TEST_NO_TAG("Eject from 3 participants in remote conference", eject_from_3_participants_remote_conference),