mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-05-06 21:33:08 +00:00
Fix case where a call is cancelled by a user while no provisionnal response has been received yet (was not functional)
Add a test for this case. Reformat the code for indentation and break statement positions.
This commit is contained in:
parent
0942ba67a6
commit
491294b279
4 changed files with 86 additions and 54 deletions
|
|
@ -173,7 +173,7 @@ static void cancelling_invite(SalOp* op ){
|
|||
op->state=SalOpStateTerminating;
|
||||
}
|
||||
|
||||
static void call_response_event(void *op_base, const belle_sip_response_event_t *event){
|
||||
static void call_process_response(void *op_base, const belle_sip_response_event_t *event){
|
||||
SalOp* op = (SalOp*)op_base;
|
||||
belle_sip_request_t* ack;
|
||||
belle_sip_dialog_state_t dialog_state;
|
||||
|
|
@ -198,16 +198,20 @@ static void call_response_event(void *op_base, const belle_sip_response_event_t
|
|||
case BELLE_SIP_DIALOG_EARLY: {
|
||||
if (strcmp("INVITE",belle_sip_request_get_method(req))==0 ) {
|
||||
if (op->state == SalOpStateTerminating) {
|
||||
/*check if CANCEL was sent before*/
|
||||
if (strcmp("CANCEL",belle_sip_request_get_method(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_client_trans))))!=0) {
|
||||
/*it wasn't sent */
|
||||
if (code<200) {
|
||||
cancelling_invite(op);
|
||||
} else if (code<400) {
|
||||
sal_op_send_request(op,belle_sip_dialog_create_request(op->dialog,"BYE"));
|
||||
} else {
|
||||
/*nop ?*/
|
||||
}else{
|
||||
/* no need to send the INVITE because the UAS rejected the INVITE*/
|
||||
if (op->dialog==NULL) call_set_released(op);
|
||||
}
|
||||
} else {
|
||||
/*nop, already cancelled*/
|
||||
/*it was sent already, so just expect the 487 or any error response to send the call_released() notification*/
|
||||
if (code>=300){
|
||||
if (op->dialog==NULL) call_set_released(op);
|
||||
}
|
||||
}
|
||||
} else if (code >= 180 && code<300) {
|
||||
handle_sdp_from_response(op,response);
|
||||
|
|
@ -221,54 +225,51 @@ static void call_response_event(void *op_base, const belle_sip_response_event_t
|
|||
break;
|
||||
case BELLE_SIP_DIALOG_CONFIRMED: {
|
||||
switch (op->state) {
|
||||
case SalOpStateEarly:/*invite case*/
|
||||
case SalOpStateActive: /*re-invite case*/
|
||||
if (code >=200
|
||||
&& code<300
|
||||
&& strcmp("INVITE",belle_sip_request_get_method(req))==0) {
|
||||
handle_sdp_from_response(op,response);
|
||||
ack=belle_sip_dialog_create_ack(op->dialog,belle_sip_dialog_get_local_seq_number(op->dialog));
|
||||
if (ack==NULL) {
|
||||
ms_error("This call has been already terminated.");
|
||||
return ;
|
||||
case SalOpStateEarly:/*invite case*/
|
||||
case SalOpStateActive: /*re-invite case*/
|
||||
if (code >=200
|
||||
&& code<300
|
||||
&& strcmp("INVITE",belle_sip_request_get_method(req))==0) {
|
||||
handle_sdp_from_response(op,response);
|
||||
ack=belle_sip_dialog_create_ack(op->dialog,belle_sip_dialog_get_local_seq_number(op->dialog));
|
||||
if (ack==NULL) {
|
||||
ms_error("This call has been already terminated.");
|
||||
return ;
|
||||
}
|
||||
if (op->sdp_answer){
|
||||
set_sdp(BELLE_SIP_MESSAGE(ack),op->sdp_answer);
|
||||
belle_sip_object_unref(op->sdp_answer);
|
||||
op->sdp_answer=NULL;
|
||||
}
|
||||
belle_sip_dialog_send_ack(op->dialog,ack);
|
||||
op->base.root->callbacks.call_accepted(op); /*INVITE*/
|
||||
op->state=SalOpStateActive;
|
||||
} else if (code >= 300 && strcmp("INVITE",belle_sip_request_get_method(req))==0){
|
||||
call_set_error(op,response);
|
||||
} else {
|
||||
/*ignoring*/
|
||||
}
|
||||
if (op->sdp_answer){
|
||||
set_sdp(BELLE_SIP_MESSAGE(ack),op->sdp_answer);
|
||||
belle_sip_object_unref(op->sdp_answer);
|
||||
op->sdp_answer=NULL;
|
||||
}
|
||||
belle_sip_dialog_send_ack(op->dialog,ack);
|
||||
op->base.root->callbacks.call_accepted(op); /*INVITE*/
|
||||
|
||||
op->state=SalOpStateActive;
|
||||
} else if (code >= 300 && strcmp("INVITE",belle_sip_request_get_method(req))==0){
|
||||
call_set_error(op,response);
|
||||
} else {
|
||||
/*ignoring*/
|
||||
}
|
||||
break;
|
||||
case SalOpStateTerminating:
|
||||
//FIXME send bye
|
||||
case SalOpStateTerminated:
|
||||
default:
|
||||
ms_error("call op [%p] receive answer [%i] not implemented",op,code);
|
||||
break;
|
||||
case SalOpStateTerminating:
|
||||
sal_op_send_request(op,belle_sip_dialog_create_request(op->dialog,"BYE"));
|
||||
break;
|
||||
case SalOpStateTerminated:
|
||||
default:
|
||||
ms_error("Call op [%p] receives unexpected answer [%i] while in state [%s].",op,code, sal_op_state_to_string(op->state));
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case BELLE_SIP_DIALOG_TERMINATED: {
|
||||
if (code >= 300){
|
||||
call_set_error(op,response);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* no break */
|
||||
break;
|
||||
default: {
|
||||
ms_error("call op [%p] receive answer [%i] not implemented",op,code);
|
||||
}
|
||||
/* no break */
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void call_process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) {
|
||||
|
|
@ -553,7 +554,7 @@ int sal_call(SalOp *op, const char *from, const char *to){
|
|||
|
||||
void sal_op_call_fill_cbs(SalOp*op) {
|
||||
op->callbacks.process_io_error=call_process_io_error;
|
||||
op->callbacks.process_response_event=call_response_event;
|
||||
op->callbacks.process_response_event=call_process_response;
|
||||
op->callbacks.process_timeout=call_process_timeout;
|
||||
op->callbacks.process_transaction_terminated=call_process_transaction_terminated;
|
||||
op->callbacks.process_request_event=process_request_event;
|
||||
|
|
@ -741,15 +742,16 @@ int sal_call_terminate(SalOp *op){
|
|||
if (op->dir == SalOpDirIncoming) {
|
||||
sal_call_decline(op, SalReasonDeclined,NULL);
|
||||
op->state=SalOpStateTerminated;
|
||||
} else if (op->pending_client_trans
|
||||
&& belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(op->pending_client_trans)) == BELLE_SIP_TRANSACTION_PROCEEDING){
|
||||
cancelling_invite(op);
|
||||
break;
|
||||
} else {
|
||||
/*just schedule call released*/
|
||||
if (op->dialog==NULL) belle_sip_main_loop_do_later(belle_sip_stack_get_main_loop(op->base.root->stack)
|
||||
,(belle_sip_callback_t) call_set_released
|
||||
, op);
|
||||
} else if (op->pending_client_trans){
|
||||
if (belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(op->pending_client_trans)) == BELLE_SIP_TRANSACTION_PROCEEDING){
|
||||
cancelling_invite(op);
|
||||
}else{
|
||||
/* Case where the CANCEL cannot be sent because no provisional response was received so far.
|
||||
* The Op must be kept for the time of the transaction in case a response is received later.
|
||||
* The state is passed to Terminating to remember to terminate later.
|
||||
*/
|
||||
op->state=SalOpStateTerminating;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,9 @@ SalOp * sal_op_new(Sal *sal){
|
|||
}
|
||||
|
||||
void sal_op_release(SalOp *op){
|
||||
op->state=SalOpStateTerminated;
|
||||
/*if in terminating state, keep this state because it means we are waiting for a response to be able to terminate the operation.*/
|
||||
if (op->state!=SalOpStateTerminating)
|
||||
op->state=SalOpStateTerminated;
|
||||
sal_op_set_user_pointer(op,NULL);/*mandatory because releasing op doesn't not mean freeing op. Make sure back pointer will not be used later*/
|
||||
if (op->refresher) {
|
||||
belle_sip_refresher_stop(op->refresher);
|
||||
|
|
@ -413,6 +415,7 @@ bool_t sal_compute_sal_errors(belle_sip_response_t* response,SalError* sal_err,S
|
|||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void set_or_update_dialog(SalOp* op, belle_sip_dialog_t* dialog) {
|
||||
/*check if dialog has changed*/
|
||||
if (dialog && dialog != op->dialog) {
|
||||
|
|
|
|||
|
|
@ -4917,7 +4917,7 @@ int linphone_core_get_device_rotation(LinphoneCore *lc ) {
|
|||
*
|
||||
**/
|
||||
void linphone_core_set_device_rotation(LinphoneCore *lc, int rotation) {
|
||||
ms_message("%s : rotation=%d\n", __FUNCTION__, rotation);
|
||||
if (rotation!=lc->device_rotation) ms_message("%s : rotation=%d\n", __FUNCTION__, rotation);
|
||||
lc->device_rotation = rotation;
|
||||
#ifdef VIDEO_ENABLED
|
||||
{
|
||||
|
|
|
|||
|
|
@ -322,6 +322,32 @@ static void call_with_dns_time_out(void) {
|
|||
linphone_core_manager_destroy(marie);
|
||||
}
|
||||
|
||||
static void early_cancelled_call(void) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_alt_rc");
|
||||
|
||||
LinphoneCall* out_call = linphone_core_invite(pauline->lc,"sip:marie@sip.example.org");
|
||||
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallOutgoingInit,1));
|
||||
linphone_core_terminate_call(pauline->lc,out_call);
|
||||
|
||||
/*since everything is executed in a row, no response can be received from the server, thus the CANCEL cannot be sent.
|
||||
It will ring at Marie's side.*/
|
||||
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
|
||||
|
||||
CU_ASSERT_EQUAL(pauline->stat.number_of_LinphoneCallEnd,1);
|
||||
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallIncomingReceived,1));
|
||||
/* now the CANCEL should have been sent and the the call at marie's side should terminate*/
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&marie->stat.number_of_LinphoneCallEnd,1));
|
||||
|
||||
CU_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallReleased,1));
|
||||
|
||||
linphone_core_manager_destroy(marie);
|
||||
linphone_core_manager_destroy(pauline);
|
||||
}
|
||||
|
||||
static void cancelled_ringing_call(void) {
|
||||
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
|
||||
LinphoneCoreManager* pauline = linphone_core_manager_new( "pauline_rc");
|
||||
|
|
@ -1037,6 +1063,7 @@ test_t call_tests[] = {
|
|||
{ "Early declined call", early_declined_call },
|
||||
{ "Call declined", call_declined },
|
||||
{ "Cancelled call", cancelled_call },
|
||||
{ "Early cancelled call", early_cancelled_call},
|
||||
{ "Call with DNS timeout", call_with_dns_time_out },
|
||||
{ "Cancelled ringing call", cancelled_ringing_call },
|
||||
{ "Simple call", simple_call },
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue