Exemple #1
0
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;
	belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event);
	belle_sip_request_t* req;
	belle_sip_response_t* response=belle_sip_response_event_get_response(event);
	int code = belle_sip_response_get_status_code(response);
	belle_sip_header_content_type_t *header_content_type=NULL;
	belle_sip_dialog_t *dialog=belle_sip_response_event_get_dialog(event);
	const char *method;

	if (!client_transaction) {
		ms_warning("Discarding stateless response [%i] on op [%p]",code,op);
		return;
	}
	req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
	set_or_update_dialog(op,dialog);
	dialog_state=dialog ? belle_sip_dialog_get_state(dialog) : BELLE_SIP_DIALOG_NULL;
	method=belle_sip_request_get_method(req);
	ms_message("Op [%p] receiving call response [%i], dialog is [%p] in state [%s]",op,code,dialog,belle_sip_dialog_state_to_string(dialog_state));
	/*to make sure no cb will destroy op*/
	sal_op_ref(op);
	switch(dialog_state) {
		case BELLE_SIP_DIALOG_NULL:
		case BELLE_SIP_DIALOG_EARLY: {
			if (strcmp("INVITE",method)==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{
							/* no need to send the INVITE because the UAS rejected the INVITE*/
							if (op->dialog==NULL) call_set_released(op);
						}
					} else {
						/*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<200) {
					belle_sip_response_t *prev_response=belle_sip_object_data_get(BELLE_SIP_OBJECT(dialog),"early_response");
					if (!prev_response || code>belle_sip_response_get_status_code(prev_response)){
						handle_sdp_from_response(op,response);
						op->base.root->callbacks.call_ringing(op);
					}
					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);
					if (op->dialog==NULL) call_set_released(op);
				}
			} else if (code >=200
						&& code<300
						&& strcmp("UPDATE",belle_sip_request_get_method(req))==0) {
					handle_sdp_from_response(op,response);
					op->base.root->callbacks.call_accepted(op);
			}
		}
		break;
		case BELLE_SIP_DIALOG_CONFIRMED: {
			switch (op->state) {
				case SalOpStateEarly:/*invite case*/
				case SalOpStateActive: /*re-invite, INFO, UPDATE case*/
					if (strcmp("INVITE",method)==0){
						if (code >=200 && code<300) {
							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){
							call_set_error(op,response);
						}
					}else if (strcmp("INFO",method)==0){
						if (code == 491
							&& (header_content_type = belle_sip_message_get_header_by_type(req,belle_sip_header_content_type_t))
							&& strcmp("application",belle_sip_header_content_type_get_type(header_content_type))==0
							&& strcmp("media_control+xml",belle_sip_header_content_type_get_subtype(header_content_type))==0) {
						unsigned int retry_in =1000*((float)rand()/RAND_MAX);
						belle_sip_source_t *s=sal_create_timer(op->base.root,vfu_retry,sal_op_ref(op), retry_in, "vfu request retry");
						ms_message("Rejected vfu request on op [%p], just retry in [%ui] ms",op,retry_in);
						belle_sip_object_unref(s);
						}else {
								/*ignoring*/
						}
					}else if (strcmp("UPDATE",method)==0){
						op->base.root->callbacks.call_accepted(op); /*INVITE*/
					}
				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;
		case BELLE_SIP_DIALOG_TERMINATED: {
			if (code >= 300){
				call_set_error(op,response);
			}
		}
		break;
		default: {
			ms_error("call op [%p] receive answer [%i] not implemented",op,code);
		}
		break;
	}
	sal_op_unref(op);
}
Exemple #2
0
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;
	belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event);
	belle_sip_request_t* req;
	belle_sip_response_t* response=belle_sip_response_event_get_response(event);
	int code = belle_sip_response_get_status_code(response);


	if (!client_transaction) {
		ms_warning("Discarding stateless response [%i] on op [%p]",code,op);
		return;
	}
	req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
	set_or_update_dialog(op,belle_sip_response_event_get_dialog(event));
	dialog_state=op->dialog?belle_sip_dialog_get_state(op->dialog):BELLE_SIP_DIALOG_NULL;
	
	ms_message("Op [%p] receiving call response [%i], dialog is [%p] in state [%s]",op,code,op->dialog,belle_sip_dialog_state_to_string(dialog_state));

	switch(dialog_state) {
		case BELLE_SIP_DIALOG_NULL:
		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{
							/* no need to send the INVITE because the UAS rejected the INVITE*/
							if (op->dialog==NULL) call_set_released(op);
						}
					} else {
						/*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);
					op->base.root->callbacks.call_ringing(op);
				} else if (code>=300){
					call_set_error(op,response);
					if (op->dialog==NULL) call_set_released(op);
				}
			}
		}
		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 ;
						}
						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:
					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;
		case BELLE_SIP_DIALOG_TERMINATED: {
			if (code >= 300){
				call_set_error(op,response);
			}
		}
		break;
		default: {
			ms_error("call op [%p] receive answer [%i] not implemented",op,code);
		}
		break;
	}
}