Exemple #1
0
/*
 * Send a request using data from the dialog structure
 */
int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
												transaction_cb cb, void* cbp)
{
	struct socket_info* send_sock;
	union sockaddr_union to_su;
	struct cell *new_cell;
	struct retr_buf *request;
	char* buf;
	int buf_len;
	int ret;
	unsigned int hi;

	ret=-1;
	
	/*** added by dcm 
	 * - needed by external ua to send a request within a dlg
	 */
	if(!dialog->hooks.next_hop && w_calculate_hooks(dialog)<0)
		goto error2;

	DBG("DEBUG:tm:t_uac: next_hop=<%.*s>\n",dialog->hooks.next_hop->len,
			dialog->hooks.next_hop->s);
	/* it's a new message, so we will take the default socket */
	send_sock = uri2sock(0, dialog->hooks.next_hop, &to_su, PROTO_NONE);
	if (!send_sock) {
		ret=ser_error;
		LOG(L_ERR, "t_uac: no socket found\n");
		goto error2;
	}	

	new_cell = build_cell(0); 
	if (!new_cell) {
		ret=E_OUT_OF_MEM;
		LOG(L_ERR, "t_uac: short of cell shmem\n");
		goto error2;
	}

	/* better reset avp list now - anyhow, it's useless from
	 * this point (bogdan) */
	reset_avps();

	/* add the callback the the transaction for LOCAL_COMPLETED event */
	if(cb && insert_tmcb(&(new_cell->tmcb_hl),TMCB_LOCAL_COMPLETED,cb,cbp)!=1){
		ret=E_OUT_OF_MEM;
		LOG(L_ERR, "t_uac: short of tmcb shmem\n");
		goto error2;
	}

	if (method->len==INVITE_LEN && memcmp(method->s, INVITE, INVITE_LEN)==0)
		new_cell->flags |= T_IS_INVITE_FLAG;
	new_cell->flags |= T_IS_LOCAL_FLAG;
	set_kr(REQ_FWDED);

	request = &new_cell->uac[0].request;
	request->dst.to = to_su;
	request->dst.send_sock = send_sock;
	request->dst.proto = send_sock->proto;
	request->dst.proto_reserved1 = 0;

	hi=dlg2hash(dialog);
	LOCK_HASH(hi);
	insert_into_hash_table_unsafe(new_cell, hi);
	UNLOCK_HASH(hi);

	buf = build_uac_req(method, headers, body, dialog, 0, new_cell,
		&buf_len, send_sock);
	if (!buf) {
		LOG(L_ERR, "t_uac: Error while building message\n");
		ret=E_OUT_OF_MEM;
		goto error1;
	}

	new_cell->method.s = buf;
	new_cell->method.len = method->len;

	request->buffer = buf;
	request->buffer_len = buf_len;
	new_cell->nr_of_outgoings++;
	
	if (SEND_BUFFER(request) == -1) {
		LOG(L_ERR, "t_uac: Attempt to send to '%.*s' failed\n", 
			dialog->hooks.next_hop->len,
			dialog->hooks.next_hop->s);
	}
	
	start_retr(request);
	return 1;

 error1:
	LOCK_HASH(hi);
	remove_from_hash_table_unsafe(new_cell);
	UNLOCK_HASH(hi);
	free_cell(new_cell);
error2:
	return ret;
}
Exemple #2
0
/*
 * Send a request using data from the dialog structure
 */
int t_uac(str* method, str* headers, str* body, dlg_t* dialog, transaction_cb cb, void* cbp)
{
	struct socket_info* send_sock;
	union sockaddr_union to_su;
	struct cell *new_cell;
	struct retr_buf *request;
	char* buf;
	int buf_len;
	int ret;
	unsigned int hi;

	ret=-1;
	
	/*** added by dcm 
	 * - needed by external ua to send a request within a dlg
	 */
	if(!dialog->hooks.next_hop && w_calculate_hooks(dialog)<0)
		goto error2;

	send_sock = uri2sock(dialog->hooks.next_hop, &to_su, PROTO_NONE);
	if (!send_sock) {
		ret=ser_error;
		LOG(L_ERR, "t_uac: no socket found\n");
		goto error2;
	}	

	new_cell = build_cell(0); 
	if (!new_cell) {
		ret=E_OUT_OF_MEM;
		LOG(L_ERR, "t_uac: short of cell shmem\n");
		goto error2;
	}

	new_cell->completion_cb = cb;
	new_cell->cbp = cbp;
	
	     /* cbp is installed -- tell error handling bellow not to free it */
	cbp = 0;

	new_cell->is_invite = method->len == INVITE_LEN && memcmp(method->s, INVITE, INVITE_LEN) == 0;
	new_cell->local= 1;
	set_kr(REQ_FWDED);
	
	request = &new_cell->uac[0].request;
	request->dst.to = to_su;
	request->dst.send_sock = send_sock;
	request->dst.proto = send_sock->proto;
	request->dst.proto_reserved1 = 0;

	hi=dlg2hash(dialog);
	LOCK_HASH(hi);
	insert_into_hash_table_unsafe(new_cell, hi);
	UNLOCK_HASH(hi);

	buf = build_uac_req(method, headers, body, dialog, 0, new_cell, &buf_len, send_sock);
	if (!buf) {
		LOG(L_ERR, "t_uac: Error while building message\n");
		ret=E_OUT_OF_MEM;
		goto error1;
	}

	new_cell->method.s = buf;
	new_cell->method.len = method->len;

	request->buffer = buf;
	request->buffer_len = buf_len;
	new_cell->nr_of_outgoings++;
	
	if (SEND_BUFFER(request) == -1) {
		LOG(L_ERR, "t_uac: Attempt to send to '%.*s' failed\n", 
		    dialog->hooks.next_hop->len,
		    dialog->hooks.next_hop->s
		    );
	}
	
	start_retr(request);
	return 1;

 error1:
	LOCK_HASH(hi);
	remove_from_hash_table_unsafe(new_cell);
	UNLOCK_HASH(hi);
	free_cell(new_cell);

 error2:
	     /* if we did not install cbp, release it now */
	if (cbp) shm_free(cbp);
	return ret;
}
Exemple #3
0
/*
 * Send a request using data from the dialog structure
 */
int t_uac(str* method, str* headers, str* body, dlg_t* dialog,
				transaction_cb cb, void* cbp,release_tmcb_param release_func)
{
	union sockaddr_union to_su;
	struct cell *new_cell;
	struct retr_buf *request;
	static struct sip_msg *req;
	struct usr_avp **backup;
	char *buf, *buf1;
	int buf_len, buf_len1;
	int ret, flags, sflag_bk;
	int backup_route_type;
	unsigned int hi;
	struct socket_info* send_sock;

	ret=-1;
	
	/*** added by dcm 
	 * - needed by external ua to send a request within a dlg
	 */
	if(!dialog->hooks.next_hop && w_calculate_hooks(dialog)<0)
		goto error2;

	if(dialog->obp.s)
		dialog->hooks.next_hop = &dialog->obp;

	LM_DBG("next_hop=<%.*s>\n",dialog->hooks.next_hop->len,
			dialog->hooks.next_hop->s);

	/* calculate the socket corresponding to next hop */
	send_sock = uri2sock(0, dialog->hooks.next_hop, &to_su,
			PROTO_NONE);
	if (send_sock==0) {
		ret=ser_error;
		LM_ERR("no socket found\n");
		goto error2;
	}
	/* if a send socket defined verify if the same protocol */
	if(dialog->send_sock) {
		if(send_sock->proto != dialog->send_sock->proto)
		{
			dialog->send_sock = send_sock;
		}
	}
	else
	{
		dialog->send_sock = send_sock;
	}

	new_cell = build_cell(0);
	if (!new_cell) {
		ret=E_OUT_OF_MEM;
		LM_ERR("short of cell shmem\n");
		goto error2;
	}

	/* pass the transaction flags from dialog to transaction */
	new_cell->flags |= dialog->T_flags;

	/* add the callback the transaction for LOCAL_COMPLETED event */
	flags = TMCB_LOCAL_COMPLETED;
	/* Add also TMCB_LOCAL_RESPONSE_OUT if provisional replies are desired */
	if (pass_provisional_replies || pass_provisional(new_cell))
		flags |= TMCB_LOCAL_RESPONSE_OUT;
	if(cb && insert_tmcb(&(new_cell->tmcb_hl),flags,cb,cbp,release_func)!=1){
		ret=E_OUT_OF_MEM;
		LM_ERR("short of tmcb shmem\n");
		goto error2;
	}

	if (method->len==INVITE_LEN && memcmp(method->s, INVITE, INVITE_LEN)==0)
		new_cell->flags |= T_IS_INVITE_FLAG;
	new_cell->flags |= T_IS_LOCAL_FLAG;

	request = &new_cell->uac[0].request;
	request->dst.to = to_su;
	request->dst.send_sock = dialog->send_sock;
	request->dst.proto = dialog->send_sock->proto;
	request->dst.proto_reserved1 = 0;

	hi=dlg2hash(dialog);
	LOCK_HASH(hi);
	insert_into_hash_table_unsafe(new_cell, hi);
	UNLOCK_HASH(hi);

	buf = build_uac_req(method, headers, body, dialog, 0, new_cell, &buf_len);
	if (!buf) {
		LM_ERR("failed to build message\n");
		ret=E_OUT_OF_MEM;
		goto error1;
	}

	if (local_rlist.a) {
		LM_DBG("building sip_msg from buffer\n");
		req = buf_to_sip_msg(buf, buf_len, dialog);
		if (req==NULL) {
			LM_ERR("failed to build sip_msg from buffer");
		} else {
			/* set transaction AVP list */
			backup = set_avp_list( &new_cell->user_avps );
			/* backup script flags */
			sflag_bk = getsflags();
			/* disable parallel forking */
			set_dset_state( 0 /*disable*/);

			/* transfer current message context back to t */
			new_cell->uac[0].br_flags = req->flags;

			/* run the route */
			swap_route_type( backup_route_type, LOCAL_ROUTE);
			run_top_route( local_rlist.a, req);
			set_route_type( backup_route_type );

			set_dset_state( 1 /*enable*/);
			setsflagsval(sflag_bk);
			set_avp_list( backup );

			/* check for changes - if none, do not regenerate the buffer 
			 * we ignore any change on RURI and DSTURI and they should not
			 * be changed  -bogdan */
			if (req->new_uri.s)
				{ pkg_free(req->new_uri.s); req->new_uri.s=0; req->new_uri.len=0; }
			if (req->dst_uri.s)
				{ pkg_free(req->dst_uri.s); req->dst_uri.s=0; req->dst_uri.len=0; }

			if (req->add_rm || req->body_lumps) {
				LM_DBG("re-building the buffer (sip_msg changed) - lumps are"
					"%p %p\n",req->add_rm, req->body_lumps);
				/* build the shm buffer now */
				buf1 = build_req_buf_from_sip_req(req,(unsigned int*)&buf_len1,
					dialog->send_sock, dialog->send_sock->proto,
					MSG_TRANS_SHM_FLAG|MSG_TRANS_NOVIA_FLAG );
				if (!buf1) {
					LM_ERR("no more shm mem\n"); 
					/* keep original buffer */
				} else {
					shm_free(buf);
					buf = buf1;
					buf_len = buf_len1;
					/* use new buffer */
				}
			}
			free_sip_msg(req);
		}
	}

	new_cell->method.s = buf;
	new_cell->method.len = method->len;

	request->buffer.s = buf;
	request->buffer.len = buf_len;
	new_cell->nr_of_outgoings++;

	if(last_localT)
	{
		*last_localT = new_cell;
		REF_UNSAFE(new_cell);
	}

	if (SEND_BUFFER(request) == -1) {
		LM_ERR("attempt to send to '%.*s' failed\n", 
			dialog->hooks.next_hop->len,
			dialog->hooks.next_hop->s);
	}

	if (method->len==ACK_LEN && memcmp(method->s, ACK, ACK_LEN)==0 ) {
		t_release_transaction(new_cell);
	} else {
		start_retr(request);
	}


	return 1;

error1:
	LOCK_HASH(hi);
	remove_from_hash_table_unsafe(new_cell);
	UNLOCK_HASH(hi);
	free_cell(new_cell);
error2:
	return ret;
}