udomain.c

来自「性能优秀的SIP Proxy」· C语言 代码 · 共 816 行 · 第 1/2 页

C
816
字号
/*  * $Id: udomain.c,v 1.18 2006/07/04 13:52:19 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-03-11 changed to the new locking scheme: locking.h (andrei) * 2003-03-12 added replication mark and zombie state (nils) * 2004-06-07 updated to the new DB api (andrei) * 2004-08-23  hash function changed to process characters as unsigned *             -> no negative results occur (jku) *    */#include "udomain.h"#include <string.h>#include "../../parser/parse_methods.h"#include "../../mem/shm_mem.h"#include "../../dprint.h"#include "../../db/db.h"#include "../../socket_info.h"#include "../../ut.h"#include "ul_mod.h"            /* usrloc module parameters */#include "utime.h"#include "notify.h"/* * Hash function */static inline int hash_func(udomain_t* _d, unsigned char* _s, int _l){	int res = 0, i;		for(i = 0; i < _l; i++) {		res += _s[i];	}		return res % _d->size;}/* * Add a record to list of all records in a domain */static inline void udomain_add(udomain_t* _d, urecord_t* _r){	if (_d->d_ll.n == 0) {		_d->d_ll.first = _r;		_d->d_ll.last = _r;	} else {		_r->d_ll.prev = _d->d_ll.last;		_d->d_ll.last->d_ll.next = _r;		_d->d_ll.last = _r;	}	_d->d_ll.n++;}/* * Remove a record from list of all records in a domain */static inline void udomain_remove(udomain_t* _d, urecord_t* _r){	if (_d->d_ll.n == 0) return;	if (_r->d_ll.prev) {		_r->d_ll.prev->d_ll.next = _r->d_ll.next;	} else {		_d->d_ll.first = _r->d_ll.next;	}	if (_r->d_ll.next) {		_r->d_ll.next->d_ll.prev = _r->d_ll.prev;	} else {		_d->d_ll.last = _r->d_ll.prev;	}	_r->d_ll.prev = _r->d_ll.next = 0;	_d->d_ll.n--;}#ifdef STATISTICSstatic char *build_stat_name( str* domain, char *var_name){	int n;	char *s;	char *p;	n = domain->len + 1 + strlen(var_name) + 1;	s = (char*)shm_malloc( n );	if (s==0) {		LOG(L_ERR,"ERROR:usrloc:build_stat_name: no more shm mem\n");		return 0;	}	memcpy( s, domain->s, domain->len);	p = s + domain->len;	*(p++) = '-';	memcpy( p , var_name, strlen(var_name));	p += strlen(var_name);	*(p++) = 0;	return s;}#endif/* * Create a new domain structure * _n is pointer to str representing * name of the domain, the string is * not copied, it should point to str * structure stored in domain list * _s is hash table size */int new_udomain(str* _n, int _s, udomain_t** _d){	int i;#ifdef STATISTICS	char *name;#endif		/* Must be always in shared memory, since	 * the cache is accessed from timer which	 * lives in a separate process	 */	*_d = (udomain_t*)shm_malloc(sizeof(udomain_t));	if (!(*_d)) {		LOG(L_ERR, "new_udomain(): No memory left\n");		goto error0;	}	memset(*_d, 0, sizeof(udomain_t));		(*_d)->table = (hslot_t*)shm_malloc(sizeof(hslot_t) * _s);	if (!(*_d)->table) {		LOG(L_ERR, "new_udomain(): No memory left 2\n");		goto error1;	}	(*_d)->name = _n;		for(i = 0; i < _s; i++) {		if (init_slot(*_d, &((*_d)->table[i])) < 0) {			LOG(L_ERR, "new_udomain(): Error while initializing hash table\n");			goto error2;		}	}	(*_d)->size = _s;	lock_init(&(*_d)->lock);#ifdef STATISTICS	/* register the statistics */	if ( (name=build_stat_name(_n,"users"))==0 || register_stat("usrloc",	name, &(*_d)->users, STAT_NO_RESET|STAT_NO_SYNC|STAT_SHM_NAME)!=0 ) {		LOG(L_ERR,"ERROR:usrloc:new_udomain: failed to add stat variable\n");		goto error2;	}	if ( (name=build_stat_name(_n,"contacts"))==0 || register_stat("usrloc",	name, &(*_d)->contacts, STAT_NO_RESET|STAT_NO_SYNC|STAT_SHM_NAME)!=0 ) {		LOG(L_ERR,"ERROR:usrloc:new_udomain: failed to add stat variable\n");		goto error2;	}	if ( (name=build_stat_name(_n,"expires"))==0 || register_stat("usrloc",	name, &(*_d)->expires, STAT_NO_SYNC|STAT_SHM_NAME)!=0 ) {		LOG(L_ERR,"ERROR:usrloc:new_udomain: failed to add stat variable\n");		goto error2;	}#endif	return 0;error2:	shm_free((*_d)->table);error1:	shm_free(*_d);error0:	return -1;}/* * Free all memory allocated for * the domain */void free_udomain(udomain_t* _d){	int i;		lock_udomain(_d);	if (_d->table) {		for(i = 0; i < _d->size; i++) {			deinit_slot(_d->table + i);		}		shm_free(_d->table);	}	unlock_udomain(_d);	lock_destroy(&_d->lock);/* destroy the lock (required for SYSV sems!)*/	shm_free(_d);}/* * Returns a statis dummy urecord for temporary usage */static inline void get_static_urecord(udomain_t* _d, str* _aor,														struct urecord** _r){	static struct urecord r;	memset( &r, 0, sizeof(struct urecord) );	r.aor = *_aor;	r.domain = _d->name;	*_r = &r;}/* * Just for debugging */void print_udomain(FILE* _f, udomain_t* _d){	struct urecord* r;	fprintf(_f, "---Domain---\n");	fprintf(_f, "name : '%.*s'\n", _d->name->len, ZSW(_d->name->s));	fprintf(_f, "size : %d\n", _d->size);	fprintf(_f, "table: %p\n", _d->table);	fprintf(_f, "d_ll {\n");	fprintf(_f, "    n    : %d\n", _d->d_ll.n);	fprintf(_f, "    first: %p\n", _d->d_ll.first);	fprintf(_f, "    last : %p\n", _d->d_ll.last);	fprintf(_f, "}\n");	/*fprintf(_f, "lock : %d\n", _d->lock); -- can be a structure --andrei*/	if (_d->d_ll.n > 0) {		fprintf(_f, "\n");		r = _d->d_ll.first;		while(r) {			print_urecord(_f, r);			r = r->d_ll.next;		}		fprintf(_f, "\n");	}	fprintf(_f, "---/Domain---\n");}/* * expects 12 rows (contact, expirs, q, callid, cseq, flags,  *   ua, received, path, socket, methods, last_modified) */static inline ucontact_info_t* dbrow2info( db_val_t *vals, str *contact){	static ucontact_info_t ci;	static str callid, ua, received, host, path;	int port, proto;	char *p;	memset( &ci, 0, sizeof(ucontact_info_t));	contact->s = (char*)VAL_STRING(vals);	if (VAL_NULL(vals) || contact->s==0 || contact->s[0]==0) {		LOG(L_CRIT, "ERROR:usrloc:dbrow2info: bad contact\n");		return 0;	}	contact->len = strlen(contact->s);	if (VAL_NULL(vals+1)) {		LOG(L_CRIT, "ERROR:usrloc:dbrow2info: empty expire\n");		return 0;	}	ci.expires = VAL_TIME(vals+1);	if (VAL_NULL(vals+2)) {		LOG(L_CRIT, "ERROR:usrloc:dbrow2info: empty q\n");		return 0;	}	ci.q = double2q(VAL_DOUBLE(vals+2));	if (VAL_NULL(vals+4)) {		LOG(L_CRIT, "ERROR:usrloc:dbrow2info: empty cseq_nr\n");		return 0;	}	ci.cseq = VAL_INT(vals+4);	callid.s = (char*)VAL_STRING(vals+3);	if (VAL_NULL(vals+3) || !callid.s || !callid.s[0]) {		LOG(L_CRIT, "ERROR:usrloc:dbrow2info: bad callid\n");		return 0;	}	callid.len  = strlen(callid.s);	ci.callid = &callid;	if (VAL_NULL(vals+5)) {		LOG(L_CRIT, "ERROR:usrloc:dbrow2info: empty flag\n");		return 0;	}	ci.flags1  = VAL_BITMAP(vals+5);	ua.s  = (char*)VAL_STRING(vals+6);	if (VAL_NULL(vals+6) || !ua.s || !ua.s[0]==0) {		ua.s = 0;		ua.len = 0;	} else {		ua.len = strlen(ua.s);	}	ci.user_agent = &ua;	received.s  = (char*)VAL_STRING(vals+7);	if (VAL_NULL(vals+7) || !received.s || !received.s[0]) {		received.len = 0;		received.s = 0;	} else {		received.len = strlen(received.s);	}	ci.received = received;		path.s  = (char*)VAL_STRING(vals+8);		if (VAL_NULL(vals+8) || !path.s || !path.s[0]) {			path.len = 0;			path.s = 0;		} else {			path.len = strlen(path.s);		}	ci.path= &path;	/* socket name */	p  = (char*)VAL_STRING(vals+9);	if (VAL_NULL(vals+9) || p==0 || p[0]==0){		ci.sock = 0;	} else {		if (parse_phostport( p, strlen(p), &host.s, &host.len, 		&port, &proto)!=0) {			LOG(L_ERR,"ERROR:usrloc:dbrow2info: bad socket <%s>\n", p);			return 0;		}		ci.sock = grep_sock_info( &host, (unsigned short)port, proto);		if (ci.sock==0) {			LOG(L_WARN,"WARNING:usrloc:dbrow2info: non-local socket "				"<%s>...ignoring\n", p);		}	}	/* supported methods */	if (VAL_NULL(vals+10)) {		ci.methods = ALL_METHODS;	} else {		ci.methods = VAL_BITMAP(vals+10);	}	/* last modified time */	if (!VAL_NULL(vals+11)) {		ci.last_modified = VAL_TIME(vals+11);	}	return &ci;}int preload_udomain(db_con_t* _c, udomain_t* _d){	char uri[MAX_URI_SIZE];	ucontact_info_t *ci;	db_row_t *row;	db_key_t columns[14];	db_res_t* res;	str user, contact;	char* domain;	int i;	urecord_t* r;	ucontact_t* c;	columns[0] = user_col.s;	columns[1] = contact_col.s;	columns[2] = expires_col.s;	columns[3] = q_col.s;	columns[4] = callid_col.s;	columns[5] = cseq_col.s;	columns[6] = flags_col.s;	columns[7] = user_agent_col.s;	columns[8] = received_col.s;	columns[9] = path_col.s;	columns[10] = sock_col.s;	columns[11] = methods_col.s;	columns[12] = last_mod_col.s;	columns[13] = domain_col.s;	if (ul_dbf.use_table(_c, _d->name->s) < 0) {		LOG(L_ERR, "preload_udomain(): Error in use_table\n");		return -1;

⌨️ 快捷键说明

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