fix crash when receiving an invalid 200Ok for INVITE

This commit is contained in:
Simon Morlat 2015-10-24 10:10:52 +02:00
parent a4b116d4e4
commit aa7adfdac7
2 changed files with 46 additions and 17 deletions

View file

@ -32,8 +32,9 @@ static void call_set_released(SalOp* op){
}
}
static void call_set_error(SalOp* op,belle_sip_response_t* response){
static void call_set_error(SalOp* op,belle_sip_response_t* response, bool_t fatal){
sal_op_set_error_info_from_response(op,response);
if (fatal) op->state = SalOpStateTerminating;
op->base.root->callbacks.call_failure(op);
}
static void set_addr_to_0000(char value[]) {
@ -149,6 +150,7 @@ static void call_process_io_error(void *user_ctx, const belle_sip_io_error_event
/*call terminated very early*/
sal_error_info_set(&op->error_info,SalReasonIOError,503,"IO error",NULL);
op->base.root->callbacks.call_failure(op);
op->state = SalOpStateTerminating;
call_set_released(op);
} else {
/*dialog will terminated shortly, nothing to do*/
@ -162,6 +164,14 @@ static void process_dialog_terminated(void *ctx, const belle_sip_dialog_terminat
ms_message("Dialog [%p] terminated for op [%p]",belle_sip_dialog_terminated_event_get_dialog(event),op);
switch(belle_sip_dialog_get_previous_state(op->dialog)) {
case BELLE_SIP_DIALOG_EARLY:
case BELLE_SIP_DIALOG_NULL:
if (op->state!=SalOpStateTerminated && op->state!=SalOpStateTerminating) {
/*this is an early termination due to incorrect response received*/
op->base.root->callbacks.call_failure(op);
op->state=SalOpStateTerminating;
}
break;
case BELLE_SIP_DIALOG_CONFIRMED:
if (op->state!=SalOpStateTerminated && op->state!=SalOpStateTerminating) {
/*this is probably a normal termination from a BYE*/
@ -201,7 +211,23 @@ static void cancelling_invite(SalOp* op ){
belle_sip_request_t* cancel;
ms_message("Cancelling INVITE request from [%s] to [%s] ",sal_op_get_from(op), sal_op_get_to(op));
cancel = belle_sip_client_transaction_create_cancel(op->pending_client_trans);
sal_op_send_request(op,cancel);
if (cancel){
sal_op_send_request(op,cancel);
}else if (op->dialog){
belle_sip_dialog_state_t state = belle_sip_dialog_get_state(op->dialog);;
/*case where the response received is invalid (could not establish a dialog), but the transaction is not cancellable
* because already terminated*/
switch(state){
case BELLE_SIP_DIALOG_EARLY:
case BELLE_SIP_DIALOG_NULL:
/*force kill the dialog*/
ms_warning("op [%p]: force kill of dialog [%p]", op, op->dialog);
belle_sip_dialog_delete(op->dialog);
break;
default:
break;
}
}
op->state=SalOpStateTerminating;
}
@ -263,7 +289,7 @@ static void call_process_response(void *op_base, const belle_sip_response_event_
}
belle_sip_object_data_set(BELLE_SIP_OBJECT(dialog),"early_response",belle_sip_object_ref(response),belle_sip_object_unref);
} else if (code>=300){
call_set_error(op,response);
call_set_error(op, response, TRUE);
if (op->dialog==NULL) call_set_released(op);
}
} else if (code >=200
@ -295,7 +321,7 @@ static void call_process_response(void *op_base, const belle_sip_response_event_
op->base.root->callbacks.call_accepted(op); /*INVITE*/
op->state=SalOpStateActive;
}else if (code >= 300){
call_set_error(op,response);
call_set_error(op,response, FALSE);
}
}else if (strcmp("INFO",method)==0){
if (code == 491
@ -324,7 +350,7 @@ static void call_process_response(void *op_base, const belle_sip_response_event_
break;
case BELLE_SIP_DIALOG_TERMINATED: {
if (strcmp("INVITE",method)==0 && code >= 300){
call_set_error(op,response);
call_set_error(op,response, TRUE);
}
}
break;
@ -345,6 +371,7 @@ static void call_process_timeout(void *user_ctx, const belle_sip_timeout_event_t
/*call terminated very early*/
sal_error_info_set(&op->error_info,SalReasonRequestTimeout,408,"Request timeout",NULL);
op->base.root->callbacks.call_failure(op);
op->state = SalOpStateTerminating;
call_set_released(op);
} else {
/*dialog will terminated shortly, nothing to do*/
@ -378,6 +405,7 @@ static void call_process_transaction_terminated(void *user_ctx, const belle_sip_
}else if (op->state == SalOpStateEarly && code < 200){
/*call terminated early*/
sal_error_info_set(&op->error_info,SalReasonIOError,503,"I/O error",NULL);
op->state = SalOpStateTerminating;
op->base.root->callbacks.call_failure(op);
release_call=TRUE;
}
@ -396,6 +424,7 @@ static void call_process_transaction_terminated(void *user_ctx, const belle_sip_
static void call_terminated(SalOp* op,belle_sip_server_transaction_t* server_transaction, belle_sip_request_t* request,int status_code) {
belle_sip_response_t* resp;
op->state = SalOpStateTerminating;
op->base.root->callbacks.call_terminated(op,op->dir==SalOpDirIncoming?sal_op_get_from(op):sal_op_get_to(op));
resp=sal_op_create_response_from_request(op,request,status_code);
belle_sip_server_transaction_send_response(server_transaction,resp);

View file

@ -71,7 +71,7 @@ static FILE *sip_start(const char *senario, const char* dest_username, LinphoneA
#endif
}
#if 0
static FILE *sip_start_recv(const char *senario) {
#if HAVE_SIPP
char *command;
@ -88,7 +88,7 @@ static FILE *sip_start_recv(const char *senario) {
return NULL;
#endif
}
#endif
/*static void dest_server_server_resolved(void *data, const char *name, struct addrinfo *ai_list) {
*(struct addrinfo **)data =ai_list;
@ -306,7 +306,7 @@ static void call_with_multiple_video_mline_in_sdp() {
linphone_core_manager_destroy(mgr);
}
#if 0
static void call_invite_200ok_without_contact_header() {
LinphoneCoreManager *mgr;
char *identity_char;
@ -333,16 +333,18 @@ static void call_invite_200ok_without_contact_header() {
BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallOutgoingInit, 1));
BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallOutgoingProgress, 1));
BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallOutgoingRinging, 1));
if (call) {
BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallStreamsRunning, 1));
check_rtcp(call);
linphone_core_terminate_call(mgr->lc, call);
}
/*assert that the call never gets connected nor terminated*/
BC_ASSERT_FALSE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallConnected, 1));
BC_ASSERT_EQUAL(mgr->stat.number_of_LinphoneCallEnd, 0, int, "%d");
BC_ASSERT_EQUAL(mgr->stat.number_of_LinphoneCallError, 0, int, "%d");
linphone_core_terminate_call(mgr->lc, call);
BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallEnd, 1));
BC_ASSERT_TRUE(wait_for(mgr->lc, mgr->lc, &mgr->stat.number_of_LinphoneCallReleased, 1));
pclose(sipp_out);
}
linphone_core_manager_destroy(mgr);
}
#endif
static test_t tests[] = {
{ "SIP UPDATE within incoming reinvite without sdp", sip_update_within_icoming_reinvite_with_no_sdp },
@ -350,9 +352,7 @@ static test_t tests[] = {
{ "Call with video mline before audio in sdp", call_with_video_mline_before_audio_in_sdp },
{ "Call with multiple audio mline in sdp", call_with_multiple_audio_mline_in_sdp },
{ "Call with multiple video mline in sdp", call_with_multiple_video_mline_in_sdp },
#if 0
{ "Call invite 200ok without contact header", call_invite_200ok_without_contact_header },
#endif
{ "Call invite 200ok without contact header", call_invite_200ok_without_contact_header }
};
test_suite_t complex_sip_call_test_suite = {