Commit ad337fff authored by Sandrine Avakian's avatar Sandrine Avakian

Adding new API int linphone_call_terminate_with_error_info(LinphoneCall *call,...

Adding new API int linphone_call_terminate_with_error_info(LinphoneCall *call, const LinphoneErrorInfo *ei) and other functions to handle  RFC3326 reason header.
parent 6adccb38
......@@ -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,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment