Commit 92c8c0e4 authored by Sandrine Avakian's avatar Sandrine Avakian

First commit for decline call with reason header support

parent a7a1c181
......@@ -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 {
......
......@@ -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;
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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();
......
......@@ -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);
......
......@@ -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.
......
......@@ -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.
......
......@@ -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);
/**
* @}
*/
......
......@@ -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);
......
......@@ -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),
......
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