Esempio n. 1
0
belle_sip_refresher_t* belle_sip_refresher_new(belle_sip_client_transaction_t* transaction) {
	belle_sip_refresher_t* refresher;
	belle_sip_transaction_state_t state=belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(transaction));
	belle_sip_request_t* request = belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(transaction));
	int is_register=strcmp("REGISTER",belle_sip_request_get_method(request))==0;

	refresher = (belle_sip_refresher_t*)belle_sip_object_new(belle_sip_refresher_t);
	refresher->transaction=transaction;
	refresher->state=stopped;
	refresher->number_of_retry=0;
	belle_sip_object_ref(transaction);
	refresher->retry_after=DEFAULT_RETRY_AFTER;

	if (belle_sip_transaction_get_dialog(BELLE_SIP_TRANSACTION(transaction))) {
		set_or_update_dialog(refresher, belle_sip_transaction_get_dialog(BELLE_SIP_TRANSACTION(transaction)));
	}
	belle_sip_provider_add_internal_sip_listener(transaction->base.provider,BELLE_SIP_LISTENER(refresher), is_register);
	if (set_expires_from_trans(refresher)==-1){
		belle_sip_error("Unable to extract refresh value from transaction [%p]",transaction);
	}
	if (belle_sip_transaction_state_is_transient(state)) {
		belle_sip_message("Refresher [%p] takes ownership of transaction [%p]",refresher,transaction);
		transaction->base.is_internal=1;
		refresher->state=started;
	}else{
		belle_sip_refresher_start(refresher);
	}
	return refresher;
}
Esempio n. 2
0
static void call_process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) {
	SalOp* op = (SalOp*)user_ctx;
	belle_sip_client_transaction_t *client_transaction=belle_sip_transaction_terminated_event_get_client_transaction(event);
	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;
	bool_t release_call=FALSE;

	if (client_transaction) {
		req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
		resp=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(client_transaction));
	} else {
		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
			&& 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))
			&& op->dialog==NULL) {
		release_call=TRUE;
	}
	if (server_transaction){
		if (op->pending_server_trans==server_transaction){
			belle_sip_object_unref(op->pending_server_trans);
			op->pending_server_trans=NULL;
		}
		if (op->pending_update_server_trans==server_transaction){
			belle_sip_object_unref(op->pending_update_server_trans);
			op->pending_update_server_trans=NULL;
		}
	}
	if (release_call) call_set_released(op);
}
Esempio n. 3
0
void belle_sip_client_transaction_notify_response(belle_sip_client_transaction_t *t, belle_sip_response_t *resp){
	belle_sip_transaction_t *base=(belle_sip_transaction_t*)t;
	belle_sip_request_t* req = belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(t));
	const char* method = belle_sip_request_get_method(req);
	belle_sip_response_event_t event;
	belle_sip_dialog_t *dialog=base->dialog;
	int status_code =  belle_sip_response_get_status_code(resp);
	if (base->last_response)
		belle_sip_object_unref(base->last_response);
	base->last_response=(belle_sip_response_t*)belle_sip_object_ref(resp);

	if (dialog){
		if (status_code>=101 && status_code<300
			&& strcmp(method,"INVITE")==0
			&& (dialog->state==BELLE_SIP_DIALOG_EARLY || dialog->state==BELLE_SIP_DIALOG_CONFIRMED)){
			/*make sure this response matches the current dialog, or creates a new one*/
			if (!belle_sip_dialog_match(dialog,(belle_sip_message_t*)resp,FALSE)){
				dialog=belle_sip_provider_find_dialog_from_message(t->base.provider,(belle_sip_message_t*)resp,FALSE);
				if (!dialog){
					dialog=belle_sip_provider_create_dialog_internal(t->base.provider,BELLE_SIP_TRANSACTION(t),FALSE);/*belle_sip_dialog_new(base);*/
					belle_sip_message("Handling response creating a new dialog !");
				}
			}
		}
	} else if (should_dialog_be_created(t,resp)) {
		dialog=belle_sip_provider_create_dialog_internal(t->base.provider,BELLE_SIP_TRANSACTION(t),FALSE);
	}

	if (dialog && belle_sip_dialog_update(dialog,BELLE_SIP_TRANSACTION(t),FALSE)) {
		/* retransmition, just return*/
		belle_sip_message("[%p] is a 200 ok retransmition on dialog [%p], skiping",resp,dialog);
		return;
	}

	event.source=(belle_sip_object_t*)base->provider;
	event.client_transaction=t;
	event.dialog=dialog;
	event.response=(belle_sip_response_t*)resp;
	BELLE_SIP_PROVIDER_INVOKE_LISTENERS_FOR_TRANSACTION(((belle_sip_transaction_t*)t),process_response_event,&event);
	/*check that 200Ok for INVITEs have been acknowledged by listener*/
	if (dialog && strcmp(method,"INVITE")==0){
		belle_sip_dialog_check_ack_sent(dialog);
	}
	/*report a server having internal errors for REGISTER to the channel, in order to go to a fallback IP*/
	if (status_code == 500 && strcmp(method,"REGISTER") == 0){
		belle_sip_channel_notify_server_error(base->channel);
	}
}
Esempio n. 4
0
/*accept an incoming call or, during a call accept a reINVITE*/
int sal_call_accept(SalOp*h){
	belle_sip_response_t *response;
	belle_sip_header_contact_t* contact_header;

	if (!h->pending_server_trans) {
		ms_error("No transaction to accept for op [%p]",h);
		return -1;
	}

	/* sends a 200 OK */
	response = sal_op_create_response_from_request(h,belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(h->pending_server_trans)),200);

	if (response==NULL){
		ms_error("Fail to build answer for call");
		return -1;
	}
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(create_allow()));
	if (h->base.root->session_expires!=0){
		if (h->supports_session_timers) {
			belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),belle_sip_header_create( "Supported", "timer"));
		}
	}

	if ((contact_header=sal_op_create_contact(h))) {
		belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact_header));
	}

	handle_offer_answer_response(h,response);

	belle_sip_server_transaction_send_response(h->pending_server_trans,response);
	return 0;
}
static void caller_process_response_event(void *user_ctx, const belle_sip_response_event_t *event){
	belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event);
	belle_sip_header_from_t* from=belle_sip_message_get_header_by_type(belle_sip_response_event_get_response(event),belle_sip_header_from_t);
	belle_sip_header_cseq_t* invite_cseq=belle_sip_message_get_header_by_type(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction)),belle_sip_header_cseq_t);
	belle_sip_request_t* ack;
	belle_sip_dialog_t* dialog;
	int status;
	if (!belle_sip_uri_equals(BELLE_SIP_URI(user_ctx),belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(from)))) {
		belle_sip_message("Message [%p] not for caller, skipping",belle_sip_response_event_get_response(event));
		return; /*not for the caller*/
	}

	status = belle_sip_response_get_status_code(belle_sip_response_event_get_response(event));
	belle_sip_message("caller_process_response_event [%i]",status);
	if (BC_ASSERT_PTR_NOT_NULL(client_transaction)) {
		dialog = belle_sip_transaction_get_dialog(BELLE_SIP_TRANSACTION(client_transaction));
		if (BC_ASSERT_PTR_NOT_NULL(dialog)) {
			BC_ASSERT_PTR_EQUAL(caller_dialog,dialog);
			if (belle_sip_dialog_get_state(dialog) == BELLE_SIP_DIALOG_NULL) {
				BC_ASSERT_EQUAL(status,100, int, "%d");
			} else if (belle_sip_dialog_get_state(dialog) == BELLE_SIP_DIALOG_EARLY){
				BC_ASSERT_EQUAL(status,180, int, "%d");
				/*send 200ok from callee*/
				belle_sip_server_transaction_send_response(inserv_transaction,ok_response);
				belle_sip_object_unref(ok_response);
				ok_response=NULL;
			} else if (belle_sip_dialog_get_state(dialog) == BELLE_SIP_DIALOG_CONFIRMED) {
Esempio n. 6
0
int sal_publish(SalOp *op, const char *from, const char *to, const char *eventname, int expires, const SalBody *body){
	belle_sip_request_t *req=NULL;
	if(!op->refresher || !belle_sip_refresher_get_transaction(op->refresher)) {
		if (from)
			sal_op_set_from(op,from);
		if (to)
			sal_op_set_to(op,to);

		sal_op_publish_fill_cbs(op);
		req=sal_op_build_request(op,"PUBLISH");
		if (sal_op_get_contact(op)){
			belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(sal_op_create_contact(op)));
		}
		belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),belle_sip_header_create("Event",eventname));
		sal_op_add_body(op,BELLE_SIP_MESSAGE(req),body);
		return sal_op_send_and_create_refresher(op,req,expires,publish_refresher_listener);
	} else {
		/*update status*/
		const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(op->refresher);
		belle_sip_request_t* last_publish=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_publish_trans));
		/*update body*/
		sal_op_add_body(op,BELLE_SIP_MESSAGE(last_publish),expires!=0 ? body : NULL);
		return belle_sip_refresher_refresh(op->refresher,expires==-1 ? BELLE_SIP_REFRESHER_REUSE_EXPIRES : expires);
	}
}
Esempio n. 7
0
int sal_call_notify_ringing(SalOp *op, bool_t early_media){
	int status_code =early_media?183:180;
	belle_sip_request_t* req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans));
	belle_sip_response_t* ringing_response = sal_op_create_response_from_request(op,req,status_code);
	belle_sip_header_t *require;
	const char *tags=NULL;

	if (early_media){
		handle_offer_answer_response(op,ringing_response);
	}
	require=belle_sip_message_get_header((belle_sip_message_t*)req,"Require");
	if (require) tags=belle_sip_header_get_unparsed_value(require);
	/* if client requires 100rel, then add necessary stuff*/
	if (tags && strstr(tags,"100rel")!=0) {
		belle_sip_message_add_header((belle_sip_message_t*)ringing_response,belle_sip_header_create("Require","100rel"));
		belle_sip_message_add_header((belle_sip_message_t*)ringing_response,belle_sip_header_create("RSeq","1"));
	}

#ifndef SAL_OP_CALL_FORCE_CONTACT_IN_RINGING
	if (tags && strstr(tags,"100rel")!=0)
#endif
	{
		belle_sip_header_address_t* contact= (belle_sip_header_address_t*)sal_op_get_contact_address(op);
		belle_sip_header_contact_t* contact_header;
		if (contact && (contact_header=belle_sip_header_contact_create(contact))) {
			belle_sip_message_add_header(BELLE_SIP_MESSAGE(ringing_response),BELLE_SIP_HEADER(contact_header));
		}
	}
	belle_sip_server_transaction_send_response(op->pending_server_trans,ringing_response);
	return 0;
}
Esempio n. 8
0
static void presence_response_event(void *op_base, const belle_sip_response_event_t *event){
	SalOp* op = (SalOp*)op_base;
	belle_sip_dialog_state_t dialog_state;
	belle_sip_client_transaction_t* client_transaction = belle_sip_response_event_get_client_transaction(event);
	belle_sip_response_t* response=belle_sip_response_event_get_response(event);
	belle_sip_request_t* request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(client_transaction));
	int code = belle_sip_response_get_status_code(response);
	char reason[256]={0};
	SalError error=SalErrorUnknown;
	SalReason sr=SalReasonUnknown;
	belle_sip_header_expires_t* expires;

	if (sal_compute_sal_errors(response,&error,&sr,reason, sizeof(reason))) {
		ms_error("subscription to [%s] rejected reason  [%s]",sal_op_get_to(op),reason[0]!=0?reason:sal_reason_to_string(sr));
		op->base.root->callbacks.notify_presence(op,SalSubscribeTerminated, NULL,NULL); /*NULL = offline*/
		return;
	}
	set_or_update_dialog(op_base,belle_sip_response_event_get_dialog(event));
	if (!op->dialog) {
		ms_message("presence op [%p] receive out of dialog answer [%i]",op,code);
		return;
	}
	dialog_state=belle_sip_dialog_get_state(op->dialog);

	switch(dialog_state) {
		case BELLE_SIP_DIALOG_NULL:
		case BELLE_SIP_DIALOG_EARLY: {
			ms_error("presence op [%p] receive an unexpected answer [%i]",op,code);
			break;
		}
		case BELLE_SIP_DIALOG_CONFIRMED: {
			if (strcmp("SUBSCRIBE",belle_sip_request_get_method(request))==0) {
				expires=belle_sip_message_get_header_by_type(request,belle_sip_header_expires_t);
				if(op->refresher) {
					belle_sip_refresher_stop(op->refresher);
					belle_sip_object_unref(op->refresher);
					op->refresher=NULL;
				}
				if (expires>0){
					op->refresher=belle_sip_client_transaction_create_refresher(client_transaction);
					belle_sip_refresher_set_listener(op->refresher,presence_refresher_listener,op);
				}
			}
			break;
		}
		case BELLE_SIP_DIALOG_TERMINATED:
			if (op->refresher) {
				belle_sip_refresher_stop(op->refresher);
				belle_sip_object_unref(op->refresher);
				op->refresher=NULL;
			}
		break;
		default: {
			ms_error("presence op [%p] receive answer [%i] not implemented",op,code);
		}
		/* no break */
	}


}
Esempio n. 9
0
static int set_expires_from_trans(belle_sip_refresher_t* refresher) {
	belle_sip_transaction_t* transaction = BELLE_SIP_TRANSACTION(refresher->transaction);
	belle_sip_response_t*response=transaction->last_response;
	belle_sip_request_t*request=belle_sip_transaction_get_request(transaction);
	belle_sip_header_expires_t*  expires_header=belle_sip_message_get_header_by_type(request,belle_sip_header_expires_t);
	belle_sip_header_contact_t* contact_header;

	refresher->obtained_expires=-1;

	if (strcmp("REGISTER",belle_sip_request_get_method(request))==0
			|| expires_header /*if request has an expire header, refresher can always work*/) {

		if (expires_header)
			refresher->target_expires = belle_sip_header_expires_get_expires(expires_header);

		/*An "expires" parameter on the "Contact" header has no semantics for
		*   SUBSCRIBE and is explicitly not equivalent to an "Expires" header in
		*  a SUBSCRIBE request or response.
		*/
		if (strcmp("REGISTER",belle_sip_request_get_method(request))==0){
			if (!expires_header && (contact_header=belle_sip_message_get_header_by_type((belle_sip_message_t*)request,belle_sip_header_contact_t))){
				int ct_expires=belle_sip_header_contact_get_expires(BELLE_SIP_HEADER_CONTACT(contact_header));
				if (ct_expires!=-1) refresher->target_expires=ct_expires;
			}
			/*check in response also to get the obtained expires*/
			if ((contact_header=belle_sip_refresher_get_contact(refresher))!=NULL){
				/*matching contact, check for its possible expires param*/
				refresher->obtained_expires=belle_sip_header_contact_get_expires(BELLE_SIP_HEADER_CONTACT(contact_header));
			}
		}
		if (refresher->obtained_expires==-1){
			/*no contact with expire or not relevant, looking for Expires header*/
			if (response && (expires_header=(belle_sip_header_expires_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_EXPIRES))) {
				refresher->obtained_expires = belle_sip_header_expires_get_expires(expires_header);
			}
		}
		if (refresher->obtained_expires==-1) {
			belle_sip_message("Neither Expires header nor corresponding Contact header found, checking from original request");
			refresher->obtained_expires=refresher->target_expires;
		}else if (refresher->target_expires>0 && refresher->obtained_expires==0){
			const char* reason = response ? belle_sip_response_get_reason_phrase(response) : NULL;
			/*check this case because otherwise we are going to loop fast in sending refresh requests.*/
			/*"Test account created" is a special reason given by testers when we create temporary account.
			Since this is a bit of hack, we can ignore logging in that case*/
			if (reason && strcmp(reason, "Test account created") != 0) {
				belle_sip_warning("Server replied with 0 expires, what does that mean?");
			}
			/*suppose it's a server bug and assume our target_expires is understood.*/
			refresher->obtained_expires=refresher->target_expires;
		}
	} else if (strcmp("INVITE",belle_sip_request_get_method(request))==0) {
		belle_sip_error("Refresher does not support INVITE yet");
		return -1;
	} else {
		belle_sip_error("Refresher does not support [%s] yet",belle_sip_request_get_method(request));
		return -1;
	}
	return 0;
}
Esempio n. 10
0
int sal_subscribe_accept(SalOp *op){
	belle_sip_request_t* req=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans));
	belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t);
	belle_sip_response_t* resp = sal_op_create_response_from_request(op,req,200);
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(resp),BELLE_SIP_HEADER(expires));
	belle_sip_server_transaction_send_response(op->pending_server_trans,resp);
	return 0;
}
Esempio n. 11
0
static void process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event) {
	belle_sip_client_transaction_t* client_transaction = belle_sip_timeout_event_get_client_transaction(event);
	SalOp* op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction));
	if (op && op->callbacks.process_timeout) {
		op->callbacks.process_timeout(op,event);
	} else {
		ms_error("Unhandled event timeout [%p]",event);
	}
}
Esempio n. 12
0
static void process_io_error(belle_sip_listener_t *user_ctx, const belle_sip_io_error_event_t *event){
	belle_sip_refresher_t* refresher=(belle_sip_refresher_t*)user_ctx;
	belle_sip_client_transaction_t*client_transaction;
	if (refresher->on_io_error==1) {
		return; /*refresher already on error*/
	}
	if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(belle_sip_io_error_event_get_source(event),belle_sip_client_transaction_t)) {
		client_transaction=BELLE_SIP_CLIENT_TRANSACTION(belle_sip_io_error_event_get_source(event));
		if (!refresher || (refresher && ((refresher->state==stopped
			&& belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(refresher->transaction)) != BELLE_SIP_TRANSACTION_TRYING
			&& belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(refresher->transaction)) != BELLE_SIP_TRANSACTION_INIT /*to cover dns or certificate error*/)
			|| client_transaction !=refresher->transaction )))
				return; /*not for me or no longuer involved*/

		if (refresher->target_expires==0
				&& belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(refresher->transaction)) != BELLE_SIP_TRANSACTION_TRYING
				&& belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(refresher->transaction)) != BELLE_SIP_TRANSACTION_INIT ) {
			return; /*not for me or no longuer involved because expire=0*/
		}
		if (refresher->state==started) retry_later_on_io_error(refresher);
		if (refresher->listener) refresher->listener(refresher,refresher->user_data,503, "io error");

		return;
	} else if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(belle_sip_io_error_event_get_source(event),belle_sip_provider_t)) {
		/*something went wrong on this provider, checking if my channel is still up*/
		if (refresher->state==started  /*refresher started or trying to refresh */
				&& belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(refresher->transaction)) == BELLE_SIP_TRANSACTION_TERMINATED /*else we are notified by transaction error*/
				&& refresher->transaction->base.channel /*transaction may not have any channel*/
				&&	(belle_sip_channel_get_state(refresher->transaction->base.channel) == BELLE_SIP_CHANNEL_DISCONNECTED
								||belle_sip_channel_get_state(refresher->transaction->base.channel) == BELLE_SIP_CHANNEL_ERROR)) {
			belle_sip_message("refresher [%p] has channel [%p] in state [%s], reporting error"
								,refresher
								,refresher->transaction->base.channel
								,belle_sip_channel_state_to_string(belle_sip_channel_get_state(refresher->transaction->base.channel)));
			if (refresher->state==started) retry_later_on_io_error(refresher);
			if (refresher->listener) refresher->listener(refresher,refresher->user_data,503, "io error");
			refresher->on_io_error=1;
		}
		return;
	}else {
		/*belle_sip_error("Refresher process_io_error not implemented yet for non transaction/provider source");*/
		/*nop, because already handle at transaction layer*/
	}
}
Esempio n. 13
0
static void process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event) {
	belle_sip_client_transaction_t* client_transaction = belle_sip_transaction_terminated_event_get_client_transaction(event);
	belle_sip_server_transaction_t* server_transaction = belle_sip_transaction_terminated_event_get_server_transaction(event);
	belle_sip_transaction_t* trans;
	SalOp* op;

	if(client_transaction)
		trans=BELLE_SIP_TRANSACTION(client_transaction);
	 else
		trans=BELLE_SIP_TRANSACTION(server_transaction);

	op = (SalOp*)belle_sip_transaction_get_application_data(trans);
	if (op && op->callbacks && op->callbacks->process_transaction_terminated) {
		op->callbacks->process_transaction_terminated(op,event);
	} else {
		ms_message("Unhandled transaction terminated [%p]",trans);
	}
	if (op) sal_op_unref(op); /*because every transaction ref op*/
}
Esempio n. 14
0
static void presence_process_request_event(void *op_base, const belle_sip_request_event_t *event) {
	SalOp* op = (SalOp*)op_base;
	belle_sip_server_transaction_t* server_transaction = belle_sip_provider_create_server_transaction(op->base.root->prov,belle_sip_request_event_get_request(event));
	belle_sip_request_t* req = belle_sip_request_event_get_request(event);
	belle_sip_dialog_state_t dialog_state;
	belle_sip_header_expires_t* expires = belle_sip_message_get_header_by_type(req,belle_sip_header_expires_t);
	belle_sip_response_t* resp;
	const char *method=belle_sip_request_get_method(req);
	
	belle_sip_object_ref(server_transaction);
	if (op->pending_server_trans)  belle_sip_object_unref(op->pending_server_trans);
	op->pending_server_trans=server_transaction;


	if (!op->dialog) {
		if (strcmp(method,"SUBSCRIBE")==0){
			op->dialog=belle_sip_provider_create_dialog(op->base.root->prov,BELLE_SIP_TRANSACTION(server_transaction));
			belle_sip_dialog_set_application_data(op->dialog,op);
			sal_op_ref(op);
			ms_message("new incoming subscription from [%s] to [%s]",sal_op_get_from(op),sal_op_get_to(op));
		}else{ /* this is a NOTIFY */
			ms_message("Receiving out of dialog notify");
			handle_notify(op,req);
			return;
		}
	}
	dialog_state=belle_sip_dialog_get_state(op->dialog);
	switch(dialog_state) {
		case BELLE_SIP_DIALOG_NULL: {
			op->base.root->callbacks.subscribe_presence_received(op,sal_op_get_from(op));
			break;
		}
		case BELLE_SIP_DIALOG_EARLY:
			ms_error("unexpected method [%s] for dialog [%p] in state BELLE_SIP_DIALOG_EARLY ",method,op->dialog);
			break;

		case BELLE_SIP_DIALOG_CONFIRMED:
			if (strcmp("NOTIFY",method)==0) {
				handle_notify(op,req);
			} else if (strcmp("SUBSCRIBE",method)==0) {
				/*either a refresh or an unsubscribe*/
				if (expires && belle_sip_header_expires_get_expires(expires)>0) {
					op->base.root->callbacks.subscribe_presence_received(op,sal_op_get_from(op));
				} else if(expires) {
					ms_message("Unsubscribe received from [%s]",sal_op_get_from(op));
					resp=sal_op_create_response_from_request(op,req,200);
					belle_sip_server_transaction_send_response(server_transaction,resp);
				}
			}
			break;
		default: 
			ms_error("unexpected dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state));
			break;
	}
}
Esempio n. 15
0
static void register_refresher_listener (belle_sip_refresher_t* refresher
		,void* user_pointer
		,unsigned int status_code
		,const char* reason_phrase) {
	SalOp* op = (SalOp*)user_pointer;
	belle_sip_response_t* response=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher)));
	ms_message("Register refresher [%i] reason [%s] for proxy [%s]",status_code,reason_phrase,sal_op_get_proxy(op));

	if (belle_sip_refresher_get_auth_events(refresher)) {
		if (op->auth_info) sal_auth_info_delete(op->auth_info);
		/*only take first one for now*/
		op->auth_info=sal_auth_info_create((belle_sip_auth_event_t*)(belle_sip_refresher_get_auth_events(refresher)->data));
	}
	sal_error_info_set(&op->error_info,SalReasonUnknown,status_code,reason_phrase,NULL);
	if (status_code>=200){
		sal_op_assign_recv_headers(op,(belle_sip_message_t*)response);
	}
	if(status_code == 200) {
		/*check service route rfc3608*/
		belle_sip_header_service_route_t* service_route;
		belle_sip_header_address_t* service_route_address=NULL;
		belle_sip_header_contact_t *contact = belle_sip_refresher_get_contact(refresher);
		if ((service_route=belle_sip_message_get_header_by_type(response,belle_sip_header_service_route_t))) {
			service_route_address=belle_sip_header_address_create(NULL,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(service_route)));
		}
		sal_op_set_service_route(op,(const SalAddress*)service_route_address);
		if (service_route_address) belle_sip_object_unref(service_route_address);

		sal_remove_pending_auth(op->base.root,op); /*just in case*/
		if (contact) {
			sal_op_set_contact_address(op,(SalAddress*)(BELLE_SIP_HEADER_ADDRESS(contact))); /*update contact with real value*/
		}
		op->base.root->callbacks.register_success(op,belle_sip_refresher_get_expires(op->refresher)>0);
	} else if (status_code>=400) {
		/* from rfc3608, 6.1.
				If the UA refreshes the registration, the stored value of the Service-
				   Route is updated according to the Service-Route header field of the
				   latest 200 class response.  If there is no Service-Route header field
				   in the response, the UA clears any service route for that address-
				   of-record previously stored by the UA.  If the re-registration
				   request is refused or if an existing registration expires and the UA
				   chooses not to re-register, the UA SHOULD discard any stored service
				   route for that address-of-record. */
		sal_op_set_service_route(op,NULL);
		sal_op_ref(op); /*take a ref while invoking the callback to make sure the operations done after are valid*/
		op->base.root->callbacks.register_failure(op);
		if (op->state!=SalOpStateTerminated && op->auth_info) {
			/*add pending auth*/
			sal_add_pending_auth(op->base.root,op);
			if (status_code==403 || status_code==401 || status_code==407 )
				op->base.root->callbacks.auth_failure(op,op->auth_info);
		}
		sal_op_unref(op);
	}
}
Esempio n. 16
0
void belle_sip_transaction_terminate(belle_sip_transaction_t *t){
	if (belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(t))!=BELLE_SIP_TRANSACTION_TERMINATED) {
		belle_sip_transaction_set_state(t,BELLE_SIP_TRANSACTION_TERMINATED);
		belle_sip_message("%s%s %s transaction [%p] terminated"	,BELLE_SIP_OBJECT_IS_INSTANCE_OF(t,belle_sip_client_transaction_t)?"Client":"Server"
									,t->is_internal?" internal":""
									,belle_sip_request_get_method(belle_sip_transaction_get_request(t))
									,t);
		BELLE_SIP_OBJECT_VPTR(t,belle_sip_transaction_t)->on_terminate(t);
		belle_sip_provider_set_transaction_terminated(t->provider,t);
	}
}
Esempio n. 17
0
belle_sip_request_t* belle_sip_client_transaction_create_authenticated_request(belle_sip_client_transaction_t *t,belle_sip_list_t** auth_infos,const char* realm) {
	belle_sip_request_t* initial_request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(t));
	belle_sip_request_t* req=belle_sip_request_clone_with_body(initial_request);
	belle_sip_header_cseq_t* cseq=belle_sip_message_get_header_by_type(req,belle_sip_header_cseq_t);
	belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1);
	if (belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(t)) != BELLE_SIP_TRANSACTION_COMPLETED
		&& belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(t)) != BELLE_SIP_TRANSACTION_TERMINATED) {
		belle_sip_error("Invalid state [%s] for transaction [%p], should be BELLE_SIP_TRANSACTION_COMPLETED | BELLE_SIP_TRANSACTION_TERMINATED"
					,belle_sip_transaction_state_to_string(belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(t)))
					,t);
		belle_sip_object_unref(req);
		return NULL;
	}
	/*remove auth headers*/
	belle_sip_message_remove_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_AUTHORIZATION);
	belle_sip_message_remove_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_PROXY_AUTHORIZATION);

	/*put auth header*/
	belle_sip_provider_add_authorization(t->base.provider,req,t->base.last_response,NULL,auth_infos,realm);
	return req;
}
Esempio n. 18
0
static int dialog_on_200Ok_end(belle_sip_dialog_t *dialog){
	belle_sip_request_t *bye;
	belle_sip_client_transaction_t *trn;
	belle_sip_dialog_stop_200Ok_retrans(dialog);
	belle_sip_error("Dialog [%p] was not ACK'd within T1*64 seconds, it is going to be terminated.",dialog);
	dialog->state=BELLE_SIP_DIALOG_CONFIRMED;
	bye=belle_sip_dialog_create_request(dialog,"BYE");
	trn=belle_sip_provider_create_client_transaction(dialog->provider,bye);
	BELLE_SIP_TRANSACTION(trn)->is_internal=1; /*don't bother user with this transaction*/
	belle_sip_client_transaction_send_request(trn);
	return BELLE_SIP_STOP;
}
Esempio n. 19
0
void belle_sip_dialog_check_ack_sent(belle_sip_dialog_t*obj){
	belle_sip_client_transaction_t* client_trans;
	if (obj->needs_ack){
		belle_sip_request_t *req;
		belle_sip_error("Your listener did not ACK'd the 200Ok for your INVITE request. The dialog will be terminated.");
		req=belle_sip_dialog_create_request(obj,"BYE");
		client_trans=belle_sip_provider_create_client_transaction(obj->provider,req);
		BELLE_SIP_TRANSACTION(client_trans)->is_internal=TRUE; /*internal transaction, don't bother user with 200ok*/
		belle_sip_client_transaction_send_request(client_trans);
		/*call dialog terminated*/
	}
}
Esempio n. 20
0
static void belle_sip_refresher_stop_internal(belle_sip_refresher_t* refresher,int cancel_pending_transaction) {
	belle_sip_message("Refresher [%p] stopped.",refresher);
	if (refresher->timer){
		belle_sip_main_loop_remove_source(belle_sip_stack_get_main_loop(refresher->transaction->base.provider->stack), refresher->timer);
		belle_sip_object_unref(refresher->timer);
		refresher->timer=NULL;
	}
	if (cancel_pending_transaction && refresher->transaction && belle_sip_transaction_state_is_transient(belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(refresher->transaction)))) {
		belle_sip_transaction_terminate(BELLE_SIP_TRANSACTION(refresher->transaction)); /*refresher cancelled, no need to continue to retransmit*/
	}
	refresher->state=stopped;
}
Esempio n. 21
0
static void register_refresher_listener ( const belle_sip_refresher_t* refresher
		,void* user_pointer
		,unsigned int status_code
		,const char* reason_phrase) {
	SalOp* op = (SalOp*)user_pointer;
	SalError sal_err;
	SalReason sal_reason;
	belle_sip_response_t* response=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher)));
	ms_message("Register refresher  [%i] reason [%s] for proxy [%s]",status_code,reason_phrase,sal_op_get_proxy(op));
	/*fix contact if needed*/
	if (op->base.root->nat_helper_enabled && belle_sip_refresher_get_nated_contact(refresher)) {
		belle_sip_header_address_t* contact_address = BELLE_SIP_HEADER_ADDRESS(belle_sip_object_clone(BELLE_SIP_OBJECT(belle_sip_refresher_get_nated_contact(refresher))));
		sal_op_set_contact_address(op,(SalAddress*)contact_address);
		belle_sip_object_unref(contact_address);
	}
	if (belle_sip_refresher_get_auth_events(refresher)) {
		if (op->auth_info) sal_auth_info_delete(op->auth_info);
		/*only take first one for now*/
		op->auth_info=sal_auth_info_create((belle_sip_auth_event_t*)(belle_sip_refresher_get_auth_events(refresher)->data));
	}
	if(status_code == 200) {
		/*check service route rfc3608*/
		belle_sip_header_service_route_t* service_route;
		belle_sip_header_address_t* service_route_address=NULL;
		if ((service_route=belle_sip_message_get_header_by_type(response,belle_sip_header_service_route_t))) {
			service_route_address=belle_sip_header_address_create(NULL,belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(service_route)));
		}
		sal_op_set_service_route(op,(const SalAddress*)service_route_address);
		if (service_route_address) belle_sip_object_unref(service_route_address);

		sal_remove_pending_auth(op->base.root,op); /*just in case*/
		op->base.root->callbacks.register_success(op,belle_sip_refresher_get_expires(op->refresher)>0);
	} else if (status_code>=400) {
		/* from rfc3608, 6.1.
				If the UA refreshes the registration, the stored value of the Service-
				   Route is updated according to the Service-Route header field of the
				   latest 200 class response.  If there is no Service-Route header field
				   in the response, the UA clears any service route for that address-
				   of-record previously stored by the UA.  If the re-registration
				   request is refused or if an existing registration expires and the UA
				   chooses not to re-register, the UA SHOULD discard any stored service
				   route for that address-of-record. */
		sal_op_set_service_route(op,NULL);

		sal_compute_sal_errors_from_code(status_code,&sal_err,&sal_reason);
		op->base.root->callbacks.register_failure(op,sal_err,sal_reason,reason_phrase);
		if (op->auth_info) {
			/*add pending auth*/
			sal_add_pending_auth(op->base.root,op);
		}
	}
}
Esempio n. 22
0
static void process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
	belle_sip_client_transaction_t*client_transaction;
	SalOp* op;
	if (BELLE_SIP_OBJECT_IS_INSTANCE_OF(belle_sip_io_error_event_get_source(event),belle_sip_client_transaction_t)) {
		client_transaction=BELLE_SIP_CLIENT_TRANSACTION(belle_sip_io_error_event_get_source(event));
		op = (SalOp*)belle_sip_transaction_get_application_data(BELLE_SIP_TRANSACTION(client_transaction));
		if (op->callbacks.process_io_error) {
				op->callbacks.process_io_error(op,event);
		}
	} else {
		/*ms_error("sal process_io_error not implemented yet for non transaction");*/
		/*nop, because already handle at transaction layer*/
	}
}
Esempio n. 23
0
static void publish_refresher_listener ( const belle_sip_refresher_t* refresher
		,void* user_pointer
		,unsigned int status_code
		,const char* reason_phrase) {
	SalOp* op = (SalOp*)user_pointer;
	/*belle_sip_response_t* response=belle_sip_transaction_get_response(BELLE_SIP_TRANSACTION(belle_sip_refresher_get_transaction(refresher)));*/
	ms_message("Publish refresher  [%i] reason [%s] for proxy [%s]",status_code,reason_phrase,sal_op_get_proxy(op));
	if (status_code==412){
		/*resubmit the request after removing the SIP-If-Match*/
		const belle_sip_client_transaction_t* last_publish_trans=belle_sip_refresher_get_transaction(op->refresher);
		belle_sip_request_t* last_publish=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(last_publish_trans));
		belle_sip_message_remove_header((belle_sip_message_t*)last_publish,"SIP-If-Match");
		belle_sip_refresher_refresh(op->refresher,BELLE_SIP_REFRESHER_REUSE_EXPIRES);
	}
}
Esempio n. 24
0
void belle_sip_transaction_terminate(belle_sip_transaction_t *t){
	if (belle_sip_transaction_get_state(BELLE_SIP_TRANSACTION(t))!=BELLE_SIP_TRANSACTION_TERMINATED) {
		int is_client=BELLE_SIP_OBJECT_IS_INSTANCE_OF(t,belle_sip_client_transaction_t);
		belle_sip_transaction_set_state(t,BELLE_SIP_TRANSACTION_TERMINATED);
		if (t->dialog && (!t->last_response || belle_sip_response_get_status_code(t->last_response)<200)){
			/*inform the dialog if a transaction terminates without final response.*/
			belle_sip_dialog_update(t->dialog,t,!is_client);
		}
		belle_sip_message("%s%s %s transaction [%p] terminated"	,is_client ? "Client":"Server"
									,t->is_internal ? " internal":""
									,belle_sip_request_get_method(belle_sip_transaction_get_request(t))
									,t);
		BELLE_SIP_OBJECT_VPTR(t,belle_sip_transaction_t)->on_terminate(t);
		belle_sip_provider_set_transaction_terminated(t->provider,t);
	}
}
static void callee_process_request_event(void *user_ctx, const belle_sip_request_event_t *event) {
	belle_sip_dialog_t* dialog;
	belle_sip_response_t* ringing_response;
	belle_sip_header_content_type_t* content_type ;
	belle_sip_header_content_length_t* content_length;
	belle_sip_server_transaction_t* server_transaction = belle_sip_request_event_get_server_transaction(event);
	belle_sip_header_to_t* to=belle_sip_message_get_header_by_type(belle_sip_request_event_get_request(event),belle_sip_header_to_t);
	const char* method;
	if (!belle_sip_uri_equals(BELLE_SIP_URI(user_ctx),belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to)))) {
		belle_sip_message("Message [%p] not for callee, skipping",belle_sip_request_event_get_request(event));
		return; /*not for the callee*/
	}
	method = belle_sip_request_get_method(belle_sip_request_event_get_request(event));
	if (!server_transaction && strcmp(method,"ACK")!=0) {
		server_transaction= belle_sip_provider_create_server_transaction(prov,belle_sip_request_event_get_request(event));
	}

	belle_sip_message("callee_process_request_event received [%s] message",method);
	dialog = belle_sip_request_event_get_dialog(event);
	if (!dialog ) {
		BC_ASSERT_STRING_EQUAL_FATAL("INVITE",method);
		dialog=belle_sip_provider_create_dialog(prov,BELLE_SIP_TRANSACTION(server_transaction));
		callee_dialog=dialog;
		inserv_transaction=server_transaction;
	}
	if (belle_sip_dialog_get_state(dialog) == BELLE_SIP_DIALOG_NULL) {
		ringing_response = belle_sip_response_create_from_request(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(server_transaction)),180);
		/*prepare 200ok*/
		ok_response = belle_sip_response_create_from_request(belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(server_transaction)),200);
		content_length= belle_sip_header_content_length_create(strlen(sdp));
		content_type = belle_sip_header_content_type_create("application","sdp");
		belle_sip_message_add_header(BELLE_SIP_MESSAGE(ok_response),BELLE_SIP_HEADER(content_type));
		belle_sip_message_add_header(BELLE_SIP_MESSAGE(ok_response),BELLE_SIP_HEADER(content_length));
		belle_sip_message_set_body(BELLE_SIP_MESSAGE(ok_response),sdp,strlen(sdp));
		belle_sip_object_ref(ok_response);
		/*only send ringing*/
		belle_sip_server_transaction_send_response(server_transaction,ringing_response);
	} else if (belle_sip_dialog_get_state(dialog) == BELLE_SIP_DIALOG_CONFIRMED) {
		/*time to send bye*/
		belle_sip_client_transaction_t* client_transaction = belle_sip_provider_create_client_transaction(prov,belle_sip_dialog_create_request(dialog,"BYE"));
		belle_sip_client_transaction_send_request(client_transaction);
	} else {
		belle_sip_warning("Unexpected state [%s] for dialog [%p]",belle_sip_dialog_state_to_string(belle_sip_dialog_get_state(dialog)),dialog );
	}

}
Esempio n. 26
0
belle_sip_header_contact_t* belle_sip_refresher_get_contact(const belle_sip_refresher_t* refresher) {
	belle_sip_transaction_t* transaction = BELLE_SIP_TRANSACTION(refresher->transaction);
	belle_sip_request_t*request=belle_sip_transaction_get_request(transaction);
	belle_sip_response_t*response=transaction->last_response;
	const belle_sip_list_t* contact_header_list;
	belle_sip_header_contact_t* unfixed_local_contact;
	belle_sip_header_contact_t* fixed_local_contact;
	char* tmp_string;
	char* tmp_string2;
	if (!response)
		return NULL;
	/*we assume, there is only one contact in request*/
	unfixed_local_contact= belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(request),belle_sip_header_contact_t);
	fixed_local_contact= BELLE_SIP_HEADER_CONTACT(belle_sip_object_clone(BELLE_SIP_OBJECT(unfixed_local_contact)));
	/*first fix contact using received/rport*/
	belle_sip_response_fix_contact(response,fixed_local_contact);
	contact_header_list = belle_sip_message_get_headers(BELLE_SIP_MESSAGE(response),BELLE_SIP_CONTACT);

	if (contact_header_list) {
		contact_header_list = belle_sip_list_find_custom((belle_sip_list_t*)contact_header_list
					,(belle_sip_compare_func)belle_sip_header_contact_not_equals
					, (const void*)fixed_local_contact);
		if (!contact_header_list) {
			/*reset header list*/
			contact_header_list = belle_sip_message_get_headers(BELLE_SIP_MESSAGE(response),BELLE_SIP_CONTACT);
			contact_header_list = belle_sip_list_find_custom((belle_sip_list_t*)contact_header_list
							,(belle_sip_compare_func)belle_sip_header_contact_not_equals
							,unfixed_local_contact);
		}
		if (!contact_header_list) {
			tmp_string=belle_sip_object_to_string(BELLE_SIP_OBJECT(fixed_local_contact));
			tmp_string2=belle_sip_object_to_string(BELLE_SIP_OBJECT(unfixed_local_contact));
			belle_sip_message("No matching contact neither for [%s] nor [%s]", tmp_string, tmp_string2);
			belle_sip_object_unref(fixed_local_contact);
			belle_sip_free(tmp_string);
			belle_sip_free(tmp_string2);
			return NULL;
		} else {
			belle_sip_object_unref(fixed_local_contact);
			return BELLE_SIP_HEADER_CONTACT(contact_header_list->data);
		}
	} else {
		return NULL;
	}

}
Esempio n. 27
0
/*accept an incoming call or, during a call accept a reINVITE*/
int sal_call_accept(SalOp*h){
	belle_sip_response_t *response;
	belle_sip_header_contact_t* contact_header;
	belle_sip_server_transaction_t* transaction;

	/*first check if an UPDATE transaction need to be accepted*/
	if (h->pending_update_server_trans) {
		transaction=h->pending_update_server_trans;
	} else if (h->pending_server_trans) {
		/*so it must be an invite/re-invite*/
		transaction=h->pending_server_trans;
	} else {
		ms_error("No transaction to accept for op [%p]",h);
		return -1;
	}
	ms_message("Accepting server transaction [%p] on op [%p]", transaction, h);
	/* sends a 200 OK */
	response = sal_op_create_response_from_request(h,belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(transaction)),200);

	if (response==NULL){
		ms_error("Fail to build answer for call");
		return -1;
	}
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(create_allow(h->base.root->enable_sip_update)));
	if (h->base.root->session_expires!=0){
/*		if (h->supports_session_timers) {*/
			belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),belle_sip_header_create("Supported", "timer"));
			belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),belle_sip_header_create( "Session-expires", "600;refresher=uac"));
		/*}*/
	}

	if ((contact_header=sal_op_create_contact(h))) {
		belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact_header));
	}

	_sal_op_add_custom_headers(h, BELLE_SIP_MESSAGE(response));

	handle_offer_answer_response(h,response);

	belle_sip_server_transaction_send_response(transaction,response);
	if (h->pending_update_server_trans) {
		belle_sip_object_unref(h->pending_update_server_trans);
		h->pending_update_server_trans=NULL;
	}
	return 0;
}
Esempio n. 28
0
int sal_call_terminate(SalOp *op){
	belle_sip_dialog_state_t dialog_state=op->dialog?belle_sip_dialog_get_state(op->dialog):BELLE_SIP_DIALOG_NULL;
	if (op->state==SalOpStateTerminating || op->state==SalOpStateTerminated) {
		ms_error("Cannot terminate op [%p] in state [%s]",op,sal_op_state_to_string(op->state));
		return -1;
	}
	switch(dialog_state) {
		case BELLE_SIP_DIALOG_CONFIRMED: {
			sal_op_send_request(op,belle_sip_dialog_create_request(op->dialog,"BYE"));
			op->state=SalOpStateTerminating;
			break;
		}
		case BELLE_SIP_DIALOG_NULL: {
			if (op->dir == SalOpDirIncoming) {
				sal_call_decline(op, SalReasonDeclined,NULL);
				op->state=SalOpStateTerminated;
			} 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;
		}
		case BELLE_SIP_DIALOG_EARLY: {
			if (op->dir == SalOpDirIncoming) {
				sal_call_decline(op, SalReasonDeclined,NULL);
				op->state=SalOpStateTerminated;
			} else  {
				cancelling_invite(op);
			}
			break;
		}
		default: {
			ms_error("sal_call_terminate not implemented yet for dialog state [%s]",belle_sip_dialog_state_to_string(dialog_state));
			return -1;
		}
	}
	return 0;
}
static void caller_process_request_event(void *user_ctx, const belle_sip_request_event_t *event) {
	belle_sip_server_transaction_t* server_transaction;
	belle_sip_response_t* resp;
	belle_sip_dialog_t* dialog;
	belle_sip_header_to_t* to=belle_sip_message_get_header_by_type(belle_sip_request_event_get_request(event),belle_sip_header_to_t);
	if (!belle_sip_uri_equals(BELLE_SIP_URI(user_ctx),belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(to)))) {
		belle_sip_message("Message [%p] not for caller, skipping",belle_sip_request_event_get_request(event));
		return; /*not for the caller*/
	}
	belle_sip_message("caller_process_request_event received [%s] message",belle_sip_request_get_method(belle_sip_request_event_get_request(event)));
	server_transaction=belle_sip_provider_create_server_transaction(prov,belle_sip_request_event_get_request(event));
	BC_ASSERT_STRING_EQUAL_FATAL("BYE",belle_sip_request_get_method(belle_sip_request_event_get_request(event)));
	dialog =  belle_sip_transaction_get_dialog(BELLE_SIP_TRANSACTION(server_transaction));
	BC_ASSERT_PTR_NOT_NULL_FATAL(dialog);
	BC_ASSERT_EQUAL(belle_sip_dialog_get_state(dialog) , BELLE_SIP_DIALOG_CONFIRMED, int, "%d");
	resp=belle_sip_response_create_from_request(belle_sip_request_event_get_request(event),200);
	belle_sip_server_transaction_send_response(server_transaction,resp);

}
Esempio n. 30
0
int sal_call_decline(SalOp *op, SalReason reason, const char *redirection /*optional*/){
	belle_sip_response_t* response;
	belle_sip_header_contact_t* contact=NULL;
	int status=sal_reason_to_sip_code(reason);
	
	if (reason==SalReasonRedirect){
		if (redirection!=NULL) {
			if (strstr(redirection,"sip:")!=0) status=302;
			status=380;
			contact= belle_sip_header_contact_new();
			belle_sip_header_address_set_uri(BELLE_SIP_HEADER_ADDRESS(contact),belle_sip_uri_parse(redirection));
		} else {
			ms_error("Cannot redirect to null");
		}
	}
	response = sal_op_create_response_from_request(op,belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(op->pending_server_trans)),status);
	if (contact) belle_sip_message_add_header(BELLE_SIP_MESSAGE(response),BELLE_SIP_HEADER(contact));
	belle_sip_server_transaction_send_response(op->pending_server_trans,response);
	return 0;
}