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
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 "ul_mod.h"
00044 #include "usrloc.h"
00045 #include "utime.h"
00046 #include "ul_callback.h"
00047 #include "usrloc.h"
00048
00050 int matching_mode = CONTACT_ONLY;
00052 int cseq_delay = 20;
00053
00061 int new_urecord(str* _dom, str* _aor, urecord_t** _r)
00062 {
00063 *_r = (urecord_t*)shm_malloc(sizeof(urecord_t));
00064 if (*_r == 0) {
00065 LM_ERR("no more share memory\n");
00066 return -1;
00067 }
00068 memset(*_r, 0, sizeof(urecord_t));
00069
00070 (*_r)->aor.s = (char*)shm_malloc(_aor->len);
00071 if ((*_r)->aor.s == 0) {
00072 LM_ERR("no more share memory\n");
00073 shm_free(*_r);
00074 *_r = 0;
00075 return -2;
00076 }
00077 memcpy((*_r)->aor.s, _aor->s, _aor->len);
00078 (*_r)->aor.len = _aor->len;
00079 (*_r)->domain = _dom;
00080 (*_r)->aorhash = ul_get_aorhash(_aor);
00081 return 0;
00082 }
00083
00084
00093 void free_urecord(urecord_t* _r)
00094 {
00095 ucontact_t* ptr;
00096
00097 while(_r->contacts) {
00098 ptr = _r->contacts;
00099 _r->contacts = _r->contacts->next;
00100 free_ucontact(ptr);
00101 }
00102
00103
00104 if (db_mode!=DB_ONLY) {
00105 if (_r->aor.s) shm_free(_r->aor.s);
00106 shm_free(_r);
00107 }
00108 }
00109
00110
00116 void print_urecord(FILE* _f, urecord_t* _r)
00117 {
00118 ucontact_t* ptr;
00119
00120 fprintf(_f, "...Record(%p)...\n", _r);
00121 fprintf(_f, "domain : '%.*s'\n", _r->domain->len, ZSW(_r->domain->s));
00122 fprintf(_f, "aor : '%.*s'\n", _r->aor.len, ZSW(_r->aor.s));
00123 fprintf(_f, "aorhash: '%u'\n", (unsigned)_r->aorhash);
00124 fprintf(_f, "slot: '%d'\n", _r->aorhash&(_r->slot->d->size-1));
00125
00126 if (_r->contacts) {
00127 ptr = _r->contacts;
00128 while(ptr) {
00129 print_ucontact(_f, ptr);
00130 ptr = ptr->next;
00131 }
00132 }
00133
00134 fprintf(_f, ".../Record...\n");
00135 }
00136
00137
00148 ucontact_t* mem_insert_ucontact(urecord_t* _r, str* _c, ucontact_info_t* _ci)
00149 {
00150 ucontact_t* ptr, *prev = 0;
00151 ucontact_t* c;
00152
00153 if ( (c=new_ucontact(_r->domain, &_r->aor, _c, _ci)) == 0) {
00154 LM_ERR("failed to create new contact\n");
00155 return 0;
00156 }
00157 if_update_stat( _r->slot, _r->slot->d->contacts, 1);
00158
00159 ptr = _r->contacts;
00160
00161 if (!desc_time_order) {
00162 while(ptr) {
00163 if (ptr->q < c->q) break;
00164 prev = ptr;
00165 ptr = ptr->next;
00166 }
00167 }
00168
00169 if (ptr) {
00170 if (!ptr->prev) {
00171 ptr->prev = c;
00172 c->next = ptr;
00173 _r->contacts = c;
00174 } else {
00175 c->next = ptr;
00176 c->prev = ptr->prev;
00177 ptr->prev->next = c;
00178 ptr->prev = c;
00179 }
00180 } else if (prev) {
00181 prev->next = c;
00182 c->prev = prev;
00183 } else {
00184 _r->contacts = c;
00185 }
00186
00187 return c;
00188 }
00189
00190
00196 void mem_remove_ucontact(urecord_t* _r, ucontact_t* _c)
00197 {
00198 if (_c->prev) {
00199 _c->prev->next = _c->next;
00200 if (_c->next) {
00201 _c->next->prev = _c->prev;
00202 }
00203 } else {
00204 _r->contacts = _c->next;
00205 if (_c->next) {
00206 _c->next->prev = 0;
00207 }
00208 }
00209 }
00210
00211
00217 void mem_delete_ucontact(urecord_t* _r, ucontact_t* _c)
00218 {
00219 mem_remove_ucontact(_r, _c);
00220 if_update_stat( _r->slot, _r->slot->d->contacts, -1);
00221 free_ucontact(_c);
00222 }
00223
00224
00232 static inline void nodb_timer(urecord_t* _r)
00233 {
00234 ucontact_t* ptr, *t;
00235
00236 ptr = _r->contacts;
00237
00238 while(ptr) {
00239 if (!VALID_CONTACT(ptr, act_time)) {
00240
00241 if (exists_ulcb_type(UL_CONTACT_EXPIRE))
00242 run_ul_callbacks( UL_CONTACT_EXPIRE, ptr);
00243
00244 LM_DBG("Binding '%.*s','%.*s' has expired\n",
00245 ptr->aor->len, ZSW(ptr->aor->s),
00246 ptr->c.len, ZSW(ptr->c.s));
00247
00248 t = ptr;
00249 ptr = ptr->next;
00250
00251 mem_delete_ucontact(_r, t);
00252 update_stat( _r->slot->d->expires, 1);
00253 } else {
00254 ptr = ptr->next;
00255 }
00256 }
00257 }
00258
00259
00268 static inline void wt_timer(urecord_t* _r)
00269 {
00270 ucontact_t* ptr, *t;
00271
00272 ptr = _r->contacts;
00273
00274 while(ptr) {
00275 if (!VALID_CONTACT(ptr, act_time)) {
00276
00277 if (exists_ulcb_type(UL_CONTACT_EXPIRE)) {
00278 run_ul_callbacks( UL_CONTACT_EXPIRE, ptr);
00279 }
00280
00281 LM_DBG("Binding '%.*s','%.*s' has expired\n",
00282 ptr->aor->len, ZSW(ptr->aor->s),
00283 ptr->c.len, ZSW(ptr->c.s));
00284
00285 t = ptr;
00286 ptr = ptr->next;
00287
00288 if (db_delete_ucontact(t) < 0) {
00289 LM_ERR("deleting contact from database failed\n");
00290 }
00291 mem_delete_ucontact(_r, t);
00292 update_stat( _r->slot->d->expires, 1);
00293 } else {
00294 ptr = ptr->next;
00295 }
00296 }
00297 }
00298
00299
00309 static inline void wb_timer(urecord_t* _r)
00310 {
00311 ucontact_t* ptr, *t;
00312 cstate_t old_state;
00313 int op;
00314 int res;
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 (ul_db_update_as_insert)
00359 res = db_insert_ucontact(ptr);
00360 else
00361 res = db_update_ucontact(ptr);
00362 if (res < 0) {
00363 LM_ERR("updating contact in db failed\n");
00364 ptr->state = old_state;
00365 }
00366 break;
00367 }
00368
00369 ptr = ptr->next;
00370 }
00371 }
00372 }
00373
00374
00382 void timer_urecord(urecord_t* _r)
00383 {
00384 switch(db_mode) {
00385 case NO_DB: nodb_timer(_r);
00386 break;
00387
00388
00389 case WRITE_THROUGH: wb_timer(_r);
00390 break;
00391 case WRITE_BACK: wb_timer(_r);
00392 break;
00393 }
00394 }
00395
00396
00402 int db_delete_urecord(urecord_t* _r)
00403 {
00404 db_key_t keys[2];
00405 db_val_t vals[2];
00406 char* dom;
00407
00408 keys[0] = &user_col;
00409 keys[1] = &domain_col;
00410 vals[0].type = DB1_STR;
00411 vals[0].nul = 0;
00412 vals[0].val.str_val.s = _r->aor.s;
00413 vals[0].val.str_val.len = _r->aor.len;
00414
00415 if (use_domain) {
00416 dom = memchr(_r->aor.s, '@', _r->aor.len);
00417 vals[0].val.str_val.len = dom - _r->aor.s;
00418
00419 vals[1].type = DB1_STR;
00420 vals[1].nul = 0;
00421 vals[1].val.str_val.s = dom + 1;
00422 vals[1].val.str_val.len = _r->aor.s + _r->aor.len - dom - 1;
00423 }
00424
00425 if (ul_dbf.use_table(ul_dbh, _r->domain) < 0) {
00426 LM_ERR("use_table failed\n");
00427 return -1;
00428 }
00429
00430 if (ul_dbf.delete(ul_dbh, keys, 0, vals, (use_domain) ? (2) : (1)) < 0) {
00431 LM_ERR("failed to delete from database\n");
00432 return -1;
00433 }
00434
00435 return 0;
00436 }
00437
00438
00447 void release_urecord(urecord_t* _r)
00448 {
00449 if (db_mode==DB_ONLY) {
00450 free_urecord(_r);
00451 } else if (_r->contacts == 0) {
00452 mem_delete_urecord(_r->slot->d, _r);
00453 }
00454 }
00455
00456
00465 int insert_ucontact(urecord_t* _r, str* _contact, ucontact_info_t* _ci,
00466 ucontact_t** _c)
00467 {
00468 if ( ((*_c)=mem_insert_ucontact(_r, _contact, _ci)) == 0) {
00469 LM_ERR("failed to insert contact\n");
00470 return -1;
00471 }
00472
00473 if (exists_ulcb_type(UL_CONTACT_INSERT)) {
00474 run_ul_callbacks( UL_CONTACT_INSERT, *_c);
00475 }
00476
00477 if (db_mode == WRITE_THROUGH || db_mode==DB_ONLY) {
00478 if (db_insert_ucontact(*_c) < 0) {
00479 LM_ERR("failed to insert in database\n");
00480 return -1;
00481 } else {
00482 (*_c)->state = CS_SYNC;
00483 }
00484 }
00485
00486 return 0;
00487 }
00488
00489
00496 int delete_ucontact(urecord_t* _r, struct ucontact* _c)
00497 {
00498 int ret = 0;
00499
00500 if (exists_ulcb_type(UL_CONTACT_DELETE)) {
00501 run_ul_callbacks( UL_CONTACT_DELETE, _c);
00502 }
00503
00504 if (st_delete_ucontact(_c) > 0) {
00505 if (db_mode == WRITE_THROUGH || db_mode==DB_ONLY) {
00506 if (db_delete_ucontact(_c) < 0) {
00507 LM_ERR("failed to remove contact from database\n");
00508 ret = -1;
00509 }
00510 }
00511
00512 mem_delete_ucontact(_r, _c);
00513 }
00514
00515 return ret;
00516 }
00517
00518
00525 static inline struct ucontact* contact_match( ucontact_t* ptr, str* _c)
00526 {
00527 while(ptr) {
00528 if ((_c->len == ptr->c.len) && !memcmp(_c->s, ptr->c.s, _c->len)) {
00529 return ptr;
00530 }
00531
00532 ptr = ptr->next;
00533 }
00534 return 0;
00535 }
00536
00537
00545 static inline struct ucontact* contact_callid_match( ucontact_t* ptr,
00546 str* _c, str *_callid)
00547 {
00548 while(ptr) {
00549 if ( (_c->len==ptr->c.len) && (_callid->len==ptr->callid.len)
00550 && !memcmp(_c->s, ptr->c.s, _c->len)
00551 && !memcmp(_callid->s, ptr->callid.s, _callid->len)
00552 ) {
00553 return ptr;
00554 }
00555
00556 ptr = ptr->next;
00557 }
00558 return 0;
00559 }
00560
00568 static inline struct ucontact* contact_path_match( ucontact_t* ptr, str* _c, str *_path)
00569 {
00570
00571
00572 if( _path == NULL) return contact_match(ptr, _c);
00573
00574 while(ptr) {
00575 if ( (_c->len==ptr->c.len) && (_path->len==ptr->path.len)
00576 && !memcmp(_c->s, ptr->c.s, _c->len)
00577 && !memcmp(_path->s, ptr->path.s, _path->len)
00578 ) {
00579 return ptr;
00580 }
00581
00582 ptr = ptr->next;
00583 }
00584 return 0;
00585 }
00586
00598 int get_ucontact(urecord_t* _r, str* _c, str* _callid, str* _path, int _cseq,
00599 struct ucontact** _co)
00600 {
00601 ucontact_t* ptr;
00602 int no_callid;
00603
00604 ptr = 0;
00605 no_callid = 0;
00606 *_co = 0;
00607
00608 switch (matching_mode) {
00609 case CONTACT_ONLY:
00610 ptr = contact_match( _r->contacts, _c);
00611 break;
00612 case CONTACT_CALLID:
00613 ptr = contact_callid_match( _r->contacts, _c, _callid);
00614 no_callid = 1;
00615 break;
00616 case CONTACT_PATH:
00617 ptr = contact_path_match( _r->contacts, _c, _path);
00618 break;
00619 default:
00620 LM_CRIT("unknown matching_mode %d\n", matching_mode);
00621 return -1;
00622 }
00623
00624 if (ptr) {
00625
00626 if ( no_callid || (ptr->callid.len==_callid->len
00627 && memcmp(_callid->s, ptr->callid.s, _callid->len)==0 ) ) {
00628 if (_cseq<ptr->cseq)
00629 return -1;
00630 if (_cseq==ptr->cseq) {
00631 get_act_time();
00632 return (ptr->last_modified+cseq_delay>act_time)?-2:-1;
00633 }
00634 }
00635 *_co = ptr;
00636 return 0;
00637 }
00638
00639 return 1;
00640 }
00641
00642
00643
00644
00645 int get_ucontact_by_instance(urecord_t* _r, str* _c, ucontact_info_t* _ci,
00646 ucontact_t** _co)
00647 {
00648 ucontact_t* ptr;
00649 str i1;
00650 str i2;
00651
00652 if (_ci->instance.s == NULL || _ci->instance.len <= 0) {
00653 return get_ucontact(_r, _c, _ci->callid, _ci->path, _ci->cseq, _co);
00654 }
00655
00656
00657 ptr = _r->contacts;
00658 while(ptr) {
00659 if (ptr->instance.len>0 && _ci->reg_id==ptr->reg_id)
00660 {
00661 i1 = _ci->instance;
00662 i2 = ptr->instance;
00663 if(i1.s[0]=='<' && i1.s[i1.len-1]=='>') {
00664 i1.s++;
00665 i1.len-=2;
00666 }
00667 if(i2.s[0]=='<' && i2.s[i2.len-1]=='>') {
00668 i2.s++;
00669 i2.len-=2;
00670 }
00671 if(i1.len==i2.len && memcmp(i1.s, i2.s, i2.len)==0) {
00672 *_co = ptr;
00673 return 0;
00674 }
00675 }
00676
00677 ptr = ptr->next;
00678 }
00679 return 1;
00680 }
00681
00682 unsigned int ul_get_aorhash(str *_aor)
00683 {
00684 return core_hash(_aor, 0, 0);
00685 }