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

📄 save.c

📁 性能优秀的SIP Proxy
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Id: save.c,v 1.31 2006/07/04 10:58:32 bogdan_iancu Exp $ * * Process REGISTER request and send reply * * 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-28 scrathcpad compatibility abandoned (jiri) * 2003-03-21 save_noreply added, patch provided by Maxim Sobolev  *            <sobomax@portaone.com> (janakj) * 2005-07-11 added sip_natping_flag for nat pinging with SIP method *            instead of UDP package (bogdan) * 2006-04-13 added tcp_persistent_flag for keeping the TCP connection as long *            as a TCP contact is registered (bogdan) */#include "../../str.h"#include "../../socket_info.h"#include "../../parser/parse_allow.h"#include "../../parser/parse_methods.h"#include "../../parser/msg_parser.h"#include "../../parser/parse_uri.h"#include "../../dprint.h"#include "../../trim.h"#include "../../ut.h"#include "../../qvalue.h"#ifdef USE_TCP#include "../../tcp_server.h"#endif#include "../usrloc/usrloc.h"#include "common.h"#include "sip_msg.h"#include "rerrno.h"#include "reply.h"#include "reg_mod.h"#include "regtime.h"#include "path.h"#include "save.h"static int mem_only = 0;int_str rcv_avp;void remove_cont(urecord_t* _r, ucontact_t* _c){	if (_c->prev) {		_c->prev->next = _c->next;		if (_c->next) {			_c->next->prev = _c->prev;		}	} else {		_r->contacts = _c->next;		if (_c->next) {			_c->next->prev = 0;		}	}}void move_on_top(urecord_t* _r, ucontact_t* _c){	ucontact_t* prev;	if (!_r->contacts) return;	if (_c->prev == 0) return;	prev = _c->prev;	remove_cont(_r, _c);		_c->next = _r->contacts;	_c->prev = 0;	_r->contacts->prev = _c;	_r->contacts = _c;}/* * Process request that contained a star, in that case,  * we will remove all bindings with the given username  * from the usrloc and return 200 OK response */static inline int star(udomain_t* _d, str* _a){	urecord_t* r;	ucontact_t* c;		ul.lock_udomain(_d);	if (!ul.get_urecord(_d, _a, &r)) {		c = r->contacts;		while(c) {			if (mem_only) {				c->flags |= FL_MEM;			} else {				c->flags &= ~FL_MEM;			}			c = c->next;		}	}	if (ul.delete_urecord(_d, _a, 0) < 0) {		LOG(L_ERR, "star(): Error while removing record from usrloc\n");				     /* Delete failed, try to get corresponding		      * record structure and send back all existing		      * contacts		      */		rerrno = R_UL_DEL_R;		if (!ul.get_urecord(_d, _a, &r)) {			build_contact(r->contacts);		}		ul.unlock_udomain(_d);		return -1;	}	ul.unlock_udomain(_d);	return 0;}/* */static struct socket_info *get_sock_hdr(struct sip_msg *msg){	struct socket_info *sock;	struct hdr_field *hf;	str socks;	str hosts;	int port;	int proto;	if (parse_headers( msg, HDR_EOH_F, 0) == -1) {		LOG(L_ERR,"ERROR:registrar:get_sock_hdr: failed to parse message\n");		return 0;	}	for (hf=msg->headers; hf; hf=hf->next) {		if (hf->name.len==sock_hdr_name.len &&		strncasecmp(hf->name.s, sock_hdr_name.s, sock_hdr_name.len)==0 )			break;	}	/* hdr found? */	if (hf==0)		return 0;	trim_len( socks.len, socks.s, hf->body );	if (socks.len==0)		return 0;	if (parse_phostport( socks.s, socks.len, &hosts.s, &hosts.len, 	&port, &proto)!=0) {		LOG(L_ERR,"ERROR:registrar:get_sock_hdr: bad socket <%.*s> in \n",			socks.len, socks.s);		return 0;	}	sock = grep_sock_info(&hosts,(unsigned short)port,(unsigned short)proto);	if (sock==0) {		LOG(L_WARN,"ERROR:registrar:get_sock_hdr: non-local socket <%.*s>\n",			socks.len, socks.s);		return 0;	}	DBG("DEBUG:registrar:get_sock_hdr: %d:<%.*s>:%d -> p=%p\n",		proto,socks.len,socks.s,port_no,sock );	return sock;}/* * Process request that contained no contact header * field, it means that we have to send back a response * containing a list of all existing bindings for the * given username (in To HF) */static inline int no_contacts(udomain_t* _d, str* _a){	urecord_t* r;	int res;		ul.lock_udomain(_d);	res = ul.get_urecord(_d, _a, &r);	if (res < 0) {		rerrno = R_UL_GET_R;		LOG(L_ERR, "ERROR:registrar:no_contacts: failed to retrieve record "			"from usrloc\n");		ul.unlock_udomain(_d);		return -1;	}		if (res == 0) {  /* Contacts found */		build_contact(r->contacts);	}	ul.unlock_udomain(_d);	return 0;}/* * Fills the common part (for all contacts) of the info structure */static inline ucontact_info_t* pack_ci( struct sip_msg* _m, contact_t* _c,													int _e, int _f1, int _f2){	static ucontact_info_t ci;	static str no_ua = str_init("n/a");	static str callid;	static str path_received = {0,0};	static str path;	static str received = {0,0};	static int received_found;	static unsigned int allowed, allow_parsed;	static struct sip_msg *m = 0;	int_str val;	if (_m!=0) {		memset( &ci, 0, sizeof(ucontact_info_t));		/* Get callid of the message */		callid = _m->callid->body;		trim_trailing(&callid);		if (callid.len > CALLID_MAX_SIZE) {			rerrno = R_CALLID_LEN;			LOG(L_ERR, "ERROR:registrar:pack_ci: callid too long\n");			goto error;		}		ci.callid = &callid;		/* Get CSeq number of the message */		if (str2int(&get_cseq(_m)->number, (unsigned int*)&ci.cseq) < 0) {			rerrno = R_INV_CSEQ;			LOG(L_ERR, "ERROR:registrar:pack_ci: failed to convert "				"cseq number\n");			goto error;		}		/* set received socket */		if (_m->flags&sock_flag) {			ci.sock = get_sock_hdr(_m);			if (ci.sock==0)				ci.sock = _m->rcv.bind_address;		} else {			ci.sock = _m->rcv.bind_address;		}		/* additional info from message */		if (parse_headers(_m, HDR_USERAGENT_F, 0) != -1 && _m->user_agent &&		_m->user_agent->body.len>0 && _m->user_agent->body.len<UA_MAX_SIZE) {			ci.user_agent = &_m->user_agent->body;		} else {			ci.user_agent = &no_ua;		}		/* extract Path headers */		if (path_enabled) {			if (build_path_vector(_m, &path, &path_received) < 0) {				rerrno = R_PARSE_PATH;				goto error;			}			if (path.len && path.s) {				ci.path = &path;				/* save in msg too for reply */				if (set_path_vector(_m, &path) < 0) {					rerrno = R_PARSE_PATH;					goto error;				}			}		}		ci.last_modified = act_time;		allow_parsed = 0; /* not parsed yet */		received_found = 0; /* not found yet */		m = _m; /* remember the message */	}	if(_c!=0) {		/* Calculate q value of the contact */		if (calc_contact_q(_c->q, &ci.q) < 0) {			rerrno = R_INV_Q;			LOG(L_ERR, "ERROR:registrar:pack_ci: failed to calculate q\n");			goto error;		}		/* set expire time */		ci.expires = _e;		/* set flags */		ci.flags1 = _f1;		ci.flags2 = _f2;		/* Get methods of contact */		if (_c->methods) {			if (parse_methods(&(_c->methods->body), &ci.methods) < 0) {				rerrno = R_PARSE;				LOG(L_ERR, "ERROR:usrloc:pack_ci: failed to parse "					"contact methods\n");				goto error;			}		} else {			/* check on Allow hdr */			if (allow_parsed == 0) {				if (m && parse_allow( m ) != -1) {					allowed = get_allow_methods(m);				} else {					allowed = ALL_METHODS;				}				allow_parsed = 1;			}			ci.methods = allowed;		}		/* get received */		if (path_received.len && path_received.s) {			ci.flags1 |= FL_NAT;			ci.flags2 &= ~FL_NAT;			ci.received = path_received;		}		else if (_c->received) {			ci.received = _c->received->body;		} else {			if (received_found==0) {				if (search_first_avp(0, rcv_avp, &val, 0) && val.s.s) {					if (val.s.len>RECEIVED_MAX_SIZE) {						rerrno = R_CONTACT_LEN;						LOG(L_ERR,"ERROR:registrar:pack_ci: received "							"too long\n");						goto error;					}					received = val.s;				} else {					received.s = 0;					received.len = 0;				}				received_found = 1;			}			ci.received = received;		}	}	return &ci;error:	return 0;}/* * Message contained some contacts, but record with same address * of record was not found so we have to create a new record * and insert all contacts from the message that have expires * > 0 */static inline int insert_contacts(struct sip_msg* _m, contact_t* _c,													udomain_t* _d, str* _a){	ucontact_info_t* ci;	urecord_t* r;	ucontact_t* c;	unsigned int flags;	int num;	int e;#ifdef USE_TCP	int e_max;	int tcp_check;	struct sip_uri uri;#endif	/* is nated flag */	if (_m->flags&nat_flag)		flags = FL_NAT;	else		flags = FL_NONE;	/* nat type flag */	if (_m->flags&sip_natping_flag)		flags |= FL_NAT_SIPPING;	flags |= mem_only;#ifdef USE_TCP	if ( (_m->flags&tcp_persistent_flag) &&	(_m->rcv.proto==PROTO_TCP||_m->rcv.proto==PROTO_TLS)) {		e_max = 0;		tcp_check = 1;	} else {		e_max = tcp_check = 0;	}#endif	for( num=0,r=0,ci=0 ; _c ; _c = get_next_contact(_c) ) {		/* calculate expires */

⌨️ 快捷键说明

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