Commit 4073c6e0 authored by jehan's avatar jehan
Browse files

Restaure previous state in case of call update failure due to pending transaction

parent 36eea822
......@@ -490,6 +490,7 @@ Sal * sal_init(){
sal->tls_verify_cn=TRUE;
sal->refresher_retry_after=60000; /*default value in ms*/
sal->enable_sip_update=TRUE;
sal->pending_trans_checking=TRUE;
return sal;
}
......@@ -1172,3 +1173,12 @@ void sal_default_set_sdp_handling(Sal *sal, SalOpSDPHandling sdp_handling_method
if (sdp_handling_method != SalOpSDPNormal ) ms_message("Enabling special SDP handling for all new SalOp in Sal[%p]!", sal);
sal->default_sdp_handling = sdp_handling_method;
}
bool_t sal_pending_trans_checking_enabled(const Sal *sal) {
return sal->pending_trans_checking;
}
int sal_enable_pending_trans_checking(Sal *sal, bool_t value) {
sal->pending_trans_checking = value;
return 0;
}
......@@ -51,6 +51,7 @@ struct Sal{
bool_t no_initial_route;
bool_t enable_sip_update; /*true by default*/
SalOpSDPHandling default_sdp_handling;
bool_t pending_trans_checking; /*testing purpose*/
};
typedef enum SalOpState {
......
......@@ -889,6 +889,8 @@ int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*opti
int sal_call_update(SalOp *op, const char *subject, bool_t no_user_consent){
belle_sip_request_t *update;
belle_sip_dialog_state_t state=belle_sip_dialog_get_state(op->dialog);
belle_sip_dialog_enable_pending_trans_checking(op->dialog,op->base.root->pending_trans_checking);
/*check for dialog state*/
if ( state == BELLE_SIP_DIALOG_CONFIRMED) {
if (no_user_consent)
......@@ -906,6 +908,11 @@ int sal_call_update(SalOp *op, const char *subject, bool_t no_user_consent){
sal_op_fill_invite(op, update);
return sal_op_send_request(op,update);
}
/*it failed why ?*/
if (belle_sip_dialog_request_pending(op->dialog))
sal_error_info_set(&op->error_info,SalReasonRequestPending,491,NULL,NULL);
else
sal_error_info_set(&op->error_info,SalReasonUnknown,500,NULL,NULL);
return -1;
}
......
......@@ -613,7 +613,10 @@ void set_or_update_dialog(SalOp* op, belle_sip_dialog_t* dialog) {
unlink_op_with_dialog(op,op->dialog);
op->dialog=NULL;
}
if (dialog) op->dialog=link_op_with_dialog(op,dialog);
if (dialog) {
op->dialog=link_op_with_dialog(op,dialog);
belle_sip_dialog_enable_pending_trans_checking(dialog,op->base.root->pending_trans_checking);
}
}
sal_op_unref(op);
}
......
......@@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
int sal_send_info(SalOp *op, const char *from, const char *to, const SalBody *body){
if (op->dialog){
belle_sip_dialog_enable_pending_trans_checking(op->dialog,op->base.root->pending_trans_checking);
belle_sip_request_t *req=belle_sip_dialog_create_queued_request(op->dialog,"INFO");
sal_op_add_body(op,(belle_sip_message_t*)req,body);
return sal_op_send_request(op,req);
......
......@@ -3270,12 +3270,13 @@ int linphone_core_start_update_call(LinphoneCore *lc, LinphoneCall *call){
**/
int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const LinphoneCallParams *params){
int err=0;
LinphoneCallState nextstate;
LinphoneCallState nextstate, initial_state;
#if defined(VIDEO_ENABLED) && defined(BUILD_UPNP)
bool_t has_video = FALSE;
#endif
switch(call->state){
switch(initial_state=call->state){
case LinphoneCallIncomingReceived:
case LinphoneCallIncomingEarlyMedia:
case LinphoneCallOutgoingRinging:
......@@ -3328,7 +3329,11 @@ int linphone_core_update_call(LinphoneCore *lc, LinphoneCall *call, const Linpho
}
}
#endif //defined(VIDEO_ENABLED) && defined(BUILD_UPNP)
err = linphone_core_start_update_call(lc, call);
if ((err = linphone_core_start_update_call(lc, call)) && call->state!=initial_state) {
/*Restore initial state*/
linphone_call_set_state(call,initial_state,NULL);
}
}else{
#ifdef VIDEO_ENABLED
if ((call->videostream != NULL) && (call->state == LinphoneCallStreamsRunning)) {
......
......@@ -800,6 +800,11 @@ 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);
LINPHONE_PUBLIC bool_t sal_pending_trans_checking_enabled(const Sal *sal) ;
LINPHONE_PUBLIC int sal_enable_pending_trans_checking(Sal *sal, bool_t 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);
......
......@@ -2829,17 +2829,15 @@ static void call_established_with_complex_rejected_operation(void) {
linphone_call_send_info_message(linphone_core_get_current_call(marie->lc),linphone_core_create_info_message(marie->lc));
/*by chance, UPDATES can be sent in // to invite, but drawback is that it will not be rejected with 491*/
params=linphone_core_create_call_params(marie->lc,linphone_core_get_current_call(marie->lc));
params->no_user_consent=TRUE;
sal_enable_pending_trans_checking(marie->lc->sal,FALSE); /*to allow // transactions*/
linphone_core_enable_payload_type(marie->lc,linphone_core_find_payload_type(marie->lc,"PCMU",8000,1),TRUE);
linphone_core_enable_payload_type(marie->lc,linphone_core_find_payload_type(marie->lc,"PCMA",8000,1),FALSE);
linphone_core_update_call( marie->lc
,linphone_core_get_current_call(marie->lc)
,params);
linphone_call_params_destroy(params);
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,3));
......@@ -2859,6 +2857,58 @@ static void call_established_with_complex_rejected_operation(void) {
linphone_core_manager_destroy(pauline);
}
static void call_established_with_rejected_info_during_reinvite(void) {
LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
bool_t call_ok=FALSE;
BC_ASSERT_TRUE((call_ok=call(pauline,marie)));
if (call_ok){
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,1));
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&marie->stat.number_of_LinphoneCallStreamsRunning,1));
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_enable_payload_type(marie->lc,linphone_core_find_payload_type(marie->lc,"PCMU",8000,1),FALSE); /*disable PCMU*/
linphone_core_enable_payload_type(marie->lc,linphone_core_find_payload_type(marie->lc,"PCMA",8000,1),TRUE); /*enable PCMA*/
/*just to authenticate marie*/
linphone_call_send_info_message(linphone_core_get_current_call(marie->lc),linphone_core_create_info_message(marie->lc));
BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_inforeceived,1));
BC_ASSERT_EQUAL(pauline->stat.number_of_inforeceived,1, int, "%d");
/*to give time for 200ok to arrive*/
wait_for_until(marie->lc,pauline->lc,NULL,0,1000);
//sal_enable_pending_trans_checking(marie->lc->sal,FALSE); /*to allow // transactions*/
linphone_call_send_info_message(linphone_core_get_current_call(marie->lc),linphone_core_create_info_message(marie->lc));
//sal_set_send_error(marie->lc->sal, -1); /*to avoid 491 pending to be sent*/
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)));
wait_for_until(pauline->lc,pauline->lc,NULL,0,2000); /*to avoid 491 pending to be sent to early*/
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,2));
/*just to sleep*/
linphone_core_terminate_all_calls(pauline->lc);
BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
BC_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");
......@@ -2987,22 +3037,32 @@ static void call_redirect(void){
}
static void call_established_with_rejected_reinvite_with_error(void) {
static void call_established_with_rejected_reinvite_with_error_base(bool_t trans_pending) {
LinphoneCoreManager* marie = linphone_core_manager_new("marie_rc");
LinphoneCoreManager* pauline = linphone_core_manager_new(transport_supported(LinphoneTransportTls) ? "pauline_rc" : "pauline_tcp_rc");
bool_t call_ok=TRUE;
int result;
BC_ASSERT_TRUE((call_ok=call(pauline,marie)));
if (call_ok){
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);
if (trans_pending) {
LinphoneInfoMessage * info = linphone_core_create_info_message(pauline->lc);
linphone_call_send_info_message(linphone_core_get_current_call(pauline->lc),info);
linphone_core_update_call( pauline->lc
} else
sal_enable_unconditional_answer(marie->lc->sal,TRUE);
result = 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)));
if (trans_pending)
BC_ASSERT_NOT_EQUAL(result,0, int, "%d");
else
BC_ASSERT_EQUAL(result,0,int, "%d");
BC_ASSERT_TRUE(wait_for(marie->lc,pauline->lc,&pauline->stat.number_of_LinphoneCallStreamsRunning,2));
......@@ -3012,6 +3072,9 @@ static void call_established_with_rejected_reinvite_with_error(void) {
check_call_state(pauline,LinphoneCallStreamsRunning);
check_call_state(marie,LinphoneCallStreamsRunning);
if (!trans_pending)
sal_enable_unconditional_answer(marie->lc->sal,FALSE);
/*just to sleep*/
linphone_core_terminate_all_calls(pauline->lc);
BC_ASSERT_TRUE(wait_for(pauline->lc,marie->lc,&pauline->stat.number_of_LinphoneCallEnd,1));
......@@ -3022,6 +3085,14 @@ static void call_established_with_rejected_reinvite_with_error(void) {
linphone_core_manager_destroy(pauline);
}
static void call_established_with_rejected_reinvite_with_error(void) {
call_established_with_rejected_reinvite_with_error_base(FALSE);
}
static void call_established_with_rejected_reinvite_with_trans_pending_error(void) {
call_established_with_rejected_reinvite_with_error_base(TRUE);
}
static void call_rejected_because_wrong_credentials_with_params(const char* user_agent,bool_t enable_auth_req_cb) {
LinphoneCoreManager* marie = linphone_core_manager_new( "marie_rc");
LinphoneAuthInfo* good_auth_info=linphone_auth_info_clone(linphone_core_find_auth_info(marie->lc,NULL,linphone_address_get_username(marie->identity),NULL));
......@@ -4339,7 +4410,9 @@ test_t call_tests[] = {
{ "Call established with rejected RE-INVITE",call_established_with_rejected_reinvite},
{ "Call established with rejected incoming RE-INVITE", call_established_with_rejected_incoming_reinvite },
{ "Call established with rejected RE-INVITE in error", call_established_with_rejected_reinvite_with_error},
{ "Call established with rejected RE-INVITE with trans pending error", call_established_with_rejected_reinvite_with_trans_pending_error},
{ "Call established with complex rejected operation",call_established_with_complex_rejected_operation},
{ "Call established with rejected info during re-invite",call_established_with_rejected_info_during_reinvite},
{ "Call redirected by callee", call_redirect},
{ "Call with specified codec bitrate", call_with_specified_codec_bitrate},
{ "Call with in-dialog UPDATE request", call_with_in_dialog_update },
......
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