Commit 08d0a608 authored by Simon Morlat's avatar Simon Morlat
Browse files

automatically close call during early states when the initiating transaction...

automatically close call during early states when the initiating transaction is closed prematurely (network disconnection for example).
add new tests for this.
parent 73cfad32
......@@ -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*/
......
......@@ -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:
......
......@@ -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 }
};
......
......@@ -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;
......
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