2 * Copyright (C) 2001-2003 FhG Fokus
4 * This file is part of Kamailio, a free SIP server.
6 * Kamailio is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version
11 * Kamailio is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 * \brief USRLOC - Usrloc contact handling functions
26 * - Module: \ref usrloc
31 #include "../../core/mem/shm_mem.h"
32 #include "../../core/ut.h"
33 #include "../../core/ip_addr.h"
34 #include "../../core/socket_info.h"
35 #include "../../core/dprint.h"
36 #include "../../lib/srdb1/db.h"
37 #include "usrloc_mod.h"
38 #include "ul_callback.h"
44 extern int ul_db_insert_null;
46 static int ul_xavp_contact_clone = 1;
48 void ul_set_xavp_contact_clone(int v)
50 ul_xavp_contact_clone = v;
54 * \brief Store xavp list per contact
55 * \param _c contact structure
57 void ucontact_xavp_store(ucontact_t *_c)
62 if(ul_xavp_contact_clone == 0)
64 if(ul_xavp_contact_name.s==NULL)
66 /* remove old list if it is set -- update case */
67 if (_c->xavp) xavp_destroy_list(&_c->xavp);
68 xavp = xavp_get(&ul_xavp_contact_name, NULL);
71 /* clone the xavp found in core */
72 LM_DBG("trying to clone per contact xavps\n");
73 _c->xavp = xavp_clone_level_nodata(xavp);
77 int uldb_delete_attrs_ruid(str* _dname, str *_ruid);
80 * \brief Create a new contact structure
82 * \param _aor address of record
83 * \param _contact contact string
84 * \param _ci contact informations
85 * \return new created contact on success, 0 on failure
87 ucontact_t* new_ucontact(str* _dom, str* _aor, str* _contact, ucontact_info_t* _ci)
91 if(unlikely(_ci->ruid.len<=0)) {
92 LM_ERR("no ruid for aor: %.*s\n", _aor->len, ZSW(_aor->s));
96 c = (ucontact_t*)shm_malloc(sizeof(ucontact_t));
101 memset(c, 0, sizeof(ucontact_t));
103 if (shm_str_dup( &c->c, _contact) < 0) goto error;
104 if (shm_str_dup( &c->callid, _ci->callid) < 0) goto error;
105 if (shm_str_dup( &c->user_agent, _ci->user_agent) < 0) goto error;
107 if (_ci->received.s && _ci->received.len) {
108 if (shm_str_dup( &c->received, &_ci->received) < 0) goto error;
110 if (_ci->path && _ci->path->len) {
111 if (shm_str_dup( &c->path, _ci->path) < 0) goto error;
113 if (_ci->ruid.s && _ci->ruid.len) {
114 if (shm_str_dup( &c->ruid, &_ci->ruid) < 0) goto error;
116 if (_ci->instance.s && _ci->instance.len) {
117 if (shm_str_dup( &c->instance, &_ci->instance) < 0) goto error;
122 c->expires = _ci->expires;
127 c->flags = _ci->flags;
128 c->cflags = _ci->cflags;
129 c->methods = _ci->methods;
130 c->reg_id = _ci->reg_id;
131 c->last_modified = _ci->last_modified;
132 c->last_keepalive = time(NULL);
133 c->tcpconn_id = _ci->tcpconn_id;
134 c->server_id = _ci->server_id;
135 c->keepalive = (_ci->cflags & ul_nat_bflag)?1:0;
136 ucontact_xavp_store(c);
142 if (c->path.s) shm_free(c->path.s);
143 if (c->received.s) shm_free(c->received.s);
144 if (c->user_agent.s) shm_free(c->user_agent.s);
145 if (c->callid.s) shm_free(c->callid.s);
146 if (c->c.s) shm_free(c->c.s);
147 if (c->ruid.s) shm_free(c->ruid.s);
148 if (c->instance.s) shm_free(c->instance.s);
149 if (c->xavp) xavp_destroy_list(&c->xavp);
157 * \brief Free all memory associated with given contact structure
158 * \param _c freed contact
160 void free_ucontact(ucontact_t* _c)
163 if (_c->path.s) shm_free(_c->path.s);
164 if (_c->received.s) shm_free(_c->received.s);
165 if (_c->user_agent.s) shm_free(_c->user_agent.s);
166 if (_c->callid.s) shm_free(_c->callid.s);
167 if (_c->c.s) shm_free(_c->c.s);
168 if (_c->ruid.s) shm_free(_c->ruid.s);
169 if (_c->instance.s) shm_free(_c->instance.s);
170 if (_c->xavp) xavp_destroy_list(&_c->xavp);
176 * \brief Print contact, for debugging purposes only
177 * \param _f output file
178 * \param _c printed contact
180 void print_ucontact(FILE* _f, ucontact_t* _c)
186 case CS_NEW: st = "CS_NEW"; break;
187 case CS_SYNC: st = "CS_SYNC"; break;
188 case CS_DIRTY: st = "CS_DIRTY"; break;
189 default: st = "CS_UNKNOWN"; break;
192 fprintf(_f, "~~~Contact(%p)~~~\n", _c);
193 fprintf(_f, "domain : '%.*s'\n", _c->domain->len, ZSW(_c->domain->s));
194 fprintf(_f, "aor : '%.*s'\n", _c->aor->len, ZSW(_c->aor->s));
195 fprintf(_f, "Contact : '%.*s'\n", _c->c.len, ZSW(_c->c.s));
196 fprintf(_f, "Expires : ");
197 if (_c->expires == 0) {
198 fprintf(_f, "Permanent\n");
199 } else if (_c->expires == UL_EXPIRED_TIME) {
200 fprintf(_f, "Deleted\n");
201 } else if (t > _c->expires) {
202 fprintf(_f, "Expired\n");
204 fprintf(_f, "%u\n", (unsigned int)(_c->expires - t));
206 fprintf(_f, "q : %s\n", q2str(_c->q, 0));
207 fprintf(_f, "Call-ID : '%.*s'\n", _c->callid.len, ZSW(_c->callid.s));
208 fprintf(_f, "CSeq : %d\n", _c->cseq);
209 fprintf(_f, "User-Agent: '%.*s'\n",
210 _c->user_agent.len, ZSW(_c->user_agent.s));
211 fprintf(_f, "received : '%.*s'\n",
212 _c->received.len, ZSW(_c->received.s));
213 fprintf(_f, "Path : '%.*s'\n",
214 _c->path.len, ZSW(_c->path.s));
215 fprintf(_f, "State : %s\n", st);
216 fprintf(_f, "Flags : %u\n", _c->flags);
218 fprintf(_f, "Sock : %.*s (%p)\n",
219 _c->sock->sock_str.len,_c->sock->sock_str.s,_c->sock);
221 fprintf(_f, "Sock : none (null)\n");
223 fprintf(_f, "Methods : %u\n", _c->methods);
224 fprintf(_f, "ruid : '%.*s'\n",
225 _c->ruid.len, ZSW(_c->ruid.s));
226 fprintf(_f, "instance : '%.*s'\n",
227 _c->instance.len, ZSW(_c->instance.s));
228 fprintf(_f, "reg-id : %u\n", _c->reg_id);
229 fprintf(_f, "next : %p\n", _c->next);
230 fprintf(_f, "prev : %p\n", _c->prev);
231 fprintf(_f, "~~~/Contact~~~~\n");
236 * \brief Update existing contact in memory with new values
238 * \param _ci contact informations
239 * \return 0 on success, -1 on failure
241 int mem_update_ucontact(ucontact_t* _c, ucontact_info_t* _ci)
243 #define update_str(_old,_new) \
245 if ((_old)->len < (_new)->len) { \
246 ptr = (char*)shm_malloc((_new)->len); \
251 memcpy(ptr, (_new)->s, (_new)->len);\
252 if ((_old)->s) shm_free((_old)->s);\
255 memcpy((_old)->s, (_new)->s, (_new)->len);\
257 (_old)->len = (_new)->len;\
262 if(_ci->instance.s!=NULL && _ci->instance.len>0)
264 /* when we have instance set, update contact address */
265 if(_ci->c!=NULL && _ci->c->s!=NULL && _ci->c->len>0)
266 update_str( &_c->c, _ci->c);
269 /* refresh call-id */
270 if(_ci->callid!=NULL && _ci->callid->s!=NULL && _ci->callid->len>0)
271 update_str( &_c->callid, _ci->callid);
272 update_str( &_c->user_agent, _ci->user_agent);
274 if (_ci->received.s && _ci->received.len) {
275 update_str( &_c->received, &_ci->received);
277 if (_c->received.s) shm_free(_c->received.s);
279 _c->received.len = 0;
283 update_str( &_c->path, _ci->path);
285 if (_c->path.s) shm_free(_c->path.s);
290 ucontact_xavp_store(_c);
292 _c->sock = _ci->sock;
293 _c->expires = _ci->expires;
295 _c->cseq = _ci->cseq;
296 _c->methods = _ci->methods;
297 _c->last_modified = _ci->last_modified;
298 _c->last_keepalive = time(NULL);
299 _c->flags = _ci->flags;
300 _c->cflags = _ci->cflags;
301 _c->server_id = _ci->server_id;
302 _c->tcpconn_id = _ci->tcpconn_id;
308 /* ================ State related functions =============== */
311 * \brief Update state of the contact if we are using write-back scheme
312 * \param _c updated contact
314 void st_update_ucontact(ucontact_t* _c)
318 /* Contact is new and is not in the database yet,
319 * we remain in the same state here because the
320 * contact must be inserted later in the timer
325 /* For db mode 1 & 2 a modified contact needs to be
326 * updated also in the database, so transit into
327 * CS_DIRTY and let the timer to do the update
328 * again. For db mode 1 we try to update right
329 * now and if fails, let the timer to do the job
331 if (ul_db_mode == WRITE_BACK || ul_db_mode == WRITE_THROUGH) {
332 _c->state = CS_DIRTY;
337 /* Modification of dirty contact results in
338 * dirty contact again, don't change anything
346 * \brief Update state of the contact
347 * \param _c updated contact
348 * \return 1 if the contact should be deleted from memory immediately, 0 otherwise
350 int st_delete_ucontact(ucontact_t* _c)
354 /* Contact is new and isn't in the database
355 * yet, we can delete it from the memory
362 /* Contact is in the database,
363 * we cannot remove it from the memory
364 * directly, but we can set expires to zero
365 * and the timer will take care of deleting
366 * the contact from the memory as well as
369 if (ul_db_mode == WRITE_BACK) {
370 _c->expires = UL_EXPIRED_TIME;
373 /* WRITE_THROUGH or NO_DB -- we can
374 * remove it from memory immediately and
375 * the calling function would also remove
376 * it from the database if needed
382 return 0; /* Makes gcc happy */
387 * \brief Called when the timer is about to delete an expired contact
388 * \param _c expired contact
389 * \return 1 if the contact should be removed from the database and 0 otherwise
391 int st_expired_ucontact(ucontact_t* _c)
393 /* There is no need to change contact
394 * state, because the contact will
400 /* Contact is not in the database
401 * yet, remove it from memory only
407 /* Remove from database here */
411 return 0; /* Makes gcc happy */
416 * \brief Called when the timer is about flushing the contact, updates contact state
417 * \param _c flushed contact
418 * \return 1 if the contact should be inserted, 2 if update and 0 otherwise
420 int st_flush_ucontact(ucontact_t* _c)
424 /* Contact is new and is not in
425 * the database yet so we have
432 /* Contact is synchronized, do
438 /* Contact has been modified and
439 * is in the db already so we
446 return 0; /* Makes gcc happy */
450 /* ============== Database related functions ================ */
452 extern unsigned int _ul_max_partition;
453 static unsigned int _ul_partition_counter = 0;
456 * \brief Insert contact into the database
457 * \param _c inserted contact
458 * \return 0 on success, -1 on failure
460 int db_insert_ucontact(ucontact_t* _c)
467 if (_c->flags & FL_MEM) {
470 if(unlikely(_c->ruid.len<=0)) {
471 LM_ERR("invalid ruid for aor: %.*s\n",
472 _c->aor->len, ZSW(_c->aor->s));
477 keys[0] = &ul_user_col;
478 vals[0].type = DB1_STR;
480 vals[0].val.str_val.s = _c->aor->s;
481 vals[0].val.str_val.len = _c->aor->len;
483 keys[1] = &ul_contact_col;
484 vals[1].type = DB1_STR;
486 vals[1].val.str_val.s = _c->c.s;
487 vals[1].val.str_val.len = _c->c.len;
489 keys[2] = &ul_expires_col;
491 UL_DB_EXPIRES_SET(&vals[2], _c->expires);
494 vals[3].type = DB1_DOUBLE;
496 vals[3].val.double_val = q2double(_c->q);
498 keys[4] = &ul_callid_col;
499 vals[4].type = DB1_STR;
501 vals[4].val.str_val.s = _c->callid.s;
502 vals[4].val.str_val.len = _c->callid.len;
504 keys[5] = &ul_cseq_col;
505 vals[5].type = DB1_INT;
507 vals[5].val.int_val = _c->cseq;
509 keys[6] = &ul_flags_col;
510 vals[6].type = DB1_INT;
512 vals[6].val.bitmap_val = _c->flags;
514 keys[7] = &ul_cflags_col;
515 vals[7].type = DB1_INT;
517 vals[7].val.bitmap_val = _c->cflags;
519 keys[8] = &ul_user_agent_col;
520 vals[8].type = DB1_STR;
522 vals[8].val.str_val.s = _c->user_agent.s;
523 vals[8].val.str_val.len = _c->user_agent.len;
527 if (_c->received.s) {
528 keys[nr_cols] = &ul_received_col;
529 vals[nr_cols].type = DB1_STR;
530 vals[nr_cols].nul = 0;
531 vals[nr_cols].val.str_val.s = _c->received.s;
532 vals[nr_cols].val.str_val.len = _c->received.len;
534 } else if(ul_db_insert_null!=0) {
535 keys[nr_cols] = &ul_received_col;
536 vals[nr_cols].type = DB1_STR;
537 vals[nr_cols].nul = 1;
542 keys[nr_cols] = &ul_path_col;
543 vals[nr_cols].type = DB1_STR;
544 vals[nr_cols].nul = 0;
545 vals[nr_cols].val.str_val.s = _c->path.s;
546 vals[nr_cols].val.str_val.len = _c->path.len;
548 } else if(ul_db_insert_null!=0) {
549 keys[nr_cols] = &ul_path_col;
550 vals[nr_cols].type = DB1_STR;
551 vals[nr_cols].nul = 1;
556 keys[nr_cols] = &ul_sock_col;
557 vals[nr_cols].type = DB1_STR;
558 vals[nr_cols].val.str_val = _c->sock->sock_str;
559 vals[nr_cols].nul = 0;
561 } else if(ul_db_insert_null!=0) {
562 keys[nr_cols] = &ul_sock_col;
563 vals[nr_cols].type = DB1_STR;
564 vals[nr_cols].nul = 1;
568 if (_c->methods != 0xFFFFFFFF) {
569 keys[nr_cols] = &ul_methods_col;
570 vals[nr_cols].type = DB1_BITMAP;
571 vals[nr_cols].val.bitmap_val = _c->methods;
572 vals[nr_cols].nul = 0;
574 } else if(ul_db_insert_null!=0) {
575 keys[nr_cols] = &ul_methods_col;
576 vals[nr_cols].type = DB1_BITMAP;
577 vals[nr_cols].nul = 1;
581 keys[nr_cols] = &ul_last_mod_col;
582 vals[nr_cols].nul = 0;
583 UL_DB_EXPIRES_SET(&vals[nr_cols], _c->last_modified);
589 keys[nr_cols] = &ul_ruid_col;
590 vals[nr_cols].type = DB1_STR;
591 vals[nr_cols].nul = 0;
592 vals[nr_cols].val.str_val = _c->ruid;
594 } else if(ul_db_insert_null!=0) {
595 keys[nr_cols] = &ul_ruid_col;
596 vals[nr_cols].type = DB1_STR;
597 vals[nr_cols].nul = 1;
601 if(_c->instance.len>0)
603 keys[nr_cols] = &ul_instance_col;
604 vals[nr_cols].type = DB1_STR;
605 vals[nr_cols].nul = 0;
606 vals[nr_cols].val.str_val = _c->instance;
608 } else if(ul_db_insert_null!=0) {
609 keys[nr_cols] = &ul_instance_col;
610 vals[nr_cols].type = DB1_STR;
611 vals[nr_cols].nul = 1;
615 keys[nr_cols] = &ul_reg_id_col;
616 vals[nr_cols].type = DB1_INT;
617 vals[nr_cols].nul = 0;
618 vals[nr_cols].val.int_val = (int)_c->reg_id;
621 keys[nr_cols] = &ul_srv_id_col;
622 vals[nr_cols].type = DB1_INT;
623 vals[nr_cols].nul = 0;
624 vals[nr_cols].val.int_val = (int)_c->server_id;
627 keys[nr_cols] = &ul_con_id_col;
628 vals[nr_cols].type = DB1_INT;
629 vals[nr_cols].nul = 0;
630 vals[nr_cols].val.int_val = (int)_c->tcpconn_id;
633 keys[nr_cols] = &ul_keepalive_col;
634 vals[nr_cols].type = DB1_INT;
635 vals[nr_cols].nul = 0;
636 vals[nr_cols].val.int_val = (int)_c->keepalive;
639 keys[nr_cols] = &ul_partition_col;
640 vals[nr_cols].type = DB1_INT;
641 vals[nr_cols].nul = 0;
642 if(_ul_max_partition>0) {
643 vals[nr_cols].val.int_val = ((_ul_partition_counter++) + my_pid())
646 vals[nr_cols].val.int_val = 0;
652 keys[nr_cols] = &ul_domain_col;
653 vals[nr_cols].type = DB1_STR;
654 vals[nr_cols].nul = 0;
656 dom = memchr(_c->aor->s, '@', _c->aor->len);
658 vals[0].val.str_val.len = 0;
659 vals[nr_cols].val.str_val = *_c->aor;
661 vals[0].val.str_val.len = dom - _c->aor->s;
662 vals[nr_cols].val.str_val.s = dom + 1;
663 vals[nr_cols].val.str_val.len = _c->aor->s + _c->aor->len - dom - 1;
668 if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
670 LM_ERR("sql use_table failed for: %.*s\n",
671 (_c->domain->s)?_c->domain->len:0,
672 (_c->domain->s)?_c->domain->s:"");
674 LM_ERR("sql use_table failed - null\n");
679 if (ul_db_insert_update && ul_dbf.insert_update) {
680 if (ul_dbf.insert_update(ul_dbh, keys, vals, nr_cols) < 0) {
681 LM_ERR("inserting with update contact in db failed %.*s (%.*s)\n",
682 _c->aor->len, ZSW(_c->aor->s), _c->ruid.len, ZSW(_c->ruid.s));
686 if (ul_dbf.insert(ul_dbh, keys, vals, nr_cols) < 0) {
687 LM_ERR("inserting contact in db failed %.*s (%.*s)\n",
688 _c->aor->len, ZSW(_c->aor->s), _c->ruid.len, ZSW(_c->ruid.s));
693 if (ul_xavp_contact_name.s) {
694 uldb_insert_attrs(_c->domain, &vals[0].val.str_val,
695 &vals[nr_cols-1].val.str_val,
696 &_c->ruid, _c->xavp);
704 * \brief Update contact in the database by address
705 * \param _c updated contact
706 * \return 0 on success, -1 on failure
708 int db_update_ucontact_addr(ucontact_t* _c)
720 if (_c->flags & FL_MEM) {
724 keys1[n1] = &ul_user_col;
725 vals1[n1].type = DB1_STR;
727 vals1[n1].val.str_val = *_c->aor;
728 LM_DBG("aor:%.*s\n", vals1[n1].val.str_val.len, vals1[n1].val.str_val.s);
731 keys1[n1] = &ul_contact_col;
732 vals1[n1].type = DB1_STR;
734 vals1[n1].val.str_val = _c->c;
735 LM_DBG("contact:%.*s\n", vals1[n1].val.str_val.len, vals1[n1].val.str_val.s);
738 switch (ul_matching_mode) {
741 keys2[nr_cols2] = &ul_callid_col;
742 vals2[nr_cols2].type = DB1_STR;
743 vals2[nr_cols2].nul = 0;
744 vals2[nr_cols2].val.str_val = _c->callid;
747 keys2[nr_cols2] = &ul_path_col;
748 vals2[nr_cols2].type = DB1_STR;
749 if (_c->path.s == 0) {
750 vals2[nr_cols2].nul = 1;
752 vals2[nr_cols2].nul = 0;
753 vals2[nr_cols2].val.str_val = _c->path;
758 keys1[n1] = &ul_callid_col;
759 vals1[n1].type = DB1_STR;
761 vals1[n1].val.str_val = _c->callid;
762 LM_DBG("callid:%.*s\n", vals1[n1].val.str_val.len, vals1[n1].val.str_val.s);
765 keys2[nr_cols2] = &ul_path_col;
766 vals2[nr_cols2].type = DB1_STR;
767 if (_c->path.s == 0) {
768 vals2[nr_cols2].nul = 1;
770 vals2[nr_cols2].nul = 0;
771 vals2[nr_cols2].val.str_val = _c->path;
776 keys1[n1] = &ul_path_col;
777 vals1[n1].type = DB1_STR;
778 if (_c->path.s == 0) {
780 LM_DBG("path: NULL\n");
783 vals1[n1].val.str_val = _c->path;
784 LM_DBG("path:%.*s\n", vals1[n1].val.str_val.len, vals1[n1].val.str_val.s);
788 keys2[nr_cols2] = &ul_callid_col;
789 vals2[nr_cols2].type = DB1_STR;
790 vals2[nr_cols2].nul = 0;
791 vals2[nr_cols2].val.str_val = _c->callid;
795 LM_CRIT("unknown matching_mode %d\n", ul_matching_mode);
799 keys2[nr_cols2] = &ul_expires_col;
800 vals2[nr_cols2].nul = 0;
801 UL_DB_EXPIRES_SET(&vals2[nr_cols2], _c->expires);
804 keys2[nr_cols2] = &ul_q_col;
805 vals2[nr_cols2].type = DB1_DOUBLE;
806 vals2[nr_cols2].nul = 0;
807 vals2[nr_cols2].val.double_val = q2double(_c->q);
810 keys2[nr_cols2] = &ul_cseq_col;
811 vals2[nr_cols2].type = DB1_INT;
812 vals2[nr_cols2].nul = 0;
813 vals2[nr_cols2].val.int_val = _c->cseq;
816 keys2[nr_cols2] = &ul_flags_col;
817 vals2[nr_cols2].type = DB1_INT;
818 vals2[nr_cols2].nul = 0;
819 vals2[nr_cols2].val.bitmap_val = _c->flags;
822 keys2[nr_cols2] = &ul_cflags_col;
823 vals2[nr_cols2].type = DB1_INT;
824 vals2[nr_cols2].nul = 0;
825 vals2[nr_cols2].val.bitmap_val = _c->cflags;
828 keys2[nr_cols2] = &ul_user_agent_col;
829 vals2[nr_cols2].type = DB1_STR;
830 vals2[nr_cols2].nul = 0;
831 vals2[nr_cols2].val.str_val = _c->user_agent;
834 keys2[nr_cols2] = &ul_received_col;
835 vals2[nr_cols2].type = DB1_STR;
836 if (_c->received.s == 0) {
837 vals2[nr_cols2].nul = 1;
839 vals2[nr_cols2].nul = 0;
840 vals2[nr_cols2].val.str_val = _c->received;
844 keys2[nr_cols2] = &ul_sock_col;
845 vals2[nr_cols2].type = DB1_STR;
847 vals2[nr_cols2].val.str_val = _c->sock->sock_str;
848 vals2[nr_cols2].nul = 0;
850 vals2[nr_cols2].nul = 1;
854 keys2[nr_cols2] = &ul_methods_col;
855 vals2[nr_cols2].type = DB1_BITMAP;
856 if (_c->methods == 0xFFFFFFFF) {
857 vals2[nr_cols2].nul = 1;
859 vals2[nr_cols2].val.bitmap_val = _c->methods;
860 vals2[nr_cols2].nul = 0;
864 keys2[nr_cols2] = &ul_last_mod_col;
865 vals2[nr_cols2].nul = 0;
866 UL_DB_EXPIRES_SET(&vals2[nr_cols2], _c->last_modified);
869 keys2[nr_cols2] = &ul_ruid_col;
870 vals2[nr_cols2].type = DB1_STR;
873 vals2[nr_cols2].nul = 0;
874 vals2[nr_cols2].val.str_val = _c->ruid;
876 vals2[nr_cols2].nul = 1;
880 keys2[nr_cols2] = &ul_instance_col;
881 vals2[nr_cols2].type = DB1_STR;
882 if(_c->instance.len>0)
884 vals2[nr_cols2].nul = 0;
885 vals2[nr_cols2].val.str_val = _c->instance;
887 vals2[nr_cols2].nul = 1;
891 keys2[nr_cols2] = &ul_reg_id_col;
892 vals2[nr_cols2].type = DB1_INT;
893 vals2[nr_cols2].nul = 0;
894 vals2[nr_cols2].val.int_val = (int)_c->reg_id;
897 keys2[nr_cols2] = &ul_srv_id_col;
898 vals2[nr_cols2].type = DB1_INT;
899 vals2[nr_cols2].nul = 0;
900 vals2[nr_cols2].val.int_val = (int)_c->server_id;
903 keys2[nr_cols2] = &ul_con_id_col;
904 vals2[nr_cols2].type = DB1_INT;
905 vals2[nr_cols2].nul = 0;
906 vals2[nr_cols2].val.int_val = (int)_c->tcpconn_id;
909 keys2[nr_cols2] = &ul_keepalive_col;
910 vals2[nr_cols2].type = DB1_INT;
911 vals2[nr_cols2].nul = 0;
912 vals2[nr_cols2].val.int_val = (int)_c->keepalive;
915 keys2[nr_cols2] = &ul_contact_col;
916 vals2[nr_cols2].type = DB1_STR;
917 vals2[nr_cols2].nul = 0;
918 vals2[nr_cols2].val.str_val = _c->c;
919 LM_DBG("contact:%.*s\n", vals2[nr_cols2].val.str_val.len, vals2[nr_cols2].val.str_val.s);
923 keys1[n1] = &ul_domain_col;
924 vals1[n1].type = DB1_STR;
926 dom = memchr(_c->aor->s, '@', _c->aor->len);
928 vals1[0].val.str_val.len = 0;
929 vals1[n1].val.str_val = *_c->aor;
931 vals1[0].val.str_val.len = dom - _c->aor->s;
932 vals1[n1].val.str_val.s = dom + 1;
933 vals1[n1].val.str_val.len = _c->aor->s + _c->aor->len - dom - 1;
938 if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
939 LM_ERR("sql use_table failed\n");
943 if (ul_dbf.update(ul_dbh, keys1, 0, vals1, keys2, vals2, n1,
945 LM_ERR("updating database failed\n");
949 if (ul_db_check_update==1 && ul_dbf.affected_rows) {
950 /* supposed to be an UPDATE, but if affected rows is 0, then try
952 if(ul_dbf.affected_rows(ul_dbh)==0) {
953 LM_DBG("affected rows by UPDATE was 0, doing an INSERT\n");
954 if(db_insert_ucontact(_c)<0)
958 /* delete old db attrs and add the current list */
959 if (ul_xavp_contact_name.s) {
961 uldb_delete_attrs(_c->domain, &vals1[0].val.str_val,
962 &vals1[n1-1].val.str_val, &_c->ruid);
963 uldb_insert_attrs(_c->domain, &vals1[0].val.str_val,
964 &vals1[n1-1].val.str_val,
965 &_c->ruid, _c->xavp);
967 uldb_delete_attrs(_c->domain, &vals1[0].val.str_val,
969 uldb_insert_attrs(_c->domain, &vals1[0].val.str_val,
970 NULL, &_c->ruid, _c->xavp);
978 * \brief Update contact in the database by ruid
979 * \param _c updated contact
980 * \return 0 on success, -1 on failure
982 int db_update_ucontact_ruid(ucontact_t* _c)
995 if (_c->flags & FL_MEM) {
999 if(_c->ruid.len<=0) {
1000 LM_ERR("updating record in database failed - empty ruid\n");
1005 keys1[n1] = &ul_ruid_col;
1006 vals1[n1].type = DB1_STR;
1008 vals1[n1].val.str_val = _c->ruid;
1009 LM_DBG("ruid:%.*s\n", vals1[n1].val.str_val.len, vals1[n1].val.str_val.s);
1013 keys2[n2] = &ul_expires_col;
1015 UL_DB_EXPIRES_SET(&vals2[n2], _c->expires);
1018 keys2[n2] = &ul_q_col;
1019 vals2[n2].type = DB1_DOUBLE;
1021 vals2[n2].val.double_val = q2double(_c->q);
1024 keys2[n2] = &ul_cseq_col;
1025 vals2[n2].type = DB1_INT;
1027 vals2[n2].val.int_val = _c->cseq;
1030 keys2[n2] = &ul_flags_col;
1031 vals2[n2].type = DB1_INT;
1033 vals2[n2].val.bitmap_val = _c->flags;
1036 keys2[n2] = &ul_cflags_col;
1037 vals2[n2].type = DB1_INT;
1039 vals2[n2].val.bitmap_val = _c->cflags;
1042 keys2[n2] = &ul_user_agent_col;
1043 vals2[n2].type = DB1_STR;
1045 vals2[n2].val.str_val = _c->user_agent;
1048 keys2[n2] = &ul_received_col;
1049 vals2[n2].type = DB1_STR;
1050 if (_c->received.s == 0) {
1054 vals2[n2].val.str_val = _c->received;
1058 keys2[n2] = &ul_path_col;
1059 vals2[n2].type = DB1_STR;
1060 if (_c->path.s == 0) {
1064 vals2[n2].val.str_val = _c->path;
1068 keys2[n2] = &ul_sock_col;
1069 vals2[n2].type = DB1_STR;
1071 vals2[n2].val.str_val = _c->sock->sock_str;
1078 keys2[n2] = &ul_methods_col;
1079 vals2[n2].type = DB1_BITMAP;
1080 if (_c->methods == 0xFFFFFFFF) {
1083 vals2[n2].val.bitmap_val = _c->methods;
1088 keys2[n2] = &ul_last_mod_col;
1090 UL_DB_EXPIRES_SET(&vals2[n2], _c->last_modified);
1093 keys2[n2] = &ul_callid_col;
1094 vals2[n2].type = DB1_STR;
1096 vals2[n2].val.str_val = _c->callid;
1099 keys2[n2] = &ul_instance_col;
1100 vals2[n2].type = DB1_STR;
1101 if(_c->instance.len>0)
1104 vals2[n2].val.str_val = _c->instance;
1110 keys2[n2] = &ul_reg_id_col;
1111 vals2[n2].type = DB1_INT;
1113 vals2[n2].val.int_val = (int)_c->reg_id;
1116 keys2[n2] = &ul_srv_id_col;
1117 vals2[n2].type = DB1_INT;
1119 vals2[n2].val.int_val = (int)_c->server_id;
1122 keys2[n2] = &ul_con_id_col;
1123 vals2[n2].type = DB1_INT;
1125 vals2[n2].val.int_val = (int)_c->tcpconn_id;
1128 keys2[n2] = &ul_keepalive_col;
1129 vals2[n2].type = DB1_INT;
1131 vals2[n2].val.int_val = (int)_c->keepalive;
1134 keys2[n2] = &ul_contact_col;
1135 vals2[n2].type = DB1_STR;
1137 vals2[n2].val.str_val = _c->c;
1138 LM_DBG("contact:%.*s\n", vals2[n2].val.str_val.len, vals2[n2].val.str_val.s);
1141 if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
1142 LM_ERR("sql use_table failed\n");
1146 if (ul_dbf.update(ul_dbh, keys1, 0, vals1, keys2, vals2, n1, n2) < 0) {
1147 LM_ERR("updating database failed\n");
1151 if (ul_db_check_update==1 && ul_dbf.affected_rows) {
1152 /* supposed to be an UPDATE, but if affected rows is 0, then try
1153 * to do an INSERT */
1154 if(ul_dbf.affected_rows(ul_dbh)==0) {
1155 LM_DBG("affected rows by UPDATE was 0, doing an INSERT\n");
1156 if(db_insert_ucontact(_c)<0)
1161 /* delete old db attrs and add the current list */
1162 if (ul_xavp_contact_name.s) {
1164 if (ul_use_domain) {
1165 adomain.s = memchr(_c->aor->s, '@', _c->aor->len);
1170 auser.len = adomain.s - _c->aor->s;
1172 adomain.len = _c->aor->s +
1173 _c->aor->len - adomain.s;
1176 uldb_delete_attrs(_c->domain, &auser,
1177 &adomain, &_c->ruid);
1178 uldb_insert_attrs(_c->domain, &auser,
1179 &adomain, &_c->ruid, _c->xavp);
1181 uldb_delete_attrs(_c->domain, &auser,
1183 uldb_insert_attrs(_c->domain, &auser,
1184 NULL, &_c->ruid, _c->xavp);
1192 * \brief Update contact in the database by instance reg_id
1193 * \param _c updated contact
1194 * \return 0 on success, -1 on failure
1196 int db_update_ucontact_instance(ucontact_t* _c)
1209 if (_c->flags & FL_MEM) {
1213 if(_c->instance.len<=0) {
1214 LM_ERR("updating record in database failed - empty instance\n");
1219 keys1[n1] = &ul_user_col;
1220 vals1[n1].type = DB1_STR;
1222 vals1[n1].val.str_val = *_c->aor;
1223 LM_DBG("aor:%.*s\n", vals1[n1].val.str_val.len, vals1[n1].val.str_val.s);
1226 keys1[n1] = &ul_instance_col;
1227 vals1[n1].type = DB1_STR;
1229 vals1[n1].val.str_val = _c->instance;
1230 LM_DBG("instance:%.*s\n", vals1[n1].val.str_val.len, vals1[n1].val.str_val.s);
1233 keys1[n1] = &ul_reg_id_col;
1234 vals1[n1].type = DB1_INT;
1236 vals1[n1].val.int_val = (int)_c->reg_id;
1237 LM_DBG("reg-id:%d\n", vals1[n1].val.int_val);
1241 keys2[n2] = &ul_expires_col;
1243 UL_DB_EXPIRES_SET(&vals2[n2], _c->expires);
1246 keys2[n2] = &ul_q_col;
1247 vals2[n2].type = DB1_DOUBLE;
1249 vals2[n2].val.double_val = q2double(_c->q);
1252 keys2[n2] = &ul_cseq_col;
1253 vals2[n2].type = DB1_INT;
1255 vals2[n2].val.int_val = _c->cseq;
1258 keys2[n2] = &ul_flags_col;
1259 vals2[n2].type = DB1_INT;
1261 vals2[n2].val.bitmap_val = _c->flags;
1264 keys2[n2] = &ul_cflags_col;
1265 vals2[n2].type = DB1_INT;
1267 vals2[n2].val.bitmap_val = _c->cflags;
1270 keys2[n2] = &ul_user_agent_col;
1271 vals2[n2].type = DB1_STR;
1273 vals2[n2].val.str_val = _c->user_agent;
1276 keys2[n2] = &ul_received_col;
1277 vals2[n2].type = DB1_STR;
1278 if (_c->received.s == 0) {
1282 vals2[n2].val.str_val = _c->received;
1286 keys2[n2] = &ul_path_col;
1287 vals2[n2].type = DB1_STR;
1288 if (_c->path.s == 0) {
1292 vals2[n2].val.str_val = _c->path;
1296 keys2[n2] = &ul_sock_col;
1297 vals2[n2].type = DB1_STR;
1299 vals2[n2].val.str_val = _c->sock->sock_str;
1306 keys2[n2] = &ul_methods_col;
1307 vals2[n2].type = DB1_BITMAP;
1308 if (_c->methods == 0xFFFFFFFF) {
1311 vals2[n2].val.bitmap_val = _c->methods;
1316 keys2[n2] = &ul_last_mod_col;
1318 UL_DB_EXPIRES_SET(&vals2[n2], _c->last_modified);
1321 keys2[n2] = &ul_callid_col;
1322 vals2[n2].type = DB1_STR;
1324 vals2[n2].val.str_val = _c->callid;
1327 keys2[n2] = &ul_srv_id_col;
1328 vals2[n2].type = DB1_INT;
1330 vals2[n2].val.bitmap_val = _c->server_id;
1333 keys2[n2] = &ul_con_id_col;
1334 vals2[n2].type = DB1_INT;
1336 vals2[n2].val.bitmap_val = _c->tcpconn_id;
1339 keys2[n2] = &ul_keepalive_col;
1340 vals2[n2].type = DB1_INT;
1342 vals2[n2].val.bitmap_val = _c->keepalive;
1345 keys2[n2] = &ul_contact_col;
1346 vals2[n2].type = DB1_STR;
1348 vals2[n2].val.str_val.s = _c->c.s;
1349 vals2[n2].val.str_val.len = _c->c.len;
1350 LM_DBG("contact:%.*s\n", vals2[n2].val.str_val.len, vals2[n2].val.str_val.s);
1354 if (ul_use_domain) {
1355 keys1[n1] = &ul_domain_col;
1356 vals1[n1].type = DB1_STR;
1358 adomain.s = memchr(_c->aor->s, '@', _c->aor->len);
1360 vals1[0].val.str_val.len = 0;
1361 vals1[n1].val.str_val = *_c->aor;
1365 vals1[0].val.str_val.len = adomain.s - _c->aor->s;
1366 vals1[n1].val.str_val.s = adomain.s + 1;
1367 vals1[n1].val.str_val.len = _c->aor->s + _c->aor->len - adomain.s - 1;
1368 auser.len = adomain.s - _c->aor->s;
1370 adomain.len = _c->aor->s +
1371 _c->aor->len - adomain.s;
1376 if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
1377 LM_ERR("sql use_table failed\n");
1381 if (ul_dbf.update(ul_dbh, keys1, 0, vals1, keys2, vals2, n1, n2) < 0) {
1382 LM_ERR("updating database failed\n");
1386 if (ul_db_check_update==1 && ul_dbf.affected_rows) {
1387 LM_DBG("update affected_rows 0\n");
1388 /* supposed to be an UPDATE, but if affected rows is 0, then try
1389 * to do an INSERT */
1390 if(ul_dbf.affected_rows(ul_dbh)==0) {
1391 LM_DBG("affected rows by UPDATE was 0, doing an INSERT\n");
1392 if(db_insert_ucontact(_c)<0)
1397 /* delete old db attrs and add the current list */
1398 if (ul_xavp_contact_name.s) {
1399 if (ul_use_domain) {
1400 uldb_delete_attrs(_c->domain, &auser,
1401 &adomain, &_c->ruid);
1402 uldb_insert_attrs(_c->domain, &auser,
1403 &adomain, &_c->ruid, _c->xavp);
1405 uldb_delete_attrs(_c->domain, &auser,
1407 uldb_insert_attrs(_c->domain, &auser,
1408 NULL, &_c->ruid, _c->xavp);
1416 * \brief Update contact in the database
1417 * \param _c updated contact
1418 * \return 0 on success, -1 on failure
1420 int db_update_ucontact(ucontact_t* _c)
1422 if(ul_db_ops_ruid==0)
1423 if (_c->instance.len<=0) {
1424 return db_update_ucontact_addr(_c);
1427 return db_update_ucontact_instance(_c);
1430 return db_update_ucontact_ruid(_c);
1434 * \brief Delete contact from the database by address
1435 * \param _c deleted contact
1436 * \return 0 on success, -1 on failure
1438 int db_delete_ucontact_addr(ucontact_t* _c)
1445 if (_c->flags & FL_MEM) {
1451 keys[n] = &ul_user_col;
1452 vals[n].type = DB1_STR;
1454 vals[n].val.str_val = *_c->aor;
1457 keys[n] = &ul_contact_col;
1458 vals[n].type = DB1_STR;
1460 vals[n].val.str_val = _c->c;
1463 switch (ul_matching_mode) {
1466 case CONTACT_CALLID:
1467 keys[n] = &ul_callid_col;
1468 vals[n].type = DB1_STR;
1470 vals[n].val.str_val = _c->callid;
1474 keys[n] = &ul_path_col;
1475 vals[n].type = DB1_STR;
1476 if (_c->path.s == 0) {
1480 vals[n].val.str_val = _c->path;
1485 LM_CRIT("unknown matching_mode %d\n", ul_matching_mode);
1489 if (ul_use_domain) {
1490 keys[n] = &ul_domain_col;
1491 vals[n].type = DB1_STR;
1493 dom = memchr(_c->aor->s, '@', _c->aor->len);
1495 vals[0].val.str_val.len = 0;
1496 vals[n].val.str_val = *_c->aor;
1498 vals[0].val.str_val.len = dom - _c->aor->s;
1499 vals[n].val.str_val.s = dom + 1;
1500 vals[n].val.str_val.len = _c->aor->s +
1501 _c->aor->len - dom - 1;
1503 uldb_delete_attrs(_c->domain, &vals[0].val.str_val,
1504 &vals[n].val.str_val, &_c->ruid);
1507 uldb_delete_attrs(_c->domain, &vals[0].val.str_val,
1511 if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
1512 LM_ERR("sql use_table failed\n");
1516 if (ul_dbf.delete(ul_dbh, keys, 0, vals, n) < 0) {
1517 LM_ERR("deleting from database failed\n");
1525 * \brief Delete contact from the database by ruid
1526 * \param _c deleted contact
1527 * \return 0 on success, -1 on failure
1529 int db_delete_ucontact_ruid(ucontact_t* _c)
1535 if (_c->flags & FL_MEM) {
1539 if(_c->ruid.len<=0) {
1540 LM_ERR("deleting from database failed - empty ruid\n");
1545 keys[n] = &ul_ruid_col;
1546 vals[n].type = DB1_STR;
1548 vals[n].val.str_val = _c->ruid;
1551 uldb_delete_attrs_ruid(_c->domain, &_c->ruid);
1553 if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
1554 LM_ERR("sql use_table failed\n");
1558 if (ul_dbf.delete(ul_dbh, keys, 0, vals, n) < 0) {
1559 LM_ERR("deleting from database failed\n");
1567 * \brief Delete contact from the database
1568 * \param _c deleted contact
1569 * \return 0 on success, -1 on failure
1571 int db_delete_ucontact(ucontact_t* _c)
1573 if(ul_db_ops_ruid==0)
1574 return db_delete_ucontact_addr(_c);
1576 return db_delete_ucontact_ruid(_c);
1580 * \brief Remove a contact from list belonging to a certain record
1581 * \param _r record the contact belongs
1582 * \param _c removed contact
1584 static inline void unlink_contact(struct urecord* _r, ucontact_t* _c)
1587 _c->prev->next = _c->next;
1589 _c->next->prev = _c->prev;
1592 _r->contacts = _c->next;
1601 * \brief Insert a new contact into the list at the correct position
1602 * \param _r record that holds the sorted contacts
1603 * \param _c new contact
1605 static inline void update_contact_pos(struct urecord* _r, ucontact_t* _c)
1607 ucontact_t *pos, *ppos;
1609 if (ul_desc_time_order) {
1610 /* order by time - first the newest */
1613 unlink_contact(_r, _c);
1614 /* insert it at the beginning */
1615 _c->next = _r->contacts;
1617 _r->contacts->prev = _c;
1620 /* order by q - first the smaller q */
1621 if ( (_c->prev==0 || _c->q<=_c->prev->q)
1622 && (_c->next==0 || _c->q>=_c->next->q) )
1624 /* need to move , but where? */
1625 unlink_contact(_r, _c);
1626 _c->next = _c->prev = 0;
1627 for(pos=_r->contacts,ppos=0;pos&&pos->q<_c->q;ppos=pos,pos=pos->next);
1635 _c->prev = pos->prev;
1636 pos->prev->next = _c;
1649 * \brief helper function for update_ucontact
1651 * \return 0 on success, -1 on failure
1653 static inline int update_contact_db(ucontact_t* _c)
1657 if (ul_db_update_as_insert)
1658 res = db_insert_ucontact(_c);
1660 res = db_update_ucontact(_c);
1663 LM_ERR("failed to update database\n");
1666 _c->state = CS_SYNC;
1672 * \brief Update ucontact with new values
1673 * \param _r record the contact belongs to
1674 * \param _c updated contact
1675 * \param _ci new contact informations
1676 * \return 0 on success, -1 on failure
1678 int update_ucontact(struct urecord* _r, ucontact_t* _c, ucontact_info_t* _ci)
1681 /* we have to update memory in any case, but database directly
1682 * only in db_mode 1 */
1683 if (mem_update_ucontact( _c, _ci) < 0) {
1684 LM_ERR("failed to update memory\n");
1688 if (ul_db_mode==DB_ONLY) {
1689 /* urecord is static generate a copy for later */
1690 if (_r) memcpy(&_ur, _r, sizeof(struct urecord));
1691 if (update_contact_db(_c) < 0) return -1;
1694 /* run callbacks for UPDATE event */
1695 if (exists_ulcb_type(UL_CONTACT_UPDATE))
1697 LM_DBG("exists callback for type= UL_CONTACT_UPDATE\n");
1698 run_ul_callbacks( UL_CONTACT_UPDATE, _c);
1702 if (ul_db_mode!=DB_ONLY) {
1703 update_contact_pos( _r, _c);
1705 /* urecord was static restore copy */
1706 memcpy(_r, &_ur, sizeof(struct urecord));
1710 st_update_ucontact(_c);
1712 if (ul_db_mode == WRITE_THROUGH) {
1713 if (update_contact_db(_c) < 0) return -1;
1719 * \brief Load all location attributes from a udomain
1721 * Load all location attributes from a udomain, useful to populate the
1722 * memory cache on startup.
1723 * \param _dname loaded domain name
1724 * \param _user sip username
1725 * \param _domain sip domain
1726 * \param _ruid usrloc record unique id
1727 * \return 0 on success, -1 on failure
1729 int uldb_delete_attrs(str* _dname, str *_user, str *_domain, str *_ruid)
1736 if(ul_db_ops_ruid==1)
1737 return uldb_delete_attrs_ruid(_dname, _ruid);
1739 LM_DBG("trying to delete location attributes\n");
1741 if(ul_xavp_contact_name.s==NULL) {
1742 /* feature disabled by mod param */
1746 if(_dname->len+6>=64) {
1747 LM_ERR("attributes table name is too big\n");
1750 strncpy(tname_buf, _dname->s, _dname->len);
1751 tname_buf[_dname->len] = '\0';
1752 strcat(tname_buf, "_attrs");
1753 tname.s = tname_buf;
1754 tname.len = _dname->len + 6;
1756 keys[0] = &ulattrs_user_col;
1757 keys[1] = &ulattrs_ruid_col;
1758 keys[2] = &ulattrs_domain_col;
1760 vals[0].type = DB1_STR;
1762 vals[0].val.str_val = *_user;
1764 vals[1].type = DB1_STR;
1766 vals[1].val.str_val = *_ruid;
1768 if (ul_use_domain) {
1769 vals[2].type = DB1_STR;
1771 vals[2].val.str_val = *_domain;
1774 if (ul_dbf.use_table(ul_dbh, &tname) < 0) {
1775 LM_ERR("sql use_table failed\n");
1779 if (ul_dbf.delete(ul_dbh, keys, 0, vals, (ul_use_domain) ? (3) : (2)) < 0) {
1780 LM_ERR("deleting from database failed\n");
1788 * \brief Delete all location attributes from a udomain by ruid
1790 * \param _dname loaded domain name
1791 * \param _ruid usrloc record unique id
1792 * \return 0 on success, -1 on failure
1794 int uldb_delete_attrs_ruid(str* _dname, str *_ruid)
1801 LM_DBG("trying to delete location attributes\n");
1803 if(ul_xavp_contact_name.s==NULL) {
1804 /* feature disabled by mod param */
1808 if(_dname->len+6>=64) {
1809 LM_ERR("attributes table name is too big\n");
1812 strncpy(tname_buf, _dname->s, _dname->len);
1813 tname_buf[_dname->len] = '\0';
1814 strcat(tname_buf, "_attrs");
1815 tname.s = tname_buf;
1816 tname.len = _dname->len + 6;
1818 keys[0] = &ulattrs_ruid_col;
1820 vals[0].type = DB1_STR;
1822 vals[0].val.str_val = *_ruid;
1824 if (ul_dbf.use_table(ul_dbh, &tname) < 0) {
1825 LM_ERR("sql use_table failed\n");
1829 if (ul_dbf.delete(ul_dbh, keys, 0, vals, 1) < 0) {
1830 LM_ERR("deleting from database failed\n");
1838 * \brief Insert contact attributes into the database
1839 * \param _dname loaded domain name
1840 * \param _user sip username
1841 * \param _domain sip domain
1842 * \param _ruid record unique id
1843 * \param _xhead head of xavp list
1844 * \return 0 on success, -1 on failure
1846 int uldb_insert_attrs(str *_dname, str *_user, str *_domain,
1847 str *_ruid, sr_xavp_t *_xhead)
1857 LM_DBG("trying to insert location attributes\n");
1859 if(ul_xavp_contact_name.s==NULL) {
1860 /* feature disabled by mod param */
1861 LM_DBG("location attributes disabled\n");
1865 if(_xhead==NULL || _xhead->val.type!=SR_XTYPE_XAVP
1866 || _xhead->val.v.xavp==NULL) {
1867 /* nothing to write */
1868 LM_DBG("no location attributes\n");
1872 if(_dname->len+6>=64) {
1873 LM_ERR("attributes table name is too big\n");
1876 strncpy(tname_buf, _dname->s, _dname->len);
1877 tname_buf[_dname->len] = '\0';
1878 strcat(tname_buf, "_attrs");
1879 tname.s = tname_buf;
1880 tname.len = _dname->len + 6;
1882 if (ul_dbf.use_table(ul_dbh, &tname) < 0) {
1883 LM_ERR("sql use_table failed for %.*s\n", tname.len, tname.s);
1887 keys[0] = &ulattrs_user_col;
1888 keys[1] = &ulattrs_ruid_col;
1889 keys[2] = &ulattrs_last_mod_col;
1890 keys[3] = &ulattrs_aname_col;
1891 keys[4] = &ulattrs_atype_col;
1892 keys[5] = &ulattrs_avalue_col;
1893 keys[6] = &ulattrs_domain_col;
1895 vals[0].type = DB1_STR;
1897 vals[0].val.str_val = *_user;
1899 vals[1].type = DB1_STR;
1901 vals[1].val.str_val = *_ruid;
1904 UL_DB_EXPIRES_SET(&vals[2], time(NULL));
1906 if (ul_use_domain && _domain!=NULL && _domain->s!=NULL) {
1908 vals[6].type = DB1_STR;
1910 vals[6].val.str_val = *_domain;
1916 for(xavp=_xhead->val.v.xavp; xavp; xavp=xavp->next) {
1917 vals[3].type = DB1_STR;
1919 vals[3].val.str_val = xavp->name;
1921 vals[4].type = DB1_INT;
1923 if(xavp->val.type==SR_XTYPE_STR) {
1924 vals[4].val.int_val = 0;
1925 avalue = xavp->val.v.s;
1926 } else if(xavp->val.type==SR_XTYPE_INT) {
1927 vals[4].val.int_val = 1;
1928 avalue.s = sint2str((long)xavp->val.v.i, &avalue.len);
1933 vals[5].type = DB1_STR;
1935 vals[5].val.str_val = avalue;
1937 if (ul_dbf.insert(ul_dbh, keys, vals, nr_cols) < 0) {
1938 LM_ERR("inserting contact in db failed\n");