udomain.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2001-2003 FhG Fokus
  5. *
  6. * This file is part of Kamailio, a free SIP server.
  7. *
  8. * Kamailio is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version
  12. *
  13. * Kamailio is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. *
  22. * History:
  23. * ---------
  24. * 2003-03-11 changed to the new locking scheme: locking.h (andrei)
  25. * 2003-03-12 added replication mark and zombie state (nils)
  26. * 2004-06-07 updated to the new DB api (andrei)
  27. * 2004-08-23 hash function changed to process characters as unsigned
  28. * -> no negative results occur (jku)
  29. */
  30. /*! \file
  31. * \brief USRLOC - Userloc domain handling functions
  32. * \ingroup usrloc
  33. *
  34. * - Module: \ref usrloc
  35. */
  36. #include "udomain.h"
  37. #include <string.h>
  38. #include "../../parser/parse_methods.h"
  39. #include "../../mem/shm_mem.h"
  40. #include "../../dprint.h"
  41. #include "../../lib/srdb1/db.h"
  42. #include "../../socket_info.h"
  43. #include "../../ut.h"
  44. #include "../../hashes.h"
  45. #include "ul_mod.h" /* usrloc module parameters */
  46. #include "usrloc.h"
  47. #include "utime.h"
  48. #include "usrloc.h"
  49. #ifdef STATISTICS
  50. static char *build_stat_name( str* domain, char *var_name)
  51. {
  52. int n;
  53. char *s;
  54. char *p;
  55. n = domain->len + 1 + strlen(var_name) + 1;
  56. s = (char*)shm_malloc( n );
  57. if (s==0) {
  58. LM_ERR("no more shm mem\n");
  59. return 0;
  60. }
  61. memcpy( s, domain->s, domain->len);
  62. p = s + domain->len;
  63. *(p++) = '-';
  64. memcpy( p , var_name, strlen(var_name));
  65. p += strlen(var_name);
  66. *(p++) = 0;
  67. return s;
  68. }
  69. #endif
  70. /*!
  71. * \brief Create a new domain structure
  72. * \param _n is pointer to str representing name of the domain, the string is
  73. * not copied, it should point to str structure stored in domain list
  74. * \param _s is hash table size
  75. * \param _d new created domain
  76. * \return 0 on success, -1 on failure
  77. */
  78. int new_udomain(str* _n, int _s, udomain_t** _d)
  79. {
  80. int i;
  81. #ifdef STATISTICS
  82. char *name;
  83. #endif
  84. /* Must be always in shared memory, since
  85. * the cache is accessed from timer which
  86. * lives in a separate process
  87. */
  88. *_d = (udomain_t*)shm_malloc(sizeof(udomain_t));
  89. if (!(*_d)) {
  90. LM_ERR("new_udomain(): No memory left\n");
  91. goto error0;
  92. }
  93. memset(*_d, 0, sizeof(udomain_t));
  94. (*_d)->table = (hslot_t*)shm_malloc(sizeof(hslot_t) * _s);
  95. if (!(*_d)->table) {
  96. LM_ERR("no memory left 2\n");
  97. goto error1;
  98. }
  99. (*_d)->name = _n;
  100. for(i = 0; i < _s; i++) {
  101. init_slot(*_d, &((*_d)->table[i]), i);
  102. }
  103. (*_d)->size = _s;
  104. #ifdef STATISTICS
  105. /* register the statistics */
  106. if ( (name=build_stat_name(_n,"users"))==0 || register_stat("usrloc",
  107. name, &(*_d)->users, STAT_NO_RESET|STAT_SHM_NAME)!=0 ) {
  108. LM_ERR("failed to add stat variable\n");
  109. goto error2;
  110. }
  111. if ( (name=build_stat_name(_n,"contacts"))==0 || register_stat("usrloc",
  112. name, &(*_d)->contacts, STAT_NO_RESET|STAT_SHM_NAME)!=0 ) {
  113. LM_ERR("failed to add stat variable\n");
  114. goto error2;
  115. }
  116. if ( (name=build_stat_name(_n,"expires"))==0 || register_stat("usrloc",
  117. name, &(*_d)->expires, STAT_SHM_NAME)!=0 ) {
  118. LM_ERR("failed to add stat variable\n");
  119. goto error2;
  120. }
  121. #endif
  122. return 0;
  123. #ifdef STATISTICS
  124. error2:
  125. shm_free((*_d)->table);
  126. #endif
  127. error1:
  128. shm_free(*_d);
  129. error0:
  130. return -1;
  131. }
  132. /*!
  133. * \brief Free all memory allocated for the domain
  134. * \param _d freed domain
  135. */
  136. void free_udomain(udomain_t* _d)
  137. {
  138. int i;
  139. if (_d->table) {
  140. for(i = 0; i < _d->size; i++) {
  141. lock_ulslot(_d, i);
  142. deinit_slot(_d->table + i);
  143. unlock_ulslot(_d, i);
  144. }
  145. shm_free(_d->table);
  146. }
  147. shm_free(_d);
  148. }
  149. /*!
  150. * \brief Returns a static dummy urecord for temporary usage
  151. * \param _d domain (needed for the name)
  152. * \param _aor address of record
  153. * \param _r new created urecord
  154. */
  155. static inline void get_static_urecord(udomain_t* _d, str* _aor,
  156. struct urecord** _r)
  157. {
  158. static struct urecord r;
  159. memset( &r, 0, sizeof(struct urecord) );
  160. r.aor = *_aor;
  161. r.aorhash = ul_get_aorhash(_aor);
  162. r.domain = _d->name;
  163. *_r = &r;
  164. }
  165. /*!
  166. * \brief Debugging helper function
  167. */
  168. void print_udomain(FILE* _f, udomain_t* _d)
  169. {
  170. int i;
  171. int max=0, slot=0, n=0;
  172. struct urecord* r;
  173. fprintf(_f, "---Domain---\n");
  174. fprintf(_f, "name : '%.*s'\n", _d->name->len, ZSW(_d->name->s));
  175. fprintf(_f, "size : %d\n", _d->size);
  176. fprintf(_f, "table: %p\n", _d->table);
  177. /*fprintf(_f, "lock : %d\n", _d->lock); -- can be a structure --andrei*/
  178. fprintf(_f, "\n");
  179. for(i=0; i<_d->size; i++)
  180. {
  181. r = _d->table[i].first;
  182. n += _d->table[i].n;
  183. if(max<_d->table[i].n){
  184. max= _d->table[i].n;
  185. slot = i;
  186. }
  187. while(r) {
  188. print_urecord(_f, r);
  189. r = r->next;
  190. }
  191. }
  192. fprintf(_f, "\nMax slot: %d (%d/%d)\n", max, slot, n);
  193. fprintf(_f, "\n---/Domain---\n");
  194. }
  195. /*!
  196. * \brief Convert database values into ucontact_info
  197. *
  198. * Convert database values into ucontact_info,
  199. * expects 12 rows (contact, expirs, q, callid, cseq, flags,
  200. * ua, received, path, socket, methods, last_modified)
  201. * \param vals database values
  202. * \param contact contact
  203. * \return pointer to the ucontact_info on success, 0 on failure
  204. */
  205. static inline ucontact_info_t* dbrow2info( db_val_t *vals, str *contact)
  206. {
  207. static ucontact_info_t ci;
  208. static str callid, ua, received, host, path;
  209. int port, proto;
  210. char *p;
  211. memset( &ci, 0, sizeof(ucontact_info_t));
  212. contact->s = (char*)VAL_STRING(vals);
  213. if (VAL_NULL(vals) || contact->s==0 || contact->s[0]==0) {
  214. LM_CRIT("bad contact\n");
  215. return 0;
  216. }
  217. contact->len = strlen(contact->s);
  218. if (VAL_NULL(vals+1)) {
  219. LM_CRIT("empty expire\n");
  220. return 0;
  221. }
  222. ci.expires = UL_DB_EXPIRES_GET(vals+1);
  223. if (VAL_NULL(vals+2)) {
  224. LM_CRIT("empty q\n");
  225. return 0;
  226. }
  227. ci.q = double2q(VAL_DOUBLE(vals+2));
  228. if (VAL_NULL(vals+4)) {
  229. LM_CRIT("empty cseq_nr\n");
  230. return 0;
  231. }
  232. ci.cseq = VAL_INT(vals+4);
  233. callid.s = (char*)VAL_STRING(vals+3);
  234. if (VAL_NULL(vals+3) || !callid.s || !callid.s[0]) {
  235. LM_CRIT("bad callid\n");
  236. return 0;
  237. }
  238. callid.len = strlen(callid.s);
  239. ci.callid = &callid;
  240. if (VAL_NULL(vals+5)) {
  241. LM_CRIT("empty flag\n");
  242. return 0;
  243. }
  244. ci.flags = VAL_BITMAP(vals+5);
  245. if (VAL_NULL(vals+6)) {
  246. LM_CRIT("empty cflag\n");
  247. return 0;
  248. }
  249. ci.cflags = VAL_BITMAP(vals+6);
  250. ua.s = (char*)VAL_STRING(vals+7);
  251. if (VAL_NULL(vals+7) || !ua.s || !ua.s[0]) {
  252. ua.s = 0;
  253. ua.len = 0;
  254. } else {
  255. ua.len = strlen(ua.s);
  256. }
  257. ci.user_agent = &ua;
  258. received.s = (char*)VAL_STRING(vals+8);
  259. if (VAL_NULL(vals+8) || !received.s || !received.s[0]) {
  260. received.len = 0;
  261. received.s = 0;
  262. } else {
  263. received.len = strlen(received.s);
  264. }
  265. ci.received = received;
  266. path.s = (char*)VAL_STRING(vals+9);
  267. if (VAL_NULL(vals+9) || !path.s || !path.s[0]) {
  268. path.len = 0;
  269. path.s = 0;
  270. } else {
  271. path.len = strlen(path.s);
  272. }
  273. ci.path= &path;
  274. /* socket name */
  275. p = (char*)VAL_STRING(vals+10);
  276. if (VAL_NULL(vals+10) || p==0 || p[0]==0){
  277. ci.sock = 0;
  278. } else {
  279. if (parse_phostport( p, &host.s, &host.len,
  280. &port, &proto)!=0) {
  281. LM_ERR("bad socket <%s>\n", p);
  282. return 0;
  283. }
  284. ci.sock = grep_sock_info( &host, (unsigned short)port, proto);
  285. if (ci.sock==0) {
  286. LM_INFO("non-local socket <%s>...ignoring\n", p);
  287. }
  288. }
  289. /* supported methods */
  290. if (VAL_NULL(vals+11)) {
  291. ci.methods = ALL_METHODS;
  292. } else {
  293. ci.methods = VAL_BITMAP(vals+11);
  294. }
  295. /* last modified time */
  296. if (!VAL_NULL(vals+12)) {
  297. ci.last_modified = UL_DB_EXPIRES_GET(vals+12);
  298. }
  299. /* record internal uid */
  300. if (!VAL_NULL(vals+13)) {
  301. ci.ruid.s = (char*)VAL_STRING(vals+13);
  302. ci.ruid.len = strlen(ci.ruid.s);
  303. }
  304. /* sip instance */
  305. if (!VAL_NULL(vals+14)) {
  306. ci.instance.s = (char*)VAL_STRING(vals+14);
  307. ci.instance.len = strlen(ci.instance.s);
  308. }
  309. /* reg-id */
  310. if (!VAL_NULL(vals+15)) {
  311. ci.reg_id = VAL_UINT(vals+15);
  312. }
  313. /* tcp connection id */
  314. ci.tcpconn_id = -1;
  315. return &ci;
  316. }
  317. /*!
  318. * \brief Load all records from a udomain
  319. *
  320. * Load all records from a udomain, useful to populate the
  321. * memory cache on startup.
  322. * \param _c database connection
  323. * \param _d loaded domain
  324. * \return 0 on success, -1 on failure
  325. */
  326. int preload_udomain(db1_con_t* _c, udomain_t* _d)
  327. {
  328. char uri[MAX_URI_SIZE];
  329. ucontact_info_t *ci;
  330. db_row_t *row;
  331. db_key_t columns[18];
  332. db1_res_t* res = NULL;
  333. str user, contact;
  334. char* domain;
  335. int i;
  336. int n;
  337. urecord_t* r;
  338. ucontact_t* c;
  339. columns[0] = &user_col;
  340. columns[1] = &contact_col;
  341. columns[2] = &expires_col;
  342. columns[3] = &q_col;
  343. columns[4] = &callid_col;
  344. columns[5] = &cseq_col;
  345. columns[6] = &flags_col;
  346. columns[7] = &cflags_col;
  347. columns[8] = &user_agent_col;
  348. columns[9] = &received_col;
  349. columns[10] = &path_col;
  350. columns[11] = &sock_col;
  351. columns[12] = &methods_col;
  352. columns[13] = &last_mod_col;
  353. columns[14] = &ruid_col;
  354. columns[15] = &instance_col;
  355. columns[16] = &reg_id_col;
  356. columns[17] = &domain_col;
  357. if (ul_dbf.use_table(_c, _d->name) < 0) {
  358. LM_ERR("sql use_table failed\n");
  359. return -1;
  360. }
  361. #ifdef EXTRA_DEBUG
  362. LM_NOTICE("load start time [%d]\n", (int)time(NULL));
  363. #endif
  364. if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
  365. if (ul_dbf.query(_c, 0, 0, 0, columns, 0, (use_domain)?(18):(17), 0,
  366. 0) < 0) {
  367. LM_ERR("db_query (1) failed\n");
  368. return -1;
  369. }
  370. if(ul_dbf.fetch_result(_c, &res, ul_fetch_rows)<0) {
  371. LM_ERR("fetching rows failed\n");
  372. return -1;
  373. }
  374. } else {
  375. if (ul_dbf.query(_c, 0, 0, 0, columns, 0, (use_domain)?(18):(17), 0,
  376. &res) < 0) {
  377. LM_ERR("db_query failed\n");
  378. return -1;
  379. }
  380. }
  381. if (RES_ROW_N(res) == 0) {
  382. LM_DBG("table is empty\n");
  383. ul_dbf.free_result(_c, res);
  384. return 0;
  385. }
  386. n = 0;
  387. do {
  388. LM_DBG("loading records - cycle [%d]\n", ++n);
  389. for(i = 0; i < RES_ROW_N(res); i++) {
  390. row = RES_ROWS(res) + i;
  391. user.s = (char*)VAL_STRING(ROW_VALUES(row));
  392. if (VAL_NULL(ROW_VALUES(row)) || user.s==0 || user.s[0]==0) {
  393. LM_CRIT("empty username record in table %s...skipping\n",
  394. _d->name->s);
  395. continue;
  396. }
  397. user.len = strlen(user.s);
  398. ci = dbrow2info( ROW_VALUES(row)+1, &contact);
  399. if (ci==0) {
  400. LM_ERR("sipping record for %.*s in table %s\n",
  401. user.len, user.s, _d->name->s);
  402. continue;
  403. }
  404. if (use_domain) {
  405. domain = (char*)VAL_STRING(ROW_VALUES(row) + 17);
  406. if (VAL_NULL(ROW_VALUES(row)+17) || domain==0 || domain[0]==0){
  407. LM_CRIT("empty domain record for user %.*s...skipping\n",
  408. user.len, user.s);
  409. continue;
  410. }
  411. /* user.s cannot be NULL - checked previosly */
  412. user.len = snprintf(uri, MAX_URI_SIZE, "%.*s@%s",
  413. user.len, user.s, domain);
  414. user.s = uri;
  415. if (user.s[user.len]!=0) {
  416. LM_CRIT("URI '%.*s@%s' longer than %d\n", user.len, user.s,
  417. domain, MAX_URI_SIZE);
  418. continue;
  419. }
  420. }
  421. lock_udomain(_d, &user);
  422. if (get_urecord(_d, &user, &r) > 0) {
  423. if (mem_insert_urecord(_d, &user, &r) < 0) {
  424. LM_ERR("failed to create a record\n");
  425. unlock_udomain(_d, &user);
  426. goto error;
  427. }
  428. }
  429. if ( (c=mem_insert_ucontact(r, &contact, ci)) == 0) {
  430. LM_ERR("inserting contact failed\n");
  431. unlock_udomain(_d, &user);
  432. goto error1;
  433. }
  434. /* We have to do this, because insert_ucontact sets state to CS_NEW
  435. * and we have the contact in the database already */
  436. c->state = CS_SYNC;
  437. unlock_udomain(_d, &user);
  438. }
  439. if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
  440. if(ul_dbf.fetch_result(_c, &res, ul_fetch_rows)<0) {
  441. LM_ERR("fetching rows (1) failed\n");
  442. ul_dbf.free_result(_c, res);
  443. return -1;
  444. }
  445. } else {
  446. break;
  447. }
  448. } while(RES_ROW_N(res)>0);
  449. ul_dbf.free_result(_c, res);
  450. #ifdef EXTRA_DEBUG
  451. LM_NOTICE("load end time [%d]\n", (int)time(NULL));
  452. #endif
  453. return 0;
  454. error1:
  455. free_ucontact(c);
  456. error:
  457. ul_dbf.free_result(_c, res);
  458. return -1;
  459. }
  460. /*!
  461. * \brief Loads from DB all contacts for an AOR
  462. * \param _c database connection
  463. * \param _d domain
  464. * \param _aor address of record
  465. * \return pointer to the record on success, 0 on errors or if nothing is found
  466. */
  467. urecord_t* db_load_urecord(db1_con_t* _c, udomain_t* _d, str *_aor)
  468. {
  469. char tname_buf[64];
  470. str tname;
  471. ucontact_info_t *ci;
  472. db_key_t columns[16];
  473. db_key_t keys[2];
  474. db_key_t order;
  475. db_val_t vals[2];
  476. db1_res_t* res = NULL;
  477. db_row_t *row;
  478. str aname;
  479. str avalue;
  480. sr_xval_t aval;
  481. str contact;
  482. char *domain;
  483. int i;
  484. urecord_t* r;
  485. ucontact_t* c;
  486. keys[0] = &user_col;
  487. vals[0].type = DB1_STR;
  488. vals[0].nul = 0;
  489. if (use_domain) {
  490. keys[1] = &domain_col;
  491. vals[1].type = DB1_STR;
  492. vals[1].nul = 0;
  493. domain = memchr(_aor->s, '@', _aor->len);
  494. vals[0].val.str_val.s = _aor->s;
  495. if (domain==0) {
  496. vals[0].val.str_val.len = 0;
  497. vals[1].val.str_val = *_aor;
  498. } else {
  499. vals[0].val.str_val.len = domain - _aor->s;
  500. vals[1].val.str_val.s = domain+1;
  501. vals[1].val.str_val.len = _aor->s + _aor->len - domain - 1;
  502. }
  503. } else {
  504. vals[0].val.str_val = *_aor;
  505. }
  506. columns[0] = &contact_col;
  507. columns[1] = &expires_col;
  508. columns[2] = &q_col;
  509. columns[3] = &callid_col;
  510. columns[4] = &cseq_col;
  511. columns[5] = &flags_col;
  512. columns[6] = &cflags_col;
  513. columns[7] = &user_agent_col;
  514. columns[8] = &received_col;
  515. columns[9] = &path_col;
  516. columns[10] = &sock_col;
  517. columns[11] = &methods_col;
  518. columns[12] = &last_mod_col;
  519. columns[13] = &ruid_col;
  520. columns[14] = &instance_col;
  521. columns[15] = &reg_id_col;
  522. if (desc_time_order)
  523. order = &last_mod_col;
  524. else
  525. order = &q_col;
  526. if (ul_dbf.use_table(_c, _d->name) < 0) {
  527. LM_ERR("failed to use table %.*s\n", _d->name->len, _d->name->s);
  528. return 0;
  529. }
  530. if (ul_dbf.query(_c, keys, 0, vals, columns, (use_domain)?2:1, 16, order,
  531. &res) < 0) {
  532. LM_ERR("db_query failed\n");
  533. return 0;
  534. }
  535. if (RES_ROW_N(res) == 0) {
  536. LM_DBG("aor %.*s not found in table %.*s\n",_aor->len, _aor->s, _d->name->len, _d->name->s);
  537. ul_dbf.free_result(_c, res);
  538. return 0;
  539. }
  540. r = 0;
  541. for(i = 0; i < RES_ROW_N(res); i++) {
  542. ci = dbrow2info( ROW_VALUES(RES_ROWS(res) + i), &contact);
  543. if (ci==0) {
  544. LM_ERR("skipping record for %.*s in table %s\n",
  545. _aor->len, _aor->s, _d->name->s);
  546. continue;
  547. }
  548. if ( r==0 )
  549. get_static_urecord( _d, _aor, &r);
  550. if ( (c=mem_insert_ucontact(r, &contact, ci)) == 0) {
  551. LM_ERR("mem_insert failed\n");
  552. free_urecord(r);
  553. ul_dbf.free_result(_c, res);
  554. return 0;
  555. }
  556. /* We have to do this, because insert_ucontact sets state to CS_NEW
  557. * and we have the contact in the database already */
  558. c->state = CS_SYNC;
  559. }
  560. ul_dbf.free_result(_c, res);
  561. /* Retrieve ul attributes */
  562. if(ul_xavp_contact_name.s==NULL) {
  563. /* feature disabled by mod param */
  564. goto done;
  565. }
  566. if(_d->name->len + 6>=64) {
  567. LM_ERR("attributes table name is too big\n");
  568. goto done;
  569. }
  570. strncpy(tname_buf, _d->name->s, _d->name->len);
  571. tname_buf[_d->name->len] = '\0';
  572. strcat(tname_buf, "_attrs");
  573. tname.s = tname_buf;
  574. tname.len = _d->name->len + 6;
  575. keys[0] = &ulattrs_ruid_col;
  576. vals[0].type = DB1_STR;
  577. vals[0].nul = 0;
  578. columns[0] = &ulattrs_aname_col;
  579. columns[1] = &ulattrs_atype_col;
  580. columns[2] = &ulattrs_avalue_col;
  581. if (ul_dbf.use_table(ul_dbh, &tname) < 0) {
  582. LM_ERR("sql use_table failed for %.*s\n", tname.len, tname.s);
  583. goto done;
  584. }
  585. for (c = r->contacts; c != NULL; c = c->next) {
  586. vals[0].val.str_val.s = c->ruid.s;
  587. vals[0].val.str_val.len = c->ruid.len;
  588. if (ul_dbf.query(ul_dbh, keys, 0, vals, columns, 1, 3, 0, &res) < 0) {
  589. LM_ERR("db_query failed\n");
  590. continue;
  591. }
  592. if (RES_ROW_N(res) == 0) {
  593. LM_DBG("location attrs table is empty\n");
  594. ul_dbf.free_result(ul_dbh, res);
  595. continue;
  596. }
  597. for(i = 0; i < RES_ROW_N(res); i++) {
  598. row = RES_ROWS(res) + i;
  599. aname.s = (char*)VAL_STRING(ROW_VALUES(row));
  600. aname.len = strlen(aname.s);
  601. avalue.s = (char*)VAL_STRING(ROW_VALUES(row) + 2);
  602. avalue.len = strlen(avalue.s);
  603. memset(&aval, 0, sizeof(sr_xval_t));
  604. if(VAL_INT(ROW_VALUES(row)+1)==0) {
  605. /* string value */
  606. aval.v.s = avalue;
  607. aval.type = SR_XTYPE_STR;
  608. } else if(VAL_INT(ROW_VALUES(row)+1)==1) {
  609. /* int value */
  610. str2sint(&avalue, &aval.v.i);
  611. aval.type = SR_XTYPE_INT;
  612. } else {
  613. /* unknown type - ignore */
  614. continue;
  615. }
  616. /* add xavp to contact */
  617. if(c->xavp==NULL) {
  618. if(xavp_add_xavp_value(&ul_xavp_contact_name, &aname,
  619. &aval, &c->xavp)==NULL)
  620. LM_INFO("cannot add first xavp to contact - ignoring\n");
  621. } else {
  622. if(c->xavp->val.type==SR_XTYPE_XAVP) {
  623. if(xavp_add_value(&aname, &aval, &c->xavp->val.v.xavp)==NULL)
  624. LM_INFO("cannot add values to contact xavp\n");
  625. }
  626. }
  627. }
  628. ul_dbf.free_result(ul_dbh, res);
  629. }
  630. done:
  631. return r;
  632. }
  633. /*!
  634. * \brief Loads from DB all contacts for a RUID
  635. * \param _c database connection
  636. * \param _d domain
  637. * \param _aor address of record
  638. * \return pointer to the record on success, 0 on errors or if nothing is found
  639. */
  640. urecord_t* db_load_urecord_by_ruid(db1_con_t* _c, udomain_t* _d, str *_ruid)
  641. {
  642. ucontact_info_t *ci;
  643. db_key_t columns[18];
  644. db_key_t keys[1];
  645. db_key_t order;
  646. db_val_t vals[1];
  647. db1_res_t* res = NULL;
  648. db_row_t *row;
  649. str contact;
  650. str aor;
  651. static char aorbuf[512];
  652. str domain;
  653. urecord_t* r;
  654. ucontact_t* c;
  655. keys[0] = &ruid_col;
  656. vals[0].type = DB1_STR;
  657. vals[0].nul = 0;
  658. vals[0].val.str_val = *_ruid;
  659. columns[0] = &contact_col;
  660. columns[1] = &expires_col;
  661. columns[2] = &q_col;
  662. columns[3] = &callid_col;
  663. columns[4] = &cseq_col;
  664. columns[5] = &flags_col;
  665. columns[6] = &cflags_col;
  666. columns[7] = &user_agent_col;
  667. columns[8] = &received_col;
  668. columns[9] = &path_col;
  669. columns[10] = &sock_col;
  670. columns[11] = &methods_col;
  671. columns[12] = &last_mod_col;
  672. columns[13] = &ruid_col;
  673. columns[14] = &instance_col;
  674. columns[15] = &reg_id_col;
  675. columns[16] = &user_col;
  676. columns[17] = &domain_col;
  677. if (desc_time_order)
  678. order = &last_mod_col;
  679. else
  680. order = &q_col;
  681. if (ul_dbf.use_table(_c, _d->name) < 0) {
  682. LM_ERR("failed to use table %.*s\n", _d->name->len, _d->name->s);
  683. return 0;
  684. }
  685. if (ul_dbf.query(_c, keys, 0, vals, columns, 1, 18, order,
  686. &res) < 0) {
  687. LM_ERR("db_query failed\n");
  688. return 0;
  689. }
  690. if (RES_ROW_N(res) == 0) {
  691. LM_DBG("aor %.*s not found in table %.*s\n",_ruid->len, _ruid->s,
  692. _d->name->len, _d->name->s);
  693. ul_dbf.free_result(_c, res);
  694. return 0;
  695. }
  696. r = 0;
  697. /* use first row - shouldn't be more */
  698. row = RES_ROWS(res);
  699. ci = dbrow2info(ROW_VALUES(RES_ROWS(res)), &contact);
  700. if (ci==0) {
  701. LM_ERR("skipping record for %.*s in table %s\n",
  702. _ruid->len, _ruid->s, _d->name->s);
  703. goto done;
  704. }
  705. aor.s = (char*)VAL_STRING(ROW_VALUES(row) + 16);
  706. aor.len = strlen(aor.s);
  707. if (use_domain) {
  708. domain.s = (char*)VAL_STRING(ROW_VALUES(row) + 17);
  709. if (VAL_NULL(ROW_VALUES(row)+17) || domain.s==0 || domain.s[0]==0){
  710. LM_CRIT("empty domain record for user %.*s...skipping\n",
  711. aor.len, aor.s);
  712. goto done;
  713. }
  714. domain.len = strlen(domain.s);
  715. if(aor.len + domain.len + 2 >= 512) {
  716. LM_ERR("AoR is too big\n");
  717. goto done;
  718. }
  719. memcpy(aorbuf, aor.s, aor.len);
  720. aorbuf[aor.len] = '@';
  721. memcpy(aorbuf + aor.len + 1, domain.s, domain.len);
  722. aor.len += 1 + domain.len;
  723. aor.s = aorbuf;
  724. aor.s[aor.len] = '\0';
  725. }
  726. get_static_urecord( _d, &aor, &r);
  727. if ( (c=mem_insert_ucontact(r, &contact, ci)) == 0) {
  728. LM_ERR("mem_insert failed\n");
  729. free_urecord(r);
  730. ul_dbf.free_result(_c, res);
  731. return 0;
  732. }
  733. /* We have to do this, because insert_ucontact sets state to CS_NEW
  734. * and we have the contact in the database already */
  735. c->state = CS_SYNC;
  736. done:
  737. ul_dbf.free_result(_c, res);
  738. return r;
  739. }
  740. /*!
  741. * \brief Timer function to cleanup expired contacts, DB_ONLY db_mode
  742. * \param _d cleaned domain
  743. * \return 0 on success, -1 on failure
  744. */
  745. int db_timer_udomain(udomain_t* _d)
  746. {
  747. db_key_t keys[2];
  748. db_op_t ops[2];
  749. db_val_t vals[2];
  750. keys[0] = &expires_col;
  751. ops[0] = "<";
  752. vals[0].nul = 0;
  753. UL_DB_EXPIRES_SET(&vals[0], act_time + 1);
  754. keys[1] = &expires_col;
  755. ops[1] = "!=";
  756. vals[1].nul = 0;
  757. UL_DB_EXPIRES_SET(&vals[1], 0);
  758. if (ul_dbf.use_table(ul_dbh, _d->name) < 0) {
  759. LM_ERR("use_table failed\n");
  760. return -1;
  761. }
  762. if (ul_dbf.delete(ul_dbh, keys, ops, vals, 2) < 0) {
  763. LM_ERR("failed to delete from table %s\n",_d->name->s);
  764. return -1;
  765. }
  766. return 0;
  767. }
  768. /*!
  769. * \brief performs a dummy query just to see if DB is ok
  770. * \param con database connection
  771. * \param d domain
  772. */
  773. int testdb_udomain(db1_con_t* con, udomain_t* d)
  774. {
  775. db_key_t key[1], col[1];
  776. db_val_t val[1];
  777. db1_res_t* res = NULL;
  778. if (ul_dbf.use_table(con, d->name) < 0) {
  779. LM_ERR("failed to change table\n");
  780. return -1;
  781. }
  782. key[0] = &user_col;
  783. col[0] = &user_col;
  784. VAL_TYPE(val) = DB1_STRING;
  785. VAL_NULL(val) = 0;
  786. VAL_STRING(val) = "dummy_user";
  787. if (ul_dbf.query( con, key, 0, val, col, 1, 1, 0, &res) < 0) {
  788. LM_ERR("failure in db_query\n");
  789. return -1;
  790. }
  791. ul_dbf.free_result( con, res);
  792. return 0;
  793. }
  794. /*!
  795. * \brief Insert a new record into domain in memory
  796. * \param _d domain the record belongs to
  797. * \param _aor address of record
  798. * \param _r new created record
  799. * \return 0 on success, -1 on failure
  800. */
  801. int mem_insert_urecord(udomain_t* _d, str* _aor, struct urecord** _r)
  802. {
  803. int sl;
  804. if (new_urecord(_d->name, _aor, _r) < 0) {
  805. LM_ERR("creating urecord failed\n");
  806. return -1;
  807. }
  808. sl = ((*_r)->aorhash)&(_d->size-1);
  809. slot_add(&_d->table[sl], *_r);
  810. update_stat( _d->users, 1);
  811. return 0;
  812. }
  813. /*!
  814. * \brief Remove a record from domain in memory
  815. * \param _d domain the record belongs to
  816. * \param _r deleted record
  817. */
  818. void mem_delete_urecord(udomain_t* _d, struct urecord* _r)
  819. {
  820. slot_rem(_r->slot, _r);
  821. free_urecord(_r);
  822. update_stat( _d->users, -1);
  823. }
  824. /*!
  825. * \brief Run timer handler for given domain
  826. * \param _d domain
  827. */
  828. void mem_timer_udomain(udomain_t* _d, int istart, int istep)
  829. {
  830. struct urecord* ptr, *t;
  831. int i;
  832. for(i=istart; i<_d->size; i+=istep)
  833. {
  834. lock_ulslot(_d, i);
  835. ptr = _d->table[i].first;
  836. while(ptr) {
  837. timer_urecord(ptr);
  838. /* Remove the entire record if it is empty */
  839. if (ptr->contacts == 0) {
  840. t = ptr;
  841. ptr = ptr->next;
  842. mem_delete_urecord(_d, t);
  843. } else {
  844. ptr = ptr->next;
  845. }
  846. }
  847. unlock_ulslot(_d, i);
  848. }
  849. }
  850. /*!
  851. * \brief Get lock for a domain
  852. * \param _d domain
  853. * \param _aor adress of record, used as hash source for the lock slot
  854. */
  855. void lock_udomain(udomain_t* _d, str* _aor)
  856. {
  857. unsigned int sl;
  858. if (db_mode!=DB_ONLY)
  859. {
  860. sl = ul_get_aorhash(_aor) & (_d->size - 1);
  861. #ifdef GEN_LOCK_T_PREFERED
  862. lock_get(_d->table[sl].lock);
  863. #else
  864. ul_lock_idx(_d->table[sl].lockidx);
  865. #endif
  866. }
  867. }
  868. /*!
  869. * \brief Release lock for a domain
  870. * \param _d domain
  871. * \param _aor address of record, uses as hash source for the lock slot
  872. */
  873. void unlock_udomain(udomain_t* _d, str* _aor)
  874. {
  875. unsigned int sl;
  876. if (db_mode!=DB_ONLY)
  877. {
  878. sl = ul_get_aorhash(_aor) & (_d->size - 1);
  879. #ifdef GEN_LOCK_T_PREFERED
  880. lock_release(_d->table[sl].lock);
  881. #else
  882. ul_release_idx(_d->table[sl].lockidx);
  883. #endif
  884. }
  885. }
  886. /*!
  887. * \brief Get lock for a slot
  888. * \param _d domain
  889. * \param i slot number
  890. */
  891. void lock_ulslot(udomain_t* _d, int i)
  892. {
  893. if (db_mode!=DB_ONLY)
  894. #ifdef GEN_LOCK_T_PREFERED
  895. lock_get(_d->table[i].lock);
  896. #else
  897. ul_lock_idx(_d->table[i].lockidx);
  898. #endif
  899. }
  900. /*!
  901. * \brief Release lock for a slot
  902. * \param _d domain
  903. * \param i slot number
  904. */
  905. void unlock_ulslot(udomain_t* _d, int i)
  906. {
  907. if (db_mode!=DB_ONLY)
  908. #ifdef GEN_LOCK_T_PREFERED
  909. lock_release(_d->table[i].lock);
  910. #else
  911. ul_release_idx(_d->table[i].lockidx);
  912. #endif
  913. }
  914. /*!
  915. * \brief Create and insert a new record
  916. * \param _d domain to insert the new record
  917. * \param _aor address of the record
  918. * \param _r new created record
  919. * \return return 0 on success, -1 on failure
  920. */
  921. int insert_urecord(udomain_t* _d, str* _aor, struct urecord** _r)
  922. {
  923. if (db_mode!=DB_ONLY) {
  924. if (mem_insert_urecord(_d, _aor, _r) < 0) {
  925. LM_ERR("inserting record failed\n");
  926. return -1;
  927. }
  928. } else {
  929. get_static_urecord( _d, _aor, _r);
  930. }
  931. return 0;
  932. }
  933. /*!
  934. * \brief Obtain a urecord pointer if the urecord exists in domain
  935. * \param _d domain to search the record
  936. * \param _aor address of record
  937. * \param _r new created record
  938. * \return 0 if a record was found, 1 if nothing could be found
  939. */
  940. int get_urecord(udomain_t* _d, str* _aor, struct urecord** _r)
  941. {
  942. unsigned int sl, i, aorhash;
  943. urecord_t* r;
  944. if (db_mode!=DB_ONLY) {
  945. /* search in cache */
  946. aorhash = ul_get_aorhash(_aor);
  947. sl = aorhash&(_d->size-1);
  948. r = _d->table[sl].first;
  949. for(i = 0; r!=NULL && i < _d->table[sl].n; i++) {
  950. if((r->aorhash==aorhash) && (r->aor.len==_aor->len)
  951. && !memcmp(r->aor.s,_aor->s,_aor->len)){
  952. *_r = r;
  953. return 0;
  954. }
  955. r = r->next;
  956. }
  957. } else {
  958. /* search in DB */
  959. r = db_load_urecord( ul_dbh, _d, _aor);
  960. if (r) {
  961. *_r = r;
  962. return 0;
  963. }
  964. }
  965. return 1; /* Nothing found */
  966. }
  967. /*!
  968. * \brief Obtain a urecord pointer if the urecord exists in domain (lock slot)
  969. * \param _d domain to search the record
  970. * \param _aorhash hash id for address of record
  971. * \param _ruid record internal unique id
  972. * \param _r store pointer to location record
  973. * \param _c store pointer to contact structure
  974. * \return 0 if a record was found, -1 if nothing could be found
  975. */
  976. int get_urecord_by_ruid(udomain_t* _d, unsigned int _aorhash,
  977. str *_ruid, struct urecord** _r, struct ucontact** _c)
  978. {
  979. unsigned int sl, i;
  980. urecord_t* r;
  981. ucontact_t* c;
  982. sl = _aorhash&(_d->size-1);
  983. lock_ulslot(_d, sl);
  984. if (db_mode!=DB_ONLY) {
  985. /* search in cache */
  986. r = _d->table[sl].first;
  987. for(i = 0; i < _d->table[sl].n; i++) {
  988. if(r->aorhash==_aorhash) {
  989. c = r->contacts;
  990. while(c) {
  991. if(c->ruid.len==_ruid->len
  992. && !memcmp(c->ruid.s, _ruid->s, _ruid->len)) {
  993. *_r = r;
  994. *_c = c;
  995. return 0;
  996. }
  997. c = c->next;
  998. }
  999. }
  1000. r = r->next;
  1001. }
  1002. } else {
  1003. /* search in DB */
  1004. r = db_load_urecord_by_ruid(ul_dbh, _d, _ruid);
  1005. if (r) {
  1006. if(r->aorhash==_aorhash) {
  1007. c = r->contacts;
  1008. while(c) {
  1009. if(c->ruid.len==_ruid->len
  1010. && !memcmp(c->ruid.s, _ruid->s, _ruid->len)) {
  1011. *_r = r;
  1012. *_c = c;
  1013. return 0;
  1014. }
  1015. c = c->next;
  1016. }
  1017. }
  1018. }
  1019. }
  1020. unlock_ulslot(_d, (_aorhash & (_d->size - 1)));
  1021. return -1; /* Nothing found */
  1022. }
  1023. /*!
  1024. * \brief Delete a urecord from domain
  1025. * \param _d domain where the record should be deleted
  1026. * \param _aor address of record
  1027. * \param _r deleted record
  1028. * \return 0 on success, -1 if the record could not be deleted
  1029. */
  1030. int delete_urecord(udomain_t* _d, str* _aor, struct urecord* _r)
  1031. {
  1032. struct ucontact* c, *t;
  1033. if (db_mode==DB_ONLY) {
  1034. if (_r==0)
  1035. get_static_urecord( _d, _aor, &_r);
  1036. if (db_delete_urecord(_r)<0) {
  1037. LM_ERR("DB delete failed\n");
  1038. return -1;
  1039. }
  1040. free_urecord(_r);
  1041. return 0;
  1042. }
  1043. if (_r==0) {
  1044. if (get_urecord(_d, _aor, &_r) > 0) {
  1045. return 0;
  1046. }
  1047. }
  1048. c = _r->contacts;
  1049. while(c) {
  1050. t = c;
  1051. c = c->next;
  1052. if (delete_ucontact(_r, t) < 0) {
  1053. LM_ERR("deleting contact failed\n");
  1054. return -1;
  1055. }
  1056. }
  1057. release_urecord(_r);
  1058. return 0;
  1059. }
  1060. /*!
  1061. * \brief Load all location attributes from an udomain
  1062. *
  1063. * Load all location attributes from a udomain, useful to populate the
  1064. * memory cache on startup.
  1065. * \param _d loaded domain
  1066. * \return 0 on success, -1 on failure
  1067. */
  1068. int uldb_preload_attrs(udomain_t *_d)
  1069. {
  1070. char uri[MAX_URI_SIZE];
  1071. str suri;
  1072. char tname_buf[64];
  1073. str tname;
  1074. db_row_t *row;
  1075. db_key_t columns[6];
  1076. db1_res_t* res = NULL;
  1077. str user = {0};
  1078. str domain = {0};
  1079. str ruid;
  1080. str aname;
  1081. str avalue;
  1082. sr_xval_t aval;
  1083. int i;
  1084. int n;
  1085. urecord_t* r;
  1086. ucontact_t* c;
  1087. if(ul_xavp_contact_name.s==NULL) {
  1088. /* feature disabled by mod param */
  1089. return 0;
  1090. }
  1091. if(_d->name->len + 6>=64) {
  1092. LM_ERR("attributes table name is too big\n");
  1093. return -1;
  1094. }
  1095. strncpy(tname_buf, _d->name->s, _d->name->len);
  1096. tname_buf[_d->name->len] = '\0';
  1097. strcat(tname_buf, "_attrs");
  1098. tname.s = tname_buf;
  1099. tname.len = _d->name->len + 6;
  1100. columns[0] = &ulattrs_user_col;
  1101. columns[1] = &ulattrs_ruid_col;
  1102. columns[2] = &ulattrs_aname_col;
  1103. columns[3] = &ulattrs_atype_col;
  1104. columns[4] = &ulattrs_avalue_col;
  1105. columns[5] = &ulattrs_domain_col;
  1106. if (ul_dbf.use_table(ul_dbh, &tname) < 0) {
  1107. LM_ERR("sql use_table failed for %.*s\n", tname.len, tname.s);
  1108. return -1;
  1109. }
  1110. #ifdef EXTRA_DEBUG
  1111. LM_NOTICE("load start time [%d]\n", (int)time(NULL));
  1112. #endif
  1113. if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
  1114. if (ul_dbf.query(ul_dbh, 0, 0, 0, columns, 0, (use_domain)?(6):(5), 0,
  1115. 0) < 0) {
  1116. LM_ERR("db_query (1) failed\n");
  1117. return -1;
  1118. }
  1119. if(ul_dbf.fetch_result(ul_dbh, &res, ul_fetch_rows)<0) {
  1120. LM_ERR("fetching rows failed\n");
  1121. return -1;
  1122. }
  1123. } else {
  1124. if (ul_dbf.query(ul_dbh, 0, 0, 0, columns, 0, (use_domain)?(6):(5), 0,
  1125. &res) < 0) {
  1126. LM_ERR("db_query failed\n");
  1127. return -1;
  1128. }
  1129. }
  1130. if (RES_ROW_N(res) == 0) {
  1131. LM_DBG("location attrs table is empty\n");
  1132. ul_dbf.free_result(ul_dbh, res);
  1133. return 0;
  1134. }
  1135. n = 0;
  1136. do {
  1137. LM_DBG("loading records - cycle [%d]\n", ++n);
  1138. for(i = 0; i < RES_ROW_N(res); i++) {
  1139. row = RES_ROWS(res) + i;
  1140. user.s = (char*)VAL_STRING(ROW_VALUES(row));
  1141. if (VAL_NULL(ROW_VALUES(row)) || user.s==0 || user.s[0]==0) {
  1142. LM_CRIT("empty username record in table %s...skipping\n",
  1143. _d->name->s);
  1144. continue;
  1145. }
  1146. user.len = strlen(user.s);
  1147. ruid.s = (char*)VAL_STRING(ROW_VALUES(row) + 1);
  1148. ruid.len = strlen(ruid.s);
  1149. aname.s = (char*)VAL_STRING(ROW_VALUES(row) + 2);
  1150. aname.len = strlen(aname.s);
  1151. avalue.s = (char*)VAL_STRING(ROW_VALUES(row) + 4);
  1152. avalue.len = strlen(avalue.s);
  1153. memset(&aval, 0, sizeof(sr_xval_t));
  1154. if(VAL_INT(ROW_VALUES(row)+3)==0) {
  1155. /* string value */
  1156. aval.v.s = avalue;
  1157. aval.type = SR_XTYPE_STR;
  1158. } else if(VAL_INT(ROW_VALUES(row)+3)==1) {
  1159. /* int value */
  1160. str2sint(&avalue, &aval.v.i);
  1161. aval.type = SR_XTYPE_INT;
  1162. } else {
  1163. /* unknown type - ignore */
  1164. continue;
  1165. }
  1166. if (use_domain) {
  1167. domain.s = (char*)VAL_STRING(ROW_VALUES(row) + 5);
  1168. if (VAL_NULL(ROW_VALUES(row)+5) || domain.s==0 || domain.s[0]==0){
  1169. LM_CRIT("empty domain record for user %.*s...skipping\n",
  1170. user.len, user.s);
  1171. continue;
  1172. }
  1173. domain.len = strlen(domain.s);
  1174. /* user.s cannot be NULL - checked previosly */
  1175. suri.len = snprintf(uri, MAX_URI_SIZE, "%.*s@%s",
  1176. user.len, user.s, domain.s);
  1177. suri.s = uri;
  1178. if (suri.s[suri.len]!=0) {
  1179. LM_CRIT("URI '%.*s@%s' longer than %d\n", user.len, user.s,
  1180. domain.s, MAX_URI_SIZE);
  1181. continue;
  1182. }
  1183. } else {
  1184. suri = user;
  1185. }
  1186. if (get_urecord_by_ruid(_d, ul_get_aorhash(&suri), &ruid, &r, &c) < 0) {
  1187. /* delete attrs records from db table */
  1188. LM_INFO("no contact record for this ruid\n");
  1189. uldb_delete_attrs(_d->name, &user, &domain, &ruid);
  1190. } else {
  1191. /* add xavp to contact */
  1192. if(c->xavp==NULL) {
  1193. if(xavp_add_xavp_value(&ul_xavp_contact_name, &aname,
  1194. &aval, &c->xavp)==NULL)
  1195. LM_INFO("cannot add first xavp to contact - ignoring\n");
  1196. } else {
  1197. if(c->xavp->val.type==SR_XTYPE_XAVP) {
  1198. if(xavp_add_value(&aname, &aval, &c->xavp->val.v.xavp)==NULL)
  1199. LM_INFO("cannot add values to contact xavp\n");
  1200. }
  1201. }
  1202. /* get_urecord_by_ruid() locks the slot */
  1203. unlock_udomain(_d, &suri);
  1204. }
  1205. }
  1206. if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
  1207. if(ul_dbf.fetch_result(ul_dbh, &res, ul_fetch_rows)<0) {
  1208. LM_ERR("fetching rows (1) failed\n");
  1209. ul_dbf.free_result(ul_dbh, res);
  1210. return -1;
  1211. }
  1212. } else {
  1213. break;
  1214. }
  1215. } while(RES_ROW_N(res)>0);
  1216. ul_dbf.free_result(ul_dbh, res);
  1217. #ifdef EXTRA_DEBUG
  1218. LM_NOTICE("load end time [%d]\n", (int)time(NULL));
  1219. #endif
  1220. return 0;
  1221. }