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

📄 t_msgbuilder.c

📁 性能优秀的SIP Proxy
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Id: t_msgbuilder.c,v 1.12 2006/05/29 16:55:21 bogdan_iancu Exp $ * * message printing * * 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-01-27  next baby-step to removing ZT - PRESERVE_ZT (jiri) * 2003-02-13  build_uac_request uses proto (andrei) * 2003-02-28  scratchpad compatibility abandoned (jiri) * 2003-04-14  build_local no longer checks reply status as it *             is now called before reply status is updated to *             avoid late ACK sending (jiri) * 2003-10-02  added via_builder set host/port support (andrei) * 2004-02-11  FIFO/CANCEL + alignments (hash=f(callid,cseq)) (uli+jiri) * 2004-02-13: t->is_invite and t->local replaced with flags (bogdan) */#include "../../hash_func.h"#include "../../globals.h"#include "t_funcs.h"#include "../../dprint.h"#include "../../config.h"#include "../../parser/parser_f.h"#include "../../ut.h"#include "../../parser/msg_parser.h"#include "../../parser/contact/parse_contact.h"#include "t_msgbuilder.h"#include "uac.h"#define ROUTE_PREFIX "Route: "#define ROUTE_PREFIX_LEN (sizeof(ROUTE_PREFIX) - 1)#define ROUTE_SEPARATOR ", "#define ROUTE_SEPARATOR_LEN (sizeof(ROUTE_SEPARATOR) - 1)/* convenience macros */#define  append_string(_d,_s,_len) \	do{\		memcpy((_d),(_s),(_len));\		(_d) += (_len);\	}while(0);#define LC(_cp) ((*(_cp))|0x20)#define SET_FOUND(_new_state) \	do{\		fill->s=b;fill->len=p-b;\		DBG("DEBUG:tm:extract_hdrs: hdr %d extracted as <%.*s>\n",\			flag,fill->len,fill->s);\		flags&=~(flag);\		if (flags) {state=_new_state;}\		else {goto done;}\	}while(0)#define GET_CSEQ() \	do{\		for(p++;p<end&&isspace((int)*p);p++);\		for(fill->s=b;p<end&&isdigit((int)*p);p++);\		fill->len=p-fill->s;\		if ( (flags&=~(flag))==0) goto done;\		state=1;\	}while(0)static int extract_hdrs( char *buf, int len, str *from, str *to, str *cseq){	char *end, *p;	char *b;	str  *fill;	int state;	int flags;	int flag;	p = buf;	end = buf+len;	state = 1;	b = 0;	flags = ((from!=0)?0x1:0) | ((to!=0)?0x2:0) | ((cseq!=0)?0x4:0);	flag = 0;	fill = 0;	while(p<end) {		switch (*p) {			case '\n':			case '\r':				switch (state) {					case 4: state=5;break;					case 5: case 6: state=6;break;					default : state=2;break;				}				break;			case ' ':			case '\t':				switch (state) {					case 4: case 6: state=5; break;					case 2: state=1; break;/*folded line*/				}				break;			case ':':				switch (state) {					case 4:case 5: state=5;if(flag==0x04)GET_CSEQ();break;					case 6: SET_FOUND(1);break;/*found*/					case 2: state=1;break;				}				break;			case 'f':			case 'F':				if (state==5) break;				if (state==6) SET_FOUND(2);/*found*/;				if (state!=2) {state = 1;break;}				/* hdr starting with 'f' */				if (from==0) break;				b = p;				if (p+3<end && LC(p+1)=='r' && LC(p+2)=='o' && LC(p+3)=='m')					p+=3;				state = 4; /* "f" or "from" found */				fill = from;				flag = 0x1;				break;			case 't':			case 'T':				if (state==5) break;				if (state==6) SET_FOUND(2);/*found*/;				if (state!=2) {state = 1;break;}				/* hdr starting with 't' */				if (to==0) break;				b = p;				if (p+1<end && LC(p+1)=='o')					p+=1;				state = 4; /* "t" or "to" found */				fill = to;				flag = 0x2;				break;			case 'c':			case 'C':				if (state==5) break;				if (state==6) SET_FOUND(2);/*found*/;				if (state!=2) {state = 1;break;}				/* hdr starting with 'c' */				if (cseq==0) break;				if (p+3<end && LC(p+1)=='s' && LC(p+2)=='e' && LC(p+3)=='q') {					b = p;					p+=3;					state = 4; /* "cseq" found */					fill = cseq;					flag = 0x4;				}				break;			default:				switch (state) {					case 2:case 4: state=1; break;					case 6: SET_FOUND(1);break;/*found*/;				}		}		p++;	}	LOG(L_CRIT,"BUG:tm:extract_hdrs: no hdrs found in outgoing buffer\n");	return -1;done:	return 0;}/* Build a local request based on a previous request; main   customers of this function are local ACK and local CANCEL */char *build_local(struct cell *Trans,unsigned int branch,	unsigned int *len, char *method, int method_len, str *uas_to){	char                *cancel_buf, *p, *via;	unsigned int         via_len;	struct hdr_field    *hdr;	struct sip_msg      *req;	char branch_buf[MAX_BRANCH_PARAM_LEN];	str branch_str;	struct hostport hp;	str from;	str to;	str cseq_n;	req = Trans->uas.request;	from = Trans->from;	cseq_n = Trans->cseq_n;	to = *uas_to;	if (req && req->msg_flags&(FL_USE_UAC_FROM|FL_USE_UAC_TO|FL_USE_UAC_CSEQ)) {		if ( extract_hdrs( Trans->uac[branch].request.buffer.s,		Trans->uac[branch].request.buffer.len,		(req->msg_flags&FL_USE_UAC_FROM)?&from:0 ,		(req->msg_flags&FL_USE_UAC_TO)?&to:0 ,		(req->msg_flags&FL_USE_UAC_CSEQ)?&cseq_n:0 )!=0 ) {			LOG(L_ERR, "ERROR:tm:build_local: "				"failed to extract UAC hdrs\n");			goto error;		}	}	DBG("DEBUG:tm:build_local: using FROM=<%.*s>, TO=<%.*s>, CSEQ_N=<%.*s>\n",		from.len,from.s , to.len,to.s , cseq_n.len,cseq_n.s);	/* method, separators, version  */	*len=SIP_VERSION_LEN + method_len + 2 /* spaces */ + CRLF_LEN;	*len+=Trans->uac[branch].uri.len;	/*via*/	branch_str.s=branch_buf;	if (!t_calc_branch(Trans,  branch, branch_str.s, &branch_str.len ))		goto error;	set_hostport(&hp, (is_local(Trans))?0:req);	via=via_builder(&via_len, Trans->uac[branch].request.dst.send_sock,		&branch_str, 0, Trans->uac[branch].request.dst.proto, &hp );	if (!via)	{		LOG(L_ERR, "ERROR: build_local: "			"no via header got from builder\n");		goto error;	}	*len+= via_len;	/*headers*/	*len+=from.len+Trans->callid.len+to.len+cseq_n.len+1+method_len+CRLF_LEN;	/* copy'n'paste Route headers */	if (!is_local(Trans)) {		for ( hdr=req->headers ; hdr ; hdr=hdr->next )			 if (hdr->type==HDR_ROUTE_T)				*len+=hdr->len;	}	/* User Agent */	if (server_signature) {		*len += user_agent_header.len + CRLF_LEN;	}	/* Content Length, EoM */	*len+=CONTENT_LENGTH_LEN+1 + CRLF_LEN + CRLF_LEN;	cancel_buf=shm_malloc( *len+1 );	if (!cancel_buf)	{		LOG(L_ERR, "ERROR: build_local: cannot allocate memory\n");		goto error01;	}	p = cancel_buf;	append_string( p, method, method_len );	*(p++) = ' ';	append_string( p, Trans->uac[branch].uri.s, Trans->uac[branch].uri.len);	append_string( p, " " SIP_VERSION CRLF, 1+SIP_VERSION_LEN+CRLF_LEN );	/* insert our via */	append_string(p,via,via_len);	/*other headers*/	append_string( p, from.s, from.len );	append_string( p, Trans->callid.s, Trans->callid.len );	append_string( p, to.s, to.len );	append_string( p, cseq_n.s, cseq_n.len );	*(p++) = ' ';	append_string( p, method, method_len );	append_string( p, CRLF, CRLF_LEN );	if (!is_local(Trans))  {		for ( hdr=req->headers ; hdr ; hdr=hdr->next )			if(hdr->type==HDR_ROUTE_T) {				append_string(p, hdr->name.s, hdr->len );			}	}	/* User Agent header, Content Length, EoM */	if (server_signature) {		append_string(p, user_agent_header.s, user_agent_header.len);		append_string(p, CRLF CONTENT_LENGTH "0" CRLF CRLF ,			CRLF_LEN+CONTENT_LENGTH_LEN+1 + CRLF_LEN + CRLF_LEN);	} else {		append_string(p, CONTENT_LENGTH "0" CRLF CRLF ,			CONTENT_LENGTH_LEN+1 + CRLF_LEN + CRLF_LEN);	}	*p=0;	pkg_free(via);	return cancel_buf;error01:	pkg_free(via);error:	return NULL;}struct rte {	rr_t* ptr;	struct rte* next;};static inline void free_rte_list(struct rte* list){	struct rte* ptr;		while(list) {		ptr = list;		list = list->next;		pkg_free(ptr);	}}static inline int process_routeset(struct sip_msg* msg, str* contact, struct rte** list, str* ruri, str* next_hop){	struct hdr_field* ptr;	rr_t* p;	struct rte* t, *head;	struct sip_uri puri;		ptr = msg->record_route;	head = 0;	while(ptr) {		if (ptr->type == HDR_RECORDROUTE_T) {			if (parse_rr(ptr) < 0) {				LOG(L_ERR, "process_routeset: Error while parsing Record-Route header\n");				return -1;			}						p = (rr_t*)ptr->parsed;			while(p) {				t = (struct rte*)pkg_malloc(sizeof(struct rte));				if (!t) {					LOG(L_ERR, "process_routeset: No memory left\n");					free_rte_list(head);					return -1;				}				t->ptr = p;				t->next = head;				head = t;				p = p->next;			}		}		ptr = ptr->next;	}		if (head) {		if (parse_uri(head->ptr->nameaddr.uri.s, head->ptr->nameaddr.uri.len, &puri) < 0) {			LOG(L_ERR, "process_routeset: Error while parsing URI\n");			free_rte_list(head);			return -1;		}				if (puri.lr.s) {			     /* Next hop is loose router */			*ruri = *contact;			*next_hop = head->ptr->nameaddr.uri;		} else {			     /* Next hop is strict router */			*ruri = head->ptr->nameaddr.uri;			*next_hop = *ruri;			t = head;			head = head->next;			pkg_free(t);		}	} else {		     /* No routes */		*ruri = *contact;		*next_hop = *contact;	}		*list = head;	return 0;}static inline int calc_routeset_len(struct rte* list, str* contact){	struct rte* ptr;	int ret;		if (list || contact) {		ret = ROUTE_PREFIX_LEN + CRLF_LEN;	} else {		return 0;	}		ptr = list;	while(ptr) {		if (ptr != list) {			ret += ROUTE_SEPARATOR_LEN;		}		ret += ptr->ptr->len;		ptr = ptr->next;	}		if (contact) {		if (list) ret += ROUTE_SEPARATOR_LEN;		ret += 2 + contact->len;	}		return ret;}/* * Print the route set */static inline char* print_rs(char* p, struct rte* list, str* contact){	struct rte* ptr;		if (list || contact) {		append_string(p, ROUTE_PREFIX, ROUTE_PREFIX_LEN);	} else {		return p;	}		ptr = list;	while(ptr) {		if (ptr != list) {			append_string(p, ROUTE_SEPARATOR, ROUTE_SEPARATOR_LEN);		}				append_string(p, ptr->ptr->nameaddr.name.s, ptr->ptr->len);		ptr = ptr->next;	}		if (contact) {		if (list) append_string(p, ROUTE_SEPARATOR, ROUTE_SEPARATOR_LEN);		*p++ = '<';		append_string(p, contact->s, contact->len);		*p++ = '>';	}		append_string(p, CRLF, CRLF_LEN);	return p;}/* * Parse Contact header field body and extract URI * Does not parse headers ! */static inline int get_contact_uri(struct sip_msg* msg, str* uri){	contact_t* c;		uri->len = 0;

⌨️ 快捷键说明

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