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 "ucontact.h"
00037 #include <string.h>
00038 #include "../../mem/shm_mem.h"
00039 #include "../../ut.h"
00040 #include "../../ip_addr.h"
00041 #include "../../socket_info.h"
00042 #include "../../dprint.h"
00043 #include "../../lib/srdb1/db.h"
00044 #include "ul_mod.h"
00045 #include "ul_callback.h"
00046 #include "usrloc.h"
00047 #include "urecord.h"
00048 #include "ucontact.h"
00049 #include "usrloc.h"
00050
00059 ucontact_t* new_ucontact(str* _dom, str* _aor, str* _contact, ucontact_info_t* _ci)
00060 {
00061 ucontact_t *c;
00062
00063 c = (ucontact_t*)shm_malloc(sizeof(ucontact_t));
00064 if (!c) {
00065 LM_ERR("no more shm memory\n");
00066 return 0;
00067 }
00068 memset(c, 0, sizeof(ucontact_t));
00069
00070 if (shm_str_dup( &c->c, _contact) < 0) goto error;
00071 if (shm_str_dup( &c->callid, _ci->callid) < 0) goto error;
00072 if (shm_str_dup( &c->user_agent, _ci->user_agent) < 0) goto error;
00073
00074 if (_ci->received.s && _ci->received.len) {
00075 if (shm_str_dup( &c->received, &_ci->received) < 0) goto error;
00076 }
00077 if (_ci->path && _ci->path->len) {
00078 if (shm_str_dup( &c->path, _ci->path) < 0) goto error;
00079 }
00080 if (_ci->ruid.s && _ci->ruid.len) {
00081 if (shm_str_dup( &c->ruid, &_ci->ruid) < 0) goto error;
00082 }
00083 if (_ci->instance.s && _ci->instance.len) {
00084 if (shm_str_dup( &c->instance, &_ci->instance) < 0) goto error;
00085 }
00086
00087 c->domain = _dom;
00088 c->aor = _aor;
00089 c->expires = _ci->expires;
00090 c->q = _ci->q;
00091 c->sock = _ci->sock;
00092 c->cseq = _ci->cseq;
00093 c->state = CS_NEW;
00094 c->flags = _ci->flags;
00095 c->cflags = _ci->cflags;
00096 c->methods = _ci->methods;
00097 c->reg_id = _ci->reg_id;
00098 c->last_modified = _ci->last_modified;
00099
00100 return c;
00101 error:
00102 LM_ERR("no more shm memory\n");
00103 if (c->path.s) shm_free(c->path.s);
00104 if (c->received.s) shm_free(c->received.s);
00105 if (c->user_agent.s) shm_free(c->user_agent.s);
00106 if (c->callid.s) shm_free(c->callid.s);
00107 if (c->c.s) shm_free(c->c.s);
00108 if (c->ruid.s) shm_free(c->ruid.s);
00109 if (c->instance.s) shm_free(c->instance.s);
00110 shm_free(c);
00111 return 0;
00112 }
00113
00114
00115
00120 void free_ucontact(ucontact_t* _c)
00121 {
00122 if (!_c) return;
00123 if (_c->path.s) shm_free(_c->path.s);
00124 if (_c->received.s) shm_free(_c->received.s);
00125 if (_c->user_agent.s) shm_free(_c->user_agent.s);
00126 if (_c->callid.s) shm_free(_c->callid.s);
00127 if (_c->c.s) shm_free(_c->c.s);
00128 if (_c->ruid.s) shm_free(_c->ruid.s);
00129 if (_c->instance.s) shm_free(_c->instance.s);
00130 shm_free( _c );
00131 }
00132
00133
00139 void print_ucontact(FILE* _f, ucontact_t* _c)
00140 {
00141 time_t t = time(0);
00142 char* st;
00143
00144 switch(_c->state) {
00145 case CS_NEW: st = "CS_NEW"; break;
00146 case CS_SYNC: st = "CS_SYNC"; break;
00147 case CS_DIRTY: st = "CS_DIRTY"; break;
00148 default: st = "CS_UNKNOWN"; break;
00149 }
00150
00151 fprintf(_f, "~~~Contact(%p)~~~\n", _c);
00152 fprintf(_f, "domain : '%.*s'\n", _c->domain->len, ZSW(_c->domain->s));
00153 fprintf(_f, "aor : '%.*s'\n", _c->aor->len, ZSW(_c->aor->s));
00154 fprintf(_f, "Contact : '%.*s'\n", _c->c.len, ZSW(_c->c.s));
00155 fprintf(_f, "Expires : ");
00156 if (_c->expires == 0) {
00157 fprintf(_f, "Permanent\n");
00158 } else if (_c->expires == UL_EXPIRED_TIME) {
00159 fprintf(_f, "Deleted\n");
00160 } else if (t > _c->expires) {
00161 fprintf(_f, "Expired\n");
00162 } else {
00163 fprintf(_f, "%u\n", (unsigned int)(_c->expires - t));
00164 }
00165 fprintf(_f, "q : %s\n", q2str(_c->q, 0));
00166 fprintf(_f, "Call-ID : '%.*s'\n", _c->callid.len, ZSW(_c->callid.s));
00167 fprintf(_f, "CSeq : %d\n", _c->cseq);
00168 fprintf(_f, "User-Agent: '%.*s'\n",
00169 _c->user_agent.len, ZSW(_c->user_agent.s));
00170 fprintf(_f, "received : '%.*s'\n",
00171 _c->received.len, ZSW(_c->received.s));
00172 fprintf(_f, "Path : '%.*s'\n",
00173 _c->path.len, ZSW(_c->path.s));
00174 fprintf(_f, "State : %s\n", st);
00175 fprintf(_f, "Flags : %u\n", _c->flags);
00176 if (_c->sock) {
00177 fprintf(_f, "Sock : %.*s (%p)\n",
00178 _c->sock->sock_str.len,_c->sock->sock_str.s,_c->sock);
00179 } else {
00180 fprintf(_f, "Sock : none (null)\n");
00181 }
00182 fprintf(_f, "Methods : %u\n", _c->methods);
00183 fprintf(_f, "ruid : '%.*s'\n",
00184 _c->ruid.len, ZSW(_c->ruid.s));
00185 fprintf(_f, "instance : '%.*s'\n",
00186 _c->instance.len, ZSW(_c->instance.s));
00187 fprintf(_f, "reg-id : %u\n", _c->reg_id);
00188 fprintf(_f, "next : %p\n", _c->next);
00189 fprintf(_f, "prev : %p\n", _c->prev);
00190 fprintf(_f, "~~~/Contact~~~~\n");
00191 }
00192
00193
00200 int mem_update_ucontact(ucontact_t* _c, ucontact_info_t* _ci)
00201 {
00202 #define update_str(_old,_new) \
00203 do{\
00204 if ((_old)->len < (_new)->len) { \
00205 ptr = (char*)shm_malloc((_new)->len); \
00206 if (ptr == 0) { \
00207 LM_ERR("no more shm memory\n"); \
00208 return -1; \
00209 }\
00210 memcpy(ptr, (_new)->s, (_new)->len);\
00211 if ((_old)->s) shm_free((_old)->s);\
00212 (_old)->s = ptr;\
00213 } else {\
00214 memcpy((_old)->s, (_new)->s, (_new)->len);\
00215 }\
00216 (_old)->len = (_new)->len;\
00217 } while(0)
00218
00219 char* ptr;
00220
00221
00222
00223
00224 update_str( &_c->user_agent, _ci->user_agent);
00225
00226 if (_ci->received.s && _ci->received.len) {
00227 update_str( &_c->received, &_ci->received);
00228 } else {
00229 if (_c->received.s) shm_free(_c->received.s);
00230 _c->received.s = 0;
00231 _c->received.len = 0;
00232 }
00233
00234 if (_ci->path) {
00235 update_str( &_c->path, _ci->path);
00236 } else {
00237 if (_c->path.s) shm_free(_c->path.s);
00238 _c->path.s = 0;
00239 _c->path.len = 0;
00240 }
00241
00242 _c->sock = _ci->sock;
00243 _c->expires = _ci->expires;
00244 _c->q = _ci->q;
00245 _c->cseq = _ci->cseq;
00246 _c->methods = _ci->methods;
00247 _c->last_modified = _ci->last_modified;
00248 _c->flags = _ci->flags;
00249 _c->cflags = _ci->cflags;
00250
00251 return 0;
00252 }
00253
00254
00255
00256
00261 void st_update_ucontact(ucontact_t* _c)
00262 {
00263 switch(_c->state) {
00264 case CS_NEW:
00265
00266
00267
00268
00269 break;
00270
00271 case CS_SYNC:
00272
00273
00274
00275
00276
00277
00278 if (db_mode == WRITE_BACK || db_mode == WRITE_THROUGH) {
00279 _c->state = CS_DIRTY;
00280 }
00281 break;
00282
00283 case CS_DIRTY:
00284
00285
00286
00287 break;
00288 }
00289 }
00290
00291
00297 int st_delete_ucontact(ucontact_t* _c)
00298 {
00299 switch(_c->state) {
00300 case CS_NEW:
00301
00302
00303
00304
00305 return 1;
00306
00307 case CS_SYNC:
00308 case CS_DIRTY:
00309
00310
00311
00312
00313
00314
00315
00316 if (db_mode == WRITE_BACK) {
00317 _c->expires = UL_EXPIRED_TIME;
00318 return 0;
00319 } else {
00320
00321
00322
00323
00324
00325 return 1;
00326 }
00327 }
00328
00329 return 0;
00330 }
00331
00332
00338 int st_expired_ucontact(ucontact_t* _c)
00339 {
00340
00341
00342
00343
00344
00345 switch(_c->state) {
00346 case CS_NEW:
00347
00348
00349
00350 return 0;
00351
00352 case CS_SYNC:
00353 case CS_DIRTY:
00354
00355 return 1;
00356 }
00357
00358 return 0;
00359 }
00360
00361
00367 int st_flush_ucontact(ucontact_t* _c)
00368 {
00369 switch(_c->state) {
00370 case CS_NEW:
00371
00372
00373
00374
00375 _c->state = CS_SYNC;
00376 return 1;
00377
00378 case CS_SYNC:
00379
00380
00381
00382 return 0;
00383
00384 case CS_DIRTY:
00385
00386
00387
00388
00389 _c->state = CS_SYNC;
00390 return 2;
00391 }
00392
00393 return 0;
00394 }
00395
00396
00397
00398
00404 int db_insert_ucontact(ucontact_t* _c)
00405 {
00406 char* dom;
00407 db_key_t keys[18];
00408 db_val_t vals[18];
00409 int nr_cols;
00410
00411 if (_c->flags & FL_MEM) {
00412 return 0;
00413 }
00414
00415 keys[0] = &user_col;
00416 keys[1] = &contact_col;
00417 keys[2] = &expires_col;
00418 keys[3] = &q_col;
00419 keys[4] = &callid_col;
00420 keys[5] = &cseq_col;
00421 keys[6] = &flags_col;
00422 keys[7] = &cflags_col;
00423 keys[8] = &user_agent_col;
00424 keys[9] = &received_col;
00425 keys[10] = &path_col;
00426 keys[11] = &sock_col;
00427 keys[12] = &methods_col;
00428 keys[13] = &last_mod_col;
00429 keys[14] = &ruid_col;
00430 keys[15] = &instance_col;
00431 keys[16] = ®_id_col;
00432 keys[17] = &domain_col;
00433
00434 vals[0].type = DB1_STR;
00435 vals[0].nul = 0;
00436 vals[0].val.str_val.s = _c->aor->s;
00437 vals[0].val.str_val.len = _c->aor->len;
00438
00439 vals[1].type = DB1_STR;
00440 vals[1].nul = 0;
00441 vals[1].val.str_val.s = _c->c.s;
00442 vals[1].val.str_val.len = _c->c.len;
00443
00444 vals[2].type = DB1_DATETIME;
00445 vals[2].nul = 0;
00446 vals[2].val.time_val = _c->expires;
00447
00448 vals[3].type = DB1_DOUBLE;
00449 vals[3].nul = 0;
00450 vals[3].val.double_val = q2double(_c->q);
00451
00452 vals[4].type = DB1_STR;
00453 vals[4].nul = 0;
00454 vals[4].val.str_val.s = _c->callid.s;
00455 vals[4].val.str_val.len = _c->callid.len;
00456
00457 vals[5].type = DB1_INT;
00458 vals[5].nul = 0;
00459 vals[5].val.int_val = _c->cseq;
00460
00461 vals[6].type = DB1_INT;
00462 vals[6].nul = 0;
00463 vals[6].val.bitmap_val = _c->flags;
00464
00465 vals[7].type = DB1_INT;
00466 vals[7].nul = 0;
00467 vals[7].val.bitmap_val = _c->cflags;
00468
00469 vals[8].type = DB1_STR;
00470 vals[8].nul = 0;
00471 vals[8].val.str_val.s = _c->user_agent.s;
00472 vals[8].val.str_val.len = _c->user_agent.len;
00473
00474 vals[9].type = DB1_STR;
00475 if (_c->received.s == 0) {
00476 vals[9].nul = 1;
00477 } else {
00478 vals[9].nul = 0;
00479 vals[9].val.str_val.s = _c->received.s;
00480 vals[9].val.str_val.len = _c->received.len;
00481 }
00482
00483 vals[10].type = DB1_STR;
00484 if (_c->path.s == 0) {
00485 vals[10].nul = 1;
00486 } else {
00487 vals[10].nul = 0;
00488 vals[10].val.str_val.s = _c->path.s;
00489 vals[10].val.str_val.len = _c->path.len;
00490 }
00491
00492 vals[11].type = DB1_STR;
00493 if (_c->sock) {
00494 vals[11].val.str_val = _c->sock->sock_str;
00495 vals[11].nul = 0;
00496 } else {
00497 vals[11].nul = 1;
00498 }
00499
00500 vals[12].type = DB1_BITMAP;
00501 if (_c->methods == 0xFFFFFFFF) {
00502 vals[12].nul = 1;
00503 } else {
00504 vals[12].val.bitmap_val = _c->methods;
00505 vals[12].nul = 0;
00506 }
00507
00508 vals[13].type = DB1_DATETIME;
00509 vals[13].nul = 0;
00510 vals[13].val.time_val = _c->last_modified;
00511
00512 nr_cols = 14;
00513
00514 if(_c->ruid.len>0)
00515 {
00516 vals[nr_cols].type = DB1_STR;
00517 vals[nr_cols].nul = 0;
00518 vals[nr_cols].val.str_val = _c->ruid;
00519 } else {
00520 vals[nr_cols].nul = 1;
00521 }
00522 nr_cols++;
00523
00524 if(_c->instance.len>0)
00525 {
00526 vals[nr_cols].type = DB1_STR;
00527 vals[nr_cols].nul = 0;
00528 vals[nr_cols].val.str_val = _c->instance;
00529 } else {
00530 vals[nr_cols].nul = 1;
00531 }
00532 nr_cols++;
00533
00534 vals[nr_cols].type = DB1_INT;
00535 vals[nr_cols].nul = 0;
00536 vals[nr_cols].val.int_val = (int)_c->reg_id;
00537 nr_cols++;
00538
00539 if (use_domain) {
00540 vals[nr_cols].type = DB1_STR;
00541 vals[nr_cols].nul = 0;
00542
00543 dom = memchr(_c->aor->s, '@', _c->aor->len);
00544 if (dom==0) {
00545 vals[0].val.str_val.len = 0;
00546 vals[nr_cols].val.str_val = *_c->aor;
00547 } else {
00548 vals[0].val.str_val.len = dom - _c->aor->s;
00549 vals[nr_cols].val.str_val.s = dom + 1;
00550 vals[nr_cols].val.str_val.len = _c->aor->s + _c->aor->len - dom - 1;
00551 }
00552 nr_cols++;
00553 }
00554
00555 if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
00556 LM_ERR("sql use_table failed\n");
00557 return -1;
00558 }
00559
00560 if (ul_dbf.insert(ul_dbh, keys, vals, nr_cols) < 0) {
00561 LM_ERR("inserting contact in db failed\n");
00562 return -1;
00563 }
00564
00565 return 0;
00566 }
00567
00568
00574 int db_update_ucontact(ucontact_t* _c)
00575 {
00576 char* dom;
00577 db_key_t keys1[4];
00578 db_val_t vals1[4];
00579
00580 db_key_t keys2[14];
00581 db_val_t vals2[14];
00582 int nr_cols2;
00583
00584
00585 if (_c->flags & FL_MEM) {
00586 return 0;
00587 }
00588
00589 keys1[0] = &user_col;
00590 keys1[1] = &contact_col;
00591 keys1[2] = &callid_col;
00592 keys1[3] = &domain_col;
00593 keys2[0] = &expires_col;
00594 keys2[1] = &q_col;
00595 keys2[2] = &cseq_col;
00596 keys2[3] = &flags_col;
00597 keys2[4] = &cflags_col;
00598 keys2[5] = &user_agent_col;
00599 keys2[6] = &received_col;
00600 keys2[7] = &path_col;
00601 keys2[8] = &sock_col;
00602 keys2[9] = &methods_col;
00603 keys2[10] = &last_mod_col;
00604 keys2[11] = &ruid_col;
00605 keys2[12] = &instance_col;
00606 keys2[13] = ®_id_col;
00607
00608 vals1[0].type = DB1_STR;
00609 vals1[0].nul = 0;
00610 vals1[0].val.str_val = *_c->aor;
00611
00612 vals1[1].type = DB1_STR;
00613 vals1[1].nul = 0;
00614 vals1[1].val.str_val = _c->c;
00615
00616 vals1[2].type = DB1_STR;
00617 vals1[2].nul = 0;
00618 vals1[2].val.str_val = _c->callid;
00619
00620 vals2[0].type = DB1_DATETIME;
00621 vals2[0].nul = 0;
00622 vals2[0].val.time_val = _c->expires;
00623
00624 vals2[1].type = DB1_DOUBLE;
00625 vals2[1].nul = 0;
00626 vals2[1].val.double_val = q2double(_c->q);
00627
00628 vals2[2].type = DB1_INT;
00629 vals2[2].nul = 0;
00630 vals2[2].val.int_val = _c->cseq;
00631
00632 vals2[3].type = DB1_INT;
00633 vals2[3].nul = 0;
00634 vals2[3].val.bitmap_val = _c->flags;
00635
00636 vals2[4].type = DB1_INT;
00637 vals2[4].nul = 0;
00638 vals2[4].val.bitmap_val = _c->cflags;
00639
00640 vals2[5].type = DB1_STR;
00641 vals2[5].nul = 0;
00642 vals2[5].val.str_val = _c->user_agent;
00643
00644 vals2[6].type = DB1_STR;
00645 if (_c->received.s == 0) {
00646 vals2[6].nul = 1;
00647 } else {
00648 vals2[6].nul = 0;
00649 vals2[6].val.str_val = _c->received;
00650 }
00651
00652 vals2[7].type = DB1_STR;
00653 if (_c->path.s == 0) {
00654 vals2[7].nul = 1;
00655 } else {
00656 vals2[7].nul = 0;
00657 vals2[7].val.str_val = _c->path;
00658 }
00659
00660 vals2[8].type = DB1_STR;
00661 if (_c->sock) {
00662 vals2[8].val.str_val = _c->sock->sock_str;
00663 vals2[8].nul = 0;
00664 } else {
00665 vals2[8].nul = 1;
00666 }
00667
00668 vals2[9].type = DB1_BITMAP;
00669 if (_c->methods == 0xFFFFFFFF) {
00670 vals2[9].nul = 1;
00671 } else {
00672 vals2[9].val.bitmap_val = _c->methods;
00673 vals2[9].nul = 0;
00674 }
00675
00676 vals2[10].type = DB1_DATETIME;
00677 vals2[10].nul = 0;
00678 vals2[10].val.time_val = _c->last_modified;
00679
00680 nr_cols2 = 11;
00681 if(_c->ruid.len>0)
00682 {
00683 vals2[nr_cols2].type = DB1_STR;
00684 vals2[nr_cols2].nul = 0;
00685 vals2[nr_cols2].val.str_val = _c->ruid;
00686 } else {
00687 vals2[nr_cols2].nul = 1;
00688 }
00689 nr_cols2++;
00690
00691 if(_c->instance.len>0)
00692 {
00693 vals2[nr_cols2].type = DB1_STR;
00694 vals2[nr_cols2].nul = 0;
00695 vals2[nr_cols2].val.str_val = _c->instance;
00696 } else {
00697 vals2[nr_cols2].nul = 1;
00698 }
00699 nr_cols2++;
00700
00701 vals2[nr_cols2].type = DB1_INT;
00702 vals2[nr_cols2].nul = 0;
00703 vals2[nr_cols2].val.int_val = (int)_c->reg_id;
00704 nr_cols2++;
00705
00706 if (use_domain) {
00707 vals1[3].type = DB1_STR;
00708 vals1[3].nul = 0;
00709 dom = memchr(_c->aor->s, '@', _c->aor->len);
00710 if (dom==0) {
00711 vals1[0].val.str_val.len = 0;
00712 vals1[3].val.str_val = *_c->aor;
00713 } else {
00714 vals1[0].val.str_val.len = dom - _c->aor->s;
00715 vals1[3].val.str_val.s = dom + 1;
00716 vals1[3].val.str_val.len = _c->aor->s + _c->aor->len - dom - 1;
00717 }
00718 }
00719
00720 if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
00721 LM_ERR("sql use_table failed\n");
00722 return -1;
00723 }
00724
00725 if (ul_dbf.update(ul_dbh, keys1, 0, vals1, keys2, vals2,
00726 (use_domain) ? (4) : (3), nr_cols2) < 0) {
00727 LM_ERR("updating database failed\n");
00728 return -1;
00729 }
00730
00731 return 0;
00732 }
00733
00734
00740 int db_delete_ucontact(ucontact_t* _c)
00741 {
00742 char* dom;
00743 db_key_t keys[4];
00744 db_val_t vals[4];
00745
00746 if (_c->flags & FL_MEM) {
00747 return 0;
00748 }
00749
00750 keys[0] = &user_col;
00751 keys[1] = &contact_col;
00752 keys[2] = &callid_col;
00753 keys[3] = &domain_col;
00754
00755 vals[0].type = DB1_STR;
00756 vals[0].nul = 0;
00757 vals[0].val.str_val = *_c->aor;
00758
00759 vals[1].type = DB1_STR;
00760 vals[1].nul = 0;
00761 vals[1].val.str_val = _c->c;
00762
00763 vals[2].type = DB1_STR;
00764 vals[2].nul = 0;
00765 vals[2].val.str_val = _c->callid;
00766
00767 if (use_domain) {
00768 vals[3].type = DB1_STR;
00769 vals[3].nul = 0;
00770 dom = memchr(_c->aor->s, '@', _c->aor->len);
00771 if (dom==0) {
00772 vals[0].val.str_val.len = 0;
00773 vals[3].val.str_val = *_c->aor;
00774 } else {
00775 vals[0].val.str_val.len = dom - _c->aor->s;
00776 vals[3].val.str_val.s = dom + 1;
00777 vals[3].val.str_val.len = _c->aor->s + _c->aor->len - dom - 1;
00778 }
00779 }
00780
00781 if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
00782 LM_ERR("sql use_table failed\n");
00783 return -1;
00784 }
00785
00786 if (ul_dbf.delete(ul_dbh, keys, 0, vals, (use_domain) ? (4) : (3)) < 0) {
00787 LM_ERR("deleting from database failed\n");
00788 return -1;
00789 }
00790
00791 return 0;
00792 }
00793
00794
00800 static inline void unlink_contact(struct urecord* _r, ucontact_t* _c)
00801 {
00802 if (_c->prev) {
00803 _c->prev->next = _c->next;
00804 if (_c->next) {
00805 _c->next->prev = _c->prev;
00806 }
00807 } else {
00808 _r->contacts = _c->next;
00809 if (_c->next) {
00810 _c->next->prev = 0;
00811 }
00812 }
00813 }
00814
00815
00821 static inline void update_contact_pos(struct urecord* _r, ucontact_t* _c)
00822 {
00823 ucontact_t *pos, *ppos;
00824
00825 if (desc_time_order) {
00826
00827 if (_c->prev==0)
00828 return;
00829 unlink_contact(_r, _c);
00830
00831 _c->next = _r->contacts;
00832 _c->prev = 0;
00833 _r->contacts->prev = _c;
00834 _r->contacts = _c;
00835 } else {
00836
00837 if ( (_c->prev==0 || _c->q<=_c->prev->q)
00838 && (_c->next==0 || _c->q>=_c->next->q) )
00839 return;
00840
00841 unlink_contact(_r, _c);
00842 _c->next = _c->prev = 0;
00843 for(pos=_r->contacts,ppos=0;pos&&pos->q<_c->q;ppos=pos,pos=pos->next);
00844 if (pos) {
00845 if (!pos->prev) {
00846 pos->prev = _c;
00847 _c->next = pos;
00848 _r->contacts = _c;
00849 } else {
00850 _c->next = pos;
00851 _c->prev = pos->prev;
00852 pos->prev->next = _c;
00853 pos->prev = _c;
00854 }
00855 } else if (ppos) {
00856 ppos->next = _c;
00857 _c->prev = ppos;
00858 } else {
00859 _r->contacts = _c;
00860 }
00861 }
00862 }
00863
00864
00872 int update_ucontact(struct urecord* _r, ucontact_t* _c, ucontact_info_t* _ci)
00873 {
00874 int res;
00875
00876
00877
00878 if (mem_update_ucontact( _c, _ci) < 0) {
00879 LM_ERR("failed to update memory\n");
00880 return -1;
00881 }
00882
00883
00884 if (exists_ulcb_type(UL_CONTACT_UPDATE))
00885 {
00886 LM_DBG("exists callback for type= UL_CONTACT_UPDATE\n");
00887 run_ul_callbacks( UL_CONTACT_UPDATE, _c);
00888 }
00889
00890 if (_r && db_mode!=DB_ONLY)
00891 update_contact_pos( _r, _c);
00892
00893 st_update_ucontact(_c);
00894
00895 if (db_mode == WRITE_THROUGH || db_mode==DB_ONLY) {
00896 if (ul_db_update_as_insert)
00897 res = db_insert_ucontact(_c);
00898 else
00899 res = db_update_ucontact(_c);
00900
00901 if (res < 0) {
00902 LM_ERR("failed to update database\n");
00903 return -1;
00904 } else {
00905 _c->state = CS_SYNC;
00906 }
00907 }
00908 return 0;
00909 }