From 22e1427eb3b64d0eb9fcb77747425a4fa2b5eca7 Mon Sep 17 00:00:00 2001 From: Simon Morlat Date: Tue, 21 Jan 2014 12:17:00 +0100 Subject: [PATCH] fix automatic resuming of calls after failed failed transfer --- coreapi/bellesip_sal/sal_op_impl.c | 8 ++++++++ coreapi/callbacks.c | 32 +++++++++++++++++++----------- coreapi/linphonecore.c | 10 +++++----- coreapi/misc.c | 8 ++++++++ coreapi/private.h | 2 ++ include/sal/sal.h | 6 ++---- tester/call_tester.c | 6 ++++++ 7 files changed, 51 insertions(+), 21 deletions(-) diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index 51dec9b01..c62f7d441 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -638,3 +638,11 @@ bool_t sal_op_is_ipv6(SalOp *op){ return sal_address_is_ipv6((SalAddress*)contact); } +bool_t sal_op_is_idle(SalOp *op){ + if (op->dialog){ + return !belle_sip_dialog_request_pending(op->dialog); + } + return TRUE; +} + + diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index c2c382114..4f84da609 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -555,6 +555,23 @@ static void call_terminated(SalOp *op, const char *from){ linphone_call_set_state(call, LinphoneCallEnd,"Call ended"); } +static int resume_call_after_failed_transfer(LinphoneCall *call){ + ms_message("!!!!!!!!!!resume_call_after_failed_transfer"); + if (call->was_automatically_paused && call->state==LinphoneCallPausing) + return BELLE_SIP_CONTINUE; /*was still in pausing state*/ + + if (call->was_automatically_paused && call->state==LinphoneCallPaused){ + if (sal_op_is_idle(call->op)){ + linphone_core_resume_call(call->core,call); + }else { + ms_message("!!!!!!!!!!resume_call_after_failed_transfer, salop was busy"); + return BELLE_SIP_CONTINUE; + } + } + linphone_call_unref(call); + return BELLE_SIP_STOP; +} + static void call_failure(SalOp *op, SalError error, SalReason sr, const char *details, int code){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); char *msg486=_("User is busy."); @@ -682,19 +699,10 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de } if (referer){ - /* - * 1- resume call automatically if we had to pause it before to execute the transfer - * 2- notify other party of the transfer faillure - * This must be done at the end because transferer call can't be resumed until transfer-target call is changed to error state. - * This must be done in this order because if the notify transaction will prevent the resume transaction to take place. - * On the contrary, the notify transaction is queued and then executed after the resume completes. - **/ - if (linphone_call_get_state(referer)==LinphoneCallPaused && referer->was_automatically_paused){ - /*resume to the call that send us the refer automatically*/ - linphone_core_resume_call(lc,referer); - referer->was_automatically_paused=FALSE; - } + /*notify referer of the failure*/ linphone_core_notify_refer_state(lc,referer,call); + /*schedule automatic resume of the call. This must be done only after the notifications are completed due to dialog serialization of requests.*/ + linphone_core_queue_task(lc,(belle_sip_source_func_t)resume_call_after_failed_transfer,linphone_call_ref(referer),"Automatic call resuming after failed transfer"); } } diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index f21f9af6e..c7d68e601 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -3594,10 +3594,8 @@ void linphone_core_preempt_sound_resources(LinphoneCore *lc){ * * @ingroup call_control **/ -int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *the_call) -{ +int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *call){ char temp[255]={0}; - LinphoneCall *call = the_call; const char *subject="Call resuming"; if(call->state!=LinphoneCallPaused ){ @@ -3606,18 +3604,20 @@ int linphone_core_resume_call(LinphoneCore *lc, LinphoneCall *the_call) } if (call->params.in_conference==FALSE){ if (linphone_core_sound_resources_locked(lc)){ - ms_warning("Cannot resume call %p because another call is locking the sound resources.",the_call); + ms_warning("Cannot resume call %p because another call is locking the sound resources.",call); return -1; } linphone_core_preempt_sound_resources(lc); ms_message("Resuming call %p",call); } + call->was_automatically_paused=FALSE; + /* Stop playing music immediately. If remote side is a conference it prevents the participants to hear it while the 200OK comes back.*/ if (call->audiostream) audio_stream_play(call->audiostream, NULL); - linphone_call_make_local_media_description(lc,the_call); + linphone_call_make_local_media_description(lc,call); if (call->ice_session != NULL) { linphone_core_update_local_media_description_from_ice(call->localdesc, call->ice_session); } diff --git a/coreapi/misc.c b/coreapi/misc.c index e1d17e8be..5273ac35b 100644 --- a/coreapi/misc.c +++ b/coreapi/misc.c @@ -1321,5 +1321,13 @@ const char *linphone_core_get_video_display_filter(LinphoneCore *lc){ return lp_config_get_string(lc->config,"video","displaytype",NULL); } +/** + * Queue a task into the main loop. The data pointer must remain valid until the task is completed. + * task_fun must return BELLE_SIP_STOP when job is finished. +**/ +void linphone_core_queue_task(LinphoneCore *lc, belle_sip_source_func_t task_fun, void *data, const char *task_description){ + belle_sip_source_t *s=sal_create_timer(lc->sal,task_fun,data, 20, task_description); + belle_sip_object_unref(s); +} diff --git a/coreapi/private.h b/coreapi/private.h index 297535c34..37546cd7b 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -382,6 +382,8 @@ bool_t linphone_core_rtcp_enabled(const LinphoneCore *lc); LinphoneCall * is_a_linphone_call(void *user_pointer); LinphoneProxyConfig * is_a_linphone_proxy_config(void *user_pointer); +void linphone_core_queue_task(LinphoneCore *lc, belle_sip_source_func_t task_fun, void *data, const char *task_description); + static const int linphone_proxy_config_magic=0x7979; /*chat*/ diff --git a/include/sal/sal.h b/include/sal/sal.h index 7e2ac70b9..ddf94a4e2 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -539,12 +539,8 @@ const char *sal_op_get_from(const SalOp *op); const SalAddress *sal_op_get_from_address(const SalOp *op); const char *sal_op_get_to(const SalOp *op); const SalAddress *sal_op_get_to_address(const SalOp *op); -#ifndef USE_BELLESIP -const char *sal_op_get_contact(const SalOp *op); -#else const SalAddress *sal_op_get_contact_address(const SalOp *op); #define sal_op_get_contact sal_op_get_contact_address /*for liblinphone compatibility*/ -#endif const char *sal_op_get_route(const SalOp *op); const MSList* sal_op_get_route_addresses(const SalOp *op); const char *sal_op_get_proxy(const SalOp *op); @@ -562,6 +558,8 @@ void sal_op_set_service_route(SalOp *op,const SalAddress* service_route); void sal_op_set_manual_refresher_mode(SalOp *op, bool_t enabled); bool_t sal_op_is_ipv6(SalOp *op); +/*returns TRUE if there is no pending request that may block a future one */ +bool_t sal_op_is_idle(SalOp *op); /*Call API*/ int sal_call_set_local_media_description(SalOp *h, SalMediaDescription *desc); diff --git a/tester/call_tester.c b/tester/call_tester.c index d8e94b5f3..05a394423 100644 --- a/tester/call_tester.c +++ b/tester/call_tester.c @@ -1257,6 +1257,12 @@ static void unattended_call_transfer_with_error(void) { /*the error must be reported back to marie*/ CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneTransferCallError,1,2000)); + /*and pauline should resume the call automatically*/ + CU_ASSERT_TRUE(wait_for_list(lcs,&pauline->stat.number_of_LinphoneCallResuming,1,2000)); + + /*and call should be resumed*/ + CU_ASSERT_TRUE(wait_for_list(lcs,&marie->stat.number_of_LinphoneCallStreamsRunning,1,2000)); + linphone_core_manager_destroy(marie); linphone_core_manager_destroy(pauline); ms_list_free(lcs);