diff --git a/coreapi/bellesip_sal/sal_impl.c b/coreapi/bellesip_sal/sal_impl.c index f5235c808..f1ce73599 100644 --- a/coreapi/bellesip_sal/sal_impl.c +++ b/coreapi/bellesip_sal/sal_impl.c @@ -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); +} diff --git a/coreapi/bellesip_sal/sal_op_call.c b/coreapi/bellesip_sal/sal_op_call.c index 66aaa4890..80173e95d 100644 --- a/coreapi/bellesip_sal/sal_op_call.c +++ b/coreapi/bellesip_sal/sal_op_call.c @@ -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); diff --git a/coreapi/bellesip_sal/sal_op_impl.c b/coreapi/bellesip_sal/sal_op_impl.c index 13b3ba004..3bf2e5ea6 100644 --- a/coreapi/bellesip_sal/sal_op_impl.c +++ b/coreapi/bellesip_sal/sal_op_impl.c @@ -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; diff --git a/coreapi/callbacks.c b/coreapi/callbacks.c index 844a06e47..fe57a5dfd 100644 --- a/coreapi/callbacks.c +++ b/coreapi/callbacks.c @@ -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); diff --git a/coreapi/linphonecall.c b/coreapi/linphonecall.c index 8036c7f10..6b27f1333 100644 --- a/coreapi/linphonecall.c +++ b/coreapi/linphonecall.c @@ -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)*/ diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c index 1a879c4a8..3f6e79ae0 100644 --- a/coreapi/linphonecore.c +++ b/coreapi/linphonecore.c @@ -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"; } diff --git a/coreapi/linphonecore.h b/coreapi/linphonecore.h index 4b2d34a9b..dbf3779ec 100644 --- a/coreapi/linphonecore.h +++ b/coreapi/linphonecore.h @@ -150,7 +150,8 @@ enum _LinphoneReason{ LinphoneReasonMedia, /**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 = { diff --git a/tester/liblinphone_tester.c b/tester/liblinphone_tester.c index 6492af82c..7b34e7f45 100644 --- a/tester/liblinphone_tester.c +++ b/tester/liblinphone_tester.c @@ -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; diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h index fa8c7a632..8d80eb2b6 100644 --- a/tester/liblinphone_tester.h +++ b/tester/liblinphone_tester.h @@ -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; diff --git a/tester/marie_early_rc b/tester/marie_early_rc index 65934c3f3..36c302a4f 100644 --- a/tester/marie_early_rc +++ b/tester/marie_early_rc @@ -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] diff --git a/tester/marie_no_sdp_rc b/tester/marie_no_sdp_rc index a3733dd83..50a740dca 100644 --- a/tester/marie_no_sdp_rc +++ b/tester/marie_no_sdp_rc @@ -11,7 +11,7 @@ sdp_200_ack=1 username=marie userid=marie passwd=secret -realm="sip.example.org" +realm=sip.example.org [proxy_0] diff --git a/tester/marie_rc b/tester/marie_rc index e221f6fad..d5b7d7c87 100644 --- a/tester/marie_rc +++ b/tester/marie_rc @@ -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] diff --git a/tester/message_tester.c b/tester/message_tester.c index f5388b0ab..5b111a302 100644 --- a/tester/message_tester.c +++ b/tester/message_tester.c @@ -198,23 +198,12 @@ static const char *info_content="blabla"; 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); diff --git a/tester/multi_account_lrc b/tester/multi_account_lrc index 23705a733..a78a5bc16 100644 --- a/tester/multi_account_lrc +++ b/tester/multi_account_lrc @@ -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 diff --git a/tester/pauline_rc b/tester/pauline_rc index 1589d2cdb..204486f66 100644 --- a/tester/pauline_rc +++ b/tester/pauline_rc @@ -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]