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