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
00038 #include "dlist.h"
00039 #include <stdlib.h>
00040 #include <string.h>
00041 #include <stdio.h>
00042 #include "../../ut.h"
00043 #include "../../lib/srdb1/db_ut.h"
00044 #include "../../mem/shm_mem.h"
00045 #include "../../dprint.h"
00046 #include "../../ip_addr.h"
00047 #include "../../socket_info.h"
00048 #include "udomain.h"
00049 #include "usrloc.h"
00050 #include "utime.h"
00051 #include "ul_mod.h"
00052
00053
00055 dlist_t* root = 0;
00056
00057
00064 static inline int find_dlist(str* _n, dlist_t** _d)
00065 {
00066 dlist_t* ptr;
00067
00068 ptr = root;
00069 while(ptr) {
00070 if ((_n->len == ptr->name.len) &&
00071 !memcmp(_n->s, ptr->name.s, _n->len)) {
00072 *_d = ptr;
00073 return 0;
00074 }
00075
00076 ptr = ptr->next;
00077 }
00078
00079 return 1;
00080 }
00081
00082
00093 static inline int get_all_db_ucontacts(void *buf, int len, unsigned int flags,
00094 unsigned int part_idx, unsigned int part_max)
00095 {
00096 static char query_buf[512];
00097 static str query_str;
00098
00099 struct socket_info *sock;
00100 unsigned int dbflags;
00101 db1_res_t* res = NULL;
00102 db_row_t *row;
00103 dlist_t *dom;
00104 char *p, *p1;
00105 char now_s[25];
00106 int now_len;
00107 int port, proto, p_len, p1_len;
00108 str host;
00109 int i;
00110 void *cp;
00111 int shortage, needed;
00112
00113 cp = buf;
00114 shortage = 0;
00115
00116 len -= sizeof(p_len);
00117
00118
00119 now_len = 25;
00120 if (db_time2str( time(0), now_s, &now_len)!=0) {
00121 LM_ERR("failed to print now time\n");
00122 return -1;
00123 }
00124
00125 for (dom = root; dom!=NULL ; dom=dom->next) {
00126
00127 i = snprintf( query_buf, sizeof(query_buf), "select %.*s, %.*s, %.*s,"
00128 #ifdef ORACLE_USRLOC
00129 " %.*s, %.*s from %s where %.*s > %.*s and "
00130 "bitand(%.*s, %d) = %d and mod(id, %u) = %u",
00131 #else
00132 " %.*s, %.*s from %s where %.*s > %.*s and %.*s & %d = %d and "
00133 "id %% %u = %u",
00134 #endif
00135 received_col.len, received_col.s,
00136 contact_col.len, contact_col.s,
00137 sock_col.len, sock_col.s,
00138 cflags_col.len, cflags_col.s,
00139 path_col.len, path_col.s,
00140 dom->d->name->s,
00141 expires_col.len, expires_col.s,
00142 now_len, now_s,
00143 cflags_col.len, cflags_col.s,
00144 flags, flags, part_max, part_idx);
00145 if ( i>=sizeof(query_buf) ) {
00146 LM_ERR("DB query too long\n");
00147 return -1;
00148 }
00149 query_str.s = query_buf;
00150 query_str.len = i;
00151 if ( ul_dbf.raw_query( ul_dbh, &query_str, &res)<0 ) {
00152 LM_ERR("raw_query failed\n");
00153 return -1;
00154 }
00155 if( RES_ROW_N(res)==0 ) {
00156 ul_dbf.free_result(ul_dbh, res);
00157 continue;
00158 }
00159
00160 for(i = 0; i < RES_ROW_N(res); i++) {
00161 row = RES_ROWS(res) + i;
00162
00163
00164 p = (char*)VAL_STRING(ROW_VALUES(row));
00165 if ( VAL_NULL(ROW_VALUES(row)) || p==0 || p[0]==0 ) {
00166
00167 p = (char*)VAL_STRING(ROW_VALUES(row)+1);
00168 if (VAL_NULL(ROW_VALUES(row)+1) || p==0 || p[0]==0) {
00169 LM_ERR("empty contact -> skipping\n");
00170 continue;
00171 }
00172 }
00173 p_len = strlen(p);
00174
00175
00176 p1 = (char*)VAL_STRING(ROW_VALUES(row)+4);
00177 if (VAL_NULL(ROW_VALUES(row)+4) || p1==0 || p1[0]==0){
00178 p1 = NULL;
00179 p1_len = 0;
00180 } else {
00181 p1_len = strlen(p1);
00182 }
00183
00184 needed = (int)(sizeof(p_len)+p_len+sizeof(sock)+sizeof(dbflags)+
00185 sizeof(p1_len)+p1_len);
00186 if (len < needed) {
00187 shortage += needed ;
00188 continue;
00189 }
00190
00191
00192 memcpy(cp, &p_len, sizeof(p_len));
00193 cp = (char*)cp + sizeof(p_len);
00194 memcpy(cp, p, p_len);
00195 cp = (char*)cp + p_len;
00196
00197
00198 p = (char*)VAL_STRING(ROW_VALUES(row) + 2);
00199 if (VAL_NULL(ROW_VALUES(row)+2) || p==0 || p[0]==0){
00200 sock = 0;
00201 } else {
00202 if (parse_phostport( p, &host.s, &host.len,
00203 &port, &proto)!=0) {
00204 LM_ERR("bad socket <%s>...ignoring\n", p);
00205 sock = 0;
00206 } else {
00207 sock = grep_sock_info( &host, (unsigned short)port, proto);
00208 if (sock==0) {
00209 LM_WARN("non-local socket <%s>...ignoring\n", p);
00210 }
00211 }
00212 }
00213
00214
00215 dbflags = VAL_BITMAP(ROW_VALUES(row) + 3);
00216
00217
00218 memcpy(cp, &sock, sizeof(sock));
00219 cp = (char*)cp + sizeof(sock);
00220 memcpy(cp, &dbflags, sizeof(dbflags));
00221 cp = (char*)cp + sizeof(dbflags);
00222
00223
00224 memcpy(cp, &p1_len, sizeof(p1_len));
00225 cp = (char*)cp + sizeof(p1_len);
00226
00227 if(p1_len){
00228 memcpy(cp, p1, p1_len);
00229 cp = (char*)cp + p1_len;
00230 }
00231
00232 len -= needed;
00233 }
00234
00235 ul_dbf.free_result(ul_dbh, res);
00236 }
00237
00238
00239 if (len >= 0)
00240 memset(cp, 0, sizeof(p_len));
00241
00242
00243 if (shortage > 0 && len > shortage) {
00244 abort();
00245 }
00246
00247 shortage -= len;
00248
00249 return shortage > 0 ? shortage : 0;
00250 }
00251
00252
00263 static inline int get_all_mem_ucontacts(void *buf, int len, unsigned int flags,
00264 unsigned int part_idx, unsigned int part_max)
00265 {
00266 dlist_t *p;
00267 urecord_t *r;
00268 ucontact_t *c;
00269 void *cp;
00270 int shortage;
00271 int needed;
00272 int i = 0;
00273 cp = buf;
00274 shortage = 0;
00275
00276 len -= sizeof(c->c.len);
00277
00278 for (p = root; p != NULL; p = p->next) {
00279
00280 for(i=0; i<p->d->size; i++) {
00281
00282 if ( (i % part_max) != part_idx )
00283 continue;
00284
00285 lock_ulslot(p->d, i);
00286 if(p->d->table[i].n<=0)
00287 {
00288 unlock_ulslot(p->d, i);
00289 continue;
00290 }
00291 for (r = p->d->table[i].first; r != NULL; r = r->next) {
00292 for (c = r->contacts; c != NULL; c = c->next) {
00293 if (c->c.len <= 0)
00294 continue;
00295
00296
00297
00298
00299 if ((c->cflags & flags) != flags)
00300 continue;
00301 if (c->received.s) {
00302 needed = (int)(sizeof(c->received.len)
00303 + c->received.len + sizeof(c->sock)
00304 + sizeof(c->cflags) + sizeof(c->path.len)
00305 + c->path.len);
00306 if (len >= needed) {
00307 memcpy(cp,&c->received.len,sizeof(c->received.len));
00308 cp = (char*)cp + sizeof(c->received.len);
00309 memcpy(cp, c->received.s, c->received.len);
00310 cp = (char*)cp + c->received.len;
00311 memcpy(cp, &c->sock, sizeof(c->sock));
00312 cp = (char*)cp + sizeof(c->sock);
00313 memcpy(cp, &c->cflags, sizeof(c->cflags));
00314 cp = (char*)cp + sizeof(c->cflags);
00315 memcpy(cp, &c->path.len, sizeof(c->path.len));
00316 cp = (char*)cp + sizeof(c->path.len);
00317 memcpy(cp, c->path.s, c->path.len);
00318 cp = (char*)cp + c->path.len;
00319 len -= needed;
00320 } else {
00321 shortage += needed;
00322 }
00323 } else {
00324 needed = (int)(sizeof(c->c.len) + c->c.len +
00325 sizeof(c->sock) + sizeof(c->cflags) +
00326 sizeof(c->path.len) + c->path.len);
00327 if (len >= needed) {
00328 memcpy(cp, &c->c.len, sizeof(c->c.len));
00329 cp = (char*)cp + sizeof(c->c.len);
00330 memcpy(cp, c->c.s, c->c.len);
00331 cp = (char*)cp + c->c.len;
00332 memcpy(cp, &c->sock, sizeof(c->sock));
00333 cp = (char*)cp + sizeof(c->sock);
00334 memcpy(cp, &c->cflags, sizeof(c->cflags));
00335 cp = (char*)cp + sizeof(c->cflags);
00336 memcpy(cp, &c->path.len, sizeof(c->path.len));
00337 cp = (char*)cp + sizeof(c->path.len);
00338 memcpy(cp, c->path.s, c->path.len);
00339 cp = (char*)cp + c->path.len;
00340 len -= needed;
00341 } else {
00342 shortage += needed;
00343 }
00344 }
00345 }
00346 }
00347 unlock_ulslot(p->d, i);
00348 }
00349 }
00350
00351 if (len >= 0)
00352 memset(cp, 0, sizeof(c->c.len));
00353
00354
00355 if (shortage > 0 && len > shortage) {
00356 abort();
00357 }
00358
00359 shortage -= len;
00360
00361 return shortage > 0 ? shortage : 0;
00362 }
00363
00364
00365
00398 int get_all_ucontacts(void *buf, int len, unsigned int flags,
00399 unsigned int part_idx, unsigned int part_max)
00400 {
00401 if (db_mode==DB_ONLY)
00402 return get_all_db_ucontacts( buf, len, flags, part_idx, part_max);
00403 else
00404 return get_all_mem_ucontacts( buf, len, flags, part_idx, part_max);
00405 }
00406
00407
00408
00417 static inline int new_dlist(str* _n, dlist_t** _d)
00418 {
00419 dlist_t* ptr;
00420
00421
00422
00423
00424 ptr = (dlist_t*)shm_malloc(sizeof(dlist_t));
00425 if (ptr == 0) {
00426 LM_ERR("no more share memory\n");
00427 return -1;
00428 }
00429 memset(ptr, 0, sizeof(dlist_t));
00430
00431
00432 ptr->name.s = (char*)shm_malloc(_n->len+1);
00433 if (ptr->name.s == 0) {
00434 LM_ERR("no more memory left\n");
00435 shm_free(ptr);
00436 return -2;
00437 }
00438
00439 memcpy(ptr->name.s, _n->s, _n->len);
00440 ptr->name.len = _n->len;
00441 ptr->name.s[ptr->name.len] = 0;
00442
00443 if (new_udomain(&(ptr->name), ul_hash_size, &(ptr->d)) < 0) {
00444 LM_ERR("creating domain structure failed\n");
00445 shm_free(ptr->name.s);
00446 shm_free(ptr);
00447 return -3;
00448 }
00449
00450 *_d = ptr;
00451 return 0;
00452 }
00453
00462 int get_udomain(const char* _n, udomain_t** _d)
00463 {
00464 dlist_t* d;
00465 str s;
00466
00467 s.s = (char*)_n;
00468 s.len = strlen(_n);
00469
00470 if (find_dlist(&s, &d) == 0) {
00471 *_d = d->d;
00472 return 0;
00473 }
00474 *_d = NULL;
00475 return -1;
00476 }
00477
00488 int register_udomain(const char* _n, udomain_t** _d)
00489 {
00490 dlist_t* d;
00491 str s;
00492 db1_con_t* con;
00493
00494 s.s = (char*)_n;
00495 s.len = strlen(_n);
00496
00497 if (find_dlist(&s, &d) == 0) {
00498 *_d = d->d;
00499 return 0;
00500 }
00501
00502 if (new_dlist(&s, &d) < 0) {
00503 LM_ERR("failed to create new domain\n");
00504 return -1;
00505 }
00506
00507
00508
00509
00510 if (db_mode != NO_DB) {
00511 con = ul_dbf.init(&db_url);
00512 if (!con) {
00513 LM_ERR("failed to open database connection\n");
00514 goto err;
00515 }
00516
00517 if(db_check_table_version(&ul_dbf, con, &s, UL_TABLE_VERSION) < 0) {
00518 LM_ERR("error during table version check.\n");
00519 goto err;
00520 }
00521
00522 if (testdb_udomain(con, d->d) < 0) {
00523 LM_ERR("testing domain '%.*s' failed\n", s.len, ZSW(s.s));
00524 goto err;
00525 }
00526
00527 ul_dbf.close(con);
00528 }
00529
00530 d->next = root;
00531 root = d;
00532
00533 *_d = d->d;
00534 return 0;
00535
00536 err:
00537 if (con) ul_dbf.close(con);
00538 free_udomain(d->d);
00539 shm_free(d->name.s);
00540 shm_free(d);
00541 return -1;
00542 }
00543
00544
00548 void free_all_udomains(void)
00549 {
00550 dlist_t* ptr;
00551
00552 while(root) {
00553 ptr = root;
00554 root = root->next;
00555
00556 free_udomain(ptr->d);
00557 shm_free(ptr->name.s);
00558 shm_free(ptr);
00559 }
00560 }
00561
00562
00567 void print_all_udomains(FILE* _f)
00568 {
00569 dlist_t* ptr;
00570
00571 ptr = root;
00572
00573 fprintf(_f, "===Domain list===\n");
00574 while(ptr) {
00575 print_udomain(_f, ptr->d);
00576 ptr = ptr->next;
00577 }
00578 fprintf(_f, "===/Domain list===\n");
00579 }
00580
00581
00586 unsigned long get_number_of_users(void)
00587 {
00588 long numberOfUsers = 0;
00589
00590 dlist_t* current_dlist;
00591
00592 current_dlist = root;
00593
00594 while (current_dlist)
00595 {
00596 numberOfUsers += get_stat_val(current_dlist->d->users);
00597 current_dlist = current_dlist->next;
00598 }
00599
00600 return numberOfUsers;
00601 }
00602
00603
00608 int synchronize_all_udomains(int istart, int istep)
00609 {
00610 int res = 0;
00611 dlist_t* ptr;
00612
00613 get_act_time();
00614
00615 if (db_mode==DB_ONLY) {
00616 for( ptr=root ; ptr ; ptr=ptr->next)
00617 res |= db_timer_udomain(ptr->d);
00618 } else {
00619 for( ptr=root ; ptr ; ptr=ptr->next)
00620 mem_timer_udomain(ptr->d, istart, istep);
00621 }
00622
00623 return res;
00624 }
00625
00626
00633 int find_domain(str* _d, udomain_t** _p)
00634 {
00635 dlist_t* d;
00636
00637 if (find_dlist(_d, &d) == 0) {
00638 *_p = d->d;
00639 return 0;
00640 }
00641
00642 return 1;
00643 }