00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "udomain.h"
00040 #include <string.h>
00041 #include "../../mem/shm_mem.h"
00042 #include "../../dprint.h"
00043 #include "../../db/db.h"
00044 #include "../../ut.h"
00045 #include "../../parser/parse_param.h"
00046 #include "../../parser/parse_uri.h"
00047 #include "../../resolve.h"
00048 #include "../../socket_info.h"
00049 #include "ul_mod.h"
00050 #include "notify.h"
00051 #include "reg_avps.h"
00052 #include "reg_avps_db.h"
00053 #include "utime.h"
00054 #include "../../hashes.h"
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 static inline int hash_func(udomain_t* _d, unsigned char* _s, int _l)
00065 {
00066 #ifdef HASH_STRING_OPTIMIZE
00067 return get_hash1_raw((char*)_s, _l) % UDOMAIN_HASH_SIZE;
00068 #else
00069 return get_hash1_raw2((char*)_s, _l) % UDOMAIN_HASH_SIZE;
00070 #endif
00071 }
00072
00073
00074
00075
00076
00077 static inline void udomain_add(udomain_t* _d, urecord_t* _r)
00078 {
00079 if (_d->d_ll.n == 0) {
00080 _d->d_ll.first = _r;
00081 _d->d_ll.last = _r;
00082 } else {
00083 _r->d_ll.prev = _d->d_ll.last;
00084 _d->d_ll.last->d_ll.next = _r;
00085 _d->d_ll.last = _r;
00086 }
00087 _d->d_ll.n++;
00088 }
00089
00090
00091
00092
00093
00094 static inline void udomain_remove(udomain_t* _d, urecord_t* _r)
00095 {
00096 if (_d->d_ll.n == 0) return;
00097
00098 if (_r->d_ll.prev) {
00099 _r->d_ll.prev->d_ll.next = _r->d_ll.next;
00100 } else {
00101 _d->d_ll.first = _r->d_ll.next;
00102 }
00103
00104 if (_r->d_ll.next) {
00105 _r->d_ll.next->d_ll.prev = _r->d_ll.prev;
00106 } else {
00107 _d->d_ll.last = _r->d_ll.prev;
00108 }
00109
00110 _r->d_ll.prev = _r->d_ll.next = 0;
00111 _d->d_ll.n--;
00112 }
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 int new_udomain(str* _n, udomain_t** _d)
00123 {
00124 int i;
00125
00126
00127
00128
00129
00130 *_d = (udomain_t*)shm_malloc(sizeof(udomain_t));
00131 if (!(*_d)) {
00132 LOG(L_ERR, "new_udomain(): No memory left\n");
00133 return -1;
00134 }
00135 memset(*_d, 0, sizeof(udomain_t));
00136
00137 (*_d)->table = (hslot_t*)shm_malloc(sizeof(hslot_t) * UDOMAIN_HASH_SIZE);
00138 if (!(*_d)->table) {
00139 LOG(L_ERR, "new_udomain(): No memory left 2\n");
00140 shm_free(*_d);
00141 return -2;
00142 }
00143
00144 (*_d)->name = _n;
00145
00146 for(i = 0; i < UDOMAIN_HASH_SIZE; i++) {
00147 if (init_slot(*_d, &((*_d)->table[i])) < 0) {
00148 LOG(L_ERR, "new_udomain(): Error while initializing hash table\n");
00149 shm_free((*_d)->table);
00150 shm_free(*_d);
00151 return -3;
00152 }
00153 }
00154
00155 lock_init(&(*_d)->lock);
00156 (*_d)->users = 0;
00157 (*_d)->expired = 0;
00158
00159 return 0;
00160 }
00161
00162
00163
00164
00165
00166
00167 void free_udomain(udomain_t* _d)
00168 {
00169 int i;
00170
00171 lock_udomain(_d);
00172 if (_d->table) {
00173 for(i = 0; i < UDOMAIN_HASH_SIZE; i++) {
00174 deinit_slot(_d->table + i);
00175 }
00176 shm_free(_d->table);
00177 }
00178 unlock_udomain(_d);
00179 lock_destroy(&_d->lock);
00180
00181 shm_free(_d);
00182 }
00183
00184
00185
00186
00187
00188 void print_udomain(FILE* _f, udomain_t* _d)
00189 {
00190 struct urecord* r;
00191 fprintf(_f, "---Domain---\n");
00192 fprintf(_f, "name : '%.*s'\n", _d->name->len, ZSW(_d->name->s));
00193 fprintf(_f, "size : %d\n", UDOMAIN_HASH_SIZE);
00194 fprintf(_f, "table: %p\n", _d->table);
00195 fprintf(_f, "d_ll {\n");
00196 fprintf(_f, " n : %d\n", _d->d_ll.n);
00197 fprintf(_f, " first: %p\n", _d->d_ll.first);
00198 fprintf(_f, " last : %p\n", _d->d_ll.last);
00199 fprintf(_f, "}\n");
00200
00201 if (_d->d_ll.n > 0) {
00202 fprintf(_f, "\n");
00203 r = _d->d_ll.first;
00204 while(r) {
00205 print_urecord(_f, r);
00206 r = r->d_ll.next;
00207 }
00208
00209
00210 fprintf(_f, "\n");
00211 }
00212 fprintf(_f, "---/Domain---\n");
00213 }
00214
00215
00216 static struct socket_info* find_socket(str* received)
00217 {
00218 struct sip_uri puri;
00219 param_hooks_t hooks;
00220 struct hostent* he;
00221 struct ip_addr ip;
00222 struct socket_info* si;
00223 param_t* params;
00224 unsigned short port;
00225 char* buf;
00226 int error;
00227
00228 if (!received) return 0;
00229
00230 si = 0;
00231 if (parse_uri(received->s, received->len, &puri) < 0) {
00232 LOG(L_ERR, "find_socket: Error while parsing received URI\n");
00233 return 0;
00234 }
00235
00236 if (parse_params(&puri.params, CLASS_URI, &hooks, ¶ms) < 0) {
00237 LOG(L_ERR, "find_socket: Error while parsing received URI parameters\n");
00238 return 0;
00239 }
00240
00241 if (!hooks.uri.dstip || !hooks.uri.dstip->body.s || !hooks.uri.dstip->body.len) goto end;
00242
00243 buf = (char*)pkg_malloc(hooks.uri.dstip->body.len + 1);
00244 if (!buf) {
00245 LOG(L_ERR, "find_socket: No memory left\n");
00246 goto end;
00247 }
00248 memcpy(buf, hooks.uri.dstip->body.s, hooks.uri.dstip->body.len);
00249 buf[hooks.uri.dstip->body.len] = '\0';
00250
00251 he = resolvehost(buf);
00252 if (he == 0) {
00253 LOG(L_ERR, "find_socket: Unable to resolve '%s'\n", buf);
00254 pkg_free(buf);
00255 goto end;
00256 }
00257 pkg_free(buf);
00258
00259 if (hooks.uri.dstport && hooks.uri.dstport->body.s && hooks.uri.dstport->body.len) {
00260 port = str2s(hooks.uri.dstport->body.s, hooks.uri.dstport->body.len, &error);
00261 if (error != 0) {
00262 LOG(L_ERR, "find_socket: Unable to convert port number\n");
00263 goto end;
00264 }
00265 } else {
00266 port = 0;
00267 }
00268
00269 hostent2ip_addr(&ip, he, 0);
00270 si = find_si(&ip, port, puri.proto);
00271 if (si == 0) {
00272 LOG(L_ERR, "find_socket: Unable to find socket, using the default one\n");
00273 goto end;
00274 }
00275
00276 end:
00277 if (params) free_params(params);
00278 return si;
00279 }
00280
00281
00282
00283 int preload_udomain(udomain_t* _d)
00284 {
00285 db_fld_t columns[] = {
00286 {.name = uid_col.s, .type = DB_STR},
00287 {.name = contact_col.s, .type = DB_STR},
00288 {.name = expires_col.s, .type = DB_DATETIME},
00289 {.name = q_col.s, .type = DB_DOUBLE},
00290 {.name = callid_col.s, .type = DB_STR},
00291 {.name = cseq_col.s, .type = DB_INT},
00292 {.name = flags_col.s, .type = DB_BITMAP},
00293 {.name = user_agent_col.s, .type = DB_STR},
00294 {.name = received_col.s, .type = DB_STR},
00295 {.name = instance_col.s, .type = DB_STR},
00296 {.name = aor_col.s, .type = DB_STR},
00297 {.name = server_id_col.s, .type = DB_INT},
00298 {.name = avp_column, .type = DB_STR},
00299 {.name = NULL}
00300 };
00301
00302 db_res_t* res = NULL;
00303 db_rec_t* rec;
00304 db_cmd_t* get_all = NULL;
00305
00306 struct socket_info* sock;
00307 str callid, ua, instance, aor;
00308 str* receivedp;
00309 qvalue_t q;
00310 unsigned int flags;
00311 urecord_t* r;
00312 ucontact_t* c;
00313
00314 get_all = db_cmd(DB_GET, db, _d->name->s, columns, NULL, NULL);
00315 if (get_all == NULL) {
00316 ERR("usrloc: Error while compiling DB_GET command\n");
00317 return -1;
00318 }
00319 if (db_setopt(get_all, "fetch_all", 0) < 0) {
00320 ERR("usrloc: Error while disabling 'fetch_all' database option\n");
00321 }
00322
00323 if (db_exec(&res, get_all) < 0) goto error;
00324
00325 rec = db_first(res);
00326 if (rec == NULL) {
00327 DBG("preload_udomain(): Table is empty\n");
00328 db_res_free(res);
00329 db_cmd_free(get_all);
00330 return 0;
00331 }
00332
00333 lock_udomain(_d);
00334 get_act_time();
00335
00336 for(; rec != NULL; rec = db_next(res)) {
00337
00338 if (rec->fld[0].flags & DB_NULL) {
00339 LOG(L_CRIT, "preload_udomain: ERROR: bad uid "
00340 "record in table %.*s, skipping...\n",
00341 _d->name->len, _d->name->s);
00342 continue;
00343 }
00344
00345
00346 if (rec->fld[1].flags & DB_NULL) {
00347 LOG(L_CRIT, "ERROR: Bad contact for uid %.*s in table %.*s, skipping\n",
00348 rec->fld[0].v.lstr.len, rec->fld[0].v.lstr.s,
00349 _d->name->len, _d->name->s);
00350 continue;
00351 }
00352
00353
00354
00355
00356
00357 if (db_skip_delete && (rec->fld[2].v.time < act_time)) {
00358 DBG("preload_udomain: Skipping expired contact\n");
00359 continue;
00360 }
00361
00362 q = double2q(rec->fld[3].v.dbl);
00363
00364 if (rec->fld[4].flags & DB_NULL) {
00365 callid.s = NULL;
00366 callid.len = 0;
00367 } else {
00368 callid = rec->fld[4].v.lstr;
00369 }
00370
00371 if (rec->fld[7].flags & DB_NULL) {
00372 ua.s = NULL;
00373 ua.len = 0;
00374 } else {
00375 ua = rec->fld[7].v.lstr;
00376 }
00377
00378 if (rec->fld[8].flags & DB_NULL) {
00379 receivedp = 0;
00380 sock = 0;
00381 } else {
00382 receivedp = &rec->fld[8].v.lstr;
00383 sock = find_socket(receivedp);
00384 }
00385
00386 if (rec->fld[9].flags & DB_NULL) {
00387 instance.s = NULL;
00388 instance.len = 0;
00389 } else {
00390 instance = rec->fld[9].v.lstr;
00391 }
00392
00393 if (rec->fld[10].flags & DB_NULL) {
00394 aor.s = NULL;
00395 aor.len = 0;
00396 } else {
00397 aor = rec->fld[10].v.lstr;
00398 }
00399
00400 if (get_urecord(_d, &rec->fld[0].v.lstr, &r) > 0) {
00401 if (mem_insert_urecord(_d, &rec->fld[0].v.lstr, &r) < 0) {
00402 LOG(L_ERR, "preload_udomain(): Can't create a record\n");
00403 unlock_udomain(_d);
00404 goto error;
00405 }
00406 }
00407
00408 flags = rec->fld[6].v.bitmap;
00409 if (rec->fld[11].v.int4 != server_id) {
00410
00411
00412
00413
00414
00415 flags |= FL_MEM;
00416 }
00417
00418 if (mem_insert_ucontact(r, &aor, &rec->fld[1].v.lstr, rec->fld[2].v.int4,
00419 q, &callid, rec->fld[5].v.int4, flags, &c, &ua, receivedp,
00420 sock, &instance, rec->fld[11].v.int4) < 0) {
00421 LOG(L_ERR, "preload_udomain(): Error while inserting contact\n");
00422 unlock_udomain(_d);
00423 goto error;
00424 }
00425
00426 if (use_reg_avps() && ((rec->fld[12].flags & DB_NULL) != DB_NULL)) {
00427 c->avps = deserialize_avps(&rec->fld[12].v.lstr);
00428
00429 }
00430
00431
00432
00433
00434
00435
00436 c->state = CS_SYNC;
00437 }
00438
00439 unlock_udomain(_d);
00440 db_res_free(res);
00441 db_cmd_free(get_all);
00442 return 0;
00443
00444 error:
00445 if (res) db_res_free(res);
00446 if (get_all) db_cmd_free(get_all);
00447 return -1;
00448 }
00449
00450
00451
00452
00453
00454 int mem_insert_urecord(udomain_t* _d, str* _uid, struct urecord** _r)
00455 {
00456 int sl;
00457
00458 if (new_urecord(_d->name, _uid, _r) < 0) {
00459 LOG(L_ERR, "insert_urecord(): Error while creating urecord\n");
00460 return -1;
00461 }
00462
00463 sl = hash_func(_d, (unsigned char*)_uid->s, _uid->len);
00464 slot_add(&_d->table[sl], *_r);
00465 udomain_add(_d, *_r);
00466 _d->users++;
00467 return 0;
00468 }
00469
00470
00471
00472
00473
00474 void mem_delete_urecord(udomain_t* _d, struct urecord* _r)
00475 {
00476 if (_r->watchers == 0) {
00477 udomain_remove(_d, _r);
00478 slot_rem(_r->slot, _r);
00479 free_urecord(_r);
00480 _d->users--;
00481 }
00482
00483 }
00484
00485
00486 int timer_udomain(udomain_t* _d)
00487 {
00488 struct urecord* ptr, *t;
00489
00490 lock_udomain(_d);
00491
00492 ptr = _d->d_ll.first;
00493
00494 while(ptr) {
00495 if (timer_urecord(ptr) < 0) {
00496 LOG(L_ERR, "timer_udomain(): Error in timer_urecord\n");
00497 unlock_udomain(_d);
00498 return -1;
00499 }
00500
00501
00502
00503
00504 if (ptr->contacts == 0) {
00505 t = ptr;
00506 ptr = ptr->d_ll.next;
00507 mem_delete_urecord(_d, t);
00508 } else {
00509 ptr = ptr->d_ll.next;
00510 }
00511 }
00512
00513 unlock_udomain(_d);
00514
00515
00516 return 0;
00517 }
00518
00519
00520
00521
00522
00523 void lock_udomain(udomain_t* _d)
00524 {
00525 lock_get(&_d->lock);
00526 cur_cmd = _d->db_cmd_idx;
00527 }
00528
00529
00530
00531
00532
00533 void unlock_udomain(udomain_t* _d)
00534 {
00535 lock_release(&_d->lock);
00536 }
00537
00538
00539
00540
00541
00542 int insert_urecord(udomain_t* _d, str* _uid, struct urecord** _r)
00543 {
00544 if (mem_insert_urecord(_d, _uid, _r) < 0) {
00545 LOG(L_ERR, "insert_urecord(): Error while inserting record\n");
00546 return -1;
00547 }
00548 return 0;
00549 }
00550
00551
00552
00553
00554
00555 int get_urecord(udomain_t* _d, str* _uid, struct urecord** _r)
00556 {
00557 int sl, i;
00558 urecord_t* r;
00559
00560 sl = hash_func(_d, (unsigned char*)_uid->s, _uid->len);
00561
00562 r = _d->table[sl].first;
00563
00564 for(i = 0; i < _d->table[sl].n; i++) {
00565 if ((r->uid.len == _uid->len) && !memcmp(r->uid.s, _uid->s, _uid->len)) {
00566 *_r = r;
00567 return 0;
00568 }
00569
00570 r = r->s_ll.next;
00571 }
00572
00573 return 1;
00574 }
00575
00576
00577
00578
00579
00580 int delete_urecord(udomain_t* _d, str* _uid)
00581 {
00582 struct ucontact* c, *t;
00583 struct urecord* r;
00584
00585 if (get_urecord(_d, _uid, &r) > 0) {
00586 return 0;
00587 }
00588
00589 c = r->contacts;
00590 while(c) {
00591 t = c;
00592 c = c->next;
00593 if (delete_ucontact(r, t) < 0) {
00594 LOG(L_ERR, "delete_urecord(): Error while deleting contact\n");
00595 return -1;
00596 }
00597 }
00598 release_urecord(r);
00599 return 0;
00600 }