automatically close call during early states when the initiating transaction is closed prematurely (network disconnection for example).

add new tests for this.
This commit is contained in:
Simon Morlat 2015-10-18 17:21:32 +02:00
parent 73cfad320d
commit 08d0a6089c
4 changed files with 58 additions and 6 deletions

View file

@ -357,6 +357,7 @@ static void call_process_transaction_terminated(void *user_ctx, const belle_sip_
belle_sip_server_transaction_t *server_transaction=belle_sip_transaction_terminated_event_get_server_transaction(event);
belle_sip_request_t* req;
belle_sip_response_t* resp;
int code = 0;
bool_t release_call=FALSE;
if (client_transaction) {
@ -366,12 +367,19 @@ static void call_process_transaction_terminated(void *user_ctx, const belle_sip_
req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(server_transaction));
resp=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(server_transaction));
}
if (op->state ==SalOpStateTerminating
if (resp) code = belle_sip_response_get_status_code(resp);
if (op->state == SalOpStateTerminating
&& strcmp("BYE",belle_sip_request_get_method(req))==0
&& (!resp || (belle_sip_response_get_status_code(resp) !=401
&& belle_sip_response_get_status_code(resp) !=407))
&& (!resp || (belle_sip_response_get_status_code(resp) != 401
&& belle_sip_response_get_status_code(resp) != 407))
&& op->dialog==NULL) {
release_call=TRUE;
}else if (op->state == SalOpStateEarly && code < 200){
/*call terminated early*/
sal_error_info_set(&op->error_info,SalReasonIOError,503,"I/O error",NULL);
op->base.root->callbacks.call_failure(op);
release_call=TRUE;
}
if (server_transaction){
if (op->pending_server_trans==server_transaction){
@ -546,10 +554,9 @@ static void process_request_event(void *op_base, const belle_sip_request_event_t
drop_op = TRUE;
}
break;
} /* else same behavior as for EARLY state*/
} /* else same behavior as for EARLY state, thus NO BREAK*/
}
case BELLE_SIP_DIALOG_EARLY: {
//hmm probably a cancel
if (strcmp("CANCEL",method)==0) {
if(belle_sip_request_event_get_server_transaction(event)) {
/*first answer 200 ok to cancel*/

View file

@ -4096,6 +4096,7 @@ static void linphone_call_lost(LinphoneCall *call, LinphoneReason reason){
linphone_core_notify_display_warning(lc, temp);
linphone_core_terminate_call(lc,call);
linphone_core_play_named_tone(lc,LinphoneToneCallLost);
ms_free(temp);
}
static void change_ice_media_destinations(LinphoneCall *call) {
@ -4721,11 +4722,14 @@ void linphone_call_set_broken(LinphoneCall *call){
case LinphoneCallOutgoingEarlyMedia:
case LinphoneCallIncomingReceived:
case LinphoneCallIncomingEarlyMedia:
linphone_call_lost(call, LinphoneReasonIOError);
/*during the early states, the SAL layer reports the failure from the dialog or transaction layer,
* hence, there is nothing special to do*/
break;
case LinphoneCallStreamsRunning:
case LinphoneCallPaused:
case LinphoneCallPausedByRemote:
/*during these states, the dialog is established. A failure of a transaction is not expected to close it.
* Instead we have to repair the dialog by sending a reINVITE*/
call->broken = TRUE;
break;
default:

View file

@ -3771,6 +3771,8 @@ static void video_call_snapshot(void) {
end_call(marie, pauline);
}
ms_free(filename);
linphone_call_params_unref(marieParams);
linphone_call_params_unref(paulineParams);
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
@ -5079,6 +5081,41 @@ static void call_record_with_custom_rtp_modifier(void) {
custom_rtp_modifier(FALSE, TRUE);
}
static void _call_with_network_switch_in_early_state(bool_t network_loosed_by_caller){
LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
linphone_core_invite_address(marie->lc, pauline->identity);
if (!BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallIncomingReceived, 1))) goto end;
if (!BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallOutgoingRinging, 1))) goto end;
if (network_loosed_by_caller){
linphone_core_set_network_reachable(marie->lc, FALSE);
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallError, 1));
linphone_core_set_network_reachable(marie->lc, TRUE);
linphone_core_terminate_call(pauline->lc, linphone_core_get_current_call(pauline->lc));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallEnd, 1));
}else{
linphone_core_set_network_reachable(pauline->lc, FALSE);
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallError, 1));
linphone_core_set_network_reachable(pauline->lc, TRUE);
linphone_core_terminate_call(marie->lc, linphone_core_get_current_call(marie->lc));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallEnd, 1));
}
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &marie->stat.number_of_LinphoneCallReleased, 1));
BC_ASSERT_TRUE(wait_for(marie->lc, pauline->lc, &pauline->stat.number_of_LinphoneCallReleased, 1));
end:
linphone_core_manager_destroy(marie);
linphone_core_manager_destroy(pauline);
}
static void call_with_network_switch_in_early_state_1(){
_call_with_network_switch_in_early_state(TRUE);
}
static void call_with_network_switch_in_early_state_2(){
_call_with_network_switch_in_early_state(FALSE);
}
static void _call_with_network_switch(bool_t use_ice, bool_t with_socket_refresh){
LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
@ -5507,6 +5544,8 @@ test_t call_tests[] = {
{ "Call paused resumed with custom RTP Modifier", call_paused_resumed_with_custom_rtp_modifier },
{ "Call record with custom RTP Modifier", call_record_with_custom_rtp_modifier },
{ "Call with network switch", call_with_network_switch },
{ "Call with network switch in early state 1", call_with_network_switch_in_early_state_1 },
{ "Call with network switch in early state 2", call_with_network_switch_in_early_state_2 },
{ "Call with network switch and ICE", call_with_network_switch_and_ice },
{ "Call with network switch with socket refresh", call_with_network_switch_and_socket_refresh }
};

View file

@ -99,6 +99,7 @@ static void auth_info_requested(LinphoneCore *lc, const char *realm, const char
void reset_counters( stats* counters) {
if (counters->last_received_chat_message) linphone_chat_message_unref(counters->last_received_chat_message);
if (counters->last_received_info_message) linphone_info_message_destroy(counters->last_received_info_message);
memset(counters,0,sizeof(stats));
}
@ -373,6 +374,7 @@ void linphone_core_manager_destroy(LinphoneCoreManager* mgr) {
if (mgr->stat.last_received_chat_message) {
linphone_chat_message_unref(mgr->stat.last_received_chat_message);
}
if (mgr->stat.last_received_info_message) linphone_info_message_destroy(mgr->stat.last_received_info_message);
if (mgr->lc){
const char *record_file=linphone_core_get_record_file(mgr->lc);
int unterminated_calls;