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

📄 urecord.c

📁 用来作为linux中SIP SERVER,完成VOIP网络电话中服务器的功能
💻 C
字号:
/*  * $Id: urecord.c,v 1.37.2.4 2005/05/10 11:23:07 janakj Exp $  * * Usrloc record structure * * 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-12 added replication mark and zombie state support (nils) * 2004-03-17 generic callbacks added (bogdan) * 2004-06-07 updated to the new DB api (andrei) */#include "urecord.h"#include <string.h>#include "../../mem/shm_mem.h"#include "../../dprint.h"#include "../../ut.h"#include "ul_mod.h"#include "utime.h"/* #include "del_list.h" *//* #include "ins_list.h" */#include "notify.h"#include "ul_callback.h"/* * Create and initialize new record structure */int new_urecord(str* _dom, str* _aor, urecord_t** _r){	*_r = (urecord_t*)shm_malloc(sizeof(urecord_t));	if (*_r == 0) {		LOG(L_ERR, "new_urecord(): No memory left\n");		return -1;	}	memset(*_r, 0, sizeof(urecord_t));	(*_r)->aor.s = (char*)shm_malloc(_aor->len);	if ((*_r)->aor.s == 0) {		LOG(L_ERR, "new_urecord(): No memory left\n");		shm_free(*_r);		return -2;	}	memcpy((*_r)->aor.s, _aor->s, _aor->len);	(*_r)->aor.len = _aor->len;	(*_r)->domain = _dom;	return 0;}/* * Free all memory used by the given structure * The structure must be removed from all linked * lists first */void free_urecord(urecord_t* _r){	ucontact_t* ptr;	while(_r->contacts) {		ptr = _r->contacts;		_r->contacts = _r->contacts->next;		free_ucontact(ptr);	}		if (_r->aor.s) shm_free(_r->aor.s);	shm_free(_r);}/* * Print a record */void print_urecord(FILE* _f, urecord_t* _r){	ucontact_t* ptr;	fprintf(_f, "...Record(%p)...\n", _r);	fprintf(_f, "domain: '%.*s'\n", _r->domain->len, ZSW(_r->domain->s));	fprintf(_f, "aor   : '%.*s'\n", _r->aor.len, ZSW(_r->aor.s));		if (_r->contacts) {		ptr = _r->contacts;		while(ptr) {			print_ucontact(_f, ptr);			ptr = ptr->next;		}	}	fprintf(_f, ".../Record...\n");}/* * Add a new contact * Contacts are ordered by: 1) q  *                          2) descending modification time */int mem_insert_ucontact(urecord_t* _r, str* _c, time_t _e, qvalue_t _q, str* _cid, int _cs, 			unsigned int _flags, struct ucontact** _con, str* _ua, str* _recv){	ucontact_t* ptr, *prev = 0;	if (new_ucontact(_r->domain, &_r->aor, _c, _e, _q, _cid, _cs, _flags, _con, _ua, _recv) < 0) {		LOG(L_ERR, "mem_insert_ucontact(): Can't create new contact\n");		return -1;	}		ptr = _r->contacts;	if (!desc_time_order) {		while(ptr) {			if (ptr->q < _q) break;			prev = ptr;			ptr = ptr->next;		}	}	if (ptr) {		if (!ptr->prev) {			ptr->prev = *_con;			(*_con)->next = ptr;			_r->contacts = *_con;		} else {			(*_con)->next = ptr;			(*_con)->prev = ptr->prev;			ptr->prev->next = *_con;			ptr->prev = *_con;		}	} else if (prev) {		prev->next = *_con;		(*_con)->prev = prev;	} else {		_r->contacts = *_con;	}	return 0;}/* * Remove the contact from lists */void mem_remove_ucontact(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;		}	}}	/* * Remove contact from the list and delete */void mem_delete_ucontact(urecord_t* _r, ucontact_t* _c){	mem_remove_ucontact(_r, _c);	free_ucontact(_c);}/* * This timer routine is used when * db_mode is set to NO_DB */static inline int nodb_timer(urecord_t* _r){	ucontact_t* ptr, *t;	int not = 0;	ptr = _r->contacts;	while(ptr) {		if (!VALID_CONTACT(ptr, act_time)) {			/* run callbacks for EXPIRE event */			if (exists_ulcb_type(UL_CONTACT_EXPIRE))				run_ul_callbacks( UL_CONTACT_EXPIRE, ptr);			notify_watchers(_r, ptr, PRES_OFFLINE);			LOG(L_NOTICE, "Binding '%.*s','%.*s' has expired\n",			    ptr->aor->len, ZSW(ptr->aor->s),			    ptr->c.len, ZSW(ptr->c.s));						t = ptr;			ptr = ptr->next;						     /* it was the last contact and it was in normal			      * state, so notify */			if (!ptr && t->state == CS_NEW) not=1;						mem_delete_ucontact(_r, t);			_r->slot->d->expired++;		} else {			ptr = ptr->next;		}	}	return 0;}/* * This routine is used when db_mode is * set to WRITE_THROUGH */static inline int wt_timer(urecord_t* _r){	ucontact_t* ptr, *t;	int not = 0;		ptr = _r->contacts;		while(ptr) {		if (!VALID_CONTACT(ptr, act_time)) {			/* run callbacks for EXPIRE event */			if (exists_ulcb_type(UL_CONTACT_EXPIRE)) {				run_ul_callbacks( UL_CONTACT_EXPIRE, ptr);			}			notify_watchers(_r, ptr, PRES_OFFLINE);			LOG(L_NOTICE, "Binding '%.*s','%.*s' has expired\n",			    ptr->aor->len, ZSW(ptr->aor->s),			    ptr->c.len, ZSW(ptr->c.s));						t = ptr;			ptr = ptr->next;						     /* it was the last contact and it was in normal			      * state, so notify */			if (!ptr && t->state == CS_SYNC) not=1;						if (db_delete_ucontact(t) < 0) {				LOG(L_ERR, "wt_timer(): Error while deleting contact from "				    "database\n");			}			mem_delete_ucontact(_r, t);			_r->slot->d->expired++;		} else {			     /* the contact was unregistered and is not marked 			      * for replication so remove it, but the notify was			      * already done during unregister */			ptr = ptr->next;		}	}		return 0;}/* * Write-back timer */static inline int wb_timer(urecord_t* _r){	ucontact_t* ptr, *t;	int op;	int not = 0;	ptr = _r->contacts;	while(ptr) {		if (!VALID_CONTACT(ptr, act_time)) {			/* run callbacks for EXPIRE event */			if (exists_ulcb_type(UL_CONTACT_EXPIRE)) {				run_ul_callbacks( UL_CONTACT_EXPIRE, ptr);			}			notify_watchers(_r, ptr, PRES_OFFLINE);			LOG(L_NOTICE, "Binding '%.*s','%.*s' has expired\n",			    ptr->aor->len, ZSW(ptr->aor->s),			    ptr->c.len, ZSW(ptr->c.s));			if (ptr->next == 0) not=1;			_r->slot->d->expired++;			t = ptr;			ptr = ptr->next;						     /* Should we remove the contact from the database ? */			if (st_expired_ucontact(t) == 1) {				if (db_delete_ucontact(t) < 0) {					LOG(L_ERR, "wb_timer(): Can't delete contact from the database\n");				}			}						mem_delete_ucontact(_r, t);		} else {			     /* Determine the operation we have to do */			op = st_flush_ucontact(ptr);						switch(op) {			case 0: /* do nothing, contact is synchronized */				break;			case 1: /* insert */				if (db_insert_ucontact(ptr) < 0) {					LOG(L_ERR, "wb_timer(): Error while inserting contact into database\n");				}				break;			case 2: /* update */				if (db_update_ucontact(ptr) < 0) {					LOG(L_ERR, "wb_timer(): Error while updating contact in db\n");				}				break;			case 4: /* delete */				if (db_delete_ucontact(ptr) < 0) {					LOG(L_ERR, "wb_timer(): Can't delete contact from database\n");				}				     /* fall through to the next case statement */			case 3: /* delete from memory */				mem_delete_ucontact(_r, ptr);				break;			}			ptr = ptr->next;		}	}	return 0;}int timer_urecord(urecord_t* _r){	switch(db_mode) {	case NO_DB:         return nodb_timer(_r);	case WRITE_THROUGH: return wt_timer(_r);	case WRITE_BACK:    return wb_timer(_r);	}	return 0; /* Makes gcc happy */}int db_delete_urecord(urecord_t* _r){	char b[256];	db_key_t keys[2];	db_val_t vals[2];	char* dom;	keys[0] = user_col.s;	keys[1] = domain_col.s;	vals[0].type = DB_STR;	vals[0].nul = 0;	vals[0].val.str_val.s = _r->aor.s;	vals[0].val.str_val.len = _r->aor.len;	if (use_domain) {		dom = q_memchr(_r->aor.s, '@', _r->aor.len);		vals[0].val.str_val.len = dom - _r->aor.s;		vals[1].type = DB_STR;		vals[1].nul = 0;		vals[1].val.str_val.s = dom + 1;		vals[1].val.str_val.len = _r->aor.s + _r->aor.len - dom - 1;	}	     /* FIXME */	memcpy(b, _r->domain->s, _r->domain->len);	b[_r->domain->len] = '\0';	if (ul_dbf.use_table(ul_dbh, b) < 0) {		LOG(L_ERR, "ERROR: db_delete_urecord():"		                " Error in use_table\n");		return -1;	}	if (ul_dbf.delete(ul_dbh, keys, 0, vals, (use_domain) ? (2) : (1)) < 0) {		LOG(L_ERR, "ERROR: db_delete_urecord():"				" Error while deleting from database\n");		return -1;	}	return 0;}/* * Release urecord previously obtained * through get_urecord */void release_urecord(urecord_t* _r){	if (_r->contacts == 0) {		mem_delete_urecord(_r->slot->d, _r);	}}/* * Create and insert new contact * into urecord */int insert_ucontact(urecord_t* _r, str* _c, time_t _e, qvalue_t _q, str* _cid, 		    int _cs, unsigned int _flags, struct ucontact** _con, str* _ua, str* _recv){	if (mem_insert_ucontact(_r, _c, _e, _q, _cid, _cs, _flags, _con, _ua, _recv) < 0) {		LOG(L_ERR, "insert_ucontact(): Error while inserting contact\n");		return -1;	}	notify_watchers(_r, *_con, (_e > 0) ? PRES_ONLINE : PRES_OFFLINE);	if (exists_ulcb_type(UL_CONTACT_INSERT)) {		run_ul_callbacks( UL_CONTACT_INSERT, *_con);	}	if (db_mode == WRITE_THROUGH) {		if (db_insert_ucontact(*_con) < 0) {			LOG(L_ERR, "insert_ucontact(): Error while inserting in database\n");		}		(*_con)->state = CS_SYNC;	}	return 0;}/* * Delete ucontact from urecord */int delete_ucontact(urecord_t* _r, struct ucontact* _c){	if (exists_ulcb_type(UL_CONTACT_DELETE)) {		run_ul_callbacks( UL_CONTACT_DELETE, _c);	}	notify_watchers(_r, _c, PRES_OFFLINE);	if (st_delete_ucontact(_c) > 0) {		if (db_mode == WRITE_THROUGH) {			if (db_delete_ucontact(_c) < 0) {				LOG(L_ERR, "delete_ucontact(): Can't remove contact from "							"database\n");			}		}		mem_delete_ucontact(_r, _c);	}	return 0;}/* * Get pointer to ucontact with given contact */int get_ucontact(urecord_t* _r, str* _c, struct ucontact** _co){	ucontact_t* ptr;		ptr = _r->contacts;	while(ptr) {		if ((_c->len == ptr->c.len) &&		    !memcmp(_c->s, ptr->c.s, _c->len)) {			*_co = ptr;			return 0;		}				ptr = ptr->next;	}	return 1;}

⌨️ 快捷键说明

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