Example #1
0
void belle_sip_server_transaction_send_response(belle_sip_server_transaction_t *t, belle_sip_response_t *resp){
	belle_sip_transaction_t *base=(belle_sip_transaction_t*)t;
	belle_sip_header_to_t *to=(belle_sip_header_to_t*)belle_sip_message_get_header((belle_sip_message_t*)resp,"to");
	belle_sip_dialog_t *dialog=base->dialog;
	int status_code;

	belle_sip_object_ref(resp);
	if (!base->last_response){
		belle_sip_hop_t* hop=belle_sip_response_get_return_hop(resp);
		base->channel=belle_sip_provider_get_channel(base->provider,hop);
		belle_sip_object_unref(hop);
		if (!base->channel){
			belle_sip_error("Transaction [%p]: No channel available for sending response.",t);
			return;
		}
		belle_sip_object_ref(base->channel);
		belle_sip_channel_add_listener(base->channel, BELLE_SIP_CHANNEL_LISTENER(t));
	}
	status_code=belle_sip_response_get_status_code(resp);
	if (status_code!=100){
		if (belle_sip_header_to_get_tag(to)==NULL){
			//add a random to tag
			belle_sip_header_to_set_tag(to,t->to_tag);
		}
		/*12.1 Creation of a Dialog
		   Dialogs are created through the generation of non-failure responses
		   to requests with specific methods.  Within this specification, only
		   2xx and 101-199 responses with a To tag, where the request was
		   INVITE, will establish a dialog.*/
		if (dialog && status_code>100 && status_code<300){
			belle_sip_response_fill_for_dialog(resp,base->request);
		}
	}
	if (BELLE_SIP_OBJECT_VPTR(t,belle_sip_server_transaction_t)->send_new_response(t,resp)==0){
		if (base->last_response)
			belle_sip_object_unref(base->last_response);
		base->last_response=resp;
	}
	if (dialog)
		belle_sip_dialog_update(dialog,BELLE_SIP_TRANSACTION(t),TRUE);
}
Example #2
0
int belle_sip_client_transaction_send_request_to(belle_sip_client_transaction_t *t,belle_sip_uri_t* outbound_proxy) {
	belle_sip_channel_t *chan;
	belle_sip_provider_t *prov=t->base.provider;
	belle_sip_dialog_t *dialog=t->base.dialog;
	belle_sip_request_t *req=t->base.request;
	int result=-1;

	if (t->base.state!=BELLE_SIP_TRANSACTION_INIT){
		belle_sip_error("belle_sip_client_transaction_send_request: bad state.");
		return -1;
	}

	/*check uris components compliance*/
	if (!belle_sip_request_check_uris_components(t->base.request)) {
		belle_sip_error("belle_sip_client_transaction_send_request: bad request for transaction [%p]",t);
		return -1;
	}
	/*store preset route for future use by refresher*/
	if (outbound_proxy){
		t->preset_route=outbound_proxy;
		belle_sip_object_ref(t->preset_route);
	}

	if (t->base.sent_by_dialog_queue){
		
		/*it can be sent immediately, so update the request with latest cseq and route_set */
		/*update route and contact just in case they changed*/
		belle_sip_dialog_update_request(dialog,req);
	} else if (t->base.request->dialog_queued){
		/*this request was created by belle_sip_dialog_create_queued_request().*/
		if (belle_sip_dialog_request_pending(dialog) || dialog->queued_ct!=NULL){
			/*it cannot be sent immediately, queue the transaction into dialog*/
			belle_sip_message("belle_sip_client_transaction_send_request(): transaction [%p], cannot send request now because dialog is busy"
			" or other transactions are queued, so queuing into dialog.",t);
			belle_sip_dialog_queue_client_transaction(dialog,t);
			return 0;
		}
		belle_sip_dialog_update_request(dialog,req);
	}

	if (dialog){
		belle_sip_dialog_update(dialog,(belle_sip_transaction_t*)t,BELLE_SIP_OBJECT_IS_INSTANCE_OF(t,belle_sip_server_transaction_t));
	}

	if (!t->next_hop) {
		if (t->preset_route) {
			t->next_hop=belle_sip_hop_new_from_uri(t->preset_route);
		} else {
			t->next_hop = belle_sip_stack_get_next_hop(prov->stack,t->base.request);
		}
		belle_sip_object_ref(t->next_hop);
	} else {
		/*next hop already preset, probably in case of CANCEL*/
	}
	belle_sip_provider_add_client_transaction(t->base.provider,t); /*add it in any case*/
	chan=belle_sip_provider_get_channel(prov,t->next_hop);
	if (chan){
		belle_sip_object_ref(chan);
		belle_sip_channel_add_listener(chan,BELLE_SIP_CHANNEL_LISTENER(t));
		t->base.channel=chan;
		if (belle_sip_channel_get_state(chan)==BELLE_SIP_CHANNEL_INIT){
			belle_sip_message("belle_sip_client_transaction_send_request(): waiting channel to be ready");
			belle_sip_channel_prepare(chan);
			/*the channel will notify us when it is ready*/
		} else if (belle_sip_channel_get_state(chan)==BELLE_SIP_CHANNEL_READY){
			/*otherwise we can send immediately*/
			BELLE_SIP_OBJECT_VPTR(t,belle_sip_client_transaction_t)->send_request(t);
		}
		result=0;
	}else {
		belle_sip_error("belle_sip_client_transaction_send_request(): no channel available");
		belle_sip_transaction_terminate(BELLE_SIP_TRANSACTION(t));
		result=-1;
	}
	return result;
}
Example #3
0
static void on_channel_destroyed(belle_http_channel_context_t *obj, belle_sip_channel_t *chan_being_destroyed){
	belle_sip_channel_remove_listener(chan_being_destroyed,BELLE_SIP_CHANNEL_LISTENER(obj));
	belle_sip_object_unref(obj);
}