Commit a5c40fac authored by jehan's avatar jehan

add tests to make sure unsuccesfull incall transactions do not abort the call.

parent 5e6693d3
......@@ -848,3 +848,6 @@ void sal_resolve_cancel(Sal *sal, unsigned long id){
belle_sip_stack_resolve_cancel(sal->stack,id);
}
void sal_enable_unconditional_answer(Sal *sal,int value) {
belle_sip_provider_enable_unconditional_answer(sal->prov,value);
}
......@@ -570,7 +570,8 @@ static void handle_offer_answer_response(SalOp* op, belle_sip_response_t* respon
set_sdp_from_desc(BELLE_SIP_MESSAGE(response),op->base.local_media);
}else{
if (op->sdp_answer==NULL) sdp_process(op);
if (op->sdp_answer==NULL)
sdp_process(op);
if (op->sdp_answer){
set_sdp(BELLE_SIP_MESSAGE(response),op->sdp_answer);
......
......@@ -351,6 +351,9 @@ SalReason sal_reason_to_sip_code(SalReason r){
case SalReasonUnauthorized:
ret=401;
break;
case SalReasonNotAcceptable:
ret=488;
break;
}
return ret;
}
......@@ -390,6 +393,10 @@ void sal_compute_sal_errors_from_code(int code ,SalError* sal_err,SalReason* sal
break;
case 487:
break;
case 488:
*sal_err=SalErrorFailure;
*sal_reason=SalReasonNotAcceptable;
break;
case 491:
*sal_err=SalErrorFailure;
*sal_reason=SalReasonRequestPending;
......
......@@ -477,6 +477,16 @@ static void call_paused_by_remote(LinphoneCore *lc, LinphoneCall *call){
}
static void call_updated_by_remote(LinphoneCore *lc, LinphoneCall *call){
/*first check if media capabilities are compatible*/
SalMediaDescription* md;
linphone_call_make_local_media_description(lc,call);
sal_call_set_local_media_description(call->op,call->localdesc);
md=sal_call_get_final_media_description(call->op);
if (md && (sal_media_description_empty(md) || linphone_core_incompatible_security(lc,md))){
sal_call_decline(call->op,SalReasonNotAcceptable,NULL);
return;
}
if(lc->vtable.display_status)
lc->vtable.display_status(lc,_("Call is updated by remote."));
call->defer_update=FALSE;
......@@ -637,8 +647,10 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de
if (lc->vtable.display_status)
lc->vtable.display_status(lc,msg);
break;
case SalReasonNotAcceptable:
case SalReasonRequestPending:
/*restore previous state, the application will decide to resubmit the action if relevant*/
call->reason=linphone_reason_from_sal(sr);
linphone_call_set_state(call,call->prevstate,msg);
return;
break;
......@@ -648,6 +660,19 @@ static void call_failure(SalOp *op, SalError error, SalReason sr, const char *de
}
}
/*some call error are not fatal*/
switch (call->state) {
case LinphoneCallUpdating:
case LinphoneCallPausing:
case LinphoneCallResuming:
ms_message("Call error on state [%s], restoring previous state",linphone_call_state_to_string(call->prevstate));
call->reason=linphone_reason_from_sal(sr);
linphone_call_set_state(call, call->prevstate,msg);
return;
default:
break; /*nothing to do*/
}
linphone_core_stop_ringing(lc);
linphone_call_stop_media_streams(call);
......
......@@ -705,8 +705,10 @@ void linphone_call_set_state(LinphoneCall *call, LinphoneCallState cstate, const
return;
}
}
ms_message("Call %p: moving from state %s to %s",call,linphone_call_state_to_string(call->state),
linphone_call_state_to_string(cstate));
linphone_call_state_to_string(cstate));
if (cstate!=LinphoneCallRefered){
/*LinphoneCallRefered is rather an event, not a state.
Indeed it does not change the state of the call (still paused or running)*/
......
......@@ -5877,7 +5877,9 @@ const char *linphone_reason_to_string(LinphoneReason err){
case LinphoneReasonDoNotDisturb:
return "Do not distrub";
case LinphoneReasonUnauthorized:
return "Unauthorized";
return "Unauthorized";
case LinphoneReasonNotAcceptable:
return "Not acceptable here";
}
return "unknown error";
}
......
......@@ -150,7 +150,8 @@ enum _LinphoneReason{
LinphoneReasonMedia, /**<Incompatible media */
LinphoneReasonIOError, /**<Transport error: connection failures, disconnections etc...*/
LinphoneReasonDoNotDisturb, /**<Do not disturb reason*/
LinphoneReasonUnauthorized /**<Operation is unauthorized because missing credential*/
LinphoneReasonUnauthorized, /**<Operation is unauthorized because missing credential*/
LinphoneReasonNotAcceptable /**<Operation like call update rejected by peer*/
};
......
......@@ -1242,6 +1242,8 @@ SalReason linphone_reason_to_sal(LinphoneReason reason){
return SalReasonDoNotDisturb;
case LinphoneReasonUnauthorized:
return SalReasonUnauthorized;
case LinphoneReasonNotAcceptable:
return SalReasonNotAcceptable;
}
return SalReasonUnknown;
}
......@@ -1284,6 +1286,9 @@ LinphoneReason linphone_reason_from_sal(SalReason r){
break;
case SalReasonUnauthorized:
ret=LinphoneReasonUnauthorized;
break;
case SalReasonNotAcceptable:
ret=LinphoneReasonNotAcceptable;
break;
}
return ret;
......
......@@ -526,6 +526,7 @@ const char* sal_reason_to_string(const SalReason reason) {
case SalReasonForbidden: return "SalReasonForbidden";
case SalReasonUnknown: return "SalReasonUnknown";
case SalReasonServiceUnavailable: return "SalReasonServiceUnavailable";
case SalReasonNotAcceptable: return "SalReasonNotAcceptable";
default: return "Unkown reason";
}
}
......
......@@ -287,7 +287,8 @@ typedef enum SalReason{
SalReasonUnknown,
SalReasonServiceUnavailable,
SalReasonRequestPending,
SalReasonUnauthorized
SalReasonUnauthorized,
SalReasonNotAcceptable
}SalReason;
const char* sal_reason_to_string(const SalReason reason);
......@@ -303,7 +304,7 @@ typedef enum SalPresenceStatus{
SalPresenceDonotdisturb,
SalPresenceMoved,
SalPresenceAltService,
SalPresenceOnVacation
SalPresenceOnVacation
}SalPresenceStatus;
struct _SalPresenceModel;
......@@ -627,6 +628,10 @@ void __sal_op_free(SalOp *b);
LINPHONE_PUBLIC void sal_set_send_error(Sal *sal,int value);
/*1 for no error*/
LINPHONE_PUBLIC void sal_set_recv_error(Sal *sal,int value);
/*always answer 480 if value=true*/
LINPHONE_PUBLIC void sal_enable_unconditional_answer(Sal *sal,int value);
/*refresher retry after value in ms*/
LINPHONE_PUBLIC void sal_set_refresher_retry_after(Sal *sal,int value);
LINPHONE_PUBLIC int sal_get_refresher_retry_after(const Sal *sal);
......
......@@ -1217,6 +1217,107 @@ static void call_transfer_existing_call_outgoing_call(void) {
ms_list_free(lcs);
}
static void check_call_state(LinphoneCoreManager* mgr,LinphoneCallState state) {
CU_ASSERT_PTR_NOT_NULL(linphone_core_get_current_call(mgr->lc));
if (linphone_core_get_current_call(mgr->lc))
CU_ASSERT_EQUAL(linphone_call_get_state(linphone_core_get_current_call(mgr->lc)),state);
}
static void call_established_with_rejected_info(void) {
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
int dummy=0;
CU_ASSERT_TRUE(call(pauline,marie));
sal_enable_unconditional_answer(marie->lc->sal,TRUE);
linphone_call_send_info_message(linphone_core_get_current_call(pauline->lc),linphone_core_create_info_message(pauline->lc));
wait_for_until(marie->lc,pauline->lc,&dummy,1,1000); /*just to sleep while iterating 1s*/
sal_enable_unconditional_answer(marie->lc->sal,FALSE);
linphone_call_send_info_message(linphone_core_get_current_call(pauline->lc),linphone_core_create_info_message(pauline->lc));
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_inforeceived,1));
CU_ASSERT_EQUAL(marie->stat.number_of_inforeceived,1);
check_call_state(pauline,LinphoneCallStreamsRunning);
check_call_state(marie,LinphoneCallStreamsRunning);
/*just to sleep*/
linphone_core_terminate_all_calls(pauline->lc);
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1));
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
static void call_established_with_rejected_reinvite(void) {
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
CU_ASSERT_TRUE(call(pauline,marie));
linphone_core_enable_payload_type(pauline->lc,linphone_core_find_payload_type(pauline->lc,"PCMU",8000,1),FALSE); /*disable PCMU*/
linphone_core_enable_payload_type(pauline->lc,linphone_core_find_payload_type(pauline->lc,"PCMA",8000,1),TRUE); /*enable PCMA*/
linphone_core_update_call( pauline->lc
,linphone_core_get_current_call(pauline->lc)
,linphone_call_get_current_params(linphone_core_get_current_call(pauline->lc)));
CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,2));
CU_ASSERT_EQUAL(linphone_call_get_reason(linphone_core_get_current_call(pauline->lc)),LinphoneReasonNotAcceptable);
CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallStreamsRunning,1);
check_call_state(pauline,LinphoneCallStreamsRunning);
check_call_state(marie,LinphoneCallStreamsRunning);
/*just to sleep*/
linphone_core_terminate_all_calls(pauline->lc);
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1));
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
static void call_established_with_rejected_reinvite_with_error(void) {
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
CU_ASSERT_TRUE(call(pauline,marie));
linphone_core_enable_payload_type(pauline->lc,linphone_core_find_payload_type(pauline->lc,"PCMA",8000,1),TRUE); /*add PCMA*/
sal_enable_unconditional_answer(marie->lc->sal,TRUE);
linphone_core_update_call( pauline->lc
,linphone_core_get_current_call(pauline->lc)
,linphone_call_get_current_params(linphone_core_get_current_call(pauline->lc)));
CU_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,2));
CU_ASSERT_EQUAL(linphone_call_get_reason(linphone_core_get_current_call(pauline->lc)),LinphoneReasonNone); /*might be change later*/
CU_ASSERT_EQUAL(marie->stat.number_of_LinphoneCallStreamsRunning,1);
check_call_state(pauline,LinphoneCallStreamsRunning);
check_call_state(marie,LinphoneCallStreamsRunning);
/*just to sleep*/
linphone_core_terminate_all_calls(pauline->lc);
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1));
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
#ifdef VIDEO_ENABLED
#endif
......@@ -1252,7 +1353,10 @@ test_t call_tests[] = {
{ "Unattended call transfer with error", unattended_call_transfer_with_error },
{ "Call transfer existing call outgoing call", call_transfer_existing_call_outgoing_call },
{ "Call with ICE", call_with_ice },
{ "Call with custom headers",call_with_custom_headers}
{ "Call with custom headers",call_with_custom_headers},
{ "Call established with rejected INFO",call_established_with_rejected_info},
{ "Call established with rejected RE-INVITE",call_established_with_rejected_reinvite},
{ "Call established with rejected RE-INVITE in error", call_established_with_rejected_reinvite_with_error}
};
test_suite_t call_test_suite = {
......
......@@ -153,7 +153,7 @@ bool_t wait_for_list(MSList* lcs,int* counter,int value,int timeout_ms) {
else return TRUE;
}
static void enable_codec(LinphoneCore* lc,const char* type,int rate) {
static void set_codec_enable(LinphoneCore* lc,const char* type,int rate,bool_t enable) {
MSList* codecs=ms_list_copy(linphone_core_get_audio_codecs(lc));
MSList* codecs_it;
PayloadType* pt;
......@@ -161,11 +161,14 @@ static void enable_codec(LinphoneCore* lc,const char* type,int rate) {
linphone_core_enable_payload_type(lc,(PayloadType*)codecs_it->data,0);
}
if((pt = linphone_core_find_payload_type(lc,type,rate,1))) {
linphone_core_enable_payload_type(lc,pt, 1);
linphone_core_enable_payload_type(lc,pt, enable);
}
ms_list_free(codecs);
}
static void enable_codec(LinphoneCore* lc,const char* type,int rate) {
set_codec_enable(lc,type,rate,TRUE);
}
stats * get_stats(LinphoneCore *lc){
LinphoneCoreManager *manager=(LinphoneCoreManager *)linphone_core_get_user_data(lc);
return &manager->stat;
......
......@@ -155,7 +155,7 @@ typedef struct _stats {
const LinphonePresenceModel *last_received_presence;
int number_of_inforeceived;
int number_of_inforeceived_with_body;
LinphoneInfoMessage* last_received_info_message;
int number_of_LinphoneSubscriptionIncomingReceived;
int number_of_LinphoneSubscriptionOutgoingInit;
......
......@@ -11,7 +11,7 @@ incoming_calls_early_media=1
username=marie
userid=marie
passwd=secret
realm="sip.example.org"
realm=sip.example.org
[proxy_0]
......
......@@ -11,7 +11,7 @@ sdp_200_ack=1
username=marie
userid=marie
passwd=secret
realm="sip.example.org"
realm=sip.example.org
[proxy_0]
......
......@@ -10,7 +10,7 @@ register_only_when_network_is_up=0
username=marie
userid=marie
passwd=secret
realm="sip.example.org"
realm=sip.example.org
[proxy_0]
......
......@@ -198,23 +198,12 @@ static const char *info_content="<somexml>blabla</somexml>";
void info_message_received(LinphoneCore *lc, LinphoneCall* call, const LinphoneInfoMessage *msg){
stats* counters = get_stats(lc);
const char *hvalue=linphone_info_message_get_header(msg, "Weather");
const LinphoneContent *content=linphone_info_message_get_content(msg);
CU_ASSERT_PTR_NOT_NULL_FATAL(hvalue);
CU_ASSERT_TRUE(strcmp(hvalue,"still bad")==0);
if (!content){
counters->number_of_inforeceived++;
}else{
CU_ASSERT_PTR_NOT_NULL_FATAL(content->data);
CU_ASSERT_PTR_NOT_NULL_FATAL(content->type);
CU_ASSERT_PTR_NOT_NULL_FATAL(content->subtype);
CU_ASSERT_TRUE(strcmp(content->type,"application")==0);
CU_ASSERT_TRUE(strcmp(content->subtype,"somexml")==0);
CU_ASSERT_TRUE(strcmp((const char*)content->data,info_content)==0);
CU_ASSERT_EQUAL(content->size,strlen(info_content));
counters->number_of_inforeceived_with_body++;
if (counters->last_received_info_message) {
linphone_info_message_destroy(counters->last_received_info_message);
}
counters->last_received_info_message=linphone_info_message_copy(msg);
counters->number_of_inforeceived++;
}
......@@ -223,9 +212,11 @@ static void info_message_with_args(bool_t with_content) {
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
LinphoneInfoMessage *info;
const LinphoneContent *content;
const char *hvalue;
CU_ASSERT_TRUE(call(pauline,marie));
info=linphone_core_create_info_message(marie->lc);
linphone_info_message_add_header(info,"Weather","still bad");
if (with_content) {
......@@ -238,11 +229,28 @@ static void info_message_with_args(bool_t with_content) {
}
linphone_call_send_info_message(linphone_core_get_current_call(marie->lc),info);
linphone_info_message_destroy(info);
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_inforeceived,1));
CU_ASSERT_PTR_NOT_NULL(pauline->stat.last_received_info_message);
hvalue=linphone_info_message_get_header(pauline->stat.last_received_info_message, "Weather");
content=linphone_info_message_get_content(pauline->stat.last_received_info_message);
CU_ASSERT_PTR_NOT_NULL(hvalue);
if (hvalue)
CU_ASSERT_TRUE(strcmp(hvalue,"still bad")==0);
if (with_content){
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_inforeceived_with_body,1));
}else{
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_inforeceived,1));
CU_ASSERT_PTR_NOT_NULL(content);
if (content) {
CU_ASSERT_PTR_NOT_NULL(content->data);
CU_ASSERT_PTR_NOT_NULL(content->type);
CU_ASSERT_PTR_NOT_NULL(content->subtype);
if (content->type) CU_ASSERT_TRUE(strcmp(content->type,"application")==0);
if (content->subtype) CU_ASSERT_TRUE(strcmp(content->subtype,"somexml")==0);
if (content->data)CU_ASSERT_TRUE(strcmp((const char*)content->data,info_content)==0);
CU_ASSERT_EQUAL(content->size,strlen(info_content));
}
}
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
......
......@@ -8,25 +8,25 @@ default_proxy=0
username=liblinphone_tester
userid=liblinphone_tester
passwd=secret
realm="auth.example.org"
realm=auth.example.org
[auth_info_1]
username=pauline
userid=pauline
passwd=secret
realm="sip.example.org"
realm=sip.example.org
[auth_info_2]
username=liblinphone_tester
userid=liblinphone_tester
passwd=secret
realm="auth1.example.org"
realm=auth1.example.org
[auth_info_3]
username=marie
userid=marie
passwd=secret
realm="sip.example.org"
realm=sip.example.org
[proxy_0]
reg_proxy=sip2.linphone.org;transport=tls
......
......@@ -10,7 +10,7 @@ register_only_when_network_is_up=0
username=pauline
userid=pauline
passwd=secret
realm="sip.example.org"
realm=sip.example.org
[proxy_0]
......
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