256d9530c2da230fab61d6504e7a214a1a5005d9
[kamailio] / src / modules / usrloc / ucontact.c
1 /*
2  * Copyright (C) 2001-2003 FhG Fokus
3  *
4  * This file is part of Kamailio, a free SIP server.
5  *
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
10  *
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.
15  *
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
19  *
20  */
21
22 /*! \file
23  *  \brief USRLOC - Usrloc contact handling functions
24  *  \ingroup usrloc
25  *
26  * - Module: \ref usrloc
27  */
28
29 #include "ucontact.h"
30 #include <string.h>             /* memcpy */
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"
39 #include "usrloc.h"
40 #include "urecord.h"
41 #include "ucontact.h"
42 #include "usrloc.h"
43
44 extern int ul_db_insert_null;
45
46 static int ul_xavp_contact_clone = 1;
47
48 void ul_set_xavp_contact_clone(int v)
49 {
50         ul_xavp_contact_clone = v;
51 }
52
53 /*!
54  * \brief Store xavp list per contact
55  * \param _c contact structure
56  */
57 void ucontact_xavp_store(ucontact_t *_c)
58 {
59         sr_xavp_t *xavp;
60         if(_c==NULL)
61                 return;
62         if(ul_xavp_contact_clone == 0)
63                 return;
64         if(ul_xavp_contact_name.s==NULL)
65                 return;
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);
69         if(xavp==NULL)
70                 return;
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);
74         return;
75 }
76
77 int uldb_delete_attrs_ruid(str* _dname, str *_ruid);
78
79 /*!
80  * \brief Create a new contact structure
81  * \param _dom domain
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
86  */
87 ucontact_t* new_ucontact(str* _dom, str* _aor, str* _contact, ucontact_info_t* _ci)
88 {
89         ucontact_t *c;
90
91         if(unlikely(_ci->ruid.len<=0)) {
92                 LM_ERR("no ruid for aor: %.*s\n", _aor->len, ZSW(_aor->s));
93                 return 0;
94         }
95
96         c = (ucontact_t*)shm_malloc(sizeof(ucontact_t));
97         if (!c) {
98                 SHM_MEM_ERROR;
99                 return 0;
100         }
101         memset(c, 0, sizeof(ucontact_t));
102
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;
106
107         if (_ci->received.s && _ci->received.len) {
108                 if (shm_str_dup( &c->received, &_ci->received) < 0) goto error;
109         }
110         if (_ci->path && _ci->path->len) {
111                 if (shm_str_dup( &c->path, _ci->path) < 0) goto error;
112         }
113         if (_ci->ruid.s && _ci->ruid.len) {
114                 if (shm_str_dup( &c->ruid, &_ci->ruid) < 0) goto error;
115         }
116         if (_ci->instance.s && _ci->instance.len) {
117                 if (shm_str_dup( &c->instance, &_ci->instance) < 0) goto error;
118         }
119
120         c->domain = _dom;
121         c->aor = _aor;
122         c->expires = _ci->expires;
123         c->q = _ci->q;
124         c->sock = _ci->sock;
125         c->cseq = _ci->cseq;
126         c->state = CS_NEW;
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 = _ci->last_modified;
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);
137
138
139         return c;
140 error:
141         SHM_MEM_ERROR;
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);
150         shm_free(c);
151         return 0;
152 }
153
154
155
156 /*!
157  * \brief Free all memory associated with given contact structure
158  * \param _c freed contact
159  */
160 void free_ucontact(ucontact_t* _c)
161 {
162         if (!_c) return;
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);
171         shm_free( _c );
172 }
173
174
175 /*!
176  * \brief Print contact, for debugging purposes only
177  * \param _f output file
178  * \param _c printed contact
179  */
180 void print_ucontact(FILE* _f, ucontact_t* _c)
181 {
182         time_t t = time(0);
183         char* st;
184
185         switch(_c->state) {
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;
190         }
191
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");
203         } else {
204                 fprintf(_f, "%u\n", (unsigned int)(_c->expires - t));
205         }
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);
217         if (_c->sock) {
218                 fprintf(_f, "Sock      : %.*s (%p)\n",
219                                 _c->sock->sock_str.len,_c->sock->sock_str.s,_c->sock);
220         } else {
221                 fprintf(_f, "Sock      : none (null)\n");
222         }
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");
232 }
233
234
235 /*!
236  * \brief Update existing contact in memory with new values
237  * \param _c contact
238  * \param _ci contact informations
239  * \return 0 on success, -1 on failure
240  */
241 int mem_update_ucontact(ucontact_t* _c, ucontact_info_t* _ci)
242 {
243 #define update_str(_old,_new) \
244         do{\
245                 if ((_old)->len < (_new)->len) { \
246                         ptr = (char*)shm_malloc((_new)->len); \
247                         if (ptr == 0) { \
248                                 SHM_MEM_ERROR; \
249                                 return -1; \
250                         }\
251                         memcpy(ptr, (_new)->s, (_new)->len);\
252                         if ((_old)->s) shm_free((_old)->s);\
253                         (_old)->s = ptr;\
254                 } else {\
255                         memcpy((_old)->s, (_new)->s, (_new)->len);\
256                 }\
257                 (_old)->len = (_new)->len;\
258         } while(0)
259
260         char* ptr;
261
262         if(_ci->instance.s!=NULL && _ci->instance.len>0)
263         {
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);
267         }
268
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);
273
274         if (_ci->received.s && _ci->received.len) {
275                 update_str( &_c->received, &_ci->received);
276         } else {
277                 if (_c->received.s) shm_free(_c->received.s);
278                 _c->received.s = 0;
279                 _c->received.len = 0;
280         }
281
282         if (_ci->path) {
283                 update_str( &_c->path, _ci->path);
284         } else {
285                 if (_c->path.s) shm_free(_c->path.s);
286                 _c->path.s = 0;
287                 _c->path.len = 0;
288         }
289
290         ucontact_xavp_store(_c);
291
292         _c->sock = _ci->sock;
293         _c->expires = _ci->expires;
294         _c->q = _ci->q;
295         _c->cseq = _ci->cseq;
296         _c->methods = _ci->methods;
297         _c->last_modified = _ci->last_modified;
298         _c->last_keepalive = _ci->last_modified;
299         _c->flags = _ci->flags;
300         _c->cflags = _ci->cflags;
301         _c->server_id = _ci->server_id;
302         _c->tcpconn_id = _ci->tcpconn_id;
303
304         return 0;
305 }
306
307
308 /* ================ State related functions =============== */
309
310 /*!
311  * \brief Update state of the contact if we are using write-back scheme
312  * \param _c updated contact
313  */
314 void st_update_ucontact(ucontact_t* _c)
315 {
316         switch(_c->state) {
317         case CS_NEW:
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
321                          */
322                 break;
323
324         case CS_SYNC:
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
330                          */
331                 if (ul_db_mode == WRITE_BACK || ul_db_mode == WRITE_THROUGH) {
332                         _c->state = CS_DIRTY;
333                 }
334                 break;
335
336         case CS_DIRTY:
337                         /* Modification of dirty contact results in
338                          * dirty contact again, don't change anything
339                          */
340                 break;
341         }
342 }
343
344
345 /*!
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
349  */
350 int st_delete_ucontact(ucontact_t* _c)
351 {
352         switch(_c->state) {
353         case CS_NEW:
354                         /* Contact is new and isn't in the database
355                          * yet, we can delete it from the memory
356                          * safely.
357                          */
358                 return 1;
359
360         case CS_SYNC:
361         case CS_DIRTY:
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
367                          * from the database
368                          */
369                 if (ul_db_mode == WRITE_BACK) {
370                         _c->expires = UL_EXPIRED_TIME;
371                         return 0;
372                 } else {
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
377                          */
378                         return 1;
379                 }
380         }
381
382         return 0; /* Makes gcc happy */
383 }
384
385
386 /*!
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
390  */
391 int st_expired_ucontact(ucontact_t* _c)
392 {
393         /* There is no need to change contact
394          * state, because the contact will
395          * be deleted anyway
396          */
397
398         switch(_c->state) {
399         case CS_NEW:
400                 /* Contact is not in the database
401                  * yet, remove it from memory only
402                  */
403                 return 0;
404
405         case CS_SYNC:
406         case CS_DIRTY:
407                 /* Remove from database here */
408                 return 1;
409         }
410
411         return 0; /* Makes gcc happy */
412 }
413
414
415 /*!
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
419  */
420 int st_flush_ucontact(ucontact_t* _c)
421 {
422         switch(_c->state) {
423         case CS_NEW:
424                 /* Contact is new and is not in
425                  * the database yet so we have
426                  * to insert it
427                  */
428                 _c->state = CS_SYNC;
429                 return 1;
430
431         case CS_SYNC:
432                 /* Contact is synchronized, do
433                  * nothing
434                  */
435                 return 0;
436
437         case CS_DIRTY:
438                 /* Contact has been modified and
439                  * is in the db already so we
440                  * have to update it
441                  */
442                 _c->state = CS_SYNC;
443                 return 2;
444         }
445
446         return 0; /* Makes gcc happy */
447 }
448
449
450 /* ============== Database related functions ================ */
451
452 extern unsigned int _ul_max_partition;
453 static unsigned int _ul_partition_counter = 0;
454
455 /*!
456  * \brief Insert contact into the database
457  * \param _c inserted contact
458  * \return 0 on success, -1 on failure
459  */
460 int db_insert_ucontact(ucontact_t* _c)
461 {
462         char* dom;
463         db_key_t keys[22];
464         db_val_t vals[22];
465         int nr_cols;
466
467         if (_c->flags & FL_MEM) {
468                 return 0;
469         }
470         if(unlikely(_c->ruid.len<=0)) {
471                 LM_ERR("invalid ruid for aor: %.*s\n",
472                                 _c->aor->len, ZSW(_c->aor->s));
473                 return -1;
474         }
475
476
477         keys[0] = &ul_user_col;
478         vals[0].type = DB1_STR;
479         vals[0].nul = 0;
480         vals[0].val.str_val.s = _c->aor->s;
481         vals[0].val.str_val.len = _c->aor->len;
482
483         keys[1] = &ul_contact_col;
484         vals[1].type = DB1_STR;
485         vals[1].nul = 0;
486         vals[1].val.str_val.s = _c->c.s;
487         vals[1].val.str_val.len = _c->c.len;
488
489         keys[2] = &ul_expires_col;
490         vals[2].nul = 0;
491         UL_DB_EXPIRES_SET(&vals[2], _c->expires);
492
493         keys[3] = &ul_q_col;
494         vals[3].type = DB1_DOUBLE;
495         vals[3].nul = 0;
496         vals[3].val.double_val = q2double(_c->q);
497
498         keys[4] = &ul_callid_col;
499         vals[4].type = DB1_STR;
500         vals[4].nul = 0;
501         vals[4].val.str_val.s = _c->callid.s;
502         vals[4].val.str_val.len = _c->callid.len;
503
504         keys[5] = &ul_cseq_col;
505         vals[5].type = DB1_INT;
506         vals[5].nul = 0;
507         vals[5].val.int_val = _c->cseq;
508
509         keys[6] = &ul_flags_col;
510         vals[6].type = DB1_INT;
511         vals[6].nul = 0;
512         vals[6].val.bitmap_val = _c->flags;
513
514         keys[7] = &ul_cflags_col;
515         vals[7].type = DB1_INT;
516         vals[7].nul = 0;
517         vals[7].val.bitmap_val = _c->cflags;
518
519         keys[8] = &ul_user_agent_col;
520         vals[8].type = DB1_STR;
521         vals[8].nul = 0;
522         vals[8].val.str_val.s = _c->user_agent.s;
523         vals[8].val.str_val.len = _c->user_agent.len;
524
525         nr_cols = 9;
526
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;
533                 nr_cols++;
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;
538                 nr_cols++;
539         }
540
541         if (_c->path.s) {
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;
547                 nr_cols++;
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;
552                 nr_cols++;
553         }
554
555         if (_c->sock) {
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;
560                 nr_cols++;
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;
565                 nr_cols++;
566         }
567
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;
573                 nr_cols++;
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;
578                 nr_cols++;
579         }
580
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);
584         nr_cols++;
585
586
587         if(_c->ruid.len>0)
588         {
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;
593                 nr_cols++;
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;
598                 nr_cols++;
599         }
600
601         if(_c->instance.len>0)
602         {
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;
607                 nr_cols++;
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;
612                 nr_cols++;
613         }
614
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;
619         nr_cols++;
620
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;
625         nr_cols++;
626
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;
631         nr_cols++;
632
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;
637         nr_cols++;
638
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())
644                                                                                 % _ul_max_partition;
645         } else {
646                 vals[nr_cols].val.int_val = 0;
647         }
648         nr_cols++;
649
650
651         if (ul_use_domain) {
652                 keys[nr_cols] = &ul_domain_col;
653                 vals[nr_cols].type = DB1_STR;
654                 vals[nr_cols].nul = 0;
655
656                 dom = memchr(_c->aor->s, '@', _c->aor->len);
657                 if (dom==0) {
658                         vals[0].val.str_val.len = 0;
659                         vals[nr_cols].val.str_val = *_c->aor;
660                 } else {
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;
664                 }
665                 nr_cols++;
666         }
667
668         if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
669                 if(_c->domain) {
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:"");
673                 } else {
674                         LM_ERR("sql use_table failed - null\n");
675                 }
676                 return -1;
677         }
678
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));
683                         return -1;
684                 }
685         } else {
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));
689                         return -1;
690                 }
691         }
692
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);
697         }
698
699         return 0;
700 }
701
702
703 /*!
704  * \brief Update contact in the database by address
705  * \param _c updated contact
706  * \return 0 on success, -1 on failure
707  */
708 int db_update_ucontact_addr(ucontact_t* _c)
709 {
710         char* dom;
711         db_key_t keys1[4];
712         db_val_t vals1[4];
713         int n1 = 0;
714
715         db_key_t keys2[19];
716         db_val_t vals2[19];
717         int nr_cols2 = 0;
718
719
720         if (_c->flags & FL_MEM) {
721                 return 0;
722         }
723
724         keys1[n1] = &ul_user_col;
725         vals1[n1].type = DB1_STR;
726         vals1[n1].nul = 0;
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);
729         n1++;
730
731         keys1[n1] = &ul_contact_col;
732         vals1[n1].type = DB1_STR;
733         vals1[n1].nul = 0;
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);
736         n1++;
737
738         switch (ul_matching_mode) {
739                 case CONTACT_ONLY:
740                         /* update call-id */
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;
745                         nr_cols2++;
746                         /* update path */
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;
751                         } else {
752                                 vals2[nr_cols2].nul = 0;
753                                 vals2[nr_cols2].val.str_val = _c->path;
754                         }
755                         nr_cols2++;
756                         break;
757                 case CONTACT_CALLID:
758                         keys1[n1] = &ul_callid_col;
759                         vals1[n1].type = DB1_STR;
760                         vals1[n1].nul = 0;
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);
763                         n1++;
764                         /* update path */
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;
769                         } else {
770                                 vals2[nr_cols2].nul = 0;
771                                 vals2[nr_cols2].val.str_val = _c->path;
772                         }
773                         nr_cols2++;
774                         break;
775                 case CONTACT_PATH:
776                         keys1[n1] = &ul_path_col;
777                         vals1[n1].type = DB1_STR;
778                         if (_c->path.s == 0) {
779                                 vals1[n1].nul = 1;
780                                 LM_DBG("path: NULL\n");
781                         } else {
782                                 vals1[n1].nul = 0;
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);
785                         }
786                         n1++;
787                         /* update call-id */
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;
792                         nr_cols2++;
793                         break;
794                 default:
795                         LM_CRIT("unknown matching_mode %d\n", ul_matching_mode);
796                         return -1;
797         }
798
799         keys2[nr_cols2] = &ul_expires_col;
800         vals2[nr_cols2].nul = 0;
801         UL_DB_EXPIRES_SET(&vals2[nr_cols2], _c->expires);
802         nr_cols2++;
803
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);
808         nr_cols2++;
809
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;
814         nr_cols2++;
815
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;
820         nr_cols2++;
821
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;
826         nr_cols2++;
827
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;
832         nr_cols2++;
833
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;
838         } else {
839                 vals2[nr_cols2].nul = 0;
840                 vals2[nr_cols2].val.str_val = _c->received;
841         }
842         nr_cols2++;
843
844         keys2[nr_cols2] = &ul_sock_col;
845         vals2[nr_cols2].type = DB1_STR;
846         if (_c->sock) {
847                 vals2[nr_cols2].val.str_val = _c->sock->sock_str;
848                 vals2[nr_cols2].nul = 0;
849         } else {
850                 vals2[nr_cols2].nul = 1;
851         }
852         nr_cols2++;
853
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;
858         } else {
859                 vals2[nr_cols2].val.bitmap_val = _c->methods;
860                 vals2[nr_cols2].nul = 0;
861         }
862         nr_cols2++;
863
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);
867         nr_cols2++;
868
869         keys2[nr_cols2] = &ul_ruid_col;
870         vals2[nr_cols2].type = DB1_STR;
871         if(_c->ruid.len>0)
872         {
873                 vals2[nr_cols2].nul = 0;
874                 vals2[nr_cols2].val.str_val = _c->ruid;
875         } else {
876                 vals2[nr_cols2].nul = 1;
877         }
878         nr_cols2++;
879
880         keys2[nr_cols2] = &ul_instance_col;
881         vals2[nr_cols2].type = DB1_STR;
882         if(_c->instance.len>0)
883         {
884                 vals2[nr_cols2].nul = 0;
885                 vals2[nr_cols2].val.str_val = _c->instance;
886         } else {
887                 vals2[nr_cols2].nul = 1;
888         }
889         nr_cols2++;
890
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;
895         nr_cols2++;
896
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;
901         nr_cols2++;
902
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;
907         nr_cols2++;
908
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;
913         nr_cols2++;
914
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);
920         nr_cols2++;
921
922         if (ul_use_domain) {
923                 keys1[n1] = &ul_domain_col;
924                 vals1[n1].type = DB1_STR;
925                 vals1[n1].nul = 0;
926                 dom = memchr(_c->aor->s, '@', _c->aor->len);
927                 if (dom==0) {
928                         vals1[0].val.str_val.len = 0;
929                         vals1[n1].val.str_val = *_c->aor;
930                 } else {
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;
934                 }
935                 n1++;
936         }
937
938         if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
939                 LM_ERR("sql use_table failed\n");
940                 return -1;
941         }
942
943         if (ul_dbf.update(ul_dbh, keys1, 0, vals1, keys2, vals2, n1,
944                                 nr_cols2) < 0) {
945                 LM_ERR("updating database failed\n");
946                 return -1;
947         }
948
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
951                  * to do an INSERT */
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)
955                                 return -1;
956                 }
957         }
958         /* delete old db attrs and add the current list */
959         if (ul_xavp_contact_name.s) {
960                 if (ul_use_domain) {
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);
966                 } else {
967                         uldb_delete_attrs(_c->domain, &vals1[0].val.str_val,
968                                         NULL, &_c->ruid);
969                         uldb_insert_attrs(_c->domain, &vals1[0].val.str_val,
970                                         NULL, &_c->ruid, _c->xavp);
971                 }
972         }
973
974         return 0;
975 }
976
977 /*!
978  * \brief Update contact in the database by ruid
979  * \param _c updated contact
980  * \return 0 on success, -1 on failure
981  */
982 int db_update_ucontact_ruid(ucontact_t* _c)
983 {
984         str auser;
985         str adomain;
986         db_key_t keys1[1];
987         db_val_t vals1[1];
988         int n1;
989
990         db_key_t keys2[18];
991         db_val_t vals2[18];
992         int n2;
993
994
995         if (_c->flags & FL_MEM) {
996                 return 0;
997         }
998
999         if(_c->ruid.len<=0) {
1000                 LM_ERR("updating record in database failed - empty ruid\n");
1001                 return -1;
1002         }
1003
1004         n1 = 0;
1005         keys1[n1] = &ul_ruid_col;
1006         vals1[n1].type = DB1_STR;
1007         vals1[n1].nul = 0;
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);
1010         n1++;
1011
1012         n2 = 0;
1013         keys2[n2] = &ul_expires_col;
1014         vals2[n2].nul = 0;
1015         UL_DB_EXPIRES_SET(&vals2[n2], _c->expires);
1016         n2++;
1017
1018         keys2[n2] = &ul_q_col;
1019         vals2[n2].type = DB1_DOUBLE;
1020         vals2[n2].nul = 0;
1021         vals2[n2].val.double_val = q2double(_c->q);
1022         n2++;
1023
1024         keys2[n2] = &ul_cseq_col;
1025         vals2[n2].type = DB1_INT;
1026         vals2[n2].nul = 0;
1027         vals2[n2].val.int_val = _c->cseq;
1028         n2++;
1029
1030         keys2[n2] = &ul_flags_col;
1031         vals2[n2].type = DB1_INT;
1032         vals2[n2].nul = 0;
1033         vals2[n2].val.bitmap_val = _c->flags;
1034         n2++;
1035
1036         keys2[n2] = &ul_cflags_col;
1037         vals2[n2].type = DB1_INT;
1038         vals2[n2].nul = 0;
1039         vals2[n2].val.bitmap_val = _c->cflags;
1040         n2++;
1041
1042         keys2[n2] = &ul_user_agent_col;
1043         vals2[n2].type = DB1_STR;
1044         vals2[n2].nul = 0;
1045         vals2[n2].val.str_val = _c->user_agent;
1046         n2++;
1047
1048         keys2[n2] = &ul_received_col;
1049         vals2[n2].type = DB1_STR;
1050         if (_c->received.s == 0) {
1051                 vals2[n2].nul = 1;
1052         } else {
1053                 vals2[n2].nul = 0;
1054                 vals2[n2].val.str_val = _c->received;
1055         }
1056         n2++;
1057
1058         keys2[n2] = &ul_path_col;
1059         vals2[n2].type = DB1_STR;
1060         if (_c->path.s == 0) {
1061                 vals2[n2].nul = 1;
1062         } else {
1063                 vals2[n2].nul = 0;
1064                 vals2[n2].val.str_val = _c->path;
1065         }
1066         n2++;
1067
1068         keys2[n2] = &ul_sock_col;
1069         vals2[n2].type = DB1_STR;
1070         if (_c->sock) {
1071                 vals2[n2].val.str_val = _c->sock->sock_str;
1072                 vals2[n2].nul = 0;
1073         } else {
1074                 vals2[n2].nul = 1;
1075         }
1076         n2++;
1077
1078         keys2[n2] = &ul_methods_col;
1079         vals2[n2].type = DB1_BITMAP;
1080         if (_c->methods == 0xFFFFFFFF) {
1081                 vals2[n2].nul = 1;
1082         } else {
1083                 vals2[n2].val.bitmap_val = _c->methods;
1084                 vals2[n2].nul = 0;
1085         }
1086         n2++;
1087
1088         keys2[n2] = &ul_last_mod_col;
1089         vals2[n2].nul = 0;
1090         UL_DB_EXPIRES_SET(&vals2[n2], _c->last_modified);
1091         n2++;
1092
1093         keys2[n2] = &ul_callid_col;
1094         vals2[n2].type = DB1_STR;
1095         vals2[n2].nul = 0;
1096         vals2[n2].val.str_val = _c->callid;
1097         n2++;
1098
1099         keys2[n2] = &ul_instance_col;
1100         vals2[n2].type = DB1_STR;
1101         if(_c->instance.len>0)
1102         {
1103                 vals2[n2].nul = 0;
1104                 vals2[n2].val.str_val = _c->instance;
1105         } else {
1106                 vals2[n2].nul = 1;
1107         }
1108         n2++;
1109
1110         keys2[n2] = &ul_reg_id_col;
1111         vals2[n2].type = DB1_INT;
1112         vals2[n2].nul = 0;
1113         vals2[n2].val.int_val = (int)_c->reg_id;
1114         n2++;
1115
1116         keys2[n2] = &ul_srv_id_col;
1117         vals2[n2].type = DB1_INT;
1118         vals2[n2].nul = 0;
1119         vals2[n2].val.int_val = (int)_c->server_id;
1120         n2++;
1121
1122         keys2[n2] = &ul_con_id_col;
1123         vals2[n2].type = DB1_INT;
1124         vals2[n2].nul = 0;
1125         vals2[n2].val.int_val = (int)_c->tcpconn_id;
1126         n2++;
1127
1128         keys2[n2] = &ul_keepalive_col;
1129         vals2[n2].type = DB1_INT;
1130         vals2[n2].nul = 0;
1131         vals2[n2].val.int_val = (int)_c->keepalive;
1132         n2++;
1133
1134         keys2[n2] = &ul_contact_col;
1135         vals2[n2].type = DB1_STR;
1136         vals2[n2].nul = 0;
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);
1139         n2++;
1140
1141         if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
1142                 LM_ERR("sql use_table failed\n");
1143                 return -1;
1144         }
1145
1146         if (ul_dbf.update(ul_dbh, keys1, 0, vals1, keys2, vals2, n1, n2) < 0) {
1147                 LM_ERR("updating database failed\n");
1148                 return -1;
1149         }
1150
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)
1157                                 return -1;
1158                 }
1159         }
1160
1161         /* delete old db attrs and add the current list */
1162         if (ul_xavp_contact_name.s) {
1163                 auser = *_c->aor;
1164                 if (ul_use_domain) {
1165                         adomain.s = memchr(_c->aor->s, '@', _c->aor->len);
1166                         if (adomain.s==0) {
1167                                 auser.len = 0;
1168                                 adomain = *_c->aor;
1169                         } else {
1170                                 auser.len = adomain.s - _c->aor->s;
1171                                 adomain.s++;
1172                                 adomain.len = _c->aor->s +
1173                                         _c->aor->len - adomain.s;
1174                         }
1175
1176                         uldb_delete_attrs(_c->domain, &auser,
1177                                         &adomain, &_c->ruid);
1178                         uldb_insert_attrs(_c->domain, &auser,
1179                                         &adomain, &_c->ruid, _c->xavp);
1180                 } else {
1181                         uldb_delete_attrs(_c->domain, &auser,
1182                                         NULL, &_c->ruid);
1183                         uldb_insert_attrs(_c->domain, &auser,
1184                                         NULL, &_c->ruid, _c->xavp);
1185                 }
1186         }
1187
1188         return 0;
1189 }
1190
1191 /*!
1192  * \brief Update contact in the database by instance reg_id
1193  * \param _c updated contact
1194  * \return 0 on success, -1 on failure
1195  */
1196 int db_update_ucontact_instance(ucontact_t* _c)
1197 {
1198         str auser;
1199         str adomain;
1200         db_key_t keys1[4];
1201         db_val_t vals1[4];
1202         int n1;
1203
1204         db_key_t keys2[16];
1205         db_val_t vals2[16];
1206         int n2;
1207
1208
1209         if (_c->flags & FL_MEM) {
1210                 return 0;
1211         }
1212
1213         if(_c->instance.len<=0) {
1214                 LM_ERR("updating record in database failed - empty instance\n");
1215                 return -1;
1216         }
1217
1218         n1 = 0;
1219         keys1[n1] = &ul_user_col;
1220         vals1[n1].type = DB1_STR;
1221         vals1[n1].nul = 0;
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);
1224         n1++;
1225
1226         keys1[n1] = &ul_instance_col;
1227         vals1[n1].type = DB1_STR;
1228         vals1[n1].nul = 0;
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);
1231         n1++;
1232
1233         keys1[n1] = &ul_reg_id_col;
1234         vals1[n1].type = DB1_INT;
1235         vals1[n1].nul = 0;
1236         vals1[n1].val.int_val = (int)_c->reg_id;
1237         LM_DBG("reg-id:%d\n", vals1[n1].val.int_val);
1238         n1++;
1239
1240         n2 = 0;
1241         keys2[n2] = &ul_expires_col;
1242         vals2[n2].nul = 0;
1243         UL_DB_EXPIRES_SET(&vals2[n2], _c->expires);
1244         n2++;
1245
1246         keys2[n2] = &ul_q_col;
1247         vals2[n2].type = DB1_DOUBLE;
1248         vals2[n2].nul = 0;
1249         vals2[n2].val.double_val = q2double(_c->q);
1250         n2++;
1251
1252         keys2[n2] = &ul_cseq_col;
1253         vals2[n2].type = DB1_INT;
1254         vals2[n2].nul = 0;
1255         vals2[n2].val.int_val = _c->cseq;
1256         n2++;
1257
1258         keys2[n2] = &ul_flags_col;
1259         vals2[n2].type = DB1_INT;
1260         vals2[n2].nul = 0;
1261         vals2[n2].val.bitmap_val = _c->flags;
1262         n2++;
1263
1264         keys2[n2] = &ul_cflags_col;
1265         vals2[n2].type = DB1_INT;
1266         vals2[n2].nul = 0;
1267         vals2[n2].val.bitmap_val = _c->cflags;
1268         n2++;
1269
1270         keys2[n2] = &ul_user_agent_col;
1271         vals2[n2].type = DB1_STR;
1272         vals2[n2].nul = 0;
1273         vals2[n2].val.str_val = _c->user_agent;
1274         n2++;
1275
1276         keys2[n2] = &ul_received_col;
1277         vals2[n2].type = DB1_STR;
1278         if (_c->received.s == 0) {
1279                 vals2[n2].nul = 1;
1280         } else {
1281                 vals2[n2].nul = 0;
1282                 vals2[n2].val.str_val = _c->received;
1283         }
1284         n2++;
1285
1286         keys2[n2] = &ul_path_col;
1287         vals2[n2].type = DB1_STR;
1288         if (_c->path.s == 0) {
1289                 vals2[n2].nul = 1;
1290         } else {
1291                 vals2[n2].nul = 0;
1292                 vals2[n2].val.str_val = _c->path;
1293         }
1294         n2++;
1295
1296         keys2[n2] = &ul_sock_col;
1297         vals2[n2].type = DB1_STR;
1298         if (_c->sock) {
1299                 vals2[n2].val.str_val = _c->sock->sock_str;
1300                 vals2[n2].nul = 0;
1301         } else {
1302                 vals2[n2].nul = 1;
1303         }
1304         n2++;
1305
1306         keys2[n2] = &ul_methods_col;
1307         vals2[n2].type = DB1_BITMAP;
1308         if (_c->methods == 0xFFFFFFFF) {
1309                 vals2[n2].nul = 1;
1310         } else {
1311                 vals2[n2].val.bitmap_val = _c->methods;
1312                 vals2[n2].nul = 0;
1313         }
1314         n2++;
1315
1316         keys2[n2] = &ul_last_mod_col;
1317         vals2[n2].nul = 0;
1318         UL_DB_EXPIRES_SET(&vals2[n2], _c->last_modified);
1319         n2++;
1320
1321         keys2[n2] = &ul_callid_col;
1322         vals2[n2].type = DB1_STR;
1323         vals2[n2].nul = 0;
1324         vals2[n2].val.str_val = _c->callid;
1325         n2++;
1326
1327         keys2[n2] = &ul_srv_id_col;
1328         vals2[n2].type = DB1_INT;
1329         vals2[n2].nul = 0;
1330         vals2[n2].val.bitmap_val = _c->server_id;
1331         n2++;
1332
1333         keys2[n2] = &ul_con_id_col;
1334         vals2[n2].type = DB1_INT;
1335         vals2[n2].nul = 0;
1336         vals2[n2].val.bitmap_val = _c->tcpconn_id;
1337         n2++;
1338
1339         keys2[n2] = &ul_keepalive_col;
1340         vals2[n2].type = DB1_INT;
1341         vals2[n2].nul = 0;
1342         vals2[n2].val.bitmap_val = _c->keepalive;
1343         n2++;
1344
1345         keys2[n2] = &ul_contact_col;
1346         vals2[n2].type = DB1_STR;
1347         vals2[n2].nul = 0;
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);
1351         n2++;
1352
1353         auser = *_c->aor;
1354         if (ul_use_domain) {
1355                 keys1[n1] = &ul_domain_col;
1356                 vals1[n1].type = DB1_STR;
1357                 vals1[n1].nul = 0;
1358                 adomain.s = memchr(_c->aor->s, '@', _c->aor->len);
1359                 if (adomain.s==0) {
1360                         vals1[0].val.str_val.len = 0;
1361                         vals1[n1].val.str_val = *_c->aor;
1362                         auser.len = 0;
1363                         adomain = *_c->aor;
1364                 } else {
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;
1369                         adomain.s++;
1370                         adomain.len = _c->aor->s +
1371                                 _c->aor->len - adomain.s;
1372                 }
1373                 n1++;
1374         }
1375
1376         if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
1377                 LM_ERR("sql use_table failed\n");
1378                 return -1;
1379         }
1380
1381         if (ul_dbf.update(ul_dbh, keys1, 0, vals1, keys2, vals2, n1, n2) < 0) {
1382                 LM_ERR("updating database failed\n");
1383                 return -1;
1384         }
1385
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)
1393                                 return -1;
1394                 }
1395         }
1396
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);
1404                 } else {
1405                         uldb_delete_attrs(_c->domain, &auser,
1406                                         NULL, &_c->ruid);
1407                         uldb_insert_attrs(_c->domain, &auser,
1408                                         NULL, &_c->ruid, _c->xavp);
1409                 }
1410         }
1411
1412         return 0;
1413 }
1414
1415 /*!
1416  * \brief Update contact in the database
1417  * \param _c updated contact
1418  * \return 0 on success, -1 on failure
1419  */
1420 int db_update_ucontact(ucontact_t* _c)
1421 {
1422         if(ul_db_ops_ruid==0)
1423                 if (_c->instance.len<=0) {
1424                         return db_update_ucontact_addr(_c);
1425                 }
1426                 else {
1427                         return db_update_ucontact_instance(_c);
1428                 }
1429         else
1430                 return db_update_ucontact_ruid(_c);
1431 }
1432
1433 /*!
1434  * \brief Delete contact from the database by address
1435  * \param _c deleted contact
1436  * \return 0 on success, -1 on failure
1437  */
1438 int db_delete_ucontact_addr(ucontact_t* _c)
1439 {
1440         char* dom;
1441         db_key_t keys[4];
1442         db_val_t vals[4];
1443         int n;
1444
1445         if (_c->flags & FL_MEM) {
1446                 return 0;
1447         }
1448
1449
1450         n = 0;
1451         keys[n] = &ul_user_col;
1452         vals[n].type = DB1_STR;
1453         vals[n].nul = 0;
1454         vals[n].val.str_val = *_c->aor;
1455         n++;
1456
1457         keys[n] = &ul_contact_col;
1458         vals[n].type = DB1_STR;
1459         vals[n].nul = 0;
1460         vals[n].val.str_val = _c->c;
1461         n++;
1462
1463         switch (ul_matching_mode) {
1464                 case CONTACT_ONLY:
1465                         break;
1466                 case CONTACT_CALLID:
1467                         keys[n] = &ul_callid_col;
1468                         vals[n].type = DB1_STR;
1469                         vals[n].nul = 0;
1470                         vals[n].val.str_val = _c->callid;
1471                         n++;
1472                         break;
1473                 case CONTACT_PATH:
1474                         keys[n] = &ul_path_col;
1475                         vals[n].type = DB1_STR;
1476                         if (_c->path.s == 0) {
1477                                 vals[n].nul = 1;
1478                         } else {
1479                                 vals[n].nul = 0;
1480                                 vals[n].val.str_val = _c->path;
1481                         }
1482                         n++;
1483                         break;
1484                 default:
1485                         LM_CRIT("unknown matching_mode %d\n", ul_matching_mode);
1486                         return -1;
1487         }
1488
1489         if (ul_use_domain) {
1490                 keys[n] = &ul_domain_col;
1491                 vals[n].type = DB1_STR;
1492                 vals[n].nul = 0;
1493                 dom = memchr(_c->aor->s, '@', _c->aor->len);
1494                 if (dom==0) {
1495                         vals[0].val.str_val.len = 0;
1496                         vals[n].val.str_val = *_c->aor;
1497                 } else {
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;
1502                 }
1503                 uldb_delete_attrs(_c->domain, &vals[0].val.str_val,
1504                                 &vals[n].val.str_val, &_c->ruid);
1505                 n++;
1506         } else {
1507                 uldb_delete_attrs(_c->domain, &vals[0].val.str_val,
1508                                 NULL, &_c->ruid);
1509         }
1510
1511         if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
1512                 LM_ERR("sql use_table failed\n");
1513                 return -1;
1514         }
1515
1516         if (ul_dbf.delete(ul_dbh, keys, 0, vals, n) < 0) {
1517                 LM_ERR("deleting from database failed\n");
1518                 return -1;
1519         }
1520
1521         return 0;
1522 }
1523
1524 /*!
1525  * \brief Delete contact from the database by ruid
1526  * \param _c deleted contact
1527  * \return 0 on success, -1 on failure
1528  */
1529 int db_delete_ucontact_ruid(ucontact_t* _c)
1530 {
1531         db_key_t keys[1];
1532         db_val_t vals[1];
1533         int n;
1534
1535         if (_c->flags & FL_MEM) {
1536                 return 0;
1537         }
1538
1539         if(_c->ruid.len<=0) {
1540                 LM_ERR("deleting from database failed - empty ruid\n");
1541                 return -1;
1542         }
1543
1544         n = 0;
1545         keys[n] = &ul_ruid_col;
1546         vals[n].type = DB1_STR;
1547         vals[n].nul = 0;
1548         vals[n].val.str_val = _c->ruid;
1549         n++;
1550
1551         uldb_delete_attrs_ruid(_c->domain, &_c->ruid);
1552
1553         if (ul_dbf.use_table(ul_dbh, _c->domain) < 0) {
1554                 LM_ERR("sql use_table failed\n");
1555                 return -1;
1556         }
1557
1558         if (ul_dbf.delete(ul_dbh, keys, 0, vals, n) < 0) {
1559                 LM_ERR("deleting from database failed\n");
1560                 return -1;
1561         }
1562
1563         return 0;
1564 }
1565
1566 /*!
1567  * \brief Delete contact from the database
1568  * \param _c deleted contact
1569  * \return 0 on success, -1 on failure
1570  */
1571 int db_delete_ucontact(ucontact_t* _c)
1572 {
1573         if(ul_db_ops_ruid==0)
1574                 return db_delete_ucontact_addr(_c);
1575         else
1576                 return db_delete_ucontact_ruid(_c);
1577 }
1578
1579 /*!
1580  * \brief Remove a contact from list belonging to a certain record
1581  * \param _r record the contact belongs
1582  * \param _c removed contact
1583  */
1584 static inline void unlink_contact(struct urecord* _r, ucontact_t* _c)
1585 {
1586         if (_c->prev) {
1587                 _c->prev->next = _c->next;
1588                 if (_c->next) {
1589                         _c->next->prev = _c->prev;
1590                 }
1591         } else {
1592                 _r->contacts = _c->next;
1593                 if (_c->next) {
1594                         _c->next->prev = 0;
1595                 }
1596         }
1597 }
1598
1599
1600 /*!
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
1604  */
1605 static inline void update_contact_pos(struct urecord* _r, ucontact_t* _c)
1606 {
1607         ucontact_t *pos, *ppos;
1608
1609         if (ul_desc_time_order) {
1610                 /* order by time - first the newest */
1611                 if (_c->prev==0)
1612                         return;
1613                 unlink_contact(_r, _c);
1614                 /* insert it at the beginning */
1615                 _c->next = _r->contacts;
1616                 _c->prev = 0;
1617                 _r->contacts->prev = _c;
1618                 _r->contacts = _c;
1619         } else {
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)  )
1623                         return;
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);
1628                 if (pos) {
1629                         if (!pos->prev) {
1630                                 pos->prev = _c;
1631                                 _c->next = pos;
1632                                 _r->contacts = _c;
1633                         } else {
1634                                 _c->next = pos;
1635                                 _c->prev = pos->prev;
1636                                 pos->prev->next = _c;
1637                                 pos->prev = _c;
1638                         }
1639                 } else if (ppos) {
1640                         ppos->next = _c;
1641                         _c->prev = ppos;
1642                 } else {
1643                         _r->contacts = _c;
1644                 }
1645         }
1646 }
1647
1648 /*!
1649  * \brief helper function for update_ucontact
1650  * \param _c contact
1651  * \return 0 on success, -1 on failure
1652  */
1653 static inline int update_contact_db(ucontact_t* _c)
1654 {
1655         int res;
1656
1657         if (ul_db_update_as_insert)
1658                 res = db_insert_ucontact(_c);
1659         else
1660                 res = db_update_ucontact(_c);
1661
1662         if (res < 0) {
1663                 LM_ERR("failed to update database\n");
1664                 return -1;
1665         } else {
1666                 _c->state = CS_SYNC;
1667         }
1668         return 0;
1669 }
1670
1671 /*!
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
1677  */
1678 int update_ucontact(struct urecord* _r, ucontact_t* _c, ucontact_info_t* _ci)
1679 {
1680         struct urecord _ur;
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");
1685                 return -1;
1686         }
1687
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;
1692         }
1693
1694         /* run callbacks for UPDATE event */
1695         if (exists_ulcb_type(UL_CONTACT_UPDATE))
1696         {
1697                 LM_DBG("exists callback for type= UL_CONTACT_UPDATE\n");
1698                 run_ul_callbacks( UL_CONTACT_UPDATE, _c);
1699         }
1700
1701         if (_r) {
1702                 if (ul_db_mode!=DB_ONLY) {
1703                         update_contact_pos( _r, _c);
1704                 } else {
1705                         /* urecord was static restore copy */
1706                         memcpy(_r, &_ur, sizeof(struct urecord));
1707                 }
1708         }
1709
1710         st_update_ucontact(_c);
1711
1712         if (ul_db_mode == WRITE_THROUGH) {
1713                 if (update_contact_db(_c) < 0) return -1;
1714         }
1715         return 0;
1716 }
1717
1718 /*!
1719  * \brief Load all location attributes from a udomain
1720  *
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
1728  */
1729 int uldb_delete_attrs(str* _dname, str *_user, str *_domain, str *_ruid)
1730 {
1731         char tname_buf[64];
1732         str tname;
1733         db_key_t keys[3];
1734         db_val_t vals[3];
1735
1736         if(ul_db_ops_ruid==1)
1737                 return uldb_delete_attrs_ruid(_dname, _ruid);
1738
1739         LM_DBG("trying to delete location attributes\n");
1740
1741         if(ul_xavp_contact_name.s==NULL) {
1742                 /* feature disabled by mod param */
1743                 return 0;
1744         }
1745
1746         if(_dname->len+6>=64) {
1747                 LM_ERR("attributes table name is too big\n");
1748                 return -1;
1749         }
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;
1755
1756         keys[0] = &ulattrs_user_col;
1757         keys[1] = &ulattrs_ruid_col;
1758         keys[2] = &ulattrs_domain_col;
1759
1760         vals[0].type = DB1_STR;
1761         vals[0].nul = 0;
1762         vals[0].val.str_val = *_user;
1763
1764         vals[1].type = DB1_STR;
1765         vals[1].nul = 0;
1766         vals[1].val.str_val = *_ruid;
1767
1768         if (ul_use_domain) {
1769                 vals[2].type = DB1_STR;
1770                 vals[2].nul = 0;
1771                 vals[2].val.str_val = *_domain;
1772         }
1773
1774         if (ul_dbf.use_table(ul_dbh, &tname) < 0) {
1775                 LM_ERR("sql use_table failed\n");
1776                 return -1;
1777         }
1778
1779         if (ul_dbf.delete(ul_dbh, keys, 0, vals, (ul_use_domain) ? (3) : (2)) < 0) {
1780                 LM_ERR("deleting from database failed\n");
1781                 return -1;
1782         }
1783
1784         return 0;
1785 }
1786
1787 /*!
1788  * \brief Delete all location attributes from a udomain by ruid
1789  *
1790  * \param _dname loaded domain name
1791  * \param _ruid usrloc record unique id
1792  * \return 0 on success, -1 on failure
1793  */
1794 int uldb_delete_attrs_ruid(str* _dname, str *_ruid)
1795 {
1796         char tname_buf[64];
1797         str tname;
1798         db_key_t keys[1];
1799         db_val_t vals[1];
1800
1801         LM_DBG("trying to delete location attributes\n");
1802
1803         if(ul_xavp_contact_name.s==NULL) {
1804                 /* feature disabled by mod param */
1805                 return 0;
1806         }
1807
1808         if(_dname->len+6>=64) {
1809                 LM_ERR("attributes table name is too big\n");
1810                 return -1;
1811         }
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;
1817
1818         keys[0] = &ulattrs_ruid_col;
1819
1820         vals[0].type = DB1_STR;
1821         vals[0].nul = 0;
1822         vals[0].val.str_val = *_ruid;
1823
1824         if (ul_dbf.use_table(ul_dbh, &tname) < 0) {
1825                 LM_ERR("sql use_table failed\n");
1826                 return -1;
1827         }
1828
1829         if (ul_dbf.delete(ul_dbh, keys, 0, vals, 1) < 0) {
1830                 LM_ERR("deleting from database failed\n");
1831                 return -1;
1832         }
1833
1834         return 0;
1835 }
1836
1837 /*!
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
1845  */
1846 int uldb_insert_attrs(str *_dname, str *_user, str *_domain,
1847                 str *_ruid, sr_xavp_t *_xhead)
1848 {
1849         char tname_buf[64];
1850         str tname;
1851         str avalue;
1852         sr_xavp_t *xavp;
1853         db_key_t keys[7];
1854         db_val_t vals[7];
1855         int nr_cols;
1856
1857         LM_DBG("trying to insert location attributes\n");
1858
1859         if(ul_xavp_contact_name.s==NULL) {
1860                 /* feature disabled by mod param */
1861                 LM_DBG("location attributes disabled\n");
1862                 return 0;
1863         }
1864
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");
1869                 return 0;
1870         }
1871
1872         if(_dname->len+6>=64) {
1873                 LM_ERR("attributes table name is too big\n");
1874                 return -1;
1875         }
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;
1881
1882         if (ul_dbf.use_table(ul_dbh, &tname) < 0) {
1883                 LM_ERR("sql use_table failed for %.*s\n", tname.len, tname.s);
1884                 return -1;
1885         }
1886
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;
1894
1895         vals[0].type = DB1_STR;
1896         vals[0].nul = 0;
1897         vals[0].val.str_val = *_user;
1898
1899         vals[1].type = DB1_STR;
1900         vals[1].nul = 0;
1901         vals[1].val.str_val = *_ruid;
1902
1903         vals[2].nul = 0;
1904         UL_DB_EXPIRES_SET(&vals[2], time(NULL));
1905
1906         if (ul_use_domain && _domain!=NULL && _domain->s!=NULL) {
1907                 nr_cols = 7;
1908                 vals[6].type = DB1_STR;
1909                 vals[6].nul = 0;
1910                 vals[6].val.str_val = *_domain;
1911
1912         } else {
1913                 nr_cols = 6;
1914         }
1915
1916         for(xavp=_xhead->val.v.xavp; xavp; xavp=xavp->next) {
1917                 vals[3].type = DB1_STR;
1918                 vals[3].nul = 0;
1919                 vals[3].val.str_val = xavp->name;
1920
1921                 vals[4].type = DB1_INT;
1922                 vals[4].nul = 0;
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);
1929                 } else {
1930                         continue;
1931                 }
1932
1933                 vals[5].type = DB1_STR;
1934                 vals[5].nul = 0;
1935                 vals[5].val.str_val = avalue;
1936
1937                 if (ul_dbf.insert(ul_dbh, keys, vals, nr_cols) < 0) {
1938                         LM_ERR("inserting contact in db failed\n");
1939                         return -1;
1940                 }
1941
1942         }
1943         return 0;
1944 }