diff --git a/coreapi/bellesip_sal/sal_address_impl.c b/coreapi/bellesip_sal/sal_address_impl.c index dbeb9b8e0..d3f5c088a 100644 --- a/coreapi/bellesip_sal/sal_address_impl.c +++ b/coreapi/bellesip_sal/sal_address_impl.c @@ -232,6 +232,11 @@ const char * sal_address_get_uri_param(const SalAddress *addr, const char *name) return belle_sip_parameters_get_parameter(parameters, name); } +void sal_address_remove_uri_param(const SalAddress *addr, const char *name) { + belle_sip_parameters_t* parameters = BELLE_SIP_PARAMETERS(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(addr))); + belle_sip_parameters_remove_parameter(parameters, name); +} + void sal_address_set_header(SalAddress *addr, const char *header_name, const char *header_value){ belle_sip_uri_set_header(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(addr)),header_name, header_value); } diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index d99dbc274..33d1b5eaa 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -116,12 +116,16 @@ belle_sip_header_contact_t* sal_op_create_contact(SalOp *op){ if (op->privacy!=SalPrivacyNone){ belle_sip_uri_set_user(contact_uri,NULL); } - belle_sip_header_contact_set_automatic(contact_header,op->base.root->auto_contacts); - if (op->base.root->uuid){ - if (belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(contact_header),"+sip.instance")==0){ - char *instance_id=belle_sip_strdup_printf("\"\"",op->base.root->uuid); - belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(contact_header),"+sip.instance",instance_id); - belle_sip_free(instance_id); + + /*don't touch contact in case of gruu*/ + if (!belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(contact_header))),"gr")) { + belle_sip_header_contact_set_automatic(contact_header,op->base.root->auto_contacts); + if (op->base.root->uuid){ + if (belle_sip_parameters_has_parameter(BELLE_SIP_PARAMETERS(contact_header),"+sip.instance")==0){ + char *instance_id=belle_sip_strdup_printf("\"\"",op->base.root->uuid); + belle_sip_parameters_set_parameter(BELLE_SIP_PARAMETERS(contact_header),"+sip.instance",instance_id); + belle_sip_free(instance_id); + } } } return contact_header; @@ -190,6 +194,7 @@ belle_sip_request_t* sal_op_build_request(SalOp *op,const char* method) { belle_sip_uri_set_secure(req_uri,sal_op_is_secure(op)); to_header = belle_sip_header_to_create(BELLE_SIP_HEADER_ADDRESS(to_address),NULL); + belle_sip_parameters_remove_parameter(BELLE_SIP_PARAMETERS(belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to_header))), "gr"); /*remove gruu in any case*/ call_id_header = belle_sip_provider_create_call_id(prov); if (sal_op_get_call_id(op)) { belle_sip_header_call_id_set_call_id(call_id_header, sal_op_get_call_id(op)); diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index cb2253672..60f708906 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -5044,8 +5044,9 @@ static LinphoneAddress *get_fixed_contact(LinphoneCore *lc, LinphoneCall *call , void linphone_call_set_contact_op(LinphoneCall* call) { LinphoneAddress *contact; - contact=get_fixed_contact(call->core,call,call->dest_proxy); - sal_op_set_and_clean_contact_address(call->op, (SalAddress *)contact); + if ((contact=get_fixed_contact(call->core,call,call->dest_proxy))) + sal_op_set_and_clean_contact_address(call->op, (SalAddress *)contact); + /*else, we already have a contact so keep it "as is"*/ } LinphonePlayer *linphone_call_get_player(LinphoneCall *call){ diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index fd5344808..f913a7677 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1383,7 +1383,7 @@ static void sip_config_read(LinphoneCore *lc) { sal_enable_sip_update_method(lc->sal,lp_config_get_int(lc->config,"sip","sip_update",1)); lc->sip_conf.vfu_with_info=lp_config_get_int(lc->config,"sip","vfu_with_info",1); linphone_core_set_sip_transport_timeout(lc, lp_config_get_int(lc->config, "sip", "transport_timeout", 63000)); - sal_set_supported_tags(lc->sal,lp_config_get_string(lc->config,"sip","supported","replaces, outbound, gruu")); + sal_set_supported_tags(lc->sal,lp_config_get_string(lc->config,"sip","supported","replaces, outbound"/*, gruu" not yet enabled by default*/)); lc->sip_conf.save_auth_info = lp_config_get_int(lc->config, "sip", "save_auth_info", 1); linphone_core_create_im_notif_policy(lc); } @@ -3488,6 +3488,7 @@ static void linphone_transfer_routes_to_op(bctbx_list_t *routes, SalOp *op){ void linphone_configure_op_with_proxy(LinphoneCore *lc, SalOp *op, const LinphoneAddress *dest, SalCustomHeader *headers, bool_t with_contact, LinphoneProxyConfig *proxy){ bctbx_list_t *routes=NULL; const char *identity; + if (proxy){ identity=linphone_proxy_config_get_identity(proxy); if (linphone_proxy_config_get_privacy(proxy)!=LinphonePrivacyDefault) { @@ -3499,7 +3500,16 @@ void linphone_configure_op_with_proxy(LinphoneCore *lc, SalOp *op, const Linphon routes=make_routes_for_proxy(proxy,dest); linphone_transfer_routes_to_op(routes,op); } - sal_op_set_to_address(op,dest); + if (sal_address_has_uri_param((const SalAddress *)dest,"gr")) { + /*in case of gruu destination remove gruu parram from to*/ + SalAddress *dest_copy = sal_address_clone(dest); + sal_address_remove_uri_param(dest_copy,"gr"); + sal_op_set_to_address(op,dest_copy); + sal_address_unref(dest_copy); + } else { + sal_op_set_to_address(op,dest); + } + sal_op_set_from(op,identity); sal_op_set_sent_custom_header(op,headers); sal_op_set_realm(op,linphone_proxy_config_get_realm(proxy)); diff --git a/coreapi/sal.c b/coreapi/sal.c index 3870e59e3..0c43532fb 100644 --- a/coreapi/sal.c +++ b/coreapi/sal.c @@ -519,16 +519,14 @@ void sal_op_set_contact_address(SalOp *op, const SalAddress *address){ } void sal_op_set_and_clean_contact_address(SalOp *op, SalAddress *contact) { - if (contact){ + if (contact && !sal_address_get_uri_param(contact, "gr")) { /*in case of gruu, nothing to do*/ SalTransport tport = sal_address_get_transport((SalAddress*)contact); - const char* gruu = bctbx_strdup(sal_address_get_uri_param(contact, "gr")); sal_address_clean((SalAddress*)contact); /* clean out contact_params that come from proxy config*/ sal_address_set_transport((SalAddress*)contact,tport); - if(gruu) - sal_address_set_uri_param(contact, "gr", gruu); - sal_op_set_contact_address(op, contact); - sal_address_unref(contact); } + sal_op_set_contact_address(op, contact); + if (contact) + sal_address_unref(contact); } const SalAddress* sal_op_get_contact_address(const SalOp *op) { diff --git a/include/sal/sal.h b/include/sal/sal.h index e108abc37..17cc3c8b5 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -139,6 +139,7 @@ void sal_address_set_uri_param(SalAddress *addr, const char *name, const char *v void sal_address_set_uri_params(SalAddress *addr, const char *params); bool_t sal_address_has_uri_param(const SalAddress *addr, const char *name); const char * sal_address_get_uri_param(const SalAddress *addr, const char *name); +void sal_address_remove_uri_param(const SalAddress *addr, const char *name); bool_t sal_address_is_ipv6(const SalAddress *addr); bool_t sal_address_is_sip(const SalAddress *addr); void sal_address_set_password(SalAddress *addr, const char *passwd); diff --git a/tester/call_single_tester.c b/tester/call_single_tester.c index 73c724a5f..c6aca886f 100644 --- a/tester/call_single_tester.c +++ b/tester/call_single_tester.c @@ -1406,7 +1406,7 @@ static void call_declined_with_error(void) { BC_ASSERT_PTR_NOT_NULL(in_call=linphone_core_get_current_call(callee_mgr->lc)); linphone_call_ref(out_call); - BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallIncomingReceived,1)); + BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallOutgoingRinging,1)); BC_ASSERT_PTR_NOT_NULL(in_call=linphone_core_get_current_call(callee_mgr->lc)); if (in_call) { linphone_call_ref(in_call); @@ -6179,38 +6179,68 @@ static void recreate_zrtpdb_when_corrupted(void) { static void simple_call_with_gruu(void) { LinphoneCoreManager* marie; LinphoneCoreManager* pauline; - const LinphoneAddress *addr; + const LinphoneAddress *pauline_addr, *marie_addr; LinphoneCall *marie_call = NULL; LinphoneCall *pauline_call = NULL; LinphoneProxyConfig* pauline_cfg; - + LinphoneAddress *contact_addr; marie = linphone_core_manager_new( "marie_rc"); pauline = linphone_core_manager_new("pauline_tcp_rc"); + + linphone_core_add_supported_tag(pauline->lc,"gruu"); + linphone_core_add_supported_tag(marie->lc,"gruu"); BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneRegistrationOk, 1)); BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneRegistrationOk, 1)); pauline_cfg = linphone_core_get_default_proxy_config(pauline->lc); - addr = linphone_proxy_config_get_contact(pauline_cfg); - BC_ASSERT_PTR_NOT_NULL(addr); - BC_ASSERT_PTR_NOT_NULL(strstr(linphone_address_as_string_uri_only(addr), "gr")); - - marie_call = linphone_core_invite_address(marie->lc, addr); + pauline_addr = linphone_proxy_config_get_contact(pauline_cfg); + + BC_ASSERT_PTR_NOT_NULL(pauline_addr); + BC_ASSERT_TRUE(linphone_address_has_uri_param(pauline_addr,"gr")); + BC_ASSERT_STRING_EQUAL(linphone_address_get_domain(pauline_addr),"sip.example.org"); + + marie_call = linphone_core_invite_address(marie->lc, pauline_addr); BC_ASSERT_PTR_NOT_NULL(marie_call); if(!marie_call) goto end; BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallIncomingReceived, 1)); pauline_call = linphone_core_get_current_call(pauline->lc); BC_ASSERT_PTR_NOT_NULL(pauline_call); if(!pauline_call) goto end; + + marie_addr = linphone_proxy_config_get_contact(linphone_core_get_default_proxy_config(marie->lc)); + BC_ASSERT_TRUE(linphone_address_has_uri_param(marie_addr,"gr")); + BC_ASSERT_STRING_EQUAL(linphone_address_get_domain(marie_addr),"sip.example.org"); + contact_addr = linphone_address_new(linphone_call_get_remote_contact(pauline_call)); + if (!BC_ASSERT_TRUE(linphone_address_equal(contact_addr, marie_addr))) { + char* expected = linphone_address_as_string(marie_addr); + char* result = linphone_address_as_string(contact_addr); + ms_error("Expected contact is [%s], result is [%s]",expected,result); + ms_free(expected); + ms_free(result); + } + linphone_address_unref(contact_addr); + linphone_call_accept(pauline_call); BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1)); BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallStreamsRunning, 1)); - - linphone_call_terminate(pauline_call); - - BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallEnd, 1)); - BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallEnd, 1)); + + contact_addr = linphone_address_new(linphone_call_get_remote_contact(marie_call)); + if (!BC_ASSERT_TRUE(linphone_address_equal(contact_addr, pauline_addr))) { + char* expected = linphone_address_as_string(pauline_addr); + char* result = linphone_address_as_string(contact_addr); + ms_error("Expected contact is [%s], result is [%s]",expected,result); + ms_free(expected); + ms_free(result); + } + linphone_address_unref(contact_addr); + + liblinphone_tester_check_rtcp(marie,pauline); + end_call(marie,pauline); + + //BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallEnd, 1)); + //BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallEnd, 1)); end: linphone_core_manager_destroy(pauline); @@ -6231,6 +6261,9 @@ static void simple_call_with_gruu_only_one_device_ring(void) { marie = linphone_core_manager_new( "marie_rc"); pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); pauline2 = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + linphone_core_add_supported_tag(pauline->lc,"gruu"); + linphone_core_add_supported_tag(pauline2->lc,"gruu"); + linphone_core_add_supported_tag(marie->lc,"gruu"); BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneRegistrationOk, 1)); BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneRegistrationOk, 1)); diff --git a/tester/complex_sip_case_tester.c b/tester/complex_sip_case_tester.c index a8bbd5377..403219b9a 100644 --- a/tester/complex_sip_case_tester.c +++ b/tester/complex_sip_case_tester.c @@ -141,9 +141,11 @@ static void sip_update_within_icoming_reinvite_with_no_sdp(void) { if (sipp_out) { BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallIncomingReceived, 1)); - linphone_call_accept(linphone_core_get_current_call(mgr->lc)); - BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallStreamsRunning, 2)); - BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallEnd, 1)); + if (linphone_core_get_current_call(mgr->lc)) { + linphone_call_accept(linphone_core_get_current_call(mgr->lc)); + BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallStreamsRunning, 2)); + BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallEnd, 1)); + } pclose(sipp_out); } linphone_core_manager_destroy(mgr); diff --git a/tester/flexisip_tester.c b/tester/flexisip_tester.c index 324b82221..bfb00aba7 100644 --- a/tester/flexisip_tester.c +++ b/tester/flexisip_tester.c @@ -1204,6 +1204,17 @@ static void redis_publish_subscribe(void) { marie2 = linphone_core_manager_new("marie2_rc"); BC_ASSERT_TRUE(wait_for_until(marie2->lc, NULL, &marie2->stat.number_of_LinphoneCallIncomingReceived, 1, 3000)); + linphone_call_accept(linphone_core_get_current_call(marie2->lc)); + BC_ASSERT_TRUE(wait_for_until(marie2->lc, pauline->lc, &marie2->stat.number_of_LinphoneCallStreamsRunning, 1, 3000)); + BC_ASSERT_TRUE(wait_for_until(marie2->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallStreamsRunning, 1, 3000)); + + liblinphone_tester_check_rtcp(marie2, pauline); + + linphone_call_terminate(linphone_core_get_current_call(marie2->lc)); + + BC_ASSERT_TRUE(wait_for_until(marie2->lc, pauline->lc, &marie2->stat.number_of_LinphoneCallEnd, 1, 3000)); + BC_ASSERT_TRUE(wait_for_until(marie2->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallEnd, 1, 3000)); + linphone_address_unref(marie_identity); linphone_core_manager_destroy(pauline); linphone_core_manager_destroy(marie2); diff --git a/tester/register_tester.c b/tester/register_tester.c index 385683708..7353ad7a8 100644 --- a/tester/register_tester.c +++ b/tester/register_tester.c @@ -1188,6 +1188,7 @@ static void tls_auth_info_client_cert_cb_2(void) { static void register_get_gruu(void) { LinphoneCoreManager *marie=linphone_core_manager_new("marie_rc"); + linphone_core_add_supported_tag(marie->lc,"gruu"); LinphoneProxyConfig *cfg=linphone_core_get_default_proxy_config(marie->lc); if(cfg) { const LinphoneAddress *addr = linphone_proxy_config_get_contact(cfg); @@ -1197,6 +1198,35 @@ static void register_get_gruu(void) { linphone_core_manager_destroy(marie); } +static void multi_devices_register_with_gruu(void) { + LinphoneCoreManager *marie=linphone_core_manager_new("marie_rc"); + LinphoneProxyConfig *cfg=linphone_core_get_default_proxy_config(marie->lc); + + linphone_core_add_supported_tag(marie->lc,"gruu"); + + if(cfg) { + const LinphoneAddress *addr = linphone_proxy_config_get_contact(cfg); + BC_ASSERT_PTR_NOT_NULL(addr); + BC_ASSERT_STRING_EQUAL(linphone_address_get_domain(addr),linphone_proxy_config_get_domain(cfg)); + BC_ASSERT_TRUE(linphone_address_has_uri_param(addr,"gr")); + } + + linphone_core_set_network_reachable(marie->lc,FALSE); /*to make sure first instance is not unregistered*/ + linphone_core_manager_destroy(marie); + + marie=linphone_core_manager_new("marie_rc"); + cfg=linphone_core_get_default_proxy_config(marie->lc); + if(cfg) { + const LinphoneAddress *addr = linphone_proxy_config_get_contact(cfg); + BC_ASSERT_PTR_NOT_NULL(addr); + BC_ASSERT_STRING_EQUAL(linphone_address_get_domain(addr),linphone_proxy_config_get_domain(cfg)); + BC_ASSERT_TRUE(linphone_address_has_uri_param(addr,"gr")); + } + + linphone_core_manager_destroy(marie); +} + + test_t register_tests[] = { TEST_NO_TAG("Simple register", simple_register), TEST_NO_TAG("Simple register unregister", simple_unregister), @@ -1242,7 +1272,8 @@ test_t register_tests[] = { TEST_NO_TAG("AuthInfo TLS client certificate authentication using API 2", tls_auth_info_client_cert_api_path), TEST_NO_TAG("AuthInfo TLS client certificate authentication in callback", tls_auth_info_client_cert_cb), TEST_NO_TAG("AuthInfo TLS client certificate authentication in callback 2", tls_auth_info_client_cert_cb_2), - TEST_NO_TAG("Register get GRUU", register_get_gruu) + TEST_NO_TAG("Register get GRUU", register_get_gruu), + TEST_NO_TAG("Register get GRUU for multi device", multi_devices_register_with_gruu) }; test_suite_t register_test_suite = {"Register", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each,