fix crash related to error occuring synchronously within linphone_core_invite()

This commit is contained in:
Simon Morlat 2016-09-13 10:22:30 +02:00
parent b2a78cbf97
commit a5341fe88a
2 changed files with 46 additions and 14 deletions

View file

@ -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);

View file

@ -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),