From a5341fe88aaf7b164f125c0c559f6bc113ec5629 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Tue, 13 Sep 2016 10:22:30 +0200 Subject: [PATCH] fix crash related to error occuring synchronously within linphone_core_invite() --- coreapi/linphonecore.c | 40 ++++++++++++++++++++++++------------- tester/call_single_tester.c | 20 +++++++++++++++++++ 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 1b07a26cc..6a5229457 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -3129,26 +3129,33 @@ int linphone_core_start_invite(LinphoneCore *lc, LinphoneCall *call, const Linph /*we are offering, set local media description before sending the call*/ sal_call_set_local_media_description(call->op,call->localdesc); } + + barmsg=ortp_strdup_printf("%s %s", _("Contacting"), real_url); + linphone_core_notify_display_status(lc,barmsg); + ms_free(barmsg); + err=sal_call(call->op,from,real_url); + + if (err < 0){ + if (call->state != LinphoneCallError && + call->state != LinphoneCallReleased){ + /*sal_call() may invoke call_failure() and call_released() SAL callbacks synchronously, + * in which case there is no need to perform a state change here.*/ + linphone_core_notify_display_status(lc,_("Could not call")); + linphone_call_stop_media_streams(call); + linphone_call_set_state(call,LinphoneCallError,"Call failed"); + } + goto end; + } if (lc->sip_conf.sdp_200_ack){ /*we are NOT offering, set local media description after sending the call so that we are ready to process the remote offer when it will arrive*/ sal_call_set_local_media_description(call->op,call->localdesc); } - call->log->call_id=ms_strdup(sal_op_get_call_id(call->op)); /*must be known at that time*/ - - barmsg=ortp_strdup_printf("%s %s", _("Contacting"), real_url); - linphone_core_notify_display_status(lc,barmsg); - ms_free(barmsg); - - if (err<0){ - linphone_core_notify_display_status(lc,_("Could not call")); - linphone_call_stop_media_streams(call); - linphone_call_set_state(call,LinphoneCallError,"Call failed"); - }else { - linphone_call_set_state(call,LinphoneCallOutgoingProgress,"Outgoing call in progress"); - } + linphone_call_set_state(call,LinphoneCallOutgoingProgress,"Outgoing call in progress"); + +end: ms_free(real_url); ms_free(from); return err; @@ -3353,7 +3360,12 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const } } - if (defer==FALSE) linphone_core_start_invite(lc,call,NULL); + if (defer==FALSE) { + if (linphone_core_start_invite(lc,call,NULL) != 0){ + /*the call has already gone to error and released state, so do not return it*/ + call = NULL; + } + } if (real_url!=NULL) ms_free(real_url); linphone_call_params_destroy(cp); diff --git a/tester/call_single_tester.c b/tester/call_single_tester.c index 53f10f2e8..750c63730 100644 --- a/tester/call_single_tester.c +++ b/tester/call_single_tester.c @@ -509,6 +509,25 @@ static void simple_call(void) { simple_call_base(FALSE); } +/*This test is added to reproduce a crash when a call is failed synchronously*/ +static void simple_call_with_no_sip_transport(void){ + LinphoneCoreManager* marie; + LinphoneCoreManager* pauline; + LCSipTransports tr={0}; + LinphoneCall *call; + + marie = linphone_core_manager_new( "marie_rc"); + pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + + /*disable all transports so that the call will fail synchronously*/ + linphone_core_set_sip_transports(marie->lc, &tr); + + call = linphone_core_invite_address(marie->lc, pauline->identity); + BC_ASSERT_PTR_NULL(call); + linphone_core_manager_destroy(pauline); + linphone_core_manager_destroy(marie); +} + static void simple_call_with_udp(void) { LinphoneCoreManager* michelle; LinphoneCoreManager* laure; @@ -4830,6 +4849,7 @@ test_t call_tests[] = { TEST_NO_TAG("Cancelled ringing call", cancelled_ringing_call), TEST_NO_TAG("Call busy when calling self", call_busy_when_calling_self), TEST_NO_TAG("Simple call", simple_call), + TEST_NO_TAG("Simple call with no SIP transport", simple_call_with_no_sip_transport), TEST_NO_TAG("Simple call with UDP", simple_call_with_udp), TEST_ONE_TAG("Call terminated automatically by linphone_core_destroy", automatic_call_termination, "LeaksMemory"), TEST_NO_TAG("Call with http proxy", call_with_http_proxy),