From 0009e277d7ca906e3d3190ba5e1af3253560aab5 Mon Sep 17 00:00:00 2001 From: Sandrine Avakian Date: Mon, 20 Mar 2017 14:14:43 +0100 Subject: [PATCH 01/16] Added linphone_call_set_params to modify SDP header and attributes. Added linphone_call_get_params to get local call params used. Added tests . --- coreapi/callbacks.c | 2 +- coreapi/linphonecall.c | 26 +++- coreapi/private.h | 4 +- tester/call_single_tester.c | 256 ++++++++++++++++++++++++++++++++++++ 4 files changed, 281 insertions(+), 7 deletions(-) diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index ea1f69d7b..59e5d390a 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -748,7 +748,7 @@ static void call_updating(SalOp *op, bool_t is_update){ if (rmd == NULL && lp_config_get_int(call->core->config,"sip","sdp_200_ack_follow_video_policy",0)) { LinphoneCallParams *p=linphone_core_create_call_params(lc, NULL); ms_message("Applying default policy for offering SDP on call [%p]",call); - linphone_call_set_new_params(call, p); + _linphone_call_set_new_params(call, p); linphone_call_params_unref(p); } linphone_call_make_local_media_description(call); diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 916d03856..463163fc2 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -4742,13 +4742,29 @@ LinphonePlayer *linphone_call_get_player(LinphoneCall *call){ return call->player; } -void linphone_call_set_new_params(LinphoneCall *call, const LinphoneCallParams *params){ + +void linphone_call_set_params(LinphoneCall *call, const LinphoneCallParams *params){ + if ( call->state == LinphoneCallOutgoingInit || call->state == LinphoneCallIncomingReceived){ + _linphone_call_set_new_params(call, params); + } + else { + ms_error("linphone_call_set_params() invalid state %s to call this function", linphone_call_state_to_string(call->state)); + } +} + + +void _linphone_call_set_new_params(LinphoneCall *call, const LinphoneCallParams *params){ LinphoneCallParams *cp=NULL; if (params) cp=linphone_call_params_copy(params); if (call->params) linphone_call_params_unref(call->params); call->params=cp; } +const LinphoneCallParams * linphone_call_get_params(LinphoneCall *call){ + return call->params; +} + + static int send_dtmf_handler(void *data, unsigned int revents){ LinphoneCall *call = (LinphoneCall*)data; /*By default we send DTMF RFC2833 if we do not have enabled SIP_INFO but we can also send RFC2833 and SIP_INFO*/ @@ -5174,7 +5190,7 @@ int linphone_call_accept_with_params(LinphoneCall *call, const LinphoneCallParam /* Try to be best-effort in giving real local or routable contact address */ linphone_call_set_contact_op(call); if (params) { - linphone_call_set_new_params(call, params); + _linphone_call_set_new_params(call, params); linphone_call_prepare_ice(call, TRUE); linphone_call_make_local_media_description(call); sal_call_set_local_media_description(call->op, call->localdesc); @@ -5230,7 +5246,7 @@ int linphone_call_accept_early_media_with_params(LinphoneCall *call, const Linph /* If parameters are passed, update the media description */ if (params) { - linphone_call_set_new_params(call, params); + _linphone_call_set_new_params(call, params); linphone_call_make_local_media_description(call); sal_call_set_local_media_description(call->op, call->localdesc); sal_op_set_sent_custom_header(call->op, params->custom_headers); @@ -5303,7 +5319,7 @@ int linphone_call_update(LinphoneCall *call, const LinphoneCallParams *params) { } } #endif /* defined(VIDEO_ENABLED) && defined(BUILD_UPNP) */ - linphone_call_set_new_params(call, params); + _linphone_call_set_new_params(call, params); err = linphone_call_prepare_ice(call, FALSE); if (err == 1) { ms_message("Defer call update to gather ICE candidates"); @@ -5451,7 +5467,7 @@ int _linphone_call_accept_update(LinphoneCall *call, const LinphoneCallParams *p linphone_call_params_enable_video_multicast(call->params, FALSE); } } else { - linphone_call_set_new_params(call, params); + _linphone_call_set_new_params(call, params); } if (call->params->has_video && !linphone_core_video_enabled(lc)) { diff --git a/coreapi/private.h b/coreapi/private.h index 9a06306cf..ee49296f8 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -378,7 +378,9 @@ BELLE_SIP_DECLARE_VPTR_NO_EXPORT(LinphoneCall); LinphoneCall * linphone_call_new_outgoing(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, const LinphoneCallParams *params, LinphoneProxyConfig *cfg); LinphoneCall * linphone_call_new_incoming(struct _LinphoneCore *lc, LinphoneAddress *from, LinphoneAddress *to, SalOp *op); -void linphone_call_set_new_params(LinphoneCall *call, const LinphoneCallParams *params); +void _linphone_call_set_new_params(LinphoneCall *call, const LinphoneCallParams *params); +void linphone_call_set_params(LinphoneCall *call, const LinphoneCallParams *params); +const LinphoneCallParams * linphone_call_get_params(LinphoneCall *call); void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const char *message); void linphone_call_set_contact_op(LinphoneCall* call); void linphone_call_set_compatible_incoming_call_parameters(LinphoneCall *call, SalMediaDescription *md); diff --git a/tester/call_single_tester.c b/tester/call_single_tester.c index 71f2f8191..54bd80b23 100644 --- a/tester/call_single_tester.c +++ b/tester/call_single_tester.c @@ -1523,6 +1523,260 @@ static void call_with_custom_sdp_attributes(void) { linphone_core_manager_destroy(pauline); } + + + +static void call_with_custom_header_or_sdp_cb(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *message) { + + + const char *value; + if (cstate == LinphoneCallOutgoingInit){ + LinphoneCallParams *params = linphone_call_params_copy(linphone_call_get_params(call)); + linphone_call_params_add_custom_sdp_attribute(params, "working", "maybe"); + linphone_call_set_params(call, params); + linphone_call_params_unref(params); + + } + + else if (cstate == LinphoneCallIncomingReceived){ + const LinphoneCallParams *tparams = linphone_call_get_remote_params(call); + LinphoneCallParams *params = linphone_call_params_copy(tparams); + //Check received params + //SDP + value = linphone_call_params_get_custom_sdp_attribute(params, "working"); + BC_ASSERT_PTR_NOT_NULL(value); + if (value) BC_ASSERT_STRING_EQUAL(value, "maybe"); + //header + value = linphone_call_params_get_custom_header(params, "weather"); + BC_ASSERT_PTR_NOT_NULL(value); + if (value) BC_ASSERT_STRING_EQUAL(value, "thunderstorm"); + //modify SDP + linphone_call_params_add_custom_sdp_attribute(params, "working", "yes"); + linphone_call_set_params(call, params); + linphone_call_params_unref(params); + + } + + + +} + +static void call_caller_with_custom_header_or_sdp_attributes(void) { + LinphoneCoreManager *callee_mgr = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *caller_mgr = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + LinphoneCall *call_caller = NULL, *call_callee = NULL; + LinphoneCallParams *caller_params; // *callee_params ; + + LinphoneCoreVTable *vtable; + + LinphoneCallTestParams caller_test_params = {0}; + LinphoneCallTestParams callee_test_params = {0}; + + stats initial_caller=caller_mgr->stat; + stats initial_callee=callee_mgr->stat; + bool_t result=FALSE; + bool_t did_receive_call; + + //Create caller params with custom header and custom SDP + caller_params = linphone_core_create_call_params(caller_mgr->lc, NULL); + linphone_call_params_add_custom_header(caller_params, "weather", "thunderstorm"); + linphone_call_params_add_custom_sdp_media_attribute(caller_params, LinphoneStreamTypeAudio, "sleeping", "almost"); + + caller_test_params.base = (LinphoneCallParams*)caller_params; + callee_test_params.base = NULL; + + /* TODO: This should be handled correctly inside the liblinphone library but meanwhile handle this here. */ + linphone_core_manager_wait_for_stun_resolution(caller_mgr); + linphone_core_manager_wait_for_stun_resolution(callee_mgr); + + setup_sdp_handling(&caller_test_params, caller_mgr); + setup_sdp_handling(&callee_test_params, callee_mgr); + + // Assign dedicated callback to vtable for caller and callee + vtable = linphone_core_v_table_new(); + vtable->call_state_changed = call_with_custom_header_or_sdp_cb; + linphone_core_add_listener(callee_mgr->lc, vtable); + linphone_core_add_listener(caller_mgr->lc, vtable); + + //Caller initates the call with INVITE + // caller params not null + BC_ASSERT_PTR_NOT_NULL((call_caller=linphone_core_invite_address_with_params(caller_mgr->lc,callee_mgr->identity,caller_params))); + + BC_ASSERT_PTR_NULL(linphone_call_get_remote_params(call_caller)); /*assert that remote params are NULL when no response is received yet*/ + + // Wait for Incoming received + did_receive_call = wait_for(callee_mgr->lc + ,caller_mgr->lc + ,&callee_mgr->stat.number_of_LinphoneCallIncomingReceived + ,initial_callee.number_of_LinphoneCallIncomingReceived+1); + BC_ASSERT_EQUAL(did_receive_call, !callee_test_params.sdp_simulate_error, int, "%d"); + + linphone_call_params_unref(caller_params); + + sal_default_set_sdp_handling(caller_mgr->lc->sal, SalOpSDPNormal); + sal_default_set_sdp_handling(callee_mgr->lc->sal, SalOpSDPNormal); + + // Wait for Outgoing Progress + if (linphone_core_get_calls_nb(callee_mgr->lc)<=1) + BC_ASSERT_TRUE(linphone_core_inc_invite_pending(callee_mgr->lc)); + BC_ASSERT_EQUAL(caller_mgr->stat.number_of_LinphoneCallOutgoingProgress,initial_caller.number_of_LinphoneCallOutgoingProgress+1, int, "%d"); + + + + + LinphoneCallParams *default_params=linphone_core_create_call_params(callee_mgr->lc,call_callee); + ms_message("Created default call params with video=%i", linphone_call_params_video_enabled(default_params)); + linphone_core_accept_call_with_params(callee_mgr->lc,call_callee,default_params); + linphone_call_params_unref(default_params); + + + BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallConnected,initial_callee.number_of_LinphoneCallConnected+1)); + BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallConnected,initial_caller.number_of_LinphoneCallConnected+1)); + + result = wait_for_until(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_caller.number_of_LinphoneCallStreamsRunning+1, 2000) + && + wait_for_until(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_callee.number_of_LinphoneCallStreamsRunning+1, 2000); + + + + caller_params = linphone_core_create_call_params(caller_mgr->lc, call_caller); + linphone_call_params_clear_custom_sdp_attributes(caller_params); + linphone_call_params_clear_custom_sdp_media_attributes(caller_params, LinphoneStreamTypeAudio); + linphone_call_params_add_custom_sdp_attribute(caller_params, "weather", "sunny"); + linphone_core_update_call(caller_mgr->lc, call_caller, caller_params); + linphone_call_params_unref(caller_params); + + + end_call(caller_mgr, callee_mgr); + + linphone_core_manager_destroy(callee_mgr); + linphone_core_manager_destroy(caller_mgr); +} + + + + +static void call_callee_with_custom_header_or_sdp_cb(LinphoneCore *lc, LinphoneCall *call, LinphoneCallState cstate, const char *message) { + + + const char *value; + if (cstate == LinphoneCallOutgoingInit){ + LinphoneCallParams *params = linphone_call_params_copy(linphone_call_get_params(call)); + linphone_call_params_add_custom_sdp_attribute(params, "working", "maybe"); + linphone_call_set_params(call, params); + linphone_call_params_unref(params); + + } + + else if (cstate == LinphoneCallIncomingReceived){ + const LinphoneCallParams *tparams = linphone_call_get_remote_params(call); + LinphoneCallParams *params = linphone_call_params_copy(tparams); + value = linphone_call_params_get_custom_sdp_attribute(params, "working"); + BC_ASSERT_PTR_NOT_NULL(value); + if (value) BC_ASSERT_STRING_EQUAL(value, "maybe"); + linphone_call_set_params(call, params); + linphone_call_params_unref(params); + + } + +} + + +static void call_callee_with_custom_header_or_sdp_attributes(void) { + LinphoneCoreManager *callee_mgr = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *caller_mgr = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + LinphoneCall *call_caller = NULL, *call_callee = NULL; + LinphoneCallParams *callee_params, *caller_params ; + + LinphoneCoreVTable *vtable; + const char *value; + LinphoneCallTestParams caller_test_params = {0}; + LinphoneCallTestParams callee_test_params = {0}; + + stats initial_caller=caller_mgr->stat; + stats initial_callee=callee_mgr->stat; + bool_t result=FALSE; + bool_t did_receive_call; + const LinphoneCallParams *caller_remote_params; + + caller_params = linphone_core_create_call_params(caller_mgr->lc, NULL); + + + callee_test_params.base = NULL; + caller_test_params.base = NULL; + + /* TODO: This should be handled correctly inside the liblinphone library but meanwhile handle this here. */ + linphone_core_manager_wait_for_stun_resolution(caller_mgr); + linphone_core_manager_wait_for_stun_resolution(callee_mgr); + + setup_sdp_handling(&caller_test_params, caller_mgr); + setup_sdp_handling(&callee_test_params, callee_mgr); + + // Assign dedicated callback to vtable for caller and callee + vtable = linphone_core_v_table_new(); + vtable->call_state_changed = call_callee_with_custom_header_or_sdp_cb; + linphone_core_add_listener(callee_mgr->lc, vtable); + linphone_core_add_listener(caller_mgr->lc, vtable); + + //Caller initates the call with INVITE + // caller params not null + BC_ASSERT_PTR_NOT_NULL((call_caller=linphone_core_invite_address_with_params(caller_mgr->lc,callee_mgr->identity,caller_params))); + + BC_ASSERT_PTR_NULL(linphone_call_get_remote_params(call_caller)); /*assert that remote params are NULL when no response is received yet*/ + + // Wait for Incoming received + did_receive_call = wait_for(callee_mgr->lc + ,caller_mgr->lc + ,&callee_mgr->stat.number_of_LinphoneCallIncomingReceived + ,initial_callee.number_of_LinphoneCallIncomingReceived+1); + BC_ASSERT_EQUAL(did_receive_call, !callee_test_params.sdp_simulate_error, int, "%d"); + + + + sal_default_set_sdp_handling(caller_mgr->lc->sal, SalOpSDPNormal); + sal_default_set_sdp_handling(callee_mgr->lc->sal, SalOpSDPNormal); + + // Wait for Outgoing Progress + if (linphone_core_get_calls_nb(callee_mgr->lc)<=1) + BC_ASSERT_TRUE(linphone_core_inc_invite_pending(callee_mgr->lc)); + BC_ASSERT_EQUAL(caller_mgr->stat.number_of_LinphoneCallOutgoingProgress,initial_caller.number_of_LinphoneCallOutgoingProgress+1, int, "%d"); + + + //Create callee params with custom header and custom SDP + + + callee_params = linphone_core_create_call_params(callee_mgr->lc,call_callee); + linphone_call_params_add_custom_header(callee_params, "weather", "thunderstorm"); + linphone_call_params_add_custom_sdp_media_attribute(callee_params, LinphoneStreamTypeAudio, "sleeping", "almost"); + linphone_call_params_add_custom_sdp_attribute(callee_params, "working", "yes"); + ms_message("Created default call params with video=%i", linphone_call_params_video_enabled(callee_params)); + linphone_core_accept_call_with_params(callee_mgr->lc,call_callee,callee_params); + linphone_call_params_unref(callee_params); + + + BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallConnected,initial_callee.number_of_LinphoneCallConnected+1)); + BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallConnected,initial_caller.number_of_LinphoneCallConnected+1)); + + result = wait_for_until(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_caller.number_of_LinphoneCallStreamsRunning+1, 2000) + && + wait_for_until(callee_mgr->lc,caller_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallStreamsRunning,initial_callee.number_of_LinphoneCallStreamsRunning+1, 2000); + + caller_remote_params = linphone_call_get_remote_params(call_caller); + value = linphone_call_params_get_custom_sdp_attribute(caller_remote_params, "working"); + BC_ASSERT_PTR_NOT_NULL(value); + if (value) BC_ASSERT_STRING_EQUAL(value, "yes"); + //header + value = linphone_call_params_get_custom_header(caller_remote_params, "weather"); + BC_ASSERT_PTR_NOT_NULL(value); + if (value) BC_ASSERT_STRING_EQUAL(value, "thunderstorm"); + + linphone_call_params_unref(caller_params); + end_call(caller_mgr, callee_mgr); + + linphone_core_manager_destroy(callee_mgr); + linphone_core_manager_destroy(caller_mgr); +} + void call_paused_resumed_base(bool_t multicast, bool_t with_losses) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); @@ -5493,6 +5747,8 @@ test_t call_tests[] = { 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 caller with custom header or sdp", call_caller_with_custom_header_or_sdp_attributes), + TEST_NO_TAG("Call callee with custom header or sdp", call_callee_with_custom_header_or_sdp_attributes), TEST_NO_TAG("Call established with rejected INFO", call_established_with_rejected_info), TEST_NO_TAG("Call established with rejected RE-INVITE", call_established_with_rejected_reinvite), TEST_NO_TAG("Call established with rejected incoming RE-INVITE", call_established_with_rejected_incoming_reinvite), From 931a13df6c53a8a2cbc1f6cccdeb2510a38bc375 Mon Sep 17 00:00:00 2001 From: Sandrine Avakian Date: Thu, 23 Mar 2017 11:26:44 +0100 Subject: [PATCH 02/16] Modifying linphone_core_notify_notify_presence_received and linphone_core_notify_notify_presence_received_for_uri_or_tel to be public. Declaring them into core.h . --- coreapi/private.h | 2 -- include/linphone/core.h | 22 ++++++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/coreapi/private.h b/coreapi/private.h index ee49296f8..f4550b6f9 100644 --- a/coreapi/private.h +++ b/coreapi/private.h @@ -1625,8 +1625,6 @@ void linphone_core_notify_display_status(LinphoneCore *lc, const char *message); void linphone_core_notify_display_message(LinphoneCore *lc, const char *message); void linphone_core_notify_display_warning(LinphoneCore *lc, const char *message); void linphone_core_notify_display_url(LinphoneCore *lc, const char *message, const char *url); -void linphone_core_notify_notify_presence_received(LinphoneCore *lc, LinphoneFriend * lf); -void linphone_core_notify_notify_presence_received_for_uri_or_tel(LinphoneCore *lc, LinphoneFriend *lf, const char *uri_or_tel, const LinphonePresenceModel *presence_model); void linphone_core_notify_new_subscription_requested(LinphoneCore *lc, LinphoneFriend *lf, const char *url); void linphone_core_notify_auth_info_requested(LinphoneCore *lc, const char *realm, const char *username, const char *domain); void linphone_core_notify_authentication_requested(LinphoneCore *lc, LinphoneAuthInfo *auth_info, LinphoneAuthMethod method); diff --git a/include/linphone/core.h b/include/linphone/core.h index 568a17672..31dea093e 100644 --- a/include/linphone/core.h +++ b/include/linphone/core.h @@ -5008,6 +5008,28 @@ LINPHONE_PUBLIC LinphonePresencePerson * linphone_core_create_presence_person(Li * @return The created #LinphonePresenceService object. */ LINPHONE_PUBLIC LinphonePresenceService * linphone_core_create_presence_service(LinphoneCore *lc, const char *id, LinphonePresenceBasicStatus basic_status, const char *contact); + + +/** + * Notifies the upper layer that a presence status has been received by calling the appropriate + * callback if one has been set. + * @param[in] lc the #LinphoneCore object. + * @param[in] lf the #LinphoneFriend whose presence information has been received. + */ +LINPHONE_PUBLIC void linphone_core_notify_notify_presence_received(LinphoneCore *lc, LinphoneFriend *lf); + + +/** + * Notifies the upper layer that a presence model change has been received for the uri or + * telephone number given as a parameter, by calling the appropriate callback if one has been set. + * @param[in] lc the #LinphoneCore object. + * @param[in] lf the #LinphoneFriend whose presence information has been received. + * @param[in] uri_or_tel telephone number or sip uri + * @param[in] presence_model the #LinphonePresenceModel that has been modified + */ +LINPHONE_PUBLIC void linphone_core_notify_notify_presence_received_for_uri_or_tel(LinphoneCore *lc, LinphoneFriend *lf, const char *uri_or_tel, const LinphonePresenceModel *presence_model); + + /** * @} From 836329e64ead2b29cccab8253fa26fede91da9b1 Mon Sep 17 00:00:00 2001 From: Sandrine Avakian Date: Thu, 23 Mar 2017 11:39:57 +0100 Subject: [PATCH 03/16] Update ortp and mediastreamer2 --- mediastreamer2 | 2 +- oRTP | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mediastreamer2 b/mediastreamer2 index cd3e093c3..1f17b3ba2 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit cd3e093c3282e99496b0eb5387a545e119e868f3 +Subproject commit 1f17b3ba22cb662c1c15655c8248036e7a69baf2 diff --git a/oRTP b/oRTP index 920817911..235e5175b 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit 920817911d9287250d9ddf506aede06744faae4b +Subproject commit 235e5175b2befa2d3e5f19cd969b0f3bda5b9b4c From ad337fffefbc372b1098735b1802f3d767fa0a41 Mon Sep 17 00:00:00 2001 From: Sandrine Avakian Date: Mon, 27 Mar 2017 15:27:42 +0200 Subject: [PATCH 04/16] Adding new API int linphone_call_terminate_with_error_info(LinphoneCall *call, const LinphoneErrorInfo *ei) and other functions to handle RFC3326 reason header. --- coreapi/bellesip_sal/sal_op_call.c | 20 +++++++++-- coreapi/bellesip_sal/sal_op_impl.c | 5 ++- coreapi/callbacks.c | 2 +- coreapi/error_info.c | 14 ++++++-- coreapi/factory.c | 6 ++++ coreapi/linphonecall.c | 42 +++++++++++++++++++++-- coreapi/linphonecore.c | 2 +- include/linphone/call.h | 9 ++++- include/linphone/error_info.h | 21 ++++++++++-- include/linphone/factory.h | 5 +++ include/sal/sal.h | 1 + tester/call_single_tester.c | 53 +++++++++++++++++++++++++++++- 12 files changed, 166 insertions(+), 14 deletions(-) diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index 6b4bc13d6..825c01642 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -1039,7 +1039,8 @@ int sal_call_send_dtmf(SalOp *h, char dtmf){ return 0; } -int sal_call_terminate(SalOp *op){ + +int sal_call_terminate_with_error(SalOp *op, const SalErrorInfo *info){ belle_sip_dialog_state_t dialog_state=op->dialog?belle_sip_dialog_get_state(op->dialog):BELLE_SIP_DIALOG_NULL; if (op->state==SalOpStateTerminating || op->state==SalOpStateTerminated) { ms_error("Cannot terminate op [%p] in state [%s]",op,sal_op_state_to_string(op->state)); @@ -1047,10 +1048,19 @@ int sal_call_terminate(SalOp *op){ } switch(dialog_state) { case BELLE_SIP_DIALOG_CONFIRMED: { - sal_op_send_request(op,belle_sip_dialog_create_request(op->dialog,"BYE")); + belle_sip_request_t * req = belle_sip_dialog_create_request(op->dialog,"BYE"); + if (info != NULL){ + belle_sip_header_reason_t* reason = BELLE_SIP_HEADER_REASON(belle_sip_header_reason_new()); + belle_sip_header_reason_set_text(reason, info->status_string); + belle_sip_header_reason_set_protocol(reason,info->protocol); + belle_sip_header_reason_set_cause(reason,info->protocol_code); + belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(reason)); + } + sal_op_send_request(op,req); op->state=SalOpStateTerminating; break; } + case BELLE_SIP_DIALOG_NULL: { if (op->dir == SalOpDirIncoming) { sal_call_decline(op, SalReasonDeclined,NULL); @@ -1085,6 +1095,12 @@ int sal_call_terminate(SalOp *op){ return 0; } + +int sal_call_terminate(SalOp *op){ + return sal_call_terminate_with_error(op, NULL); +} + + bool_t sal_call_autoanswer_asked(SalOp *op){ return op->auto_answer_asked; } diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index d7ddaa959..a8e263d37 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -606,7 +606,7 @@ void sal_error_info_set(SalErrorInfo *ei, SalReason reason, const char *protocol void sal_op_set_reason_error_info(SalOp *op, belle_sip_message_t *msg){ belle_sip_header_reason_t* reason_header = belle_sip_message_get_header_by_type(msg,belle_sip_header_reason_t); if (reason_header){ - SalErrorInfo *ei=&op->reason_error_info; + SalErrorInfo *ei=&op->reason_error_info; // ?// const char *protocol = belle_sip_header_reason_get_protocol(reason_header); int code = belle_sip_header_reason_get_cause(reason_header); const char *text = belle_sip_header_reason_get_text(reason_header); @@ -633,6 +633,9 @@ const SalErrorInfo * sal_op_get_reason_error_info(const SalOp *op){ return &op->reason_error_info; } + + + static void unlink_op_with_dialog(SalOp *op, belle_sip_dialog_t* dialog){ belle_sip_dialog_set_application_data(dialog,NULL); sal_op_unref(op); diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 3ec88f4a8..1d46cd3a0 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -818,7 +818,7 @@ static void call_terminated(SalOp *op, const char *from){ break; case LinphoneCallIncomingReceived: case LinphoneCallIncomingEarlyMedia: - linphone_error_info_set(call->ei, LinphoneReasonNotAnswered, 0, "Incoming call cancelled", NULL); + linphone_error_info_set(call->ei,NULL, LinphoneReasonNotAnswered, 0, "Incoming call cancelled", NULL); call->non_op_error = TRUE; break; default: diff --git a/coreapi/error_info.c b/coreapi/error_info.c index 288b8e793..0311ac497 100644 --- a/coreapi/error_info.c +++ b/coreapi/error_info.c @@ -216,12 +216,20 @@ void linphone_error_info_from_sal_op(LinphoneErrorInfo *ei, const SalOp *op){ } } -void linphone_error_info_set(LinphoneErrorInfo *ei, LinphoneReason reason, int code, const char *status_string, const char *warning){ +void linphone_error_info_set(LinphoneErrorInfo *ei, const char *protocol, LinphoneReason reason, int code, const char *status_string, const char *warning){ linphone_error_info_reset(ei); ei->reason = reason; ei->protocol_code = code; - ei->phrase = ms_strdup_safe(status_string); - ei->warnings = ms_strdup_safe(warning); + if (protocol != NULL){ + ei->protocol = bctbx_strdup(protocol); + } + else{ + const char* prot = "SIP"; + ei->protocol = bctbx_strdup(prot); + } + + ei->phrase = bctbx_strdup(status_string); + ei->warnings = bctbx_strdup(warning); } diff --git a/coreapi/factory.c b/coreapi/factory.c index 867d6be24..1ac43dc9f 100644 --- a/coreapi/factory.c +++ b/coreapi/factory.c @@ -169,3 +169,9 @@ void linphone_factory_set_msplugins_dir(LinphoneFactory *factory, const char *pa if (factory->msplugins_dir) bctbx_free(factory->msplugins_dir); factory->msplugins_dir = bctbx_strdup(path); } + +LinphoneErrorInfo *linphone_factory_create_error_info(void){ + + return linphone_error_info_new(); + +} diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 8e97cd567..750afb677 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -4327,7 +4327,7 @@ static void linphone_call_lost(LinphoneCall *call){ ms_message("LinphoneCall [%p]: %s", call, temp); linphone_core_notify_display_warning(lc, temp); call->non_op_error = TRUE; - linphone_error_info_set(call->ei, LinphoneReasonIOError, 503, "Media lost", NULL); + linphone_error_info_set(call->ei,NULL, LinphoneReasonIOError, 503, "Media lost", NULL); linphone_call_terminate(call); linphone_core_play_named_tone(lc, LinphoneToneCallLost); ms_free(temp); @@ -5088,6 +5088,44 @@ int linphone_call_terminate(LinphoneCall *call) { return 0; } +static void linphone_call_error_info_to_sal_op(const LinphoneErrorInfo* ei, SalErrorInfo* sei){ + + sei->reason = linphone_error_info_get_reason(ei); + sei->status_string = ms_strdup_safe(ei->phrase); + sei->full_string = ms_strdup_safe(ei->full_string); + sei->warnings = ms_strdup_safe(ei->warnings); + sei->protocol_code = ei->protocol_code; + sei->protocol = ms_strdup_safe(ei->protocol); +} + +int linphone_call_terminate_with_error(LinphoneCall *call , const LinphoneErrorInfo *ei){ + SalErrorInfo sei; + linphone_call_error_info_to_sal_op(ei, &sei); + + ms_message("Terminate call [%p] which is currently in state %s", call, linphone_call_state_to_string(call->state)); + switch (call->state) { + case LinphoneCallReleased: + case LinphoneCallEnd: + case LinphoneCallError: + ms_warning("No need to terminate a call [%p] in state [%s]", call, linphone_call_state_to_string(call->state)); + return -1; + case LinphoneCallIncomingReceived: + case LinphoneCallIncomingEarlyMedia: + return linphone_call_decline(call, LinphoneReasonDeclined); + case LinphoneCallOutgoingInit: + /* In state OutgoingInit, op has to be destroyed */ + sal_op_release(call->op); + call->op = NULL; + break; + default: + sal_call_terminate_with_error(call->op, &sei); + break; + } + terminate_call(call); + return 0; + +} + int linphone_call_redirect(LinphoneCall *call, const char *redirect_uri) { char *real_url = NULL; LinphoneCore *lc; @@ -5109,7 +5147,7 @@ int linphone_call_redirect(LinphoneCall *call, const char *redirect_uri) { real_url = linphone_address_as_string(real_parsed_url); sal_call_decline(call->op, SalReasonRedirect, real_url); ms_free(real_url); - linphone_error_info_set(call->ei, LinphoneReasonMovedPermanently, 302, "Call redirected", NULL); + linphone_error_info_set(call->ei, NULL, LinphoneReasonMovedPermanently, 302, "Call redirected", NULL); call->non_op_error = TRUE; terminate_call(call); linphone_address_unref(real_parsed_url); diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index d4c64e416..576d99095 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -2980,7 +2980,7 @@ void linphone_core_iterate(LinphoneCore *lc){ decline_reason = (lc->current_call != call) ? LinphoneReasonBusy : LinphoneReasonDeclined; call->log->status=LinphoneCallMissed; call->non_op_error = TRUE; - linphone_error_info_set(call->ei, decline_reason, linphone_reason_to_error_code(decline_reason), "Not answered", NULL); + linphone_error_info_set(call->ei, NULL, decline_reason, linphone_reason_to_error_code(decline_reason), "Not answered", NULL); linphone_call_decline(call, decline_reason); } } diff --git a/include/linphone/call.h b/include/linphone/call.h index 8d5985274..c1b86fa69 100644 --- a/include/linphone/call.h +++ b/include/linphone/call.h @@ -371,12 +371,19 @@ LINPHONE_PUBLIC int linphone_call_pause(LinphoneCall *call); **/ LINPHONE_PUBLIC int linphone_call_resume(LinphoneCall *call); +/** + * Terminates a call. + * @param[in] call LinphoneCall object + * @return 0 on success, -1 on failure +**/LINPHONE_PUBLIC int linphone_call_terminate(LinphoneCall *call); + + /** * Terminates a call. * @param[in] call LinphoneCall object * @return 0 on success, -1 on failure **/ -LINPHONE_PUBLIC int linphone_call_terminate(LinphoneCall *call); +LINPHONE_PUBLIC int linphone_call_terminate_with_error(LinphoneCall *call, const LinphoneErrorInfo *ei); /** * Redirect the specified call to the given redirect URI. diff --git a/include/linphone/error_info.h b/include/linphone/error_info.h index 22f5e59fa..49980608c 100644 --- a/include/linphone/error_info.h +++ b/include/linphone/error_info.h @@ -69,6 +69,13 @@ LINPHONE_PUBLIC LinphoneReason linphone_error_info_get_reason(const LinphoneErro * @return The error phrase **/ LINPHONE_PUBLIC const char * linphone_error_info_get_phrase(const LinphoneErrorInfo *ei); + +/** + * Get protocol from the error info. + * @param[in] ei ErrorInfo object + * @return The protocol + */ +LINPHONE_PUBLIC const char *linphone_error_info_get_protocol(const LinphoneErrorInfo *ei); /** * Provides additional information regarding the failure. @@ -88,10 +95,20 @@ LINPHONE_PUBLIC int linphone_error_info_get_protocol_code(const LinphoneErrorInf /** * Assign information to a LinphoneErrorInfo object. - * @param[in] ei ErrorInfo object + * @param[in] ei ErrorInfo object + * @param[in] protocol protocol name + * @param[in] reason reason from LinphoneReason enum + * @param[in] code protocol code + * @param[in] status_string description of the reason + * @param[in] warning warning message */ -LINPHONE_PUBLIC void linphone_error_info_set(LinphoneErrorInfo *ei, LinphoneReason reason, int code, const char *status_string, const char *warning); +LINPHONE_PUBLIC void linphone_error_info_set(LinphoneErrorInfo *ei, const char *protocol, LinphoneReason reason, int code, const char *status_string, const char *warning); +/** + * Assign reason LinphoneReason to a LinphoneErrorUnfo object. + * @param[in] ei ErrorInfo object + * @param[in] reason reason from LinphoneReason enum + */ LINPHONE_PUBLIC void linphone_error_info_set_reason(LinphoneErrorInfo *ei, LinphoneReason reason); /** diff --git a/include/linphone/factory.h b/include/linphone/factory.h index c24d9005f..f570278da 100644 --- a/include/linphone/factory.h +++ b/include/linphone/factory.h @@ -203,6 +203,11 @@ LINPHONE_PUBLIC char * linphone_factory_get_msplugins_dir(const LinphoneFactory */ LINPHONE_PUBLIC void linphone_factory_set_msplugins_dir(LinphoneFactory *factory, const char *path); +/** + * Creates an object LinphoneErrorInfo. + * @return LinphoneErrorInfo object. + */ +LINPHONE_PUBLIC LinphoneErrorInfo *linphone_factory_create_error_info(void); /** * @} */ diff --git a/include/sal/sal.h b/include/sal/sal.h index 40ed02341..09df18d47 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -757,6 +757,7 @@ int sal_call_set_referer(SalOp *h, SalOp *refered_call); SalOp *sal_call_get_replaces(SalOp *h); int sal_call_send_dtmf(SalOp *h, char dtmf); int sal_call_terminate(SalOp *h); +int sal_call_terminate_with_error(SalOp *op, const SalErrorInfo *info); bool_t sal_call_autoanswer_asked(SalOp *op); void sal_call_send_vfu_request(SalOp *h); int sal_call_is_offerer(const SalOp *h); diff --git a/tester/call_single_tester.c b/tester/call_single_tester.c index ab29c52c3..315c49742 100644 --- a/tester/call_single_tester.c +++ b/tester/call_single_tester.c @@ -980,6 +980,56 @@ static void simple_call_compatibility_mode(void) { linphone_core_manager_destroy(pauline); } +static void terminate_call_with_error(void) { + LinphoneCoreManager *callee_mgr = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager *caller_mgr = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + + LinphoneCall* out_call = linphone_core_invite_address(caller_mgr->lc,callee_mgr->identity); + LinphoneCall* call_callee ; + + linphone_call_ref(out_call); + LinphoneErrorInfo *ei = linphone_error_info_new(); + linphone_error_info_set(ei, NULL, LinphoneReasonNone, 200, "Call completed elsewhere", NULL); + + BC_ASSERT_TRUE(wait_for(caller_mgr->lc, callee_mgr->lc, &caller_mgr->stat.number_of_LinphoneCallOutgoingInit,1)); + BC_ASSERT_TRUE(wait_for(caller_mgr->lc, callee_mgr->lc, &callee_mgr->stat.number_of_LinphoneCallIncomingReceived, 1)); + BC_ASSERT_TRUE(wait_for(caller_mgr->lc, callee_mgr->lc, &caller_mgr->stat.number_of_LinphoneCallOutgoingProgress, 1)); + + call_callee = linphone_core_get_current_call(callee_mgr->lc); + BC_ASSERT_PTR_NOT_NULL(call_callee); + + BC_ASSERT_EQUAL( linphone_core_accept_call(callee_mgr->lc,call_callee), 0 , int, "%d"); + BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallConnected,1)); + + + + BC_ASSERT_TRUE(wait_for(caller_mgr->lc, callee_mgr->lc, &caller_mgr->stat.number_of_LinphoneCallStreamsRunning, 1)); + + + const LinphoneErrorInfo *rei = ei; + + linphone_call_terminate_with_error(out_call,rei); + BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallEnd,1)); + + BC_ASSERT_PTR_NOT_NULL(rei); + if (rei){ + BC_ASSERT_EQUAL(linphone_error_info_get_protocol_code(rei),200, int, "%d"); + BC_ASSERT_PTR_NOT_NULL(linphone_error_info_get_phrase(rei)); + BC_ASSERT_STRING_EQUAL(linphone_error_info_get_phrase(rei), "Call completed elsewhere"); + BC_ASSERT_STRING_EQUAL(linphone_error_info_get_protocol(ei), "SIP"); + + } + + + BC_ASSERT_EQUAL(caller_mgr->stat.number_of_LinphoneCallEnd,1, int, "%d"); + BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallReleased,1)); + + linphone_error_info_unref(ei); + linphone_call_unref(out_call); + linphone_core_manager_destroy(callee_mgr); + linphone_core_manager_destroy(caller_mgr); +} + static void cancelled_call(void) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); @@ -5825,7 +5875,8 @@ test_t call_tests[] = { TEST_NO_TAG("Call with ZRTP configured receiver side only", call_with_zrtp_configured_callee_side), TEST_NO_TAG("Call from plain RTP to ZRTP mandatory should be silent", call_from_plain_rtp_to_zrtp), TEST_NO_TAG("Call ZRTP mandatory to plain RTP should be silent", call_from_zrtp_to_plain_rtp), - TEST_NO_TAG("Call with network reachable down in callback", call_with_network_reachable_down_in_callback) + TEST_NO_TAG("Call with network reachable down in callback", call_with_network_reachable_down_in_callback), + TEST_NO_TAG("Call terminated with reason", terminate_call_with_error) }; test_suite_t call_test_suite = {"Single Call", NULL, NULL, liblinphone_tester_before_each, liblinphone_tester_after_each, From 5f9ba4ea90c5e8b556c5e51d57cacd092da5fbba Mon Sep 17 00:00:00 2001 From: Sandrine Avakian Date: Mon, 27 Mar 2017 16:05:43 +0200 Subject: [PATCH 05/16] replacing ms_strdup_safe by bctbx_strdup. Adding checks in sal_call_terminate_with_error --- coreapi/linphonecall.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 750afb677..006387f35 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -5091,16 +5091,19 @@ int linphone_call_terminate(LinphoneCall *call) { static void linphone_call_error_info_to_sal_op(const LinphoneErrorInfo* ei, SalErrorInfo* sei){ sei->reason = linphone_error_info_get_reason(ei); - sei->status_string = ms_strdup_safe(ei->phrase); - sei->full_string = ms_strdup_safe(ei->full_string); - sei->warnings = ms_strdup_safe(ei->warnings); + sei->status_string = bctbx_strdup(ei->phrase); + sei->full_string = bctbx_strdup(ei->full_string); + sei->warnings = bctbx_strdup(ei->warnings); sei->protocol_code = ei->protocol_code; - sei->protocol = ms_strdup_safe(ei->protocol); + sei->protocol = bctbx_strdup(ei->protocol); } int linphone_call_terminate_with_error(LinphoneCall *call , const LinphoneErrorInfo *ei){ SalErrorInfo sei; - linphone_call_error_info_to_sal_op(ei, &sei); + if (ei != NULL) + { + linphone_call_error_info_to_sal_op(ei, &sei); + } ms_message("Terminate call [%p] which is currently in state %s", call, linphone_call_state_to_string(call->state)); switch (call->state) { @@ -5118,7 +5121,12 @@ int linphone_call_terminate_with_error(LinphoneCall *call , const LinphoneErrorI call->op = NULL; break; default: - sal_call_terminate_with_error(call->op, &sei); + if (ei == NULL){ + sal_call_terminate(call->op); + } + else{ + sal_call_terminate_with_error(call->op, &sei); + } break; } terminate_call(call); From db0191ec9e97831895677f7704edc966a095c482 Mon Sep 17 00:00:00 2001 From: Sandrine Avakian Date: Thu, 30 Mar 2017 10:47:42 +0200 Subject: [PATCH 06/16] Renaming functions : -linphone_call_error_info_to_sal_op into linphone_error_info_to_sal as there is no LinponeCall object involved here. - linphone_call_terminate_with_error into linphone_call_terminate_with_error_info Fixes in linphone_call_terminate_with_error_info. --- coreapi/linphonecall.c | 14 +++++++------- include/linphone/call.h | 2 +- tester/call_single_tester.c | 11 +++++++---- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 006387f35..6a74909c5 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -5088,7 +5088,7 @@ int linphone_call_terminate(LinphoneCall *call) { return 0; } -static void linphone_call_error_info_to_sal_op(const LinphoneErrorInfo* ei, SalErrorInfo* sei){ +static void linphone_error_info_to_sal(const LinphoneErrorInfo* ei, SalErrorInfo* sei){ sei->reason = linphone_error_info_get_reason(ei); sei->status_string = bctbx_strdup(ei->phrase); @@ -5098,13 +5098,9 @@ static void linphone_call_error_info_to_sal_op(const LinphoneErrorInfo* ei, SalE sei->protocol = bctbx_strdup(ei->protocol); } -int linphone_call_terminate_with_error(LinphoneCall *call , const LinphoneErrorInfo *ei){ +int linphone_call_terminate_with_error_info(LinphoneCall *call , const LinphoneErrorInfo *ei){ SalErrorInfo sei; - if (ei != NULL) - { - linphone_call_error_info_to_sal_op(ei, &sei); - } - + ms_message("Terminate call [%p] which is currently in state %s", call, linphone_call_state_to_string(call->state)); switch (call->state) { case LinphoneCallReleased: @@ -5121,14 +5117,18 @@ int linphone_call_terminate_with_error(LinphoneCall *call , const LinphoneErrorI call->op = NULL; break; default: + if (ei == NULL){ sal_call_terminate(call->op); } else{ + linphone_error_info_to_sal(ei, &sei); sal_call_terminate_with_error(call->op, &sei); + sal_error_info_reset(&sei); } break; } + terminate_call(call); return 0; diff --git a/include/linphone/call.h b/include/linphone/call.h index c1b86fa69..61e48c807 100644 --- a/include/linphone/call.h +++ b/include/linphone/call.h @@ -383,7 +383,7 @@ LINPHONE_PUBLIC int linphone_call_resume(LinphoneCall *call); * @param[in] call LinphoneCall object * @return 0 on success, -1 on failure **/ -LINPHONE_PUBLIC int linphone_call_terminate_with_error(LinphoneCall *call, const LinphoneErrorInfo *ei); +LINPHONE_PUBLIC int linphone_call_terminate_with_error_info(LinphoneCall *call, const LinphoneErrorInfo *ei); /** * Redirect the specified call to the given redirect URI. diff --git a/tester/call_single_tester.c b/tester/call_single_tester.c index 315c49742..9c56c968a 100644 --- a/tester/call_single_tester.c +++ b/tester/call_single_tester.c @@ -981,14 +981,17 @@ static void simple_call_compatibility_mode(void) { } static void terminate_call_with_error(void) { + LinphoneCall* call_callee ; + LinphoneErrorInfo *ei ; + const LinphoneErrorInfo *rei ; LinphoneCoreManager *callee_mgr = linphone_core_manager_new("marie_rc"); LinphoneCoreManager *caller_mgr = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); LinphoneCall* out_call = linphone_core_invite_address(caller_mgr->lc,callee_mgr->identity); - LinphoneCall* call_callee ; + linphone_call_ref(out_call); - LinphoneErrorInfo *ei = linphone_error_info_new(); + ei = linphone_error_info_new(); linphone_error_info_set(ei, NULL, LinphoneReasonNone, 200, "Call completed elsewhere", NULL); BC_ASSERT_TRUE(wait_for(caller_mgr->lc, callee_mgr->lc, &caller_mgr->stat.number_of_LinphoneCallOutgoingInit,1)); @@ -1006,9 +1009,9 @@ static void terminate_call_with_error(void) { BC_ASSERT_TRUE(wait_for(caller_mgr->lc, callee_mgr->lc, &caller_mgr->stat.number_of_LinphoneCallStreamsRunning, 1)); - const LinphoneErrorInfo *rei = ei; + rei = ei; - linphone_call_terminate_with_error(out_call,rei); + linphone_call_terminate_with_error_info(out_call,rei); BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallEnd,1)); BC_ASSERT_PTR_NOT_NULL(rei); From 92c8c0e4da40fb440f4a7f761601e5123969e281 Mon Sep 17 00:00:00 2001 From: Sandrine Avakian Date: Mon, 3 Apr 2017 14:31:53 +0200 Subject: [PATCH 07/16] First commit for decline call with reason header support --- coreapi/bellesip_sal/sal_op_call.c | 56 +++++++++++++++++++++++++++--- coreapi/bellesip_sal/sal_op_impl.c | 24 +++++++++++-- coreapi/callbacks.c | 13 ++++++- coreapi/error_info.c | 7 ++++ coreapi/factory.c | 3 +- coreapi/linphonecall.c | 50 +++++++++++++++++++++++--- include/linphone/call.h | 2 ++ include/linphone/error_info.h | 2 ++ include/linphone/factory.h | 3 +- include/sal/sal.h | 3 ++ tester/call_single_tester.c | 43 +++++++++++++++++++++++ 11 files changed, 193 insertions(+), 13 deletions(-) diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index 825c01642..7b347d503 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -511,6 +511,7 @@ static int process_sdp_for_invite(SalOp* op,belle_sip_request_t* invite) { belle_sdp_session_description_t* sdp; int err=0; SalReason reason; + SalErrorInfo sei; if (extract_sdp(op,BELLE_SIP_MESSAGE(invite),&sdp,&reason)==0) { if (sdp){ @@ -527,6 +528,7 @@ static int process_sdp_for_invite(SalOp* op,belle_sip_request_t* invite) { }else err=-1; if (err==-1){ + sal_error_info_set(&sei, reason,"SIP", 0, NULL, NULL); sal_call_decline(op,reason,NULL); } return err; @@ -942,6 +944,17 @@ int sal_call_accept(SalOp*h){ return 0; } +static belle_sip_header_reason_t *sal_call_make_reason_header( const SalErrorInfo *info){ + if (info != NULL){ + belle_sip_header_reason_t* reason = BELLE_SIP_HEADER_REASON(belle_sip_header_reason_new()); + belle_sip_header_reason_set_text(reason, info->status_string); + belle_sip_header_reason_set_protocol(reason,info->protocol); + belle_sip_header_reason_set_cause(reason,info->protocol_code); + return reason; + } + return NULL; +} + int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*optional*/){ belle_sip_response_t* response; belle_sip_header_contact_t* contact=NULL; @@ -970,6 +983,41 @@ int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*opti return 0; } +int sal_call_decline_with_error_info(SalOp *op, const SalErrorInfo *info, const char *redirection /*optional*/){ + belle_sip_response_t* response; + belle_sip_header_contact_t* contact=NULL; + int status = info->protocol_code; + belle_sip_transaction_t *trans; + + if (info->reason==SalReasonRedirect){ + if (redirection!=NULL) { + if (strstr(redirection,"sip:")!=0) status=302; + else status=380; + contact= belle_sip_header_contact_new(); + belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(contact),belle_sip_uri_parse(redirection)); + } else { + ms_error("Cannot redirect to null"); + } + } + trans=(belle_sip_transaction_t*)op->pending_server_trans; + if (!trans) trans=(belle_sip_transaction_t*)op->pending_update_server_trans; + if (!trans){ + ms_error("sal_call_decline(): no pending transaction to decline."); + return -1; + } + response = sal_op_create_response_from_request(op,belle_sip_transaction_get_request(trans),status); + belle_sip_header_reason_t* reason_header = sal_call_make_reason_header(info->sub_sei); + if (reason_header) { + belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(reason_header)); + } + + if (contact) { + belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact)); + } + belle_sip_server_transaction_send_response(BELLE_SIP_SERVER_TRANSACTION(trans),response); + return 0; +} + int sal_call_update(SalOp *op, const char *subject, bool_t no_user_consent){ belle_sip_request_t *update; belle_sip_dialog_state_t state; @@ -1041,6 +1089,7 @@ int sal_call_send_dtmf(SalOp *h, char dtmf){ int sal_call_terminate_with_error(SalOp *op, const SalErrorInfo *info){ +// SalErrorInfo sei; belle_sip_dialog_state_t dialog_state=op->dialog?belle_sip_dialog_get_state(op->dialog):BELLE_SIP_DIALOG_NULL; if (op->state==SalOpStateTerminating || op->state==SalOpStateTerminated) { ms_error("Cannot terminate op [%p] in state [%s]",op,sal_op_state_to_string(op->state)); @@ -1050,10 +1099,7 @@ int sal_call_terminate_with_error(SalOp *op, const SalErrorInfo *info){ case BELLE_SIP_DIALOG_CONFIRMED: { belle_sip_request_t * req = belle_sip_dialog_create_request(op->dialog,"BYE"); if (info != NULL){ - belle_sip_header_reason_t* reason = BELLE_SIP_HEADER_REASON(belle_sip_header_reason_new()); - belle_sip_header_reason_set_text(reason, info->status_string); - belle_sip_header_reason_set_protocol(reason,info->protocol); - belle_sip_header_reason_set_cause(reason,info->protocol_code); + belle_sip_header_reason_t* reason = sal_call_make_reason_header(info); belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(reason)); } sal_op_send_request(op,req); @@ -1063,6 +1109,7 @@ int sal_call_terminate_with_error(SalOp *op, const SalErrorInfo *info){ case BELLE_SIP_DIALOG_NULL: { if (op->dir == SalOpDirIncoming) { + //sal_error_info_set(&sei, SalReasonDeclined,"SIP", 0, NULL, NULL); sal_call_decline(op, SalReasonDeclined,NULL); op->state=SalOpStateTerminated; } else if (op->pending_client_trans){ @@ -1080,6 +1127,7 @@ int sal_call_terminate_with_error(SalOp *op, const SalErrorInfo *info){ } case BELLE_SIP_DIALOG_EARLY: { if (op->dir == SalOpDirIncoming) { + //sal_error_info_set(&sei, SalReasonDeclined,"SIP", 0, NULL, NULL); sal_call_decline(op, SalReasonDeclined,NULL); op->state=SalOpStateTerminated; } else { diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index a8e263d37..a9c9c8ca1 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -561,11 +561,22 @@ const SalErrorInfo *sal_error_info_none(void){ "Ok", 200, NULL, - NULL + NULL, + }; return &none; } +void sal_error_info_init_to_null(SalErrorInfo *sei){ + sei->status_string = NULL; + sei->full_string = NULL; + sei->protocol = NULL; + sei->sub_sei = NULL; + sei->warnings = NULL; + sei->protocol_code=0; + sei->reason=SalReasonNone; +} + void sal_error_info_reset(SalErrorInfo *ei){ if (ei->status_string){ ms_free(ei->status_string); @@ -584,6 +595,10 @@ void sal_error_info_reset(SalErrorInfo *ei){ ms_free(ei->protocol); ei->protocol = NULL; } + if (ei->sub_sei){ + ms_free(ei->sub_sei); + ei->sub_sei = NULL; + } ei->protocol_code=0; ei->reason=SalReasonNone; } @@ -591,7 +606,12 @@ void sal_error_info_reset(SalErrorInfo *ei){ void sal_error_info_set(SalErrorInfo *ei, SalReason reason, const char *protocol, int code, const char *status_string, const char *warning){ sal_error_info_reset(ei); if (reason==SalReasonUnknown && strcmp(protocol, "SIP") == 0) ei->reason=_sal_reason_from_sip_code(code); - else ei->reason=reason; + else{ + ei->reason=reason; + if (code == 0) { + code = sal_reason_to_sip_code(reason); + } + } ei->protocol_code=code; ei->status_string=status_string ? ms_strdup(status_string) : NULL; ei->warnings=warning ? ms_strdup(warning) : NULL; diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 1d46cd3a0..81618bab6 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -269,6 +269,7 @@ static void call_received(SalOp *h){ LinphoneAddress *from_address_to_search_if_me=NULL; /*address used to know if I'm the caller*/ SalMediaDescription *md; const char * p_asserted_id; + SalErrorInfo sei; /* Look if this INVITE is for a call that has already been notified but broken because of network failure */ replaced_call = look_for_broken_call_to_replace(h, lc); @@ -284,6 +285,8 @@ static void call_received(SalOp *h){ case LinphonePresenceActivityPermanentAbsence: alt_contact = linphone_presence_model_get_contact(lc->presence_model); if (alt_contact != NULL) { + sal_error_info_set(&sei,SalReasonRedirect, "SIP", 0, NULL, NULL); + sal_call_decline_with_error_info(h, SalReasonRedirect,alt_contact); sal_call_decline(h,SalReasonRedirect,alt_contact); ms_free(alt_contact); sal_op_release(h); @@ -297,6 +300,7 @@ static void call_received(SalOp *h){ } if (!linphone_core_can_we_add_call(lc)){/*busy*/ + sal_error_info_set(&sei,SalReasonBusy, "SIP", 0, NULL, NULL); sal_call_decline(h,SalReasonBusy,NULL); sal_op_release(h); return; @@ -333,6 +337,7 @@ static void call_received(SalOp *h){ if (from_address_to_search_if_me && already_a_call_with_remote_address(lc,from_address_to_search_if_me)){ char *addr = linphone_address_as_string(from_addr); ms_warning("Receiving a call while one with same address [%s] is initiated, refusing this one with busy message.",addr); + sal_error_info_set(&sei,SalReasonBusy, "SIP", 0, NULL, NULL); sal_call_decline(h,SalReasonBusy,NULL); sal_op_release(h); linphone_address_unref(from_addr); @@ -351,6 +356,7 @@ static void call_received(SalOp *h){ md=sal_call_get_final_media_description(call->op); if (md){ if (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md)){ + sal_error_info_set(&sei,SalReasonNotAcceptable, "SIP", 0, NULL, NULL); sal_call_decline(call->op,SalReasonNotAcceptable,NULL); linphone_call_unref(call); return; @@ -678,6 +684,7 @@ static void call_updated_by_remote(LinphoneCore *lc, LinphoneCall *call){ /* this callback is called when an incoming re-INVITE/ SIP UPDATE modifies the session*/ static void call_updated(LinphoneCore *lc, LinphoneCall *call, SalOp *op, bool_t is_update){ + SalErrorInfo sei; SalMediaDescription *rmd=sal_call_get_remote_media_description(op); call->defer_update = lp_config_get_int(lc->config, "sip", "defer_update_default", FALSE); @@ -715,6 +722,7 @@ static void call_updated(LinphoneCore *lc, LinphoneCall *call, SalOp *op, bool_t case LinphoneCallUpdating: case LinphoneCallPausing: case LinphoneCallResuming: + sal_error_info_set(&sei,SalReasonInternalError, "SIP", 0, NULL, NULL); sal_call_decline(call->op,SalReasonInternalError,NULL); /*no break*/ case LinphoneCallIdle: @@ -737,7 +745,8 @@ static void call_updating(SalOp *op, bool_t is_update){ LinphoneCore *lc=(LinphoneCore *)sal_get_user_pointer(sal_op_get_sal(op)); LinphoneCall *call=(LinphoneCall*)sal_op_get_user_pointer(op); SalMediaDescription *rmd=sal_call_get_remote_media_description(op); - + SalErrorInfo sei; + if (!call) { ms_error("call_updating(): call doesn't exist anymore"); return ; @@ -767,6 +776,7 @@ static void call_updating(SalOp *op, bool_t is_update){ md=sal_call_get_final_media_description(call->op); if (md && (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md))){ + sal_error_info_set(&sei,SalReasonNotAcceptable, "SIP", 0, NULL, NULL); sal_call_decline(call->op,SalReasonNotAcceptable,NULL); return; } @@ -774,6 +784,7 @@ static void call_updating(SalOp *op, bool_t is_update){ int diff=sal_media_description_equals(prev_result_desc,md); if (diff & (SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED|SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED)){ ms_warning("Cannot accept this update, it is changing parameters that require user approval"); + sal_error_info_set(&sei,SalReasonNotAcceptable, "SIP", 0, NULL, NULL); sal_call_decline(call->op,SalReasonNotAcceptable,NULL); /*FIXME should send 504 Cannot change the session parameters without prompting the user"*/ return; } diff --git a/coreapi/error_info.c b/coreapi/error_info.c index 832a8361d..8f9e9cbb4 100644 --- a/coreapi/error_info.c +++ b/coreapi/error_info.c @@ -31,6 +31,7 @@ static void error_info_destroy(LinphoneErrorInfo *ei){ } static void error_info_clone(LinphoneErrorInfo *ei, const LinphoneErrorInfo *other){ + linphone_error_info_set_reason(ei, linphone_error_info_get_reason(other)); ei->protocol = bctbx_strdup(other->protocol); ei->phrase = bctbx_strdup(other->phrase); ei->warnings = bctbx_strdup(other->warnings); @@ -213,6 +214,12 @@ void linphone_error_info_from_sal_op(LinphoneErrorInfo *ei, const SalOp *op){ } } +void linphone_error_info_set_sub_error_info(LinphoneErrorInfo *ei, LinphoneErrorInfo *appended_ei){ + if (appended_ei != NULL){ + ei->sub_ei = appended_ei; + } +} + void linphone_error_info_set(LinphoneErrorInfo *ei, const char *protocol, LinphoneReason reason, int code, const char *status_string, const char *warning){ linphone_error_info_reset(ei); ei->reason = reason; diff --git a/coreapi/factory.c b/coreapi/factory.c index 05d8ad4ce..738dc9db4 100644 --- a/coreapi/factory.c +++ b/coreapi/factory.c @@ -53,6 +53,7 @@ struct _LinphoneFactory { char *cached_ring_resources_dir; char *cached_image_resources_dir; char *cached_msplugins_dir; + LinphoneErrorInfo* ei; }; static void linphone_factory_uninit(LinphoneFactory *obj){ @@ -207,7 +208,7 @@ void linphone_factory_set_msplugins_dir(LinphoneFactory *factory, const char *pa STRING_SET(factory->msplugins_dir, path); } -LinphoneErrorInfo *linphone_factory_create_error_info(void){ +LinphoneErrorInfo *linphone_factory_create_error_info(LinphoneFactory *factory){ return linphone_error_info_new(); diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 504e549f0..02b508247 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -5100,18 +5100,29 @@ int linphone_call_terminate(LinphoneCall *call) { return 0; } -static void linphone_error_info_to_sal(const LinphoneErrorInfo* ei, SalErrorInfo* sei){ - +static void linphone_error_info_fields_to_sal(const LinphoneErrorInfo* ei, SalErrorInfo* sei){ + sei->reason = linphone_error_info_get_reason(ei); sei->status_string = bctbx_strdup(ei->phrase); sei->full_string = bctbx_strdup(ei->full_string); sei->warnings = bctbx_strdup(ei->warnings); sei->protocol_code = ei->protocol_code; sei->protocol = bctbx_strdup(ei->protocol); + +} + +static void linphone_error_info_to_sal(const LinphoneErrorInfo* ei, SalErrorInfo* sei){ + + linphone_error_info_fields_to_sal(ei, sei); + if (ei->sub_ei !=NULL) { + + linphone_error_info_to_sal(ei->sub_ei, sei->sub_sei); + } } int linphone_call_terminate_with_error_info(LinphoneCall *call , const LinphoneErrorInfo *ei){ - SalErrorInfo sei; + SalErrorInfo sei ; + sal_error_info_init_to_null(&sei); ms_message("Terminate call [%p] which is currently in state %s", call, linphone_call_state_to_string(call->state)); switch (call->state) { @@ -5150,6 +5161,7 @@ int linphone_call_redirect(LinphoneCall *call, const char *redirect_uri) { char *real_url = NULL; LinphoneCore *lc; LinphoneAddress *real_parsed_url; + SalErrorInfo sei; if (call->state != LinphoneCallIncomingReceived) { ms_error("Bad state for call redirection."); @@ -5165,6 +5177,7 @@ int linphone_call_redirect(LinphoneCall *call, const char *redirect_uri) { } real_url = linphone_address_as_string(real_parsed_url); + sal_error_info_set(&sei,SalReasonRedirect, "SIP", 0, NULL, NULL); sal_call_decline(call->op, SalReasonRedirect, real_url); ms_free(real_url); linphone_error_info_set(call->ei, NULL, LinphoneReasonMovedPermanently, 302, "Call redirected", NULL); @@ -5175,16 +5188,43 @@ int linphone_call_redirect(LinphoneCall *call, const char *redirect_uri) { } int linphone_call_decline(LinphoneCall * call, LinphoneReason reason) { + SalErrorInfo sei; if ((call->state != LinphoneCallIncomingReceived) && (call->state != LinphoneCallIncomingEarlyMedia)) { ms_error("Cannot decline a call that is in state %s", linphone_call_state_to_string(call->state)); return -1; } - + sal_error_info_set(&sei, linphone_reason_to_sal(reason),"SIP", 0, NULL, NULL); sal_call_decline(call->op, linphone_reason_to_sal(reason), NULL); terminate_call(call); return 0; } + +static const LinphoneErrorInfo* linphone_error_info_get_sub(const LinphoneErrorInfo *ei){ + + return ei->sub_ei; +} + +int linphone_call_decline_with_error(LinphoneCall * call, const LinphoneErrorInfo *ei) { + SalErrorInfo sei; + sal_error_info_init_to_null(&sei); + SalErrorInfo sub_sei; + sal_error_info_init_to_null(&sub_sei); + sei.sub_sei = &sub_sei; + + if ((call->state != LinphoneCallIncomingReceived) && (call->state != LinphoneCallIncomingEarlyMedia)) { + ms_error("Cannot decline a call that is in state %s", linphone_call_state_to_string(call->state)); + return -1; + } + linphone_error_info_to_sal(ei, &sei); + //linphone_error_info_to_sal(ei->sub_ei, &sub_sei); + //sei.sub_sei = &sub_sei; + // check if sub reason exists + + sal_call_decline_with_error_info(call->op, &sei , NULL); + terminate_call(call); + return 0; +} int linphone_call_accept(LinphoneCall *call) { return linphone_call_accept_with_params(call, NULL); } @@ -5779,6 +5819,7 @@ void linphone_call_reinvite_to_recover_from_connection_loss(LinphoneCall *call) } void linphone_call_repair_if_broken(LinphoneCall *call){ + SalErrorInfo sei; if (!call->broken) return; if (!call->core->media_network_reachable) return; @@ -5808,6 +5849,7 @@ void linphone_call_repair_if_broken(LinphoneCall *call){ break; case LinphoneCallUpdatedByRemote: if (sal_call_dialog_request_pending(call->op)) { + sal_error_info_set(&sei, SalReasonServiceUnavailable,"SIP", 0, NULL, NULL); sal_call_decline(call->op, SalReasonServiceUnavailable, NULL); } linphone_call_reinvite_to_recover_from_connection_loss(call); diff --git a/include/linphone/call.h b/include/linphone/call.h index d23c10867..0afd289ca 100644 --- a/include/linphone/call.h +++ b/include/linphone/call.h @@ -401,6 +401,8 @@ LINPHONE_PUBLIC int linphone_call_redirect(LinphoneCall *call, const char *redir * @return 0 on success, -1 on failure **/ LINPHONE_PUBLIC int linphone_call_decline(LinphoneCall * call, LinphoneReason reason); + +LINPHONE_PUBLIC int linphone_call_decline_with_error(LinphoneCall * call, const LinphoneErrorInfo *ei); /** * Accept an incoming call. diff --git a/include/linphone/error_info.h b/include/linphone/error_info.h index 49980608c..61ea9b6e6 100644 --- a/include/linphone/error_info.h +++ b/include/linphone/error_info.h @@ -103,6 +103,8 @@ LINPHONE_PUBLIC int linphone_error_info_get_protocol_code(const LinphoneErrorInf * @param[in] warning warning message */ LINPHONE_PUBLIC void linphone_error_info_set(LinphoneErrorInfo *ei, const char *protocol, LinphoneReason reason, int code, const char *status_string, const char *warning); + +LINPHONE_PUBLIC void linphone_error_info_set_sub_error_info(LinphoneErrorInfo *ei, LinphoneErrorInfo *appended_ei); /** * Assign reason LinphoneReason to a LinphoneErrorUnfo object. diff --git a/include/linphone/factory.h b/include/linphone/factory.h index b4f785ad4..ef26ea7d3 100644 --- a/include/linphone/factory.h +++ b/include/linphone/factory.h @@ -205,9 +205,10 @@ LINPHONE_PUBLIC void linphone_factory_set_msplugins_dir(LinphoneFactory *factory /** * Creates an object LinphoneErrorInfo. + * @param[in] factory LinphoneFactory object * @return LinphoneErrorInfo object. */ -LINPHONE_PUBLIC LinphoneErrorInfo *linphone_factory_create_error_info(void); +LINPHONE_PUBLIC LinphoneErrorInfo *linphone_factory_create_error_info(LinphoneFactory *factory); /** * @} */ diff --git a/include/sal/sal.h b/include/sal/sal.h index 09df18d47..d5eb9d91c 100644 --- a/include/sal/sal.h +++ b/include/sal/sal.h @@ -412,6 +412,7 @@ typedef struct SalErrorInfo{ char *warnings; char *protocol; char *full_string; /*concatenation of status_string + warnings*/ + struct SalErrorInfo *sub_sei; }SalErrorInfo; typedef enum SalPresenceStatus{ @@ -729,6 +730,7 @@ const SalErrorInfo *sal_error_info_none(void); LINPHONE_PUBLIC const SalErrorInfo *sal_op_get_error_info(const SalOp *op); const SalErrorInfo *sal_op_get_reason_error_info(const SalOp *op); void sal_error_info_reset(SalErrorInfo *ei); +void sal_error_info_init_to_null(SalErrorInfo *sei); void sal_error_info_set(SalErrorInfo *ei, SalReason reason, const char *protocol, int code, const char *status_string, const char *warning); /*entity tag used for publish (see RFC 3903)*/ @@ -744,6 +746,7 @@ int sal_call_notify_ringing(SalOp *h, bool_t early_media); /*accept an incoming call or, during a call accept a reINVITE*/ int sal_call_accept(SalOp*h); int sal_call_decline(SalOp *h, SalReason reason, const char *redirection /*optional*/); +int sal_call_decline_with_error_info(SalOp *h, const SalErrorInfo* info, const char *redirection /*optional*/); int sal_call_update(SalOp *h, const char *subject, bool_t no_user_consent); void sal_call_cancel_invite(SalOp *op); SalMediaDescription * sal_call_get_remote_media_description(SalOp *h); diff --git a/tester/call_single_tester.c b/tester/call_single_tester.c index 9c56c968a..c00065237 100644 --- a/tester/call_single_tester.c +++ b/tester/call_single_tester.c @@ -1189,6 +1189,48 @@ static void call_busy_when_calling_self(void) { linphone_core_manager_destroy(marie); } +static void call_declined_with_error(void) { + LinphoneCoreManager* callee_mgr = linphone_core_manager_new("marie_rc"); + LinphoneCoreManager* caller_mgr = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); + + LinphoneCall* in_call; + LinphoneCall* out_call = linphone_core_invite_address(caller_mgr->lc,callee_mgr->identity); + LinphoneFactory* factory = linphone_factory_get(); + + LinphoneErrorInfo *ei = linphone_factory_create_error_info(factory); + LinphoneErrorInfo *reason_ei = linphone_factory_create_error_info(factory); + + linphone_error_info_set(ei, "SIP", LinphoneReasonUnknown, 603, "Decline", NULL); //ordre des arguments à vérifier + linphone_error_info_set(reason_ei, "hardware", LinphoneReasonUnknown, 66, "J'ai plus de batterie", NULL); + + linphone_error_info_set_sub_error_info(ei, reason_ei); + + linphone_call_ref(out_call); + BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallIncomingReceived,1)); + BC_ASSERT_PTR_NOT_NULL(in_call=linphone_core_get_current_call(callee_mgr->lc)); + if (in_call) { + linphone_call_ref(in_call); + linphone_call_decline_with_error(in_call, ei); + // linphone_call_terminate(in_call); + BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallReleased,1)); + BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallReleased,1)); + BC_ASSERT_EQUAL(callee_mgr->stat.number_of_LinphoneCallEnd,1, int, "%d"); + BC_ASSERT_EQUAL(caller_mgr->stat.number_of_LinphoneCallEnd,1, int, "%d"); + BC_ASSERT_EQUAL(linphone_call_get_reason(in_call),LinphoneReasonDeclined, int, "%d"); + BC_ASSERT_EQUAL(linphone_call_log_get_status(linphone_call_get_call_log(in_call)),LinphoneCallDeclined, int, "%d"); + BC_ASSERT_EQUAL(linphone_call_get_reason(out_call),LinphoneReasonDeclined, int, "%d"); + BC_ASSERT_EQUAL(linphone_call_log_get_status(linphone_call_get_call_log(out_call)),LinphoneCallDeclined, int, "%d"); + + + linphone_call_unref(in_call); + } + linphone_call_unref(out_call); + //linphone_error_info_unref(reason_ei); + linphone_error_info_unref(ei); + + linphone_core_manager_destroy(callee_mgr); + linphone_core_manager_destroy(caller_mgr); +} static void call_declined(void) { LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc"); @@ -5736,6 +5778,7 @@ static void call_with_network_reachable_down_in_callback(void){ test_t call_tests[] = { TEST_NO_TAG("Early declined call", early_declined_call), TEST_NO_TAG("Call declined", call_declined), + TEST_NO_TAG("Call declined with error", call_declined_with_error), TEST_NO_TAG("Cancelled call", cancelled_call), TEST_NO_TAG("Early cancelled call", early_cancelled_call), TEST_NO_TAG("Call with DNS timeout", call_with_dns_time_out), From ca3e442d9fc38185cab32d0b7fb220fd7cccb65d Mon Sep 17 00:00:00 2001 From: Sandrine Avakian Date: Tue, 4 Apr 2017 14:09:44 +0200 Subject: [PATCH 08/16] Replacing most calls to sal_call_decline with sal_call_decline_with_error_info --- coreapi/bellesip_sal/sal_op_call.c | 23 ++++++++++++++++------- coreapi/bellesip_sal/sal_op_impl.c | 2 +- coreapi/callbacks.c | 24 +++++++++++++++--------- coreapi/linphonecall.c | 18 ++++++++---------- include/linphone/call.h | 8 +++++++- include/linphone/error_info.h | 5 +++++ 6 files changed, 52 insertions(+), 28 deletions(-) diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index 7b347d503..0621232da 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -528,8 +528,10 @@ static int process_sdp_for_invite(SalOp* op,belle_sip_request_t* invite) { }else err=-1; if (err==-1){ + sal_error_info_init_to_null(&sei); sal_error_info_set(&sei, reason,"SIP", 0, NULL, NULL); - sal_call_decline(op,reason,NULL); + sal_call_decline_with_error_info(op, &sei,NULL); + } return err; } @@ -1002,7 +1004,7 @@ int sal_call_decline_with_error_info(SalOp *op, const SalErrorInfo *info, const trans=(belle_sip_transaction_t*)op->pending_server_trans; if (!trans) trans=(belle_sip_transaction_t*)op->pending_update_server_trans; if (!trans){ - ms_error("sal_call_decline(): no pending transaction to decline."); + ms_error("sal_call_decline_with_error_info(): no pending transaction to decline."); return -1; } response = sal_op_create_response_from_request(op,belle_sip_transaction_get_request(trans),status); @@ -1089,7 +1091,16 @@ int sal_call_send_dtmf(SalOp *h, char dtmf){ int sal_call_terminate_with_error(SalOp *op, const SalErrorInfo *info){ -// SalErrorInfo sei; + SalErrorInfo sei; + const SalErrorInfo *p_sei; + if (info == NULL){ + sal_error_info_init_to_null(&sei); + sal_error_info_set(&sei,SalReasonDeclined, "SIP", 0, NULL, NULL); + p_sei = &sei; + } else{ + p_sei = info; + + } belle_sip_dialog_state_t dialog_state=op->dialog?belle_sip_dialog_get_state(op->dialog):BELLE_SIP_DIALOG_NULL; if (op->state==SalOpStateTerminating || op->state==SalOpStateTerminated) { ms_error("Cannot terminate op [%p] in state [%s]",op,sal_op_state_to_string(op->state)); @@ -1109,8 +1120,7 @@ int sal_call_terminate_with_error(SalOp *op, const SalErrorInfo *info){ case BELLE_SIP_DIALOG_NULL: { if (op->dir == SalOpDirIncoming) { - //sal_error_info_set(&sei, SalReasonDeclined,"SIP", 0, NULL, NULL); - sal_call_decline(op, SalReasonDeclined,NULL); + sal_call_decline_with_error_info(op, p_sei, NULL); op->state=SalOpStateTerminated; } else if (op->pending_client_trans){ if (belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(op->pending_client_trans)) == BELLE_SIP_TRANSACTION_PROCEEDING){ @@ -1127,8 +1137,7 @@ int sal_call_terminate_with_error(SalOp *op, const SalErrorInfo *info){ } case BELLE_SIP_DIALOG_EARLY: { if (op->dir == SalOpDirIncoming) { - //sal_error_info_set(&sei, SalReasonDeclined,"SIP", 0, NULL, NULL); - sal_call_decline(op, SalReasonDeclined,NULL); + sal_call_decline_with_error_info(op, p_sei,NULL); op->state=SalOpStateTerminated; } else { cancelling_invite(op); diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index a9c9c8ca1..ce7851f82 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -605,7 +605,7 @@ void sal_error_info_reset(SalErrorInfo *ei){ void sal_error_info_set(SalErrorInfo *ei, SalReason reason, const char *protocol, int code, const char *status_string, const char *warning){ sal_error_info_reset(ei); - if (reason==SalReasonUnknown && strcmp(protocol, "SIP") == 0) ei->reason=_sal_reason_from_sip_code(code); + if (reason==SalReasonUnknown && strcmp(protocol, "SIP") == 0 && code != 0) ei->reason=_sal_reason_from_sip_code(code); else{ ei->reason=reason; if (code == 0) { diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 81618bab6..e6301fb36 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -285,9 +285,9 @@ static void call_received(SalOp *h){ case LinphonePresenceActivityPermanentAbsence: alt_contact = linphone_presence_model_get_contact(lc->presence_model); if (alt_contact != NULL) { + sal_error_info_init_to_null(&sei); sal_error_info_set(&sei,SalReasonRedirect, "SIP", 0, NULL, NULL); - sal_call_decline_with_error_info(h, SalReasonRedirect,alt_contact); - sal_call_decline(h,SalReasonRedirect,alt_contact); + sal_call_decline_with_error_info(h, &sei,alt_contact); ms_free(alt_contact); sal_op_release(h); return; @@ -300,8 +300,9 @@ static void call_received(SalOp *h){ } if (!linphone_core_can_we_add_call(lc)){/*busy*/ + sal_error_info_init_to_null(&sei); sal_error_info_set(&sei,SalReasonBusy, "SIP", 0, NULL, NULL); - sal_call_decline(h,SalReasonBusy,NULL); + sal_call_decline_with_error_info(h, &sei,NULL); sal_op_release(h); return; } @@ -337,8 +338,9 @@ static void call_received(SalOp *h){ if (from_address_to_search_if_me && already_a_call_with_remote_address(lc,from_address_to_search_if_me)){ char *addr = linphone_address_as_string(from_addr); ms_warning("Receiving a call while one with same address [%s] is initiated, refusing this one with busy message.",addr); + sal_error_info_init_to_null(&sei); sal_error_info_set(&sei,SalReasonBusy, "SIP", 0, NULL, NULL); - sal_call_decline(h,SalReasonBusy,NULL); + sal_call_decline_with_error_info(h, &sei,NULL); sal_op_release(h); linphone_address_unref(from_addr); linphone_address_unref(to_addr); @@ -356,8 +358,9 @@ static void call_received(SalOp *h){ md=sal_call_get_final_media_description(call->op); if (md){ if (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md)){ + sal_error_info_init_to_null(&sei); sal_error_info_set(&sei,SalReasonNotAcceptable, "SIP", 0, NULL, NULL); - sal_call_decline(call->op,SalReasonNotAcceptable,NULL); + sal_call_decline_with_error_info(call->op, &sei,NULL); linphone_call_unref(call); return; } @@ -722,8 +725,9 @@ static void call_updated(LinphoneCore *lc, LinphoneCall *call, SalOp *op, bool_t case LinphoneCallUpdating: case LinphoneCallPausing: case LinphoneCallResuming: + sal_error_info_init_to_null(&sei); sal_error_info_set(&sei,SalReasonInternalError, "SIP", 0, NULL, NULL); - sal_call_decline(call->op,SalReasonInternalError,NULL); + sal_call_decline_with_error_info(call->op, &sei,NULL); /*no break*/ case LinphoneCallIdle: case LinphoneCallOutgoingInit: @@ -776,16 +780,18 @@ static void call_updating(SalOp *op, bool_t is_update){ md=sal_call_get_final_media_description(call->op); if (md && (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md))){ + sal_error_info_init_to_null(&sei); sal_error_info_set(&sei,SalReasonNotAcceptable, "SIP", 0, NULL, NULL); - sal_call_decline(call->op,SalReasonNotAcceptable,NULL); + sal_call_decline_with_error_info(call->op, &sei,NULL); return; } if (is_update && prev_result_desc && md){ int diff=sal_media_description_equals(prev_result_desc,md); if (diff & (SAL_MEDIA_DESCRIPTION_CRYPTO_POLICY_CHANGED|SAL_MEDIA_DESCRIPTION_STREAMS_CHANGED)){ ms_warning("Cannot accept this update, it is changing parameters that require user approval"); - sal_error_info_set(&sei,SalReasonNotAcceptable, "SIP", 0, NULL, NULL); - sal_call_decline(call->op,SalReasonNotAcceptable,NULL); /*FIXME should send 504 Cannot change the session parameters without prompting the user"*/ + sal_error_info_init_to_null(&sei); + sal_error_info_set(&sei,SalReasonUnknown, "SIP", 504, "Cannot change the session parameters without prompting the user", NULL); + sal_call_decline_with_error_info(call->op, &sei,NULL); return; } } diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 02b508247..6f717c30f 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -5123,7 +5123,8 @@ static void linphone_error_info_to_sal(const LinphoneErrorInfo* ei, SalErrorInfo int linphone_call_terminate_with_error_info(LinphoneCall *call , const LinphoneErrorInfo *ei){ SalErrorInfo sei ; sal_error_info_init_to_null(&sei); - + LinphoneErrorInfo* p_ei = (LinphoneErrorInfo*) ei; + ms_message("Terminate call [%p] which is currently in state %s", call, linphone_call_state_to_string(call->state)); switch (call->state) { case LinphoneCallReleased: @@ -5133,7 +5134,8 @@ int linphone_call_terminate_with_error_info(LinphoneCall *call , const LinphoneE return -1; case LinphoneCallIncomingReceived: case LinphoneCallIncomingEarlyMedia: - return linphone_call_decline(call, LinphoneReasonDeclined); + linphone_error_info_set_reason(p_ei, LinphoneReasonDeclined); + return linphone_call_decline_with_error(call, p_ei); case LinphoneCallOutgoingInit: /* In state OutgoingInit, op has to be destroyed */ sal_op_release(call->op); @@ -5177,8 +5179,9 @@ int linphone_call_redirect(LinphoneCall *call, const char *redirect_uri) { } real_url = linphone_address_as_string(real_parsed_url); + sal_error_info_init_to_null(&sei); sal_error_info_set(&sei,SalReasonRedirect, "SIP", 0, NULL, NULL); - sal_call_decline(call->op, SalReasonRedirect, real_url); + sal_call_decline_with_error_info(call->op, &sei, real_url); ms_free(real_url); linphone_error_info_set(call->ei, NULL, LinphoneReasonMovedPermanently, 302, "Call redirected", NULL); call->non_op_error = TRUE; @@ -5188,12 +5191,10 @@ int linphone_call_redirect(LinphoneCall *call, const char *redirect_uri) { } int linphone_call_decline(LinphoneCall * call, LinphoneReason reason) { - SalErrorInfo sei; if ((call->state != LinphoneCallIncomingReceived) && (call->state != LinphoneCallIncomingEarlyMedia)) { ms_error("Cannot decline a call that is in state %s", linphone_call_state_to_string(call->state)); return -1; } - sal_error_info_set(&sei, linphone_reason_to_sal(reason),"SIP", 0, NULL, NULL); sal_call_decline(call->op, linphone_reason_to_sal(reason), NULL); terminate_call(call); return 0; @@ -5216,10 +5217,6 @@ int linphone_call_decline_with_error(LinphoneCall * call, const LinphoneErrorInf return -1; } linphone_error_info_to_sal(ei, &sei); - //linphone_error_info_to_sal(ei->sub_ei, &sub_sei); - //sei.sub_sei = &sub_sei; - // check if sub reason exists - sal_call_decline_with_error_info(call->op, &sei , NULL); terminate_call(call); @@ -5849,8 +5846,9 @@ void linphone_call_repair_if_broken(LinphoneCall *call){ break; case LinphoneCallUpdatedByRemote: if (sal_call_dialog_request_pending(call->op)) { + sal_error_info_init_to_null(&sei); sal_error_info_set(&sei, SalReasonServiceUnavailable,"SIP", 0, NULL, NULL); - sal_call_decline(call->op, SalReasonServiceUnavailable, NULL); + sal_call_decline_with_error_info(call->op, &sei,NULL); } linphone_call_reinvite_to_recover_from_connection_loss(call); break; diff --git a/include/linphone/call.h b/include/linphone/call.h index 0afd289ca..fef709333 100644 --- a/include/linphone/call.h +++ b/include/linphone/call.h @@ -401,7 +401,13 @@ LINPHONE_PUBLIC int linphone_call_redirect(LinphoneCall *call, const char *redir * @return 0 on success, -1 on failure **/ LINPHONE_PUBLIC int linphone_call_decline(LinphoneCall * call, LinphoneReason reason); - + +/** + * Decline a pending incoming call, with a LinphoneErrorInfo object. + * @param[in] call A LinphoneCall object that must be in the IncomingReceived state + * @param[in] ei LinphoneErrorInfo containing more information on the call rejection. + * @return 0 on success, -1 on failure + */ LINPHONE_PUBLIC int linphone_call_decline_with_error(LinphoneCall * call, const LinphoneErrorInfo *ei); /** diff --git a/include/linphone/error_info.h b/include/linphone/error_info.h index 61ea9b6e6..11d5af65c 100644 --- a/include/linphone/error_info.h +++ b/include/linphone/error_info.h @@ -104,6 +104,11 @@ LINPHONE_PUBLIC int linphone_error_info_get_protocol_code(const LinphoneErrorInf */ LINPHONE_PUBLIC void linphone_error_info_set(LinphoneErrorInfo *ei, const char *protocol, LinphoneReason reason, int code, const char *status_string, const char *warning); +/** + * [linphone_error_info_set_sub_error_info description] + * @param[in] ei LinphoneErrorInfo object to which the other LinphoneErrorInfo will be appended as ei->sub_ei. + * @param[in] appended_ei LinphoneErrorInfo to append + */ LINPHONE_PUBLIC void linphone_error_info_set_sub_error_info(LinphoneErrorInfo *ei, LinphoneErrorInfo *appended_ei); /** From c78fa631f1d1df160b8c489dc26d2ed3855c0b57 Mon Sep 17 00:00:00 2001 From: Jehan Monnier Date: Tue, 4 Apr 2017 11:21:40 +0200 Subject: [PATCH 09/16] Update media streamer and ortp --- mediastreamer2 | 2 +- oRTP | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mediastreamer2 b/mediastreamer2 index b937df188..954652074 160000 --- a/mediastreamer2 +++ b/mediastreamer2 @@ -1 +1 @@ -Subproject commit b937df188829f73c3f5db35ff0191aa695f27884 +Subproject commit 954652074fd168323c0846d6d8cd6c5b4d859d75 diff --git a/oRTP b/oRTP index 235e5175b..67c0672e2 160000 --- a/oRTP +++ b/oRTP @@ -1 +1 @@ -Subproject commit 235e5175b2befa2d3e5f19cd969b0f3bda5b9b4c +Subproject commit 67c0672e2680baa85a74d8966b813fac259649df From 9e9ec48cedb6a2be2afc48edca7868bd4a2a4c1f Mon Sep 17 00:00:00 2001 From: Sandrine Avakian Date: Tue, 4 Apr 2017 14:54:47 +0200 Subject: [PATCH 10/16] removing ortp --- oRTP | 1 - 1 file changed, 1 deletion(-) delete mode 160000 oRTP diff --git a/oRTP b/oRTP deleted file mode 160000 index 67c0672e2..000000000 --- a/oRTP +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 67c0672e2680baa85a74d8966b813fac259649df From a5ffae6b0301355bdc4e8ffd1d558fe27868ed7d Mon Sep 17 00:00:00 2001 From: Sandrine Avakian Date: Wed, 5 Apr 2017 16:19:26 +0200 Subject: [PATCH 11/16] Fixing errors in linphone_error_info_set parameter usage induced by merge from master. --- coreapi/bellesip_sal/sal_op_call.c | 1 + coreapi/callbacks.c | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index 88d339204..90b078405 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -510,6 +510,7 @@ static int is_media_description_acceptable(SalMediaDescription *md){ static SalReason process_sdp_for_invite(SalOp* op,belle_sip_request_t* invite) { belle_sdp_session_description_t* sdp; SalReason reason = SalReasonNone; + SalErrorInfo sei; if (extract_sdp(op,BELLE_SIP_MESSAGE(invite),&sdp,&reason)==0) { if (sdp){ diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 6737638a4..6fa511fa5 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -312,7 +312,7 @@ static void call_received(SalOp *h){ sal_call_decline_with_error_info(h, &sei,alt_contact); ms_free(alt_contact); ei = linphone_error_info_new(); - linphone_error_info_set(ei, LinphoneReasonMovedPermanently, 302, "Moved permanently", NULL); + linphone_error_info_set(ei, NULL, LinphoneReasonMovedPermanently, 302, "Moved permanently", NULL); linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, from_addr, to_addr, ei); sal_op_release(h); return; @@ -327,7 +327,7 @@ static void call_received(SalOp *h){ if (!linphone_core_can_we_add_call(lc)){/*busy*/ sal_call_decline(h,SalReasonBusy,NULL); ei = linphone_error_info_new(); - linphone_error_info_set(ei, LinphoneReasonBusy, 486, "Busy - too many calls", NULL); + linphone_error_info_set(ei, NULL, LinphoneReasonBusy, 486, "Busy - too many calls", NULL); linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, from_addr, to_addr, ei); sal_op_release(h); return; @@ -347,7 +347,7 @@ static void call_received(SalOp *h){ ms_warning("Receiving a call while one with same address [%s] is initiated, refusing this one with busy message.",addr); sal_call_decline(h,SalReasonBusy,NULL); ei = linphone_error_info_new(); - linphone_error_info_set(ei, LinphoneReasonBusy, 486, "Busy - duplicated call", NULL); + linphone_error_info_set(ei, NULL, LinphoneReasonBusy, 486, "Busy - duplicated call", NULL); linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, from_addr, to_addr, ei); sal_op_release(h); linphone_address_unref(from_addr); @@ -367,7 +367,7 @@ static void call_received(SalOp *h){ if (md){ if (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md)){ ei = linphone_error_info_new(); - linphone_error_info_set(ei, LinphoneReasonNotAcceptable, 488, "Not acceptable here", NULL); + linphone_error_info_set(ei, NULL, LinphoneReasonNotAcceptable, 488, "Not acceptable here", NULL); linphone_core_report_early_failed_call(lc, LinphoneCallIncoming, linphone_address_ref(from_addr), linphone_address_ref(to_addr), ei); sal_call_decline(call->op,SalReasonNotAcceptable,NULL); linphone_call_unref(call); From 5f084675bd5eb72c9c891746f2d7b58f5b4f9969 Mon Sep 17 00:00:00 2001 From: Sandrine Avakian Date: Thu, 6 Apr 2017 11:27:54 +0200 Subject: [PATCH 12/16] remove unused variable in tests. Moving function for api to error_info.h --- coreapi/error_info.c | 5 +++++ include/linphone/error_info.h | 7 +++++++ tester/call_single_tester.c | 1 - 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/coreapi/error_info.c b/coreapi/error_info.c index b889bbf46..4c9008b60 100644 --- a/coreapi/error_info.c +++ b/coreapi/error_info.c @@ -215,6 +215,11 @@ void linphone_error_info_from_sal_op(LinphoneErrorInfo *ei, const SalOp *op){ } } +LinphoneErrorInfo* linphone_error_info_get_sub(const LinphoneErrorInfo *ei){ + + return ei->sub_ei; +} + void linphone_error_info_set_sub_error_info(LinphoneErrorInfo *ei, LinphoneErrorInfo *appended_ei){ if (appended_ei != NULL){ ei->sub_ei = appended_ei; diff --git a/include/linphone/error_info.h b/include/linphone/error_info.h index 11d5af65c..8336c7ae8 100644 --- a/include/linphone/error_info.h +++ b/include/linphone/error_info.h @@ -62,6 +62,13 @@ LINPHONE_PUBLIC void linphone_error_info_unref(LinphoneErrorInfo *ei); **/ LINPHONE_PUBLIC LinphoneReason linphone_error_info_get_reason(const LinphoneErrorInfo *ei); +/** + * Get pointer to chained LinphoneErrorInfo set in sub_ei. + * @param ei ErrorInfo object + * @return LinphoneErrorInfo pointer defined in the ei object. + */ +LINPHONE_PUBLIC LinphoneErrorInfo* linphone_error_info_get_sub(const LinphoneErrorInfo *ei); + /** * Get textual phrase from the error info. * This is the text that is provided by the peer in the protocol (SIP). diff --git a/tester/call_single_tester.c b/tester/call_single_tester.c index 0fa27e694..df66f7849 100644 --- a/tester/call_single_tester.c +++ b/tester/call_single_tester.c @@ -1790,7 +1790,6 @@ static void call_callee_with_custom_header_or_sdp_attributes(void) { stats initial_caller=caller_mgr->stat; stats initial_callee=callee_mgr->stat; - bool_t result=FALSE; bool_t did_receive_call; const LinphoneCallParams *caller_remote_params; From f3bd0a7272dc06487db4a544054dd8820951b368 Mon Sep 17 00:00:00 2001 From: Sandrine Avakian Date: Thu, 6 Apr 2017 11:38:30 +0200 Subject: [PATCH 13/16] Forgotten file from previous commit. --- coreapi/linphonecall.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index ea729df4e..86726209b 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -5257,10 +5257,6 @@ int linphone_call_decline(LinphoneCall * call, LinphoneReason reason) { return 0; } -static const LinphoneErrorInfo* linphone_error_info_get_sub(const LinphoneErrorInfo *ei){ - - return ei->sub_ei; -} int linphone_call_decline_with_error(LinphoneCall * call, const LinphoneErrorInfo *ei) { SalErrorInfo sei; From 95387d37856885d1a143f24be356fe7ff9b28cbf Mon Sep 17 00:00:00 2001 From: Sandrine Avakian Date: Fri, 7 Apr 2017 14:43:24 +0200 Subject: [PATCH 14/16] Fixes with reason header call decline. --- coreapi/bellesip_sal/sal_op_impl.c | 1 + coreapi/error_info.c | 2 +- tester/call_single_tester.c | 31 ++++++++++++++++++++++-------- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index ce7851f82..f859b221e 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -643,6 +643,7 @@ void sal_op_set_error_info_from_response(SalOp *op, belle_sip_response_t *respon warnings=warning ? belle_sip_header_get_unparsed_value(warning) : NULL; sal_error_info_set(ei,SalReasonUnknown,"SIP", code,reason_phrase,warnings); + sal_op_set_reason_error_info(op, BELLE_SIP_MESSAGE(response)); } const SalErrorInfo *sal_op_get_error_info(const SalOp *op){ diff --git a/coreapi/error_info.c b/coreapi/error_info.c index 4c9008b60..4883a0d5f 100644 --- a/coreapi/error_info.c +++ b/coreapi/error_info.c @@ -222,7 +222,7 @@ LinphoneErrorInfo* linphone_error_info_get_sub(const LinphoneErrorInfo *ei){ void linphone_error_info_set_sub_error_info(LinphoneErrorInfo *ei, LinphoneErrorInfo *appended_ei){ if (appended_ei != NULL){ - ei->sub_ei = appended_ei; + ei->sub_ei = linphone_error_info_ref(appended_ei); } } diff --git a/tester/call_single_tester.c b/tester/call_single_tester.c index df66f7849..5acadc44d 100644 --- a/tester/call_single_tester.c +++ b/tester/call_single_tester.c @@ -1193,18 +1193,23 @@ static void call_declined_with_error(void) { LinphoneCoreManager* callee_mgr = linphone_core_manager_new("marie_rc"); LinphoneCoreManager* caller_mgr = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); - LinphoneCall* in_call; + LinphoneCall* in_call = NULL; LinphoneCall* out_call = linphone_core_invite_address(caller_mgr->lc,callee_mgr->identity); LinphoneFactory* factory = linphone_factory_get(); + const LinphoneErrorInfo* rcvd_ei; + const LinphoneErrorInfo* sub_rcvd_ei; LinphoneErrorInfo *ei = linphone_factory_create_error_info(factory); LinphoneErrorInfo *reason_ei = linphone_factory_create_error_info(factory); - + linphone_error_info_set(ei, "SIP", LinphoneReasonUnknown, 603, "Decline", NULL); //ordre des arguments à vérifier linphone_error_info_set(reason_ei, "hardware", LinphoneReasonUnknown, 66, "J'ai plus de batterie", NULL); linphone_error_info_set_sub_error_info(ei, reason_ei); + BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallIncomingReceived,1)); + BC_ASSERT_PTR_NOT_NULL(in_call=linphone_core_get_current_call(callee_mgr->lc)); + linphone_call_ref(out_call); BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallIncomingReceived,1)); BC_ASSERT_PTR_NOT_NULL(in_call=linphone_core_get_current_call(callee_mgr->lc)); @@ -1212,20 +1217,29 @@ static void call_declined_with_error(void) { linphone_call_ref(in_call); linphone_call_decline_with_error(in_call, ei); // linphone_call_terminate(in_call); - BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallReleased,1)); - BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallReleased,1)); - BC_ASSERT_EQUAL(callee_mgr->stat.number_of_LinphoneCallEnd,1, int, "%d"); - BC_ASSERT_EQUAL(caller_mgr->stat.number_of_LinphoneCallEnd,1, int, "%d"); + + BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallEnd,1)); + BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallEnd,1)); + + rcvd_ei = linphone_call_get_error_info(out_call); + sub_rcvd_ei = linphone_error_info_get_sub(rcvd_ei); + BC_ASSERT_STRING_EQUAL(linphone_error_info_get_phrase(rcvd_ei), "Decline"); + BC_ASSERT_STRING_EQUAL(linphone_error_info_get_protocol(rcvd_ei), "SIP"); + BC_ASSERT_STRING_EQUAL(linphone_error_info_get_phrase(sub_rcvd_ei), "J'ai plus de batterie"); + BC_ASSERT_STRING_EQUAL(linphone_error_info_get_protocol(sub_rcvd_ei), "hardware"); + BC_ASSERT_EQUAL(linphone_call_get_reason(in_call),LinphoneReasonDeclined, int, "%d"); BC_ASSERT_EQUAL(linphone_call_log_get_status(linphone_call_get_call_log(in_call)),LinphoneCallDeclined, int, "%d"); BC_ASSERT_EQUAL(linphone_call_get_reason(out_call),LinphoneReasonDeclined, int, "%d"); BC_ASSERT_EQUAL(linphone_call_log_get_status(linphone_call_get_call_log(out_call)),LinphoneCallDeclined, int, "%d"); - + + BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallReleased,1)); + BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallReleased,1)); linphone_call_unref(in_call); } linphone_call_unref(out_call); - //linphone_error_info_unref(reason_ei); + linphone_error_info_unref(reason_ei); linphone_error_info_unref(ei); linphone_core_manager_destroy(callee_mgr); @@ -1778,6 +1792,7 @@ static void call_callee_with_custom_header_or_sdp_cb(LinphoneCore *lc, LinphoneC static void call_callee_with_custom_header_or_sdp_attributes(void) { + int result; LinphoneCoreManager *callee_mgr = linphone_core_manager_new("marie_rc"); LinphoneCoreManager *caller_mgr = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc"); LinphoneCall *call_caller = NULL, *call_callee = NULL; From 64a18a5b23597c9610703185c71773f7b0ea97d9 Mon Sep 17 00:00:00 2001 From: Sandrine Avakian Date: Tue, 11 Apr 2017 13:28:47 +0200 Subject: [PATCH 15/16] Documenting functions --- include/linphone/call.h | 8 ++++++-- include/linphone/error_info.h | 3 ++- tester/call_single_tester.c | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/include/linphone/call.h b/include/linphone/call.h index 6614fb16d..9cbe17ad1 100644 --- a/include/linphone/call.h +++ b/include/linphone/call.h @@ -203,9 +203,12 @@ LINPHONE_PUBLIC int linphone_call_take_preview_snapshot(LinphoneCall *call, cons **/ LINPHONE_PUBLIC LinphoneReason linphone_call_get_reason(const LinphoneCall *call); + /** * Returns full details about call errors or termination reasons. -**/ + * @param call LinphoneCall object on which we want the information error + * @return LinphoneErrorInfo object holding the reason error. + */ LINPHONE_PUBLIC const LinphoneErrorInfo *linphone_call_get_error_info(const LinphoneCall *call); /** @@ -381,7 +384,8 @@ LINPHONE_PUBLIC int linphone_call_resume(LinphoneCall *call); /** * Terminates a call. - * @param[in] call LinphoneCall object + * @param[in] call LinphoneCall object + * @param[in] ei LinphoneErrorInfo * @return 0 on success, -1 on failure **/ LINPHONE_PUBLIC int linphone_call_terminate_with_error_info(LinphoneCall *call, const LinphoneErrorInfo *ei); diff --git a/include/linphone/error_info.h b/include/linphone/error_info.h index 8336c7ae8..025a18e66 100644 --- a/include/linphone/error_info.h +++ b/include/linphone/error_info.h @@ -112,7 +112,8 @@ LINPHONE_PUBLIC int linphone_error_info_get_protocol_code(const LinphoneErrorInf LINPHONE_PUBLIC void linphone_error_info_set(LinphoneErrorInfo *ei, const char *protocol, LinphoneReason reason, int code, const char *status_string, const char *warning); /** - * [linphone_error_info_set_sub_error_info description] + * Set the sub_ei in LinphoneErrorInfo to another LinphoneErrorInfo. + * Used when there is more than one reason header. * @param[in] ei LinphoneErrorInfo object to which the other LinphoneErrorInfo will be appended as ei->sub_ei. * @param[in] appended_ei LinphoneErrorInfo to append */ diff --git a/tester/call_single_tester.c b/tester/call_single_tester.c index 5acadc44d..a63347a4a 100644 --- a/tester/call_single_tester.c +++ b/tester/call_single_tester.c @@ -1216,13 +1216,13 @@ static void call_declined_with_error(void) { if (in_call) { linphone_call_ref(in_call); linphone_call_decline_with_error(in_call, ei); - // linphone_call_terminate(in_call); BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallEnd,1)); BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallEnd,1)); rcvd_ei = linphone_call_get_error_info(out_call); sub_rcvd_ei = linphone_error_info_get_sub(rcvd_ei); + BC_ASSERT_STRING_EQUAL(linphone_error_info_get_phrase(rcvd_ei), "Decline"); BC_ASSERT_STRING_EQUAL(linphone_error_info_get_protocol(rcvd_ei), "SIP"); BC_ASSERT_STRING_EQUAL(linphone_error_info_get_phrase(sub_rcvd_ei), "J'ai plus de batterie"); From 34c276541ea4cc5a14a66164460d4fe200ab7b61 Mon Sep 17 00:00:00 2001 From: Sandrine Avakian Date: Wed, 12 Apr 2017 10:35:32 +0200 Subject: [PATCH 16/16] Renaming linphone_call_decline_with_error into linphone_call_decline_with_error_info --- coreapi/linphonecall.c | 4 ++-- include/linphone/call.h | 2 +- tester/call_single_tester.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 66927da34..4760aee76 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -5192,7 +5192,7 @@ int linphone_call_terminate_with_error_info(LinphoneCall *call , const LinphoneE case LinphoneCallIncomingReceived: case LinphoneCallIncomingEarlyMedia: linphone_error_info_set_reason(p_ei, LinphoneReasonDeclined); - return linphone_call_decline_with_error(call, p_ei); + return linphone_call_decline_with_error_info(call, p_ei); case LinphoneCallOutgoingInit: /* In state OutgoingInit, op has to be destroyed */ sal_op_release(call->op); @@ -5258,7 +5258,7 @@ int linphone_call_decline(LinphoneCall * call, LinphoneReason reason) { } -int linphone_call_decline_with_error(LinphoneCall * call, const LinphoneErrorInfo *ei) { +int linphone_call_decline_with_error_info(LinphoneCall * call, const LinphoneErrorInfo *ei) { SalErrorInfo sei; sal_error_info_init_to_null(&sei); SalErrorInfo sub_sei; diff --git a/include/linphone/call.h b/include/linphone/call.h index 9cbe17ad1..56bd6480a 100644 --- a/include/linphone/call.h +++ b/include/linphone/call.h @@ -412,7 +412,7 @@ LINPHONE_PUBLIC int linphone_call_decline(LinphoneCall * call, LinphoneReason re * @param[in] ei LinphoneErrorInfo containing more information on the call rejection. * @return 0 on success, -1 on failure */ -LINPHONE_PUBLIC int linphone_call_decline_with_error(LinphoneCall * call, const LinphoneErrorInfo *ei); +LINPHONE_PUBLIC int linphone_call_decline_with_error_info(LinphoneCall * call, const LinphoneErrorInfo *ei); /** * Accept an incoming call. diff --git a/tester/call_single_tester.c b/tester/call_single_tester.c index d456ad5d4..c2cb29b7e 100644 --- a/tester/call_single_tester.c +++ b/tester/call_single_tester.c @@ -1215,7 +1215,7 @@ static void call_declined_with_error(void) { BC_ASSERT_PTR_NOT_NULL(in_call=linphone_core_get_current_call(callee_mgr->lc)); if (in_call) { linphone_call_ref(in_call); - linphone_call_decline_with_error(in_call, ei); + linphone_call_decline_with_error_info(in_call, ei); BC_ASSERT_TRUE(wait_for(caller_mgr->lc,callee_mgr->lc,&callee_mgr->stat.number_of_LinphoneCallEnd,1)); BC_ASSERT_TRUE(wait_for(callee_mgr->lc,caller_mgr->lc,&caller_mgr->stat.number_of_LinphoneCallEnd,1));