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

📄 udomain.c

📁 SIP Express Router, Linux下的SIP代理服务器,小巧实用,开发测试VoIP设备和应用的必备.
💻 C
字号:
/*  * $Id: udomain.c,v 1.41.2.1 2005/03/29 11:54:35 janakj Exp $  * * Copyright (C) 2001-2003 FhG Fokus * * This file is part of ser, a free SIP server. * * ser 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 * * For a license to use the ser software under conditions * other than those described here, or to purchase support for this * software, please contact iptel.org by e-mail at the following addresses: *    info@iptel.org * * ser 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 "../../mem/shm_mem.h"#include "../../dprint.h"#include "../../db/db.h"#include "../../ut.h"#include "ul_mod.h"            /* usrloc module parameters */#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--;}/* * 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;		     /* 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");		return -1;	}	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");		shm_free(*_d);		return -2;	}	(*_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");			shm_free((*_d)->table);			shm_free(*_d);			return -3;		}	}	(*_d)->size = _s;	lock_init(&(*_d)->lock);	(*_d)->users = 0;	(*_d)->expired = 0;		return 0;}/* * 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);}/* * 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");}int preload_udomain(db_con_t* _c, udomain_t* _d){	char b[256];	db_key_t columns[10];	db_res_t* res;	db_row_t* row;	int i, cseq;	unsigned int flags;	str user, contact, callid, ua, received;	str* rec;	char* domain;	time_t expires;	qvalue_t q;	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] = domain_col.s;		memcpy(b, _d->name->s, _d->name->len);	b[_d->name->len] = '\0';	if (ul_dbf.use_table(_c, b) < 0) {		LOG(L_ERR, "preload_udomain(): Error in use_table\n");		return -1;	}	if (ul_dbf.query(_c, 0, 0, 0, columns, 0, (use_domain) ? 10 : 9, 0,				&res) < 0) {		LOG(L_ERR, "preload_udomain(): Error while doing db_query\n");		return -1;	}	if (RES_ROW_N(res) == 0) {		DBG("preload_udomain(): Table is empty\n");		ul_dbf.free_result(_c, res);		return 0;	}	lock_udomain(_d);	for(i = 0; i < RES_ROW_N(res); i++) {		row = RES_ROWS(res) + i;				user.s      = (char*)VAL_STRING(ROW_VALUES(row));		if (user.s == 0) {			LOG(L_CRIT, "preload_udomain: ERROR: bad username "							"record in table %s\n", b);			LOG(L_CRIT, "preload_udomain: ERROR: skipping...\n");			continue;		} else {			user.len = strlen(user.s);		}		contact.s = (char*)VAL_STRING(ROW_VALUES(row) + 1);		if (contact.s == 0) {			LOG(L_CRIT, "preload_udomain: ERROR: bad contact "							"record in table %s\n", b);			LOG(L_CRIT, "preload_udomain: ERROR: for username %.*s\n",							user.len, user.s);			LOG(L_CRIT, "preload_udomain: ERROR: skipping...\n");			continue;		} else {			contact.len = strlen(contact.s);		}		expires     = VAL_TIME  (ROW_VALUES(row) + 2);		q           = double2q(VAL_DOUBLE(ROW_VALUES(row) + 3));		cseq        = VAL_INT   (ROW_VALUES(row) + 5);		callid.s    = (char*)VAL_STRING(ROW_VALUES(row) + 4);		if (callid.s == 0) {			LOG(L_CRIT, "preload_udomain: ERROR: bad callid record in"							" table %s\n", b);			LOG(L_CRIT, "preload_udomain: ERROR: for username %.*s,"							" contact %.*s\n",							user.len, user.s, contact.len, contact.s);			LOG(L_CRIT, "preload_udomain: ERROR: skipping...\n");			continue;		} else {			callid.len  = strlen(callid.s);		}		flags  = VAL_BITMAP(ROW_VALUES(row) + 6);		ua.s  = (char*)VAL_STRING(ROW_VALUES(row) + 7);		if (ua.s) {			ua.len = strlen(ua.s);		} else {			ua.len = 0;		}		if (!VAL_NULL(ROW_VALUES(row) + 8)) {			received.s  = (char*)VAL_STRING(ROW_VALUES(row) + 8);			if (received.s) {				received.len = strlen(received.s);				rec = &received;			} else {				received.len = 0;				rec = 0;			}		} else {			rec = 0;		}		if (use_domain) {			domain  = (char*)VAL_STRING(ROW_VALUES(row) + 9);			snprintf(b, 256, "%.*s@%s", user.len, ZSW(user.s), domain);			user.s = b;			user.len = strlen(b);		}		if (get_urecord(_d, &user, &r) > 0) {			if (mem_insert_urecord(_d, &user, &r) < 0) {				LOG(L_ERR, "preload_udomain(): Can't create a record\n");				ul_dbf.free_result(_c, res);				unlock_udomain(_d);				return -2;			}		}				if (mem_insert_ucontact(r, &contact, expires, q, &callid, cseq, flags, &c, &ua, rec) < 0) {			LOG(L_ERR, "preload_udomain(): Error while inserting contact\n");			ul_dbf.free_result(_c, res);			unlock_udomain(_d);			return -3;		}		     /* We have to do this, because insert_ucontact sets state to CS_NEW		      * and we have the contact in the database already			  * we also store zombies in database so we have to restore			  * the correct state		      */		c->state = CS_SYNC;	}	ul_dbf.free_result(_c, res);	unlock_udomain(_d);	return 0;}/* * Insert a new record into domain */int mem_insert_urecord(udomain_t* _d, str* _aor, struct urecord** _r){	int sl;		if (new_urecord(_d->name, _aor, _r) < 0) {		LOG(L_ERR, "insert_urecord(): Error while creating urecord\n");		return -1;	}	sl = hash_func(_d, (unsigned char*)_aor->s, _aor->len);	slot_add(&_d->table[sl], *_r);	udomain_add(_d, *_r);	_d->users++;	return 0;}/* * Remove a record from domain */void mem_delete_urecord(udomain_t* _d, struct urecord* _r){	if (_r->watchers == 0) {		udomain_remove(_d, _r);		slot_rem(_r->slot, _r);		free_urecord(_r);		_d->users--; /* FIXME */	}		}int timer_udomain(udomain_t* _d){	struct urecord* ptr, *t;	lock_udomain(_d);	ptr = _d->d_ll.first;	while(ptr) {		if (timer_urecord(ptr) < 0) {			LOG(L_ERR, "timer_udomain(): Error in timer_urecord\n");			unlock_udomain(_d);			return -1;		}				     /* Remove the entire record		      * if it is empty		      */		if (ptr->contacts == 0) {			t = ptr;			ptr = ptr->d_ll.next;			mem_delete_urecord(_d, t);		} else {			ptr = ptr->d_ll.next;		}	}		unlock_udomain(_d);/*	process_del_list(_d->name); *//*	process_ins_list(_d->name); */	return 0;}/* * Get lock */void lock_udomain(udomain_t* _d){	lock_get(&_d->lock);}/* * Release lock */void unlock_udomain(udomain_t* _d){	lock_release(&_d->lock);}/* * Create and insert a new record */int insert_urecord(udomain_t* _d, str* _aor, struct urecord** _r){	if (mem_insert_urecord(_d, _aor, _r) < 0) {		LOG(L_ERR, "insert_urecord(): Error while inserting record\n");		return -1;	}	return 0;}/* * Obtain a urecord pointer if the urecord exists in domain */int get_urecord(udomain_t* _d, str* _aor, struct urecord** _r){	int sl, i;	urecord_t* r;	sl = hash_func(_d, (unsigned char*)_aor->s, _aor->len);	r = _d->table[sl].first;	for(i = 0; i < _d->table[sl].n; i++) {		if ((r->aor.len == _aor->len) && !memcmp(r->aor.s, _aor->s, _aor->len)) {			*_r = r;			return 0;		}		r = r->s_ll.next;	}	return 1;   /* Nothing found */}/* * Delete a urecord from domain */int delete_urecord(udomain_t* _d, str* _aor){	struct ucontact* c, *t;	struct urecord* r;	if (get_urecord(_d, _aor, &r) > 0) {		return 0;	}			c = r->contacts;	while(c) {		t = c;		c = c->next;		if (delete_ucontact(r, t) < 0) {			LOG(L_ERR, "delete_urecord(): Error while deleting contact\n");			return -1;		}	}	release_urecord(r);	return 0;}

⌨️ 快捷键说明

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