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
00036 #include "../usrloc/usrloc.h"
00037 #include "urecord.h"
00038 #include <string.h>
00039 #include "../../mem/shm_mem.h"
00040 #include "../../dprint.h"
00041 #include "../../ut.h"
00042 #include "../../hashes.h"
00043 #include "p_usrloc_mod.h"
00044 #include "utime.h"
00045 #include "../usrloc/ul_callback.h"
00046
00047 #include "ul_db_layer.h"
00048
00049
00051 int matching_mode = CONTACT_ONLY;
00053 int cseq_delay = 20;
00054
00062 int new_urecord(str* _dom, str* _aor, urecord_t** _r)
00063 {
00064 *_r = (urecord_t*)shm_malloc(sizeof(urecord_t));
00065 if (*_r == 0) {
00066 LM_ERR("no more share memory\n");
00067 return -1;
00068 }
00069 memset(*_r, 0, sizeof(urecord_t));
00070
00071 (*_r)->aor.s = (char*)shm_malloc(_aor->len);
00072 if ((*_r)->aor.s == 0) {
00073 LM_ERR("no more share memory\n");
00074 shm_free(*_r);
00075 *_r = 0;
00076 return -2;
00077 }
00078 memcpy((*_r)->aor.s, _aor->s, _aor->len);
00079 (*_r)->aor.len = _aor->len;
00080 (*_r)->domain = _dom;
00081 (*_r)->aorhash = core_hash(_aor, 0, 0);
00082 return 0;
00083 }
00084
00085
00094 void free_urecord(urecord_t* _r)
00095 {
00096 ucontact_t* ptr;
00097
00098 while(_r->contacts) {
00099 ptr = _r->contacts;
00100 _r->contacts = _r->contacts->next;
00101 free_ucontact(ptr);
00102 }
00103
00104
00105 if (db_mode!=DB_ONLY) {
00106 if (_r->aor.s) shm_free(_r->aor.s);
00107 shm_free(_r);
00108 }
00109 }
00110
00111
00117 void print_urecord(FILE* _f, urecord_t* _r)
00118 {
00119 ucontact_t* ptr;
00120
00121 fprintf(_f, "...Record(%p)...\n", _r);
00122 fprintf(_f, "domain : '%.*s'\n", _r->domain->len, ZSW(_r->domain->s));
00123 fprintf(_f, "aor : '%.*s'\n", _r->aor.len, ZSW(_r->aor.s));
00124 fprintf(_f, "aorhash: '%u'\n", (unsigned)_r->aorhash);
00125 fprintf(_f, "slot: '%d'\n", _r->aorhash&(_r->slot->d->size-1));
00126
00127 if (_r->contacts) {
00128 ptr = _r->contacts;
00129 while(ptr) {
00130 print_ucontact(_f, ptr);
00131 ptr = ptr->next;
00132 }
00133 }
00134
00135 fprintf(_f, ".../Record...\n");
00136 }
00137
00138
00149 ucontact_t* mem_insert_ucontact(urecord_t* _r, str* _c, ucontact_info_t* _ci)
00150 {
00151 ucontact_t* ptr, *prev = 0;
00152 ucontact_t* c;
00153
00154 if ( (c=new_ucontact(_r->domain, &_r->aor, _c, _ci)) == 0) {
00155 LM_ERR("failed to create new contact\n");
00156 return 0;
00157 }
00158 if_update_stat( _r->slot, _r->slot->d->contacts, 1);
00159
00160 ptr = _r->contacts;
00161
00162 if (!desc_time_order) {
00163 while(ptr) {
00164 if (ptr->q < c->q) break;
00165 prev = ptr;
00166 ptr = ptr->next;
00167 }
00168 }
00169
00170 if (ptr) {
00171 if (!ptr->prev) {
00172 ptr->prev = c;
00173 c->next = ptr;
00174 _r->contacts = c;
00175 } else {
00176 c->next = ptr;
00177 c->prev = ptr->prev;
00178 ptr->prev->next = c;
00179 ptr->prev = c;
00180 }
00181 } else if (prev) {
00182 prev->next = c;
00183 c->prev = prev;
00184 } else {
00185 _r->contacts = c;
00186 }
00187
00188 return c;
00189 }
00190
00191
00197 void mem_remove_ucontact(urecord_t* _r, ucontact_t* _c)
00198 {
00199 if (_c->prev) {
00200 _c->prev->next = _c->next;
00201 if (_c->next) {
00202 _c->next->prev = _c->prev;
00203 }
00204 } else {
00205 _r->contacts = _c->next;
00206 if (_c->next) {
00207 _c->next->prev = 0;
00208 }
00209 }
00210 }
00211
00212
00218 void mem_delete_ucontact(urecord_t* _r, ucontact_t* _c)
00219 {
00220 mem_remove_ucontact(_r, _c);
00221 if_update_stat( _r->slot, _r->slot->d->contacts, -1);
00222 free_ucontact(_c);
00223 }
00224
00225
00233 static inline void nodb_timer(urecord_t* _r)
00234 {
00235 ucontact_t* ptr, *t;
00236
00237 ptr = _r->contacts;
00238
00239 while(ptr) {
00240 if (!VALID_CONTACT(ptr, act_time)) {
00241
00242 if (exists_ulcb_type(UL_CONTACT_EXPIRE))
00243 run_ul_callbacks( UL_CONTACT_EXPIRE, ptr);
00244
00245 LM_DBG("Binding '%.*s','%.*s' has expired\n",
00246 ptr->aor->len, ZSW(ptr->aor->s),
00247 ptr->c.len, ZSW(ptr->c.s));
00248
00249 t = ptr;
00250 ptr = ptr->next;
00251
00252 mem_delete_ucontact(_r, t);
00253 update_stat( _r->slot->d->expires, 1);
00254 } else {
00255 ptr = ptr->next;
00256 }
00257 }
00258 }
00259
00260
00269 static inline void wt_timer(urecord_t* _r)
00270 {
00271 ucontact_t* ptr, *t;
00272
00273 ptr = _r->contacts;
00274
00275 while(ptr) {
00276 if (!VALID_CONTACT(ptr, act_time)) {
00277
00278 if (exists_ulcb_type(UL_CONTACT_EXPIRE)) {
00279 run_ul_callbacks( UL_CONTACT_EXPIRE, ptr);
00280 }
00281
00282 LM_DBG("Binding '%.*s','%.*s' has expired\n",
00283 ptr->aor->len, ZSW(ptr->aor->s),
00284 ptr->c.len, ZSW(ptr->c.s));
00285
00286 t = ptr;
00287 ptr = ptr->next;
00288
00289 if (db_delete_ucontact(t) < 0) {
00290 LM_ERR("deleting contact from database failed\n");
00291 }
00292 mem_delete_ucontact(_r, t);
00293 update_stat( _r->slot->d->expires, 1);
00294 } else {
00295 ptr = ptr->next;
00296 }
00297 }
00298 }
00299
00300
00310 static inline void wb_timer(urecord_t* _r)
00311 {
00312 ucontact_t* ptr, *t;
00313 cstate_t old_state;
00314 int op;
00315
00316 ptr = _r->contacts;
00317
00318 while(ptr) {
00319 if (!VALID_CONTACT(ptr, act_time)) {
00320
00321 if (exists_ulcb_type(UL_CONTACT_EXPIRE)) {
00322 run_ul_callbacks( UL_CONTACT_EXPIRE, ptr);
00323 }
00324
00325 LM_DBG("Binding '%.*s','%.*s' has expired\n",
00326 ptr->aor->len, ZSW(ptr->aor->s),
00327 ptr->c.len, ZSW(ptr->c.s));
00328 update_stat( _r->slot->d->expires, 1);
00329
00330 t = ptr;
00331 ptr = ptr->next;
00332
00333
00334 if (st_expired_ucontact(t) == 1) {
00335 if (db_delete_ucontact(t) < 0) {
00336 LM_ERR("failed to delete contact from the database\n");
00337 }
00338 }
00339
00340 mem_delete_ucontact(_r, t);
00341 } else {
00342
00343 old_state = ptr->state;
00344 op = st_flush_ucontact(ptr);
00345
00346 switch(op) {
00347 case 0:
00348 break;
00349
00350 case 1:
00351 if (db_insert_ucontact(ptr) < 0) {
00352 LM_ERR("inserting contact into database failed\n");
00353 ptr->state = old_state;
00354 }
00355 break;
00356
00357 case 2:
00358 if (db_update_ucontact(ptr) < 0) {
00359 LM_ERR("updating contact in db failed\n");
00360 ptr->state = old_state;
00361 }
00362 break;
00363 }
00364
00365 ptr = ptr->next;
00366 }
00367 }
00368 }
00369
00370
00378 void timer_urecord(urecord_t* _r)
00379 {
00380 switch(db_mode) {
00381 case NO_DB: nodb_timer(_r);
00382 break;
00383
00384
00385 case WRITE_THROUGH: wb_timer(_r);
00386 break;
00387 case WRITE_BACK: wb_timer(_r);
00388 break;
00389 }
00390 }
00391
00392
00398 int db_delete_urecord(udomain_t* _d, urecord_t* _r)
00399 {
00400 db_key_t keys[2];
00401 db_val_t vals[2];
00402 char* dom;
00403
00404 keys[0] = &user_col;
00405 keys[1] = &domain_col;
00406 vals[0].type = DB1_STR;
00407 vals[0].nul = 0;
00408 vals[0].val.str_val.s = _r->aor.s;
00409 vals[0].val.str_val.len = _r->aor.len;
00410
00411 if (use_domain) {
00412 dom = memchr(_r->aor.s, '@', _r->aor.len);
00413 vals[0].val.str_val.len = dom - _r->aor.s;
00414
00415 vals[1].type = DB1_STR;
00416 vals[1].nul = 0;
00417 vals[1].val.str_val.s = dom + 1;
00418 vals[1].val.str_val.len = _r->aor.s + _r->aor.len - dom - 1;
00419 }
00420
00421 if (ul_db_layer_delete(_d, &vals[0].val.str_val, &vals[1].val.str_val, keys, 0, vals, (use_domain) ? (2) : (1)) < 0) {
00422 return -1;
00423 }
00424
00425 return 0;
00426 }
00427
00428
00437 void release_urecord(urecord_t* _r)
00438 {
00439 if (db_mode==DB_ONLY) {
00440 free_urecord(_r);
00441 } else if (_r->contacts == 0) {
00442 mem_delete_urecord(_r->slot->d, _r);
00443 }
00444 }
00445
00446
00455 int insert_ucontact(urecord_t* _r, str* _contact, ucontact_info_t* _ci,
00456 ucontact_t** _c)
00457 {
00458 if ( ((*_c)=mem_insert_ucontact(_r, _contact, _ci)) == 0) {
00459 LM_ERR("failed to insert contact\n");
00460 return -1;
00461 }
00462
00463 if (exists_ulcb_type(UL_CONTACT_INSERT)) {
00464 run_ul_callbacks( UL_CONTACT_INSERT, *_c);
00465 }
00466
00467 if (db_mode == WRITE_THROUGH || db_mode==DB_ONLY) {
00468 if (db_insert_ucontact(*_c) < 0) {
00469 LM_ERR("failed to insert in database\n");
00470 return -1;
00471 } else {
00472 (*_c)->state = CS_SYNC;
00473 }
00474 }
00475
00476 return 0;
00477 }
00478
00479
00486 int delete_ucontact(urecord_t* _r, struct ucontact* _c)
00487 {
00488 int ret = 0;
00489
00490 if (exists_ulcb_type(UL_CONTACT_DELETE)) {
00491 run_ul_callbacks( UL_CONTACT_DELETE, _c);
00492 }
00493
00494 if (st_delete_ucontact(_c) > 0) {
00495 if (db_mode == WRITE_THROUGH || db_mode==DB_ONLY) {
00496 if (db_delete_ucontact(_c) < 0) {
00497 LM_ERR("failed to remove contact from database\n");
00498 ret = -1;
00499 }
00500 }
00501
00502 mem_delete_ucontact(_r, _c);
00503 }
00504
00505 return ret;
00506 }
00507
00508
00515 static inline struct ucontact* contact_match( ucontact_t* ptr, str* _c)
00516 {
00517 while(ptr) {
00518 if ((_c->len == ptr->c.len) && !memcmp(_c->s, ptr->c.s, _c->len)) {
00519 return ptr;
00520 }
00521
00522 ptr = ptr->next;
00523 }
00524 return 0;
00525 }
00526
00527
00535 static inline struct ucontact* contact_callid_match( ucontact_t* ptr,
00536 str* _c, str *_callid)
00537 {
00538 while(ptr) {
00539 if ( (_c->len==ptr->c.len) && (_callid->len==ptr->callid.len)
00540 && !memcmp(_c->s, ptr->c.s, _c->len)
00541 && !memcmp(_callid->s, ptr->callid.s, _callid->len)
00542 ) {
00543 return ptr;
00544 }
00545
00546 ptr = ptr->next;
00547 }
00548 return 0;
00549 }
00550
00551
00559 static inline struct ucontact* contact_path_match( ucontact_t* ptr, str* _c, str *_path)
00560 {
00561
00562
00563 if( _path == NULL) return contact_match(ptr, _c);
00564
00565 while(ptr) {
00566 if ( (_c->len==ptr->c.len) && (_path->len==ptr->path.len)
00567 && !memcmp(_c->s, ptr->c.s, _c->len)
00568 && !memcmp(_path->s, ptr->path.s, _path->len)
00569 ) {
00570 return ptr;
00571 }
00572
00573 ptr = ptr->next;
00574 }
00575 return 0;
00576 }
00577
00588 int get_ucontact(urecord_t* _r, str* _c, str* _callid, str* _path, int _cseq,
00589 struct ucontact** _co)
00590 {
00591 ucontact_t* ptr;
00592 int no_callid;
00593
00594 ptr = 0;
00595 no_callid = 0;
00596 *_co = 0;
00597
00598 switch (matching_mode) {
00599 case CONTACT_ONLY:
00600 ptr = contact_match( _r->contacts, _c);
00601 break;
00602 case CONTACT_CALLID:
00603 ptr = contact_callid_match( _r->contacts, _c, _callid);
00604 no_callid = 1;
00605 break;
00606 case CONTACT_PATH:
00607 ptr = contact_path_match( _r->contacts, _c, _path);
00608 break;
00609 default:
00610 LM_CRIT("unknown matching_mode %d\n", matching_mode);
00611 return -1;
00612 }
00613
00614 if (ptr) {
00615
00616 if ( no_callid || (ptr->callid.len==_callid->len
00617 && memcmp(_callid->s, ptr->callid.s, _callid->len)==0 ) ) {
00618 if (_cseq<ptr->cseq)
00619 return -1;
00620 if (_cseq==ptr->cseq) {
00621 get_act_time();
00622 return (ptr->last_modified+cseq_delay>act_time)?-2:-1;
00623 }
00624 }
00625 *_co = ptr;
00626 return 0;
00627 }
00628
00629 return 1;
00630 }