From 922caf698f8df8d5d57f5154b51d5903a29a6412 Mon Sep 17 00:00:00 2001 From: Ghislain MARY Date: Wed, 1 Aug 2012 09:30:27 +0200 Subject: [PATCH] Fix some crashes related to asynchronous ICE candidates gathering. --- coreapi/callbacks.c | 11 +++++++++-- coreapi/linphonecall.c | 25 +++++++++++++++++-------- coreapi/linphonecore.c | 6 ++---- coreapi/private.h | 1 + 4 files changed, 29 insertions(+), 14 deletions(-) diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index cd3290aa..dd17650f 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -187,7 +187,7 @@ static void call_received(SalOp *h){ linphone_core_add_call(lc,call); linphone_call_ref(call); /*prevent the call from being destroyed while we are notifying, if the user declines within the state callback */ - if (linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) { + if ((linphone_core_get_firewall_policy(lc) == LinphonePolicyUseIce) && sal_op_get_ice_session(call->op)) { /* Defer ringing until the end of the ICE candidates gathering process. */ ms_message("Defer ringing to gather ICE candidates"); return; @@ -254,13 +254,20 @@ static void call_ringing(SalOp *h){ static void call_accepted(SalOp *op){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); + IceSession *ice_session=sal_op_get_ice_session(op); SalMediaDescription *md; if (call==NULL){ ms_warning("No call to accept."); return ; } - + + if (ice_session == NULL) { + /* Ensure the ICE check list pointers for the call streams are resetted to prevent crashes */ + if (call->audiostream != NULL) call->audiostream->ice_check_list = NULL; + if (call->videostream != NULL) call->videostream->ice_check_list = NULL; + } + md=sal_call_get_final_media_description(op); if (call->state==LinphoneCallOutgoingProgress || diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index e2948f59..52c01d45 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -394,8 +394,7 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro linphone_call_start_media_streams_for_ice_gathering(call); if (linphone_core_gather_ice_candidates(call->core,call)<0) { /* Ice candidates gathering failed, proceed with the call anyway. */ - ice_session_destroy(sal_op_get_ice_session(call->op)); - sal_op_set_ice_session(call->op, NULL); + linphone_call_delete_ice_session(call); linphone_call_stop_media_streams(call); } break; @@ -404,8 +403,7 @@ LinphoneCall * linphone_call_new_incoming(LinphoneCore *lc, LinphoneAddress *fro /* No break to also destroy ice session in this case. */ default: if (sal_op_get_ice_session(call->op) != NULL) { - ice_session_destroy(sal_op_get_ice_session(call->op)); - sal_op_set_ice_session(call->op, NULL); + linphone_call_delete_ice_session(call); } break; } @@ -1466,6 +1464,16 @@ void linphone_call_start_media_streams_for_ice_gathering(LinphoneCall *call){ } } +void linphone_call_delete_ice_session(LinphoneCall *call){ + IceSession *ice_session = sal_op_get_ice_session(call->op); + if (ice_session != NULL) { + ice_session_destroy(ice_session); + sal_op_set_ice_session(call->op, NULL); + if (call->audiostream != NULL) call->audiostream->ice_check_list = NULL; + if (call->videostream != NULL) call->videostream->ice_check_list = NULL; + } +} + static void linphone_call_log_fill_stats(LinphoneCallLog *log, AudioStream *st){ audio_stream_get_local_rtp_stats (st,&log->local_stats); log->quality=audio_stream_get_average_quality_rating(st); @@ -1473,6 +1481,7 @@ static void linphone_call_log_fill_stats(LinphoneCallLog *log, AudioStream *st){ void linphone_call_stop_media_streams(LinphoneCall *call){ if (call->audiostream!=NULL) { + call->audiostream->ice_check_list = NULL; rtp_session_unregister_event_queue(call->audiostream->session,call->audiostream_app_evq); ortp_ev_queue_flush(call->audiostream_app_evq); ortp_ev_queue_destroy(call->audiostream_app_evq); @@ -1497,9 +1506,11 @@ void linphone_call_stop_media_streams(LinphoneCall *call){ #ifdef VIDEO_ENABLED if (call->videostream!=NULL){ + call->videostream->ice_check_list = NULL; rtp_session_unregister_event_queue(call->videostream->session,call->videostream_app_evq); ortp_ev_queue_flush(call->videostream_app_evq); ortp_ev_queue_destroy(call->videostream_app_evq); + call->videostream_app_evq=NULL; video_stream_stop(call->videostream); call->videostream=NULL; } @@ -1737,8 +1748,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse ice_session_eliminate_redundant_candidates(ice_session); ice_session_choose_default_candidates(ice_session); } else { - ice_session_destroy(ice_session); - sal_op_set_ice_session(call->op, NULL); + linphone_call_delete_ice_session(call); } if (call->state==LinphoneCallOutgoingInit) { linphone_core_start_invite(call->core,call,NULL); @@ -1792,8 +1802,7 @@ void linphone_call_background_tasks(LinphoneCall *call, bool_t one_second_elapse ice_session_eliminate_redundant_candidates(ice_session); ice_session_choose_default_candidates(ice_session); } else { - ice_session_destroy(sal_op_get_ice_session(call->op)); - sal_op_set_ice_session(call->op, NULL); + linphone_call_delete_ice_session(call); } if (call->state==LinphoneCallOutgoingInit) { linphone_core_start_invite(call->core,call,NULL); diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 73ef52c3..da573d07 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -1854,8 +1854,7 @@ void linphone_core_iterate(LinphoneCore *lc){ /*start the call even if the OPTIONS reply did not arrive*/ if (sal_op_get_ice_session(call->op) != NULL) { /* ICE candidates gathering has not finished yet, proceed with the call without ICE anyway. */ - ice_session_destroy(sal_op_get_ice_session(call->op)); - sal_op_set_ice_session(call->op, NULL); + linphone_call_delete_ice_session(call); linphone_call_stop_media_streams(call); } linphone_core_start_invite(lc,call,NULL); @@ -2294,8 +2293,7 @@ LinphoneCall * linphone_core_invite_address_with_params(LinphoneCore *lc, const call->start_time=time(NULL); if (linphone_core_gather_ice_candidates(lc,call)<0) { /* Ice candidates gathering failed, proceed with the call anyway. */ - ice_session_destroy(sal_op_get_ice_session(call->op)); - sal_op_set_ice_session(call->op, NULL); + linphone_call_delete_ice_session(call); linphone_call_stop_media_streams(call); } else { if (real_url!=NULL) ms_free(real_url); diff --git a/coreapi/private.h b/coreapi/private.h index 33c6985d..1b826c57 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -247,6 +247,7 @@ void linphone_call_init_media_streams(LinphoneCall *call); void linphone_call_start_media_streams(LinphoneCall *call, bool_t all_inputs_muted, bool_t send_ringbacktone); void linphone_call_start_media_streams_for_ice_gathering(LinphoneCall *call); void linphone_call_stop_media_streams(LinphoneCall *call); +void linphone_call_delete_ice_session(LinphoneCall *call); const char * linphone_core_get_identity(LinphoneCore *lc); const char * linphone_core_get_route(LinphoneCore *lc); -- 2.39.2