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 + -
显示快捷键?