⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 t_fwd.c

📁 性能优秀的SIP Proxy
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Id: t_fwd.c,v 1.26 2006/05/30 15:41:57 bogdan_iancu Exp $ * * Copyright (C) 2001-2003 FhG Fokus * * This file is part of openser, a free SIP server. * * openser is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version * * openser is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License  * along with this program; if not, write to the Free Software  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * History: * ------- *  2003-02-13  proto support added (andrei) *  2003-02-24  s/T_NULL/T_NULL_CELL/ to avoid redefinition conflict w/ *              nameser_compat.h (andrei) *  2003-03-01  kr set through a function now (jiri) *  2003-03-06  callbacks renamed; "blind UAC" introduced, which makes *              transaction behave as if it was forwarded even if it was *              not -- good for local UAS, like VM (jiri) *  2003-03-19  replaced all the mallocs/frees w/ pkg_malloc/pkg_free (andrei) *  2003-03-30  we now watch downstream delivery and if it fails, send an *              error message upstream (jiri) *  2003-04-14  use protocol from uri (jiri) *  2003-12-04  global TM callbacks switched to per transaction callbacks *              (bogdan) *  2004-02-13: t->is_invite and t->local replaced with flags (bogdan) */#include "../../dprint.h"#include "../../config.h"#include "../../ut.h"#include "../../dset.h"#include "../../timer.h"#include "../../hash_func.h"#include "../../globals.h"#include "../../action.h"#include "../../data_lump.h"#include "../../usr_avp.h"#include "../../mem/mem.h"#include "../../parser/parser_f.h"#include "t_funcs.h"#include "t_hooks.h"#include "t_msgbuilder.h"#include "ut.h"#include "t_cancel.h"#include "t_lookup.h"#include "t_fwd.h"#include "fix_lumps.h"#include "path.h"#include "config.h"/* route to execute for the branches */static int goto_on_branch;unsigned int gflags_mask = 0xffffffff;int _tm_branch_index = 0;void t_on_branch( unsigned int go_to ){	struct cell *t = get_t();	/* in MODE_REPLY and MODE_ONFAILURE T will be set to current transaction;	 * in MODE_REQUEST T will be set only if the transaction was already 	 * created; if not -> use the static variable */	if (route_type==BRANCH_ROUTE || !t || t==T_UNDEFINED )		goto_on_branch=go_to;	else		t->on_branch = go_to;}unsigned int get_on_branch(){	return goto_on_branch;}static inline int pre_print_uac_request( struct cell *t, int branch, 		struct sip_msg *request){	int backup_route_type;	struct usr_avp **backup_list;	char *p;	/* ... we calculate branch ... */	if (!t_calc_branch(t, branch, request->add_to_branch_s,			&request->add_to_branch_len ))	{		LOG(L_ERR, "ERROR:pre_print_uac_request: branch computation failed\n");		goto error;	}	/* from now on, flag all new lumps with LUMPFLAG_BRANCH flag in order to	 * be able to remove them later --bogdan */	set_init_lump_flags(LUMPFLAG_BRANCH);	/* add path vector as Route HF */	if (request->path_vec.s && request->path_vec.len) {		if (insert_path_as_route(request, &request->path_vec) < 0)			goto error;	}	/********** run route & callback ************/	/* run branch route, if any; run it before RURI's DNS lookup 	 * to allow to be changed --bogdan */	if (t->on_branch) {		/* need to pkg_malloc the dst_uri */		if ( request->dst_uri.len ) {			if ( (p=pkg_malloc(request->dst_uri.len))==0 ) {				LOG(L_ERR,"ERROR:tm:pre_print_uac_request: no more pkg mem\n");				ser_error=E_OUT_OF_MEM;				goto error;			}			memcpy( p, request->dst_uri.s, request->dst_uri.len);			request->dst_uri.s = p;		}		/* need to pkg_malloc the new_uri */		if ( (p=pkg_malloc(request->new_uri.len))==0 ) {			LOG(L_ERR,"ERROR:tm:pre_print_uac_request: no more pkg mem\n");			ser_error=E_OUT_OF_MEM;			goto error;		}		memcpy( p, request->new_uri.s, request->new_uri.len);		request->new_uri.s = p;		/* make available the avp list from transaction */		backup_list = set_avp_list( &t->user_avps );		/* run branch route */		swap_route_type( backup_route_type, BRANCH_ROUTE);		_tm_branch_index = branch+1;		if (run_top_route(branch_rlist[t->on_branch], request)&ACT_FL_DROP) {			DBG("DEBUG:tm:pre_print_uac_request: dropping branch <%.*s>\n",				request->new_uri.len, request->new_uri.s);			_tm_branch_index = 0;			goto error;		}		_tm_branch_index = 0;		set_route_type( backup_route_type );		/* restore original avp list */		set_avp_list( backup_list );	}	/* run the specific callbacks for this transaction */	run_trans_callbacks( TMCB_REQUEST_FWDED, t, request, 0,			-request->REQ_METHOD);	return 0;error:	return -1;}/* be aware and use it *all* the time between pre_* and post_* functions! */static inline char *print_uac_request(struct sip_msg *i_req, unsigned int *len,		struct socket_info *send_sock, enum sip_protos proto ){	char *buf, *shbuf;	shbuf=0;	/* build the shm buffer now */	buf=build_req_buf_from_sip_req( i_req, len, send_sock, proto );	if (!buf) {		LOG(L_ERR, "ERROR:tm:print_uac_request: no pkg_mem\n"); 		ser_error=E_OUT_OF_MEM;		goto error01;	}	shbuf=(char *)shm_malloc(*len);	if (!shbuf) {		ser_error=E_OUT_OF_MEM;		LOG(L_ERR, "ERROR:tm:print_uac_request: no shmem\n");		goto error02;	}	memcpy( shbuf, buf, *len );error02:	pkg_free( buf );error01:	return shbuf;}static inline void post_print_uac_request(struct sip_msg *request,		str *org_uri, str *org_dst){	reset_init_lump_flags();	/* delete inserted branch lumps */	del_flaged_lumps( &request->add_rm, LUMPFLAG_BRANCH);	del_flaged_lumps( &request->body_lumps, LUMPFLAG_BRANCH);	/* reset branch flags */	request->flags &= gflags_mask;	/* free any potential new uri */	if (request->new_uri.s!=org_uri->s) {		pkg_free(request->new_uri.s);		/* and just to be sure */		request->new_uri.s = 0;		request->new_uri.len = 0;		request->parsed_uri_ok = 0;	}	/* free any potential dst uri */	if (request->dst_uri.s!=org_dst->s) {		pkg_free(request->dst_uri.s);		/* and just to be sure */		request->dst_uri.s = 0;		request->dst_uri.len = 0;	}}/* introduce a new uac, which is blind -- it only creates the   data structures and starts FR timer, but that's it; it does   not print messages and send anything anywhere; that is good   for FIFO apps -- the transaction must look operationally   and FR must be ticking, whereas the request is "forwarded"   using a non-SIP way and will be replied the same way*/int add_blind_uac( /*struct cell *t*/ ){	unsigned short branch;	struct cell *t;	t=get_t();	if (t==T_UNDEFINED || !t ) {		LOG(L_ERR, "ERROR: add_blind_uac: no transaction context\n");		return -1;	}	branch=t->nr_of_outgoings;		if (branch==MAX_BRANCHES) {		LOG(L_ERR, "ERROR: add_blind_uac: "			"maximum number of branches exceeded\n");		return -1;	}	/* make sure it will be replied */	t->flags |= T_NOISY_CTIMER_FLAG;	t->nr_of_outgoings++;	/* start FR timer -- protocol set by default to PROTO_NONE,       which means retransmission timer will not be started    */	start_retr(&t->uac[branch].request);	/* we are on a timer -- don't need to put on wait on script	   clean-up		*/	set_kr(REQ_FWDED); 	return 1; /* success */}/* introduce a new uac to transaction; returns its branch id (>=0)   or error (<0); it doesn't send a message yet -- a reply to it   might interfere with the processes of adding multiple branches*/int add_uac( struct cell *t, struct sip_msg *request, str *uri, str* next_hop, str* path,	struct proxy_l *proxy){	int ret;	short temp_proxy;	union sockaddr_union to;	unsigned short branch;	struct socket_info* send_sock;	char *shbuf;	unsigned int len;	branch=t->nr_of_outgoings;	if (branch==MAX_BRANCHES) {		LOG(L_ERR, "ERROR:tm:add_uac: maximum number of branches exceeded\n");		ret=E_CFG;		goto error;	}	/* check existing buffer -- rewriting should never occur */	if (t->uac[branch].request.buffer.s) {		LOG(L_CRIT, "ERROR:tm:add_uac: buffer rewrite attempt\n");		ret=ser_error=E_BUG;		goto error;	}	/* set proper RURI to request to reflect the branch */	request->new_uri=*uri;	request->parsed_uri_ok=0;	request->dst_uri=*next_hop;	request->path_vec=*path;	if ( pre_print_uac_request( t, branch, request)!= 0 ) {		ret = -1;		goto error01;	}	/* check DNS resolution */	if (proxy){		temp_proxy=0;	}else {		proxy=uri2proxy( request->dst_uri.len ?			&request->dst_uri:&request->new_uri, PROTO_NONE );		if (proxy==0)  {			ret=E_BAD_ADDRESS;			goto error01;		}		temp_proxy=1;	}	if (proxy->ok==0) {		if (proxy->host.h_addr_list[proxy->addr_idx+1])			proxy->addr_idx++;		else proxy->addr_idx=0;		proxy->ok=1;	}	hostent2su( &to, &proxy->host, proxy->addr_idx, 		proxy->port ? proxy->port:SIP_PORT);	send_sock=get_send_socket( request, &to , proxy->proto);	if (send_sock==0) {		LOG(L_ERR, "ERROR:tm:add_uac: can't fwd to af %d, proto %d "			" (no corresponding listening socket)\n",			to.s.sa_family, proxy->proto );		ret=ser_error=E_NO_SOCKET;		goto error02;	}	/* now message printing starts ... */	shbuf=print_uac_request( request, &len, send_sock, proxy->proto );	if (!shbuf) {		ret=ser_error=E_OUT_OF_MEM;		goto error02;	}	/* things went well, move ahead and install new buffer! */	t->uac[branch].request.dst.to=to;	t->uac[branch].request.dst.send_sock=send_sock;	t->uac[branch].request.dst.proto=proxy->proto;	t->uac[branch].request.dst.proto_reserved1=0;	t->uac[branch].request.buffer.s=shbuf;	t->uac[branch].request.buffer.len=len;	t->uac[branch].uri.s=t->uac[branch].request.buffer.s+		request->first_line.u.request.method.len+1;	t->uac[branch].uri.len=request->new_uri.len;	t->uac[branch].br_flags = request->flags&(~gflags_mask);	t->nr_of_outgoings++;	/* update stats */	proxy->tx++;	proxy->tx_bytes+=len;	/* done! */	ret=branch;error02:	if (temp_proxy) {		free_proxy( proxy );		pkg_free( proxy );	}error01:	post_print_uac_request( request, uri, next_hop);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -