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 #include "urecord.h"
00038 #include <string.h>
00039 #include "../../mem/shm_mem.h"
00040 #include "../../dprint.h"
00041 #include "../../ut.h"
00042 #include "../../hash_func.h"
00043 #include "ul_mod.h"
00044 #include "utime.h"
00045 #include "ul_callback.h"
00046
00047
00048
00049 int matching_mode = CONTACT_ONLY;
00050
00051 int cseq_delay = 20;
00052
00053
00054
00055
00056
00057
00058
00059
00060 int new_urecord(str* _dom, str* _aor, urecord_t** _r)
00061 {
00062 *_r = (urecord_t*)shm_malloc(sizeof(urecord_t));
00063 if (*_r == 0) {
00064 LM_ERR("no more share memory\n");
00065 return -1;
00066 }
00067 memset(*_r, 0, sizeof(urecord_t));
00068
00069 (*_r)->aor.s = (char*)shm_malloc(_aor->len);
00070 if ((*_r)->aor.s == 0) {
00071 LM_ERR("no more share memory\n");
00072 shm_free(*_r);
00073 *_r = 0;
00074 return -2;
00075 }
00076 memcpy((*_r)->aor.s, _aor->s, _aor->len);
00077 (*_r)->aor.len = _aor->len;
00078 (*_r)->domain = _dom;
00079 (*_r)->aorhash = core_hash(_aor, 0, 0);
00080 return 0;
00081 }
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092 void free_urecord(urecord_t* _r)
00093 {
00094 ucontact_t* ptr;
00095
00096 while(_r->contacts) {
00097 ptr = _r->contacts;
00098 _r->contacts = _r->contacts->next;
00099 free_ucontact(ptr);
00100 }
00101
00102
00103 if (db_mode!=DB_ONLY) {
00104 if (_r->aor.s) shm_free(_r->aor.s);
00105 shm_free(_r);
00106 }
00107 }
00108
00109
00110
00111
00112
00113
00114
00115 void print_urecord(FILE* _f, urecord_t* _r)
00116 {
00117 ucontact_t* ptr;
00118
00119 fprintf(_f, "...Record(%p)...\n", _r);
00120 fprintf(_f, "domain : '%.*s'\n", _r->domain->len, ZSW(_r->domain->s));
00121 fprintf(_f, "aor : '%.*s'\n", _r->aor.len, ZSW(_r->aor.s));
00122 fprintf(_f, "aorhash: '%u'\n", (unsigned)_r->aorhash);
00123 fprintf(_f, "slot: '%d'\n", _r->aorhash&(_r->slot->d->size-1));
00124
00125 if (_r->contacts) {
00126 ptr = _r->contacts;
00127 while(ptr) {
00128 print_ucontact(_f, ptr);
00129 ptr = ptr->next;
00130 }
00131 }
00132
00133 fprintf(_f, ".../Record...\n");
00134 }
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147 ucontact_t* mem_insert_ucontact(urecord_t* _r, str* _c, ucontact_info_t* _ci)
00148 {
00149 ucontact_t* ptr, *prev = 0;
00150 ucontact_t* c;
00151
00152 if ( (c=new_ucontact(_r->domain, &_r->aor, _c, _ci)) == 0) {
00153 LM_ERR("failed to create new contact\n");
00154 return 0;
00155 }
00156 if_update_stat( _r->slot, _r->slot->d->contacts, 1);
00157
00158 ptr = _r->contacts;
00159
00160 if (!desc_time_order) {
00161 while(ptr) {
00162 if (ptr->q < c->q) break;
00163 prev = ptr;
00164 ptr = ptr->next;
00165 }
00166 }
00167
00168 if (ptr) {
00169 if (!ptr->prev) {
00170 ptr->prev = c;
00171 c->next = ptr;
00172 _r->contacts = c;
00173 } else {
00174 c->next = ptr;
00175 c->prev = ptr->prev;
00176 ptr->prev->next = c;
00177 ptr->prev = c;
00178 }
00179 } else if (prev) {
00180 prev->next = c;
00181 c->prev = prev;
00182 } else {
00183 _r->contacts = c;
00184 }
00185
00186 return c;
00187 }
00188
00189
00190
00191
00192
00193
00194
00195 void mem_remove_ucontact(urecord_t* _r, ucontact_t* _c)
00196 {
00197 if (_c->prev) {
00198 _c->prev->next = _c->next;
00199 if (_c->next) {
00200 _c->next->prev = _c->prev;
00201 }
00202 } else {
00203 _r->contacts = _c->next;
00204 if (_c->next) {
00205 _c->next->prev = 0;
00206 }
00207 }
00208 }
00209
00210
00211
00212
00213
00214
00215
00216 void mem_delete_ucontact(urecord_t* _r, ucontact_t* _c)
00217 {
00218 mem_remove_ucontact(_r, _c);
00219 if_update_stat( _r->slot, _r->slot->d->contacts, -1);
00220 free_ucontact(_c);
00221 }
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 static inline void nodb_timer(urecord_t* _r)
00232 {
00233 ucontact_t* ptr, *t;
00234
00235 ptr = _r->contacts;
00236
00237 while(ptr) {
00238 if (!VALID_CONTACT(ptr, act_time)) {
00239
00240 if (exists_ulcb_type(UL_CONTACT_EXPIRE))
00241 run_ul_callbacks( UL_CONTACT_EXPIRE, ptr);
00242
00243 LM_DBG("Binding '%.*s','%.*s' has expired\n",
00244 ptr->aor->len, ZSW(ptr->aor->s),
00245 ptr->c.len, ZSW(ptr->c.s));
00246
00247 t = ptr;
00248 ptr = ptr->next;
00249
00250 mem_delete_ucontact(_r, t);
00251 update_stat( _r->slot->d->expires, 1);
00252 } else {
00253 ptr = ptr->next;
00254 }
00255 }
00256 }
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267 static inline void wt_timer(urecord_t* _r)
00268 {
00269 ucontact_t* ptr, *t;
00270
00271 ptr = _r->contacts;
00272
00273 while(ptr) {
00274 if (!VALID_CONTACT(ptr, act_time)) {
00275
00276 if (exists_ulcb_type(UL_CONTACT_EXPIRE)) {
00277 run_ul_callbacks( UL_CONTACT_EXPIRE, ptr);
00278 }
00279
00280 LM_DBG("Binding '%.*s','%.*s' has expired\n",
00281 ptr->aor->len, ZSW(ptr->aor->s),
00282 ptr->c.len, ZSW(ptr->c.s));
00283
00284 t = ptr;
00285 ptr = ptr->next;
00286
00287 if (db_delete_ucontact(t) < 0) {
00288 LM_ERR("deleting contact from database failed\n");
00289 }
00290 mem_delete_ucontact(_r, t);
00291 update_stat( _r->slot->d->expires, 1);
00292 } else {
00293 ptr = ptr->next;
00294 }
00295 }
00296 }
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 static inline void wb_timer(urecord_t* _r)
00309 {
00310 ucontact_t* ptr, *t;
00311 cstate_t old_state;
00312 int op;
00313
00314 ptr = _r->contacts;
00315
00316 while(ptr) {
00317 if (!VALID_CONTACT(ptr, act_time)) {
00318
00319 if (exists_ulcb_type(UL_CONTACT_EXPIRE)) {
00320 run_ul_callbacks( UL_CONTACT_EXPIRE, ptr);
00321 }
00322
00323 LM_DBG("Binding '%.*s','%.*s' has expired\n",
00324 ptr->aor->len, ZSW(ptr->aor->s),
00325 ptr->c.len, ZSW(ptr->c.s));
00326 update_stat( _r->slot->d->expires, 1);
00327
00328 t = ptr;
00329 ptr = ptr->next;
00330
00331
00332 if (st_expired_ucontact(t) == 1) {
00333 if (db_delete_ucontact(t) < 0) {
00334 LM_ERR("failed to delete contact from the database\n");
00335 }
00336 }
00337
00338 mem_delete_ucontact(_r, t);
00339 } else {
00340
00341 old_state = ptr->state;
00342 op = st_flush_ucontact(ptr);
00343
00344 switch(op) {
00345 case 0:
00346 break;
00347
00348 case 1:
00349 if (db_insert_ucontact(ptr) < 0) {
00350 LM_ERR("inserting contact into database failed\n");
00351 ptr->state = old_state;
00352 }
00353 break;
00354
00355 case 2:
00356 if (db_update_ucontact(ptr) < 0) {
00357 LM_ERR("updating contact in db failed\n");
00358 ptr->state = old_state;
00359 }
00360 break;
00361 }
00362
00363 ptr = ptr->next;
00364 }
00365 }
00366 }
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 void timer_urecord(urecord_t* _r)
00377 {
00378 switch(db_mode) {
00379 case NO_DB: nodb_timer(_r);
00380 break;
00381
00382
00383 case WRITE_THROUGH: wb_timer(_r);
00384 break;
00385 case WRITE_BACK: wb_timer(_r);
00386 break;
00387 }
00388 }
00389
00390
00391
00392
00393
00394
00395
00396 int db_delete_urecord(urecord_t* _r)
00397 {
00398 db_key_t keys[2];
00399 db_val_t vals[2];
00400 char* dom;
00401
00402 keys[0] = &user_col;
00403 keys[1] = &domain_col;
00404 vals[0].type = DB_STR;
00405 vals[0].nul = 0;
00406 vals[0].val.str_val.s = _r->aor.s;
00407 vals[0].val.str_val.len = _r->aor.len;
00408
00409 if (use_domain) {
00410 dom = memchr(_r->aor.s, '@', _r->aor.len);
00411 vals[0].val.str_val.len = dom - _r->aor.s;
00412
00413 vals[1].type = DB_STR;
00414 vals[1].nul = 0;
00415 vals[1].val.str_val.s = dom + 1;
00416 vals[1].val.str_val.len = _r->aor.s + _r->aor.len - dom - 1;
00417 }
00418
00419 if (ul_dbf.use_table(ul_dbh, _r->domain) < 0) {
00420 LM_ERR("use_table failed\n");
00421 return -1;
00422 }
00423
00424 if (ul_dbf.delete(ul_dbh, keys, 0, vals, (use_domain) ? (2) : (1)) < 0) {
00425 LM_ERR("failed to delete from database\n");
00426 return -1;
00427 }
00428
00429 return 0;
00430 }
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 void release_urecord(urecord_t* _r)
00442 {
00443 if (db_mode==DB_ONLY) {
00444 free_urecord(_r);
00445 } else if (_r->contacts == 0) {
00446 mem_delete_urecord(_r->slot->d, _r);
00447 }
00448 }
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459 int insert_ucontact(urecord_t* _r, str* _contact, ucontact_info_t* _ci,
00460 ucontact_t** _c)
00461 {
00462 if ( ((*_c)=mem_insert_ucontact(_r, _contact, _ci)) == 0) {
00463 LM_ERR("failed to insert contact\n");
00464 return -1;
00465 }
00466
00467 if (exists_ulcb_type(UL_CONTACT_INSERT)) {
00468 run_ul_callbacks( UL_CONTACT_INSERT, *_c);
00469 }
00470
00471 if (db_mode == WRITE_THROUGH || db_mode==DB_ONLY) {
00472 if (db_insert_ucontact(*_c) < 0) {
00473 LM_ERR("failed to insert in database\n");
00474 return -1;
00475 } else {
00476 (*_c)->state = CS_SYNC;
00477 }
00478 }
00479
00480 return 0;
00481 }
00482
00483
00484
00485
00486
00487
00488
00489
00490 int delete_ucontact(urecord_t* _r, struct ucontact* _c)
00491 {
00492 int ret = 0;
00493
00494 if (exists_ulcb_type(UL_CONTACT_DELETE)) {
00495 run_ul_callbacks( UL_CONTACT_DELETE, _c);
00496 }
00497
00498 if (st_delete_ucontact(_c) > 0) {
00499 if (db_mode == WRITE_THROUGH || db_mode==DB_ONLY) {
00500 if (db_delete_ucontact(_c) < 0) {
00501 LM_ERR("failed to remove contact from database\n");
00502 ret = -1;
00503 }
00504 }
00505
00506 mem_delete_ucontact(_r, _c);
00507 }
00508
00509 return ret;
00510 }
00511
00512
00513
00514
00515
00516
00517
00518
00519 static inline struct ucontact* contact_match( ucontact_t* ptr, str* _c)
00520 {
00521 while(ptr) {
00522 if ((_c->len == ptr->c.len) && !memcmp(_c->s, ptr->c.s, _c->len)) {
00523 return ptr;
00524 }
00525
00526 ptr = ptr->next;
00527 }
00528 return 0;
00529 }
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539 static inline struct ucontact* contact_callid_match( ucontact_t* ptr,
00540 str* _c, str *_callid)
00541 {
00542 while(ptr) {
00543 if ( (_c->len==ptr->c.len) && (_callid->len==ptr->callid.len)
00544 && !memcmp(_c->s, ptr->c.s, _c->len)
00545 && !memcmp(_callid->s, ptr->callid.s, _callid->len)
00546 ) {
00547 return ptr;
00548 }
00549
00550 ptr = ptr->next;
00551 }
00552 return 0;
00553 }
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566 int get_ucontact(urecord_t* _r, str* _c, str* _callid, int _cseq,
00567 struct ucontact** _co)
00568 {
00569 ucontact_t* ptr;
00570 int no_callid;
00571
00572 ptr = 0;
00573 no_callid = 0;
00574 *_co = 0;
00575
00576 switch (matching_mode) {
00577 case CONTACT_ONLY:
00578 ptr = contact_match( _r->contacts, _c);
00579 break;
00580 case CONTACT_CALLID:
00581 ptr = contact_callid_match( _r->contacts, _c, _callid);
00582 no_callid = 1;
00583 break;
00584 default:
00585 LM_CRIT("unknown matching_mode %d\n", matching_mode);
00586 return -1;
00587 }
00588
00589 if (ptr) {
00590
00591 if ( no_callid || (ptr->callid.len==_callid->len
00592 && memcmp(_callid->s, ptr->callid.s, _callid->len)==0 ) ) {
00593 if (_cseq<ptr->cseq)
00594 return -1;
00595 if (_cseq==ptr->cseq) {
00596 get_act_time();
00597 return (ptr->last_modified+cseq_delay>act_time)?-2:-1;
00598 }
00599 }
00600 *_co = ptr;
00601 return 0;
00602 }
00603
00604 return 1;
00605 }