diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 5c6480244..f6da6e656 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -1113,7 +1113,15 @@ void linphone_call_fill_media_multicast_addr(LinphoneCall *call) { call->media_ports[call->main_video_stream_index].multicast_ip[0]='\0'; } -static void linphone_call_create_ice_session(LinphoneCall *call, IceRole role){ +void linphone_call_check_ice_session(LinphoneCall *call, IceRole role, bool_t is_reinvite){ + if (call->ice_session) return; /*already created*/ + + if (!linphone_nat_policy_ice_enabled(linphone_core_get_nat_policy(call->core))){ + return; + } + + if (is_reinvite && lp_config_get_int(call->core->config, "net", "allow_late_ice", 0) == 0) return; + call->ice_session = ice_session_new(); /*for backward compatibility purposes, shall be enabled by default in futur*/ ice_session_enable_message_integrity_check(call->ice_session,lp_config_get_int(call->core->config,"net","ice_session_enable_message_integrity_check",1)); @@ -1124,7 +1132,6 @@ static void linphone_call_create_ice_session(LinphoneCall *call, IceRole role){ types[2] = ICT_CandidateInvalid; ice_session_set_default_candidates_types(call->ice_session, types); } - ice_session_set_role(call->ice_session, role); } @@ -1142,9 +1149,8 @@ LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddr linphone_call_fill_media_multicast_addr(call); - if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseIce) { - linphone_call_create_ice_session(call, IR_Controlling); - } + linphone_call_check_ice_session(call, IR_Controlling, FALSE); + if (linphone_core_get_firewall_policy(call->core) == LinphonePolicyUseStun) { call->ping_time=linphone_core_run_stun_tests(call->core,call); } @@ -1393,7 +1399,7 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro if ((nat_policy != NULL) && linphone_nat_policy_ice_enabled(nat_policy)) { /* Create the ice session now if ICE is required */ if (md){ - linphone_call_create_ice_session(call, IR_Controlled); + linphone_call_check_ice_session(call, IR_Controlled, FALSE); }else{ nat_policy = NULL; ms_warning("ICE not supported for incoming INVITE without SDP."); diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 5c7b4f846..e7a7274f3 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -3615,6 +3615,8 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho ms_error("linphone_core_update_call() is not allowed in [%s] state",linphone_call_state_to_string(call->state)); return -1; } + + linphone_call_check_ice_session(call, IR_Controlling, TRUE); if (params!=NULL){ call->broken = FALSE; @@ -3798,11 +3800,10 @@ int _linphone_core_accept_call_update(LinphoneCore *lc, LinphoneCall *call, cons /*update multicast params according to call params*/ linphone_call_fill_media_multicast_addr(call); + linphone_call_check_ice_session(call, IR_Controlled, TRUE); linphone_call_init_media_streams(call); /*so that video stream is initialized if necessary*/ - if (call->ice_session != NULL) { - if (linphone_call_prepare_ice(call,TRUE)==1) - return 0;/*deferred to completion of ICE gathering*/ - } + if (linphone_call_prepare_ice(call,TRUE)==1) + return 0;/*deferred to completion of ICE gathering*/ #ifdef BUILD_UPNP if(call->upnp_session != NULL) { @@ -5281,8 +5282,19 @@ LinphoneFirewallPolicy linphone_core_get_firewall_policy(const LinphoneCore *lc) void linphone_core_set_nat_policy(LinphoneCore *lc, LinphoneNatPolicy *policy) { if (policy != NULL) policy = linphone_nat_policy_ref(policy); /* Prevent object destruction if the same policy is used */ - if (lc->nat_policy != NULL) linphone_nat_policy_unref(lc->nat_policy); - if (policy != NULL) lc->nat_policy = policy; + else{ + ms_error("linphone_core_set_nat_policy() setting to NULL is not allowed"); + return ; + } + if (lc->nat_policy != NULL) { + linphone_nat_policy_unref(lc->nat_policy); + lc->nat_policy = NULL; + } + if (policy != NULL){ + lc->nat_policy = policy; + /*start an immediate (but asynchronous) resolution.*/ + linphone_nat_policy_resolve_stun_server(policy); + } #ifdef BUILD_UPNP linphone_core_enable_keep_alive(lc, (lc->sip_conf.keepalive_period > 0)); diff --git a/coreapi/nat_policy.c b/coreapi/nat_policy.c index 5df7e3c24..c41bd96e5 100644 --- a/coreapi/nat_policy.c +++ b/coreapi/nat_policy.c @@ -40,6 +40,7 @@ static void linphone_nat_policy_destroy(LinphoneNatPolicy *policy) { if (policy->stun_server) belle_sip_free(policy->stun_server); if (policy->stun_server_username) belle_sip_free(policy->stun_server_username); if (policy->stun_addrinfo) bctbx_freeaddrinfo(policy->stun_addrinfo); + //if (policy->stun_resolver_context) sal_resolve_cancel(policy->stun_resolver_context); } static bool_t linphone_nat_policy_stun_server_activated(LinphoneNatPolicy *policy) { diff --git a/coreapi/private.h b/coreapi/private.h index ddc3d60d1..7351cfbc5 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -1552,6 +1552,8 @@ char *linphone_presence_model_to_xml(LinphonePresenceModel *model) ; #define LINPHONE_SQLITE3_VFS "sqlite3bctbx_vfs" +void linphone_call_check_ice_session(LinphoneCall *call, IceRole role, bool_t is_reinvite); + #ifdef __cplusplus } #endif diff --git a/tester/call_tester.c b/tester/call_tester.c index d3601279d..c48dd5f85 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -1304,7 +1304,7 @@ static void call_with_ice_no_sdp(void){ linphone_core_set_firewall_policy(pauline->lc,LinphonePolicyUseIce); - call(pauline,marie); + BC_ASSERT_TRUE(call(pauline,marie)); liblinphone_tester_check_rtcp(marie,pauline); @@ -1329,6 +1329,55 @@ static void not_ice_to_ice(void){ _call_with_ice(FALSE,TRUE,FALSE,FALSE); } +static void ice_added_by_reinvite(void){ + LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + LinphoneNatPolicy *pol; + LinphoneCallParams *params; + LinphoneCall *c; + bool_t call_ok; + + lp_config_set_int(linphone_core_get_config(marie->lc), "net", "allow_late_ice", 1); + lp_config_set_int(linphone_core_get_config(pauline->lc), "net", "allow_late_ice", 1); + + BC_ASSERT_TRUE((call_ok=call(pauline,marie))); + if (!call_ok) goto end; + liblinphone_tester_check_rtcp(marie,pauline); + + /*enable ICE on both ends*/ + pol = linphone_core_get_nat_policy(marie->lc); + linphone_nat_policy_enable_ice(pol, TRUE); + linphone_nat_policy_enable_stun(pol, TRUE); + linphone_core_set_nat_policy(marie->lc, pol); + + pol = linphone_core_get_nat_policy(pauline->lc); + linphone_nat_policy_enable_ice(pol, TRUE); + linphone_nat_policy_enable_stun(pol, TRUE); + linphone_core_set_nat_policy(pauline->lc, pol); + + c = linphone_core_get_current_call(marie->lc); + params = linphone_core_create_call_params(marie->lc, c); + linphone_core_update_call(marie->lc, c, params); + linphone_call_params_destroy(params); + + BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallUpdatedByRemote,1)); + BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,2)); + BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,2)); + + BC_ASSERT_TRUE(check_ice(marie, pauline, LinphoneIceStateHostConnection)); + + /*wait for the ICE reINVITE*/ + BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,3)); + BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,3)); + + + end_call(pauline, marie); + +end: + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + static void call_with_custom_headers(void) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); @@ -6371,6 +6420,18 @@ static void call_with_ice_without_stun(void){ linphone_core_manager_destroy(pauline); } +static void call_with_ice_without_stun2(void){ + LinphoneCoreManager * marie = linphone_core_manager_new( "marie_rc"); + LinphoneCoreManager *pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + + //linphone_core_set_stun_server(marie->lc, NULL); + linphone_core_set_stun_server(pauline->lc, NULL); + _call_with_ice_base(marie, pauline, TRUE, TRUE, TRUE, FALSE); + + linphone_core_manager_destroy(marie); + linphone_core_manager_destroy(pauline); +} + static void call_with_zrtp_configured_calling_side(void) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); @@ -6578,6 +6639,7 @@ test_t call_tests[] = { TEST_ONE_TAG("Call with ICE (forced relay)", call_with_ice_forced_relay, "ICE"), TEST_ONE_TAG("Call from ICE to not ICE", ice_to_not_ice, "ICE"), TEST_ONE_TAG("Call from not ICE to ICE", not_ice_to_ice, "ICE"), + TEST_ONE_TAG("Call with ICE added by reINVITE", ice_added_by_reinvite, "ICE"), TEST_NO_TAG("Call with custom headers", call_with_custom_headers), TEST_NO_TAG("Call with custom SDP attributes", call_with_custom_sdp_attributes), TEST_NO_TAG("Call established with rejected INFO", call_established_with_rejected_info), @@ -6636,6 +6698,7 @@ test_t call_tests[] = { TEST_ONE_TAG("Call with ICE and rtcp-mux without ICE re-invite", call_with_ice_and_rtcp_mux_without_reinvite, "ICE"), TEST_ONE_TAG("Call with ICE with default candidate not stun", call_with_ice_with_default_candidate_not_stun, "ICE"), TEST_ONE_TAG("Call with ICE without stun server", call_with_ice_without_stun, "ICE"), + TEST_ONE_TAG("Call with ICE without stun server one side", call_with_ice_without_stun2, "ICE"), TEST_NO_TAG("call with ZRTP configured calling side only", call_with_zrtp_configured_calling_side), TEST_NO_TAG("call with ZRTP configured receiver side only", call_with_zrtp_configured_callee_side) }; diff --git a/tester/tester.c b/tester/tester.c index 90a810b00..57d4cc851 100644 --- a/tester/tester.c +++ b/tester/tester.c @@ -233,7 +233,7 @@ static void set_codec_enable(LinphoneCore* lc,const char* type,int rate,bool_t e for (codecs_it=codecs;codecs_it!=NULL;codecs_it=codecs_it->next) { linphone_core_enable_payload_type(lc,(PayloadType*)codecs_it->data,0); } - if((pt = linphone_core_find_payload_type(lc,type,rate,1))) { + if ((pt = linphone_core_find_payload_type(lc,type,rate,1))) { linphone_core_enable_payload_type(lc,pt, enable); } ms_list_free(codecs);