mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-18 11:38:08 +00:00
Adding new API int linphone_call_terminate_with_error_info(LinphoneCall *call, const LinphoneErrorInfo *ei) and other functions to handle RFC3326 reason header.
This commit is contained in:
parent
6adccb389b
commit
ad337fffef
12 changed files with 166 additions and 14 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue