fda1a6ce5b7a35173b69466b847800e6a8699449
[kamailio] / src / modules / pua / pua_db.c
1 /*
2  * pua db - presence user agent database support 
3  *
4  * Copyright (C) 2011 Crocodile RCS Ltd
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
8  * Kamailio is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * Kamailio is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License 
19  * along with this program; if not, write to the Free Software 
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  */
22
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "../../core/mem/mem.h"
29 #include "../../core/mem/shm_mem.h"
30 #include "../../core/dprint.h"
31 #include "../../lib/srdb1/db.h"
32 #include "../../core/parser/msg_parser.h"
33 #include "../../core/parser/parse_from.h"
34
35 #include "pua.h"
36 #include "pua_db.h"
37
38 /* database colums */
39 static str str_id_col = str_init( "id" );
40 static str str_pres_uri_col = str_init("pres_uri");
41 static str str_pres_id_col = str_init("pres_id");
42 static str str_expires_col= str_init("expires");
43 static str str_flag_col= str_init("flag");
44 static str str_etag_col= str_init("etag");
45 static str str_tuple_id_col= str_init("tuple_id");
46 static str str_watcher_uri_col= str_init("watcher_uri");
47 static str str_call_id_col= str_init("call_id");
48 static str str_to_tag_col= str_init("to_tag");
49 static str str_from_tag_col= str_init("from_tag");
50 static str str_cseq_col= str_init("cseq");
51 static str str_event_col= str_init("event");
52 static str str_record_route_col= str_init("record_route");
53 static str str_contact_col= str_init("contact");
54 static str str_remote_contact_col= str_init("remote_contact");
55 static str str_extra_headers_col= str_init("extra_headers");
56 static str str_desired_expires_col= str_init("desired_expires");
57 static str str_version_col = str_init("version");
58
59
60 /******************************************************************************/
61
62 void free_results_puadb( db1_res_t *res )
63
64 {
65         if (res) 
66         {
67                 pua_dbf.free_result(pua_db, res);
68                 res = NULL;
69         }
70 }
71
72 /******************************************************************************/
73
74 static void extract_row( db_val_t *values, ua_pres_t *result )
75
76 {
77
78         if (result->pres_uri != NULL )
79         {
80                 result->pres_uri->s = (char *)VAL_STRING(values+1);
81                 result->pres_uri->len = strlen(VAL_STRING(values+1));
82         }
83
84         result->id.s = (char *)VAL_STRING(values+2);
85         result->id.len = strlen(VAL_STRING(values+2));
86
87         result->event = VAL_INT(values+3);
88
89         result->expires = VAL_INT(values+4);
90
91         result->desired_expires = VAL_INT(values+5);
92
93         result->flag = VAL_INT(values+6);
94
95         /* publish */
96         result->etag.s = (char *)VAL_STRING(values+7);
97         result->etag.len = strlen(VAL_STRING(values+7));
98
99         result->tuple_id.s = (char *)VAL_STRING(values+8);
100         result->tuple_id.len = strlen(VAL_STRING(values+8));
101
102         /* subscribe */
103         if (result->watcher_uri != NULL )
104         {
105                 result->watcher_uri->s = (char *)VAL_STRING(values+9);
106                 result->watcher_uri->len = strlen(VAL_STRING(values+9));
107         }
108
109         result->call_id.s = (char *)VAL_STRING(values+10);
110         result->call_id.len = strlen(VAL_STRING(values+10));
111
112         result->to_tag.s = (char *)VAL_STRING(values+11);
113         result->to_tag.len = strlen(VAL_STRING(values+11));
114
115         result->from_tag.s = (char *)VAL_STRING(values+12);
116         result->from_tag.len = strlen(VAL_STRING(values+12));
117
118         result->cseq = VAL_INT(values+13);
119
120         result->record_route.s = (char *)VAL_STRING(values+14);
121         result->record_route.len = strlen(VAL_STRING(values+14));
122
123         result->contact.s = (char *)VAL_STRING(values+15);
124         result->contact.len = strlen(VAL_STRING(values+15));
125
126         result->remote_contact.s = (char *)VAL_STRING(values+16);
127         result->remote_contact.len = strlen(VAL_STRING(values+16));
128
129         result->version = VAL_INT(values+17);
130
131         if (result->extra_headers != NULL )
132         {
133                 result->extra_headers->s = (char *)VAL_STRING(values+18);
134                 result->extra_headers->len = strlen(VAL_STRING(values+18));
135         }
136 }
137
138 /******************************************************************************/
139
140 int clean_puadb( int update_period, int min_expires )
141
142 {
143         int i, nr_rows;
144         db_row_t *rows;
145         db_val_t *values;
146         db_key_t q_cols[1];
147         db1_res_t *res= NULL;
148         db_val_t q_vals[1];
149         db_op_t  q_ops[1];
150         int id;
151         time_t now;
152         ua_pres_t p;
153         str pres_uri={0,0}, watcher_uri={0,0}, extra_headers={0,0};
154
155         memset(&p, 0, sizeof(p));
156         p.pres_uri = &pres_uri;
157         p.watcher_uri = &watcher_uri;
158         p.extra_headers = &extra_headers;
159
160         now = time(NULL);
161
162         /* cols and values used for search query */
163         q_cols[0] = &str_expires_col;
164         q_vals[0].type = DB1_INT;
165         q_vals[0].nul = 0;
166         q_vals[0].val.int_val = now+update_period;
167         q_ops[0] = OP_LT;       
168
169         if (pua_dbf.use_table(pua_db, &db_table) < 0) {
170             LM_ERR("error in use_table pua\n");
171             return(-1);
172         }
173
174         if(db_fetch_query(&pua_dbf, pua_fetch_rows, pua_db, q_cols, q_ops,
175                                 q_vals, NULL, 1, 0, 0, &res) < 0)
176         {
177                 LM_ERR("DB query error\n");
178                 return(-1);
179         }
180
181         if (res == NULL)
182         {
183                 LM_ERR("bad result\n");
184                 return(-1);
185         }
186
187         if (RES_ROW_N(res) == 0)
188         {
189                 /* no match */ 
190                 LM_DBG( "No records matched for clean\n");
191                 pua_dbf.free_result(pua_db, res);
192                 return(0);
193         }
194
195         do {
196                 nr_rows = RES_ROW_N(res);
197
198                 /* get the results and update matching entries */
199                 rows = RES_ROWS(res);
200
201                 for (i=0; i < nr_rows; i++)
202                 {
203                         values = ROW_VALUES(rows+i);
204
205                         extract_row( values, &p ); 
206                         id = VAL_INT(values);
207
208                         if((p.desired_expires> p.expires + min_expires) || (p.desired_expires== 0 ))
209                         {
210                                 if(update_pua(&p)< 0)
211                                 {
212                                         LM_ERR("update_pua failed\n");
213                                 }
214                                 continue;
215                         }
216
217                         if(p.expires < now - 10)
218                         {
219                                 LM_DBG("Found expired: uri= %.*s\n", p.pres_uri->len, p.pres_uri->s);
220                                 q_cols[0] = &str_id_col;
221                                 q_vals[0].type = DB1_INT;
222                                 q_vals[0].nul = 0;
223                                 q_vals[0].val.int_val = id;
224
225                                 if ( pua_dbf.delete(pua_db, q_cols, 0, q_vals, 1) < 0 )
226                                 {
227                                         LM_ERR( "Failed to delete from db\n" ); 
228                                 }                       
229                         }
230
231                 }
232         } while ((db_fetch_next(&pua_dbf, pua_fetch_rows, pua_db, &res)==1)
233                         && (RES_ROWS(res)>0));
234
235         pua_dbf.free_result(pua_db, res);
236         return(0);
237 }
238
239 /******************************************************************************/
240
241 int is_dialog_puadb(ua_pres_t *pres) 
242
243 {
244         int nr_rows;
245         db_key_t q_cols[3], res_cols[1];
246         db1_res_t *res= NULL;
247         db_val_t q_vals[3];
248         int n_query_cols= 0, n_res_cols=0;
249
250         if (pres==NULL)
251         {
252                 LM_ERR("called with NULL param\n");
253                 return(-1);
254         }
255
256         /* cols and values used for search query */
257         q_cols[n_query_cols] = &str_call_id_col;        
258         q_vals[n_query_cols].type = DB1_STR;
259         q_vals[n_query_cols].nul = 0;
260         q_vals[n_query_cols].val.str_val = pres->call_id;
261         n_query_cols++;
262
263         q_cols[n_query_cols] = &str_to_tag_col; 
264         q_vals[n_query_cols].type = DB1_STR;
265         q_vals[n_query_cols].nul = 0;
266         q_vals[n_query_cols].val.str_val = pres->to_tag;
267         n_query_cols++;
268
269         q_cols[n_query_cols] = &str_from_tag_col;       
270         q_vals[n_query_cols].type = DB1_STR;
271         q_vals[n_query_cols].nul = 0;
272         q_vals[n_query_cols].val.str_val = pres->from_tag;
273         n_query_cols++;
274
275         /* return the id column, even though don't actually need */
276         res_cols[n_res_cols] = &str_id_col;     
277         n_res_cols++;
278
279         if(pua_db == NULL)
280         {
281                 LM_ERR("null database connection\n");
282                 return(-1);
283         }
284
285         if (pua_dbf.use_table(pua_db, &db_table) < 0)
286         {
287                 LM_ERR("error in use_table pua\n");
288                 return(-1);
289         }
290
291         if(pua_dbf.query(pua_db, q_cols, 0, q_vals,
292                                 res_cols,n_query_cols,n_res_cols,0,&res) < 0)
293         {
294                 LM_ERR("DB query error\n");
295                 return(-1);
296         }
297
298         if (res == NULL)
299         {
300                 LM_ERR("bad result\n");
301                 return(-1);
302         }
303
304         nr_rows = RES_ROW_N(res);
305         pua_dbf.free_result(pua_db, res);
306
307         if (nr_rows == 0)
308         {
309                 /* no match */ 
310                 LM_DBG("No rows found.\n");
311                 return(-1);
312         }
313
314         if (nr_rows != 1)
315         {
316                 LM_WARN("Too many rows found (%d)\n", nr_rows);
317                 /* no need to return here - drop thro */
318         }
319
320         /* established dialog */
321         if(pres->to_tag.len>0)
322                 return 0;
323         /* temporary dialog */
324         return 1;
325 }
326
327 /******************************************************************************/
328
329 int get_record_id_puadb(ua_pres_t *pres, str **rec_id ) 
330
331 {
332         int nr_rows;
333         db_row_t *rows;
334         db_key_t q_cols[3], res_cols[2];
335         db1_res_t *res= NULL;
336         db_val_t q_vals[3];
337         int n_query_cols=0, n_res_cols=0;
338         db_val_t *values;       
339         str *id;
340         str to_tag;
341
342         if (pres==NULL)
343         {
344                 LM_ERR("called with NULL param\n");
345                 return(-1);
346         }
347
348         /* cols and values used for search query */
349         q_cols[n_query_cols] = &str_call_id_col;        
350         q_vals[n_query_cols].type = DB1_STR;
351         q_vals[n_query_cols].nul = 0;
352         q_vals[n_query_cols].val.str_val = pres->call_id;
353         n_query_cols++;
354
355         q_cols[n_query_cols] = &str_from_tag_col;       
356         q_vals[n_query_cols].type = DB1_STR;
357         q_vals[n_query_cols].nul = 0;
358         q_vals[n_query_cols].val.str_val = pres->from_tag;
359         n_query_cols++;
360
361         q_cols[n_query_cols] = &str_to_tag_col; 
362         q_vals[n_query_cols].type = DB1_STR;
363         q_vals[n_query_cols].nul = 0;
364         q_vals[n_query_cols].val.str_val = pres->to_tag;
365         n_query_cols++;
366
367         res_cols[n_res_cols] = &str_pres_id_col;        
368         n_res_cols++;
369
370         *rec_id = NULL;
371
372         if(pua_db == NULL)
373         {
374                 LM_ERR("null database connection\n");
375                 return(-1);
376         }
377
378         if (pua_dbf.use_table(pua_db, &db_table) < 0)
379         {
380                 LM_ERR("error in use_table pua\n");
381                 return(-1);
382         }
383
384         if(pua_dbf.query(pua_db, q_cols, 0, q_vals,
385                                 res_cols,n_query_cols,n_res_cols,0,&res) < 0)
386         {
387                 LM_ERR("DB query error\n");
388                 return(-1);
389         }
390
391         if (res == NULL)
392         {
393                 LM_ERR("bad result\n");
394                 return(-1);
395         }
396
397         nr_rows = RES_ROW_N(res);
398
399         switch (nr_rows)
400         {
401         case 1:
402                 rows = RES_ROWS(res);
403                 values = ROW_VALUES(rows);
404                 break;
405
406         case 0:
407                 /* no match */
408                 LM_DBG("No rows found. Looking for temporary dialog\n");
409                 pua_dbf.free_result(pua_db, res);
410
411                 n_query_cols--;
412
413                 res_cols[n_res_cols] = &str_to_tag_col;
414                 n_res_cols++;
415
416                 if(pua_dbf.query(pua_db, q_cols, 0, q_vals,
417                         res_cols,n_query_cols,n_res_cols,0,&res) < 0)
418                 {
419                         LM_ERR("DB query error\n");
420                         return(-1);
421                 }
422
423                 if (res == NULL)
424                 {
425                         LM_ERR("bad result\n");
426                         return(-1);
427                 }
428
429                 nr_rows = RES_ROW_N(res);
430
431                 if (nr_rows == 1)
432                 {
433                         rows = RES_ROWS(res);
434                         values = ROW_VALUES(rows);
435
436                         to_tag.s = (char *) VAL_STRING(values + 1);
437                         to_tag.len = strlen(to_tag.s);
438
439                         if (to_tag.len == 0 ||
440                                 (to_tag.len > 0
441                                  && strncmp(to_tag.s, pres->to_tag.s, pres->to_tag.len) == 0))
442                         {
443                                 LM_DBG( "Found a (possibly temporary) Dialog\n" );
444                                 break;
445                         }
446                         else
447                                 LM_WARN("Failed to find temporary dialog for To-tag: %.*s, found To-tag: %.*s\n",
448                                         pres->to_tag.len, pres->to_tag.s, to_tag.len, to_tag.s);
449                 }
450
451                 if (nr_rows <= 1)
452                 {
453                         LM_DBG("Dialog not found\n" );
454                         pua_dbf.free_result(pua_db, res);
455                         return(0);
456                 }
457
458                 /* Fall-thru */
459
460         default:
461                 LM_ERR("Too many rows found (%d)\n", nr_rows);
462                 pua_dbf.free_result(pua_db, res);
463                 return(-1);
464         }
465
466         id= (str*)pkg_malloc(sizeof(str));
467
468         if(id== NULL)
469         {
470                 LM_ERR("No more memory\n");
471                 pua_dbf.free_result(pua_db, res);
472                 return(-1);
473         }
474
475         id->s= (char*)pkg_malloc( strlen(VAL_STRING(values)) * sizeof(char));
476
477         if(id->s== NULL)
478         {
479                 LM_ERR("No more memory\n");
480                 pkg_free(id);
481                 pua_dbf.free_result(pua_db, res);
482                 return(-1);
483         }
484
485         memcpy(id->s, VAL_STRING(values), strlen(VAL_STRING(values)) );
486         id->len= strlen(VAL_STRING(values));
487
488         *rec_id= id;
489         pua_dbf.free_result(pua_db, res);
490
491         LM_DBG("Found id=%.*s\n", id->len, id->s);
492         return(0);
493 }
494
495 /******************************************************************************/
496 int convert_temporary_dialog_puadb(ua_pres_t *pres)
497 {
498         db_key_t query_cols[18];
499         db_val_t query_vals[18];
500         int n_query_cols = 0;
501
502         if (pres==NULL)
503         {
504                 LM_ERR("called with NULL param\n");
505                 return(-1);
506         }
507
508         /* The columns I need to query to find the temporary dialog */
509         query_cols[n_query_cols] = &str_pres_id_col;
510         query_vals[n_query_cols].type = DB1_STR;
511         query_vals[n_query_cols].nul = 0;
512         query_vals[n_query_cols].val.str_val = pres->id;
513         n_query_cols++;
514
515         query_cols[n_query_cols] = &str_pres_uri_col;
516         query_vals[n_query_cols].type = DB1_STR;
517         query_vals[n_query_cols].nul = 0;
518         query_vals[n_query_cols].val.str_val.s = pres->pres_uri->s;
519         query_vals[n_query_cols].val.str_val.len = pres->pres_uri->len;
520         n_query_cols++;
521
522         query_cols[n_query_cols] = &str_call_id_col;    
523         query_vals[n_query_cols].type = DB1_STR;
524         query_vals[n_query_cols].nul = 0;
525         query_vals[n_query_cols].val.str_val = pres->call_id;
526         n_query_cols++;
527
528         query_cols[n_query_cols] = &str_from_tag_col;   
529         query_vals[n_query_cols].type = DB1_STR;
530         query_vals[n_query_cols].nul = 0;
531         query_vals[n_query_cols].val.str_val = pres->from_tag;
532         n_query_cols++;
533
534         /* The columns I need to fill in to convert a temporary dialog to a dialog */
535         query_cols[n_query_cols] = &str_expires_col;
536         query_vals[n_query_cols].type = DB1_INT;
537         query_vals[n_query_cols].nul = 0;
538         query_vals[n_query_cols].val.int_val = pres->expires;
539         n_query_cols++;
540
541         query_cols[n_query_cols] = &str_desired_expires_col;
542         query_vals[n_query_cols].type = DB1_INT;
543         query_vals[n_query_cols].nul = 0;
544         query_vals[n_query_cols].val.int_val = pres->desired_expires;
545         n_query_cols++;
546
547         query_cols[n_query_cols] = &str_flag_col;
548         query_vals[n_query_cols].type = DB1_INT;
549         query_vals[n_query_cols].nul = 0;
550         query_vals[n_query_cols].val.int_val = pres->flag;
551         n_query_cols++;
552
553         query_cols[n_query_cols] = &str_to_tag_col;
554         query_vals[n_query_cols].type = DB1_STR;
555         query_vals[n_query_cols].nul = 0;
556         query_vals[n_query_cols].val.str_val = pres->to_tag;
557         n_query_cols++;
558
559         query_cols[n_query_cols] = &str_cseq_col;
560         query_vals[n_query_cols].type = DB1_INT;
561         query_vals[n_query_cols].nul = 0;
562         query_vals[n_query_cols].val.int_val = pres->cseq;
563         n_query_cols++;
564
565         query_cols[n_query_cols] = &str_record_route_col;
566         query_vals[n_query_cols].type = DB1_STR;
567         query_vals[n_query_cols].nul = 0;
568         query_vals[n_query_cols].val.str_val = pres->record_route;
569         n_query_cols++;
570
571         query_cols[n_query_cols] = &str_contact_col;
572         query_vals[n_query_cols].type = DB1_STR;
573         query_vals[n_query_cols].nul = 0;
574         query_vals[n_query_cols].val.str_val = pres->contact;
575         n_query_cols++;
576
577         query_cols[n_query_cols] = &str_remote_contact_col;
578         query_vals[n_query_cols].type = DB1_STR;
579         query_vals[n_query_cols].nul = 0;
580         query_vals[n_query_cols].val.str_val = pres->remote_contact;
581         n_query_cols++;
582
583         query_cols[n_query_cols] = &str_version_col;
584         query_vals[n_query_cols].type = DB1_INT;
585         query_vals[n_query_cols].nul = 0;
586         query_vals[n_query_cols].val.int_val = pres->version;
587         n_query_cols++;
588
589         query_cols[n_query_cols] = &str_extra_headers_col;
590         query_vals[n_query_cols].type = DB1_STR;
591         query_vals[n_query_cols].nul = 0;
592         if (pres->extra_headers)
593         {
594                 query_vals[n_query_cols].val.str_val.s = pres->extra_headers->s;
595                 query_vals[n_query_cols].val.str_val.len = pres->extra_headers->len;
596         }
597         else
598         {
599                 query_vals[n_query_cols].val.str_val.s = "";
600                 query_vals[n_query_cols].val.str_val.len = 0;
601         }
602         n_query_cols++;
603
604         query_cols[n_query_cols] = &str_event_col;      
605         query_vals[n_query_cols].type = DB1_INT;
606         query_vals[n_query_cols].nul = 0;
607         query_vals[n_query_cols].val.int_val = pres->event;
608         n_query_cols++;
609
610         query_cols[n_query_cols] = &str_watcher_uri_col;
611         query_vals[n_query_cols].type = DB1_STR;
612         query_vals[n_query_cols].nul = 0; 
613         query_vals[n_query_cols].val.str_val.s = pres->watcher_uri->s;
614         query_vals[n_query_cols].val.str_val.len = pres->watcher_uri->len;
615         n_query_cols++;
616
617         query_cols[n_query_cols] = &str_etag_col;
618         query_vals[n_query_cols].type = DB1_STR;
619         query_vals[n_query_cols].nul = 0; 
620         query_vals[n_query_cols].val.str_val.s = 0;
621         query_vals[n_query_cols].val.str_val.len = 0;
622         n_query_cols++;
623
624         query_cols[n_query_cols] = &str_tuple_id_col;
625         query_vals[n_query_cols].type = DB1_STR;
626         query_vals[n_query_cols].nul = 0; 
627         query_vals[n_query_cols].val.str_val.s = 0;
628         query_vals[n_query_cols].val.str_val.len = 0;
629         n_query_cols++;
630
631         if (pua_dbf.use_table(pua_db, &db_table) < 0)
632         {
633                 LM_ERR("error in use_table pua\n");
634                 return(-1);
635         }
636
637         if (pua_dbf.replace != NULL)
638         {
639                 if (pua_dbf.replace(pua_db, query_cols, query_vals, n_query_cols,
640                                         4, 0) < 0)
641                 {
642                         LM_ERR("Failed replace db\n");
643                         return -1;
644                 }
645         }
646         else
647         {
648                 if (pua_dbf.update(pua_db, query_cols, 0, query_vals,
649                                 query_cols + 4, query_vals + 4, 4, n_query_cols - 4) < 0)
650                 {
651                         LM_ERR("Failed update db\n");
652                         return -1;
653                 }
654
655                 LM_DBG("affected_rows: %d\n", pua_dbf.affected_rows(pua_db));
656                 if (pua_dbf.affected_rows(pua_db) == 0)
657                 {
658                         if (pua_dbf.insert(pua_db, query_cols, query_vals, n_query_cols) < 0)
659                         {
660                                 LM_ERR("Failed insert db\n");
661                                 return -1;
662                         }
663                 }
664         }
665
666
667         shm_free(pres->remote_contact.s);
668         shm_free(pres);
669
670         return 1;
671 }
672
673 /******************************************************************************/
674
675 int insert_record_puadb(ua_pres_t* pres)
676
677 {
678         db_key_t db_cols[18];
679         db_val_t db_vals[18];
680         int n_cols= 0;
681
682         if (pres==NULL)
683         {
684                 LM_ERR("called with NULL param\n");
685                 return(-1);
686         }
687
688         db_cols[n_cols] = &str_pres_uri_col;
689         db_vals[n_cols].type = DB1_STR;
690         db_vals[n_cols].nul = 0;
691         db_vals[n_cols].val.str_val.s = pres->pres_uri->s;
692         db_vals[n_cols].val.str_val.len = pres->pres_uri->len;
693         n_cols++;
694
695         db_cols[n_cols] = &str_pres_id_col;     
696         db_vals[n_cols].type = DB1_STR;
697         db_vals[n_cols].nul = 0;
698         db_vals[n_cols].val.str_val.s = pres->id.s;
699         db_vals[n_cols].val.str_val.len = pres->id.len;
700         n_cols++;
701
702         db_cols[n_cols] = &str_event_col;       
703         db_vals[n_cols].type = DB1_INT;
704         db_vals[n_cols].nul = 0;
705         db_vals[n_cols].val.int_val = pres->event;
706         n_cols++;
707
708         db_cols[n_cols] = &str_expires_col;
709         db_vals[n_cols].type = DB1_INT;
710         db_vals[n_cols].nul = 0;
711         db_vals[n_cols].val.int_val = pres->expires;
712         n_cols++;
713
714         db_cols[n_cols] = &str_desired_expires_col;
715         db_vals[n_cols].type = DB1_INT;
716         db_vals[n_cols].nul = 0;
717         db_vals[n_cols].val.int_val = pres->desired_expires;
718         n_cols++;
719
720         db_cols[n_cols] = &str_flag_col;
721         db_vals[n_cols].type = DB1_INT;
722         db_vals[n_cols].nul = 0;
723         db_vals[n_cols].val.int_val = pres->flag;
724         n_cols++;
725
726         db_cols[n_cols] = &str_etag_col;
727         db_vals[n_cols].type = DB1_STR;
728         db_vals[n_cols].nul = 0; 
729         db_vals[n_cols].val.str_val.s = pres->etag.s;
730         db_vals[n_cols].val.str_val.len = pres->etag.len;
731         n_cols++;
732
733         db_cols[n_cols] = &str_tuple_id_col;
734         db_vals[n_cols].type = DB1_STR;
735         db_vals[n_cols].nul = 0; 
736         db_vals[n_cols].val.str_val.s = pres->tuple_id.s;
737         db_vals[n_cols].val.str_val.len = pres->tuple_id.len;
738         n_cols++;
739
740         db_cols[n_cols] = &str_watcher_uri_col;
741         db_vals[n_cols].type = DB1_STR;
742         db_vals[n_cols].nul = 0; 
743         db_vals[n_cols].val.str_val.s = "";
744         db_vals[n_cols].val.str_val.len = 0;
745         n_cols++;
746
747         db_cols[n_cols] = &str_call_id_col;
748         db_vals[n_cols].type = DB1_STR;
749         db_vals[n_cols].nul = 0; 
750         db_vals[n_cols].val.str_val.s = "";
751         db_vals[n_cols].val.str_val.len = 0;
752         n_cols++;
753
754         db_cols[n_cols] = &str_to_tag_col;
755         db_vals[n_cols].type = DB1_STR;
756         db_vals[n_cols].nul = 0; 
757         db_vals[n_cols].val.str_val.s = "";
758         db_vals[n_cols].val.str_val.len = 0;
759         n_cols++;
760
761         db_cols[n_cols] = &str_from_tag_col;
762         db_vals[n_cols].type = DB1_STR;
763         db_vals[n_cols].nul = 0; 
764         db_vals[n_cols].val.str_val.s = "";
765         db_vals[n_cols].val.str_val.len = 0;
766         n_cols++;
767
768         db_cols[n_cols] = &str_cseq_col;
769         db_vals[n_cols].type = DB1_INT;
770         db_vals[n_cols].nul = 0;
771         db_vals[n_cols].val.int_val = 0;
772         n_cols++;
773
774         db_cols[n_cols] = &str_record_route_col;
775         db_vals[n_cols].type = DB1_STR;
776         db_vals[n_cols].nul = 0; 
777         db_vals[n_cols].val.str_val.s = "";
778         db_vals[n_cols].val.str_val.len = 0;
779         n_cols++;
780
781         db_cols[n_cols] = &str_contact_col;
782         db_vals[n_cols].type = DB1_STR;
783         db_vals[n_cols].nul = 0; 
784         db_vals[n_cols].val.str_val.s = "";
785         db_vals[n_cols].val.str_val.len = 0;
786         n_cols++;
787
788         db_cols[n_cols] = &str_remote_contact_col;
789         db_vals[n_cols].type = DB1_STR;
790         db_vals[n_cols].nul = 0; 
791         db_vals[n_cols].val.str_val.s = "";
792         db_vals[n_cols].val.str_val.len = 0;
793         n_cols++;
794
795         db_cols[n_cols] = &str_version_col;
796         db_vals[n_cols].type = DB1_INT;
797         db_vals[n_cols].nul = 0;
798         db_vals[n_cols].val.int_val = pres->version;
799         n_cols++;
800
801         db_cols[n_cols] = &str_extra_headers_col;
802         db_vals[n_cols].type = DB1_STR;
803         db_vals[n_cols].nul = 0; 
804         if (pres->extra_headers)
805         {
806                 db_vals[n_cols].val.str_val.s = pres->extra_headers->s;
807                 db_vals[n_cols].val.str_val.len = pres->extra_headers->len;
808         }
809         else
810         {
811                 db_vals[n_cols].val.str_val.s = "";
812                 db_vals[n_cols].val.str_val.len = 0;
813         }
814         n_cols++;
815
816         if(pua_db == NULL)
817         {
818                 LM_ERR("null database connection\n");
819                 return(-1);
820         }
821
822         if(pua_dbf.insert(pua_db, db_cols, db_vals, n_cols) < 0)  
823         {
824                 LM_ERR("DB insert failed\n");
825                 return(-1);
826         }
827
828         return(0);
829 }
830
831 /******************************************************************************/
832
833 ua_pres_t *get_record_puadb(str pres_id, str *etag, ua_pres_t *result, db1_res_t **dbres)
834 {
835         db_key_t q_cols[2];
836         db_val_t q_vals[2], *values;
837         db_row_t *rows;
838         db1_res_t *res;
839         int n_query_cols = 0, nr_rows;
840         db_query_f query_fn = pua_dbf.query_lock ? pua_dbf.query_lock : pua_dbf.query;
841
842         q_cols[n_query_cols] = &str_pres_id_col;        
843         q_vals[n_query_cols].type = DB1_STR;
844         q_vals[n_query_cols].nul = 0;
845         q_vals[n_query_cols].val.str_val = pres_id;
846         n_query_cols++;
847
848         if (etag != NULL)
849         {
850                 q_cols[n_query_cols] = &str_etag_col;
851                 q_vals[n_query_cols].type = DB1_STR;
852                 q_vals[n_query_cols].nul = 0;
853                 q_vals[n_query_cols].val.str_val.s = etag->s;
854                 q_vals[n_query_cols].val.str_val.len = etag->len;
855                 n_query_cols++;
856         }
857
858         if(pua_db == NULL)
859         {
860                 LM_ERR("null database connection\n");
861                 return(NULL);
862         }
863
864         if (pua_dbf.use_table(pua_db, &db_table) < 0)
865         {
866                 LM_ERR("error in use_table pua\n");
867                 return(NULL);
868         }
869
870         if(query_fn(pua_db, q_cols, 0, q_vals,
871                                 NULL,n_query_cols,0,0,&res) < 0)
872         {
873                 LM_ERR("DB query error\n");
874                 return(NULL);
875         }
876
877         if (res == NULL)
878         {
879                 LM_ERR("bad result\n");
880                 return(NULL);
881         }
882
883         nr_rows = RES_ROW_N(res);
884
885         if (nr_rows == 0)
886         {
887                 /* no match */ 
888                 LM_DBG("No rows found\n");
889                 pua_dbf.free_result(pua_db, res);
890                 return(NULL);
891         }
892
893         if (nr_rows != 1)
894         {
895                 LM_ERR("Too many rows found (%d)\n", nr_rows);
896                 pua_dbf.free_result(pua_db, res);
897                 return(NULL);
898         }
899
900         /* get the results and fill in return data structure */
901         rows = RES_ROWS(res);
902         values = ROW_VALUES(rows);
903
904         extract_row( values, result );
905
906         *dbres = res;
907
908         return(result);
909 }
910
911 /******************************************************************************/
912
913 int delete_record_puadb(ua_pres_t *pres)
914 {
915         db_key_t q_cols[2];
916         db_val_t q_vals[2];
917         int n_query_cols = 0;
918
919         if (pres==NULL)
920         {
921                 LM_ERR("called with NULL param\n");
922                 return(-1);
923         }
924
925         q_cols[n_query_cols] = &str_pres_id_col;        
926         q_vals[n_query_cols].type = DB1_STR;
927         q_vals[n_query_cols].nul = 0;
928         q_vals[n_query_cols].val.str_val = pres->id;
929         n_query_cols++;
930
931         if (pres->etag.s)
932         {
933                 q_cols[n_query_cols] = &str_etag_col;
934                 q_vals[n_query_cols].type = DB1_STR;
935                 q_vals[n_query_cols].nul = 0;
936                 q_vals[n_query_cols].val.str_val = pres->etag;
937                 n_query_cols++;
938         }
939
940         if(pua_db == NULL)
941         {
942                 LM_ERR("null database connection\n");
943                 return(-1);
944         }
945
946         if (pua_dbf.use_table(pua_db, &db_table) < 0)
947         {
948                 LM_ERR("error in use_table pua\n");
949                 return(-1);
950         }
951
952         if (pua_dbf.delete(pua_db, q_cols, 0, q_vals, n_query_cols) < 0) 
953         {
954                 LM_ERR("deleting record\n");
955                 return -1;
956         }
957
958         return 1;
959 }
960
961 /******************************************************************************/
962
963 int update_record_puadb(ua_pres_t *pres, int expires, str *etag)
964 {
965         db_key_t q_cols[2], u_cols[3];
966         db_val_t q_vals[2], u_vals[3];
967         int n_query_cols = 0, n_update_cols = 0;
968
969         if (pres==NULL)
970         {
971                 LM_ERR("called with NULL param\n");
972                 return(-1);
973         }
974
975         q_cols[n_query_cols] = &str_pres_id_col;        
976         q_vals[n_query_cols].type = DB1_STR;
977         q_vals[n_query_cols].nul = 0;
978         q_vals[n_query_cols].val.str_val = pres->id;
979         n_query_cols++;
980
981         if (pres->etag.s)
982         {
983                 q_cols[n_query_cols] = &str_etag_col;
984                 q_vals[n_query_cols].type = DB1_STR;
985                 q_vals[n_query_cols].nul = 0;
986                 q_vals[n_query_cols].val.str_val = pres->etag;
987                 n_query_cols++;
988         }
989
990         u_cols[n_update_cols] = &str_desired_expires_col;
991         u_vals[n_update_cols].type = DB1_INT;
992         u_vals[n_update_cols].nul = 0;
993         u_vals[n_update_cols].val.int_val = pres->desired_expires;
994         n_update_cols++;
995
996         u_cols[n_update_cols] = &str_expires_col;
997         u_vals[n_update_cols].type = DB1_INT;
998         u_vals[n_update_cols].nul = 0;
999         u_vals[n_update_cols].val.int_val = expires + (int) time(NULL);
1000         n_update_cols++;
1001
1002         if (etag)
1003         {
1004                 u_cols[n_update_cols] = &str_etag_col;
1005                 u_vals[n_update_cols].type = DB1_STR;
1006                 u_vals[n_update_cols].nul = 0;
1007                 u_vals[n_update_cols].val.str_val.s = etag->s;
1008                 u_vals[n_update_cols].val.str_val.len = etag->len;
1009                 n_update_cols++;
1010         }
1011
1012         if(pua_db == NULL)
1013         {
1014                 LM_ERR("null database connection\n");
1015                 return(-1);
1016         }
1017
1018         if (pua_dbf.use_table(pua_db, &db_table) < 0)
1019         {
1020                 LM_ERR("error in use_table pua\n");
1021                 return(-1);
1022         }
1023
1024         if (pua_dbf.update(pua_db, q_cols, 0, q_vals, u_cols, u_vals,
1025                         n_query_cols, n_update_cols) < 0)
1026         {
1027                 LM_ERR("updating dialog\n");
1028                 return -1;
1029         }
1030
1031         if (pua_dbf.affected_rows != NULL)
1032                 return pua_dbf.affected_rows(pua_db);
1033
1034         return 1;
1035 }
1036
1037 /******************************************************************************/
1038
1039 int insert_dialog_puadb(ua_pres_t* pres)
1040
1041 {
1042         db_key_t db_cols[18];
1043         db_val_t db_vals[18];
1044         int n_cols= 0;
1045
1046         if (pres==NULL)
1047         {
1048                 LM_ERR("called with NULL param\n");
1049                 return(-1);
1050         }
1051
1052         db_cols[n_cols] = &str_pres_uri_col;
1053         db_vals[n_cols].type = DB1_STR;
1054         db_vals[n_cols].nul = 0;
1055         db_vals[n_cols].val.str_val.s = pres->pres_uri->s;
1056         db_vals[n_cols].val.str_val.len = pres->pres_uri->len;
1057         n_cols++;
1058
1059         db_cols[n_cols] = &str_pres_id_col;     
1060         db_vals[n_cols].type = DB1_STR;
1061         db_vals[n_cols].nul = 0;
1062         db_vals[n_cols].val.str_val.s = pres->id.s;
1063         db_vals[n_cols].val.str_val.len = pres->id.len;
1064         n_cols++;
1065
1066         db_cols[n_cols] = &str_event_col;       
1067         db_vals[n_cols].type = DB1_INT;
1068         db_vals[n_cols].nul = 0;
1069         db_vals[n_cols].val.int_val = pres->event;
1070         n_cols++;
1071
1072         db_cols[n_cols] = &str_expires_col;
1073         db_vals[n_cols].type = DB1_INT;
1074         db_vals[n_cols].nul = 0;
1075         db_vals[n_cols].val.int_val = pres->expires;
1076         n_cols++;
1077
1078         db_cols[n_cols] = &str_desired_expires_col;
1079         db_vals[n_cols].type = DB1_INT;
1080         db_vals[n_cols].nul = 0;
1081         db_vals[n_cols].val.int_val = pres->desired_expires;
1082         n_cols++;
1083
1084         db_cols[n_cols] = &str_flag_col;
1085         db_vals[n_cols].type = DB1_INT;
1086         db_vals[n_cols].nul = 0;
1087         db_vals[n_cols].val.int_val = pres->flag;
1088         n_cols++;
1089
1090         db_cols[n_cols] = &str_etag_col;
1091         db_vals[n_cols].type = DB1_STR;
1092         db_vals[n_cols].nul = 0; 
1093         db_vals[n_cols].val.str_val.s = "";
1094         db_vals[n_cols].val.str_val.len = 0;
1095         n_cols++;
1096
1097         db_cols[n_cols] = &str_tuple_id_col;
1098         db_vals[n_cols].type = DB1_STR;
1099         db_vals[n_cols].nul = 0; 
1100         db_vals[n_cols].val.str_val.s = "";
1101         db_vals[n_cols].val.str_val.len = 0;
1102         n_cols++;
1103
1104         db_cols[n_cols] = &str_watcher_uri_col;
1105         db_vals[n_cols].type = DB1_STR;
1106         db_vals[n_cols].nul = 0; 
1107         db_vals[n_cols].val.str_val.s = pres->watcher_uri->s;
1108         db_vals[n_cols].val.str_val.len = pres->watcher_uri->len;
1109         n_cols++;
1110
1111         db_cols[n_cols] = &str_call_id_col;
1112         db_vals[n_cols].type = DB1_STR;
1113         db_vals[n_cols].nul = 0; 
1114         db_vals[n_cols].val.str_val.s = pres->call_id.s;
1115         db_vals[n_cols].val.str_val.len = pres->call_id.len;
1116         n_cols++;
1117
1118         db_cols[n_cols] = &str_to_tag_col;
1119         db_vals[n_cols].type = DB1_STR;
1120         db_vals[n_cols].nul = 0; 
1121         db_vals[n_cols].val.str_val.s = pres->to_tag.s;
1122         db_vals[n_cols].val.str_val.len = pres->to_tag.len;
1123         n_cols++;
1124
1125         db_cols[n_cols] = &str_from_tag_col;
1126         db_vals[n_cols].type = DB1_STR;
1127         db_vals[n_cols].nul = 0; 
1128         db_vals[n_cols].val.str_val.s = pres->from_tag.s;
1129         db_vals[n_cols].val.str_val.len = pres->from_tag.len;
1130         n_cols++;
1131
1132         db_cols[n_cols] = &str_cseq_col;
1133         db_vals[n_cols].type = DB1_INT;
1134         db_vals[n_cols].nul = 0;
1135         db_vals[n_cols].val.int_val = pres->cseq;
1136         n_cols++;
1137
1138         db_cols[n_cols] = &str_record_route_col;
1139         db_vals[n_cols].type = DB1_STR;
1140         db_vals[n_cols].nul = 0; 
1141         db_vals[n_cols].val.str_val.s = pres->record_route.s;
1142         db_vals[n_cols].val.str_val.len = pres->record_route.len;
1143         n_cols++;
1144
1145         db_cols[n_cols] = &str_contact_col;
1146         db_vals[n_cols].type = DB1_STR;
1147         db_vals[n_cols].nul = 0; 
1148         db_vals[n_cols].val.str_val.s = pres->contact.s;
1149         db_vals[n_cols].val.str_val.len = pres->contact.len;
1150         n_cols++;
1151
1152         db_cols[n_cols] = &str_remote_contact_col;
1153         db_vals[n_cols].type = DB1_STR;
1154         db_vals[n_cols].nul = 0; 
1155         db_vals[n_cols].val.str_val.s = pres->remote_contact.s;
1156         db_vals[n_cols].val.str_val.len = pres->remote_contact.len;
1157         n_cols++;
1158
1159         db_cols[n_cols] = &str_version_col;
1160         db_vals[n_cols].type = DB1_INT;
1161         db_vals[n_cols].nul = 0;
1162         db_vals[n_cols].val.int_val = pres->version;
1163         n_cols++;
1164
1165         db_cols[n_cols] = &str_extra_headers_col;
1166         db_vals[n_cols].type = DB1_STR;
1167         db_vals[n_cols].nul = 0; 
1168         if (pres->extra_headers)
1169         {
1170                 db_vals[n_cols].val.str_val.s = pres->extra_headers->s;
1171                 db_vals[n_cols].val.str_val.len = pres->extra_headers->len;
1172         }
1173         else
1174         {
1175                 db_vals[n_cols].val.str_val.s = "";
1176                 db_vals[n_cols].val.str_val.len = 0;
1177         }
1178         n_cols++;
1179
1180         if(pua_db == NULL)
1181         {
1182                 LM_ERR("null database connection\n");
1183                 return(-1);
1184         }
1185
1186         if(pua_dbf.insert(pua_db, db_cols, db_vals, n_cols) < 0)  
1187         {
1188                 LM_ERR("DB insert failed\n");
1189                 return(-1);
1190         }
1191
1192         return(0);
1193 }
1194
1195 /******************************************************************************/
1196
1197 ua_pres_t *get_dialog_puadb(str pres_id, str *pres_uri, ua_pres_t *result, db1_res_t **dbres)
1198 {
1199         db_key_t q_cols[2];
1200         db_val_t q_vals[2], *values;
1201         db_row_t *rows;
1202         db1_res_t *res;
1203         int n_query_cols = 0, nr_rows;
1204         db_query_f query_fn = pua_dbf.query_lock ? pua_dbf.query_lock : pua_dbf.query;
1205
1206         if (pres_uri == NULL)
1207         {
1208                 LM_ERR("Attempting to search for a dialog without specifying pres_uri\n");
1209                 return(NULL);
1210         }
1211
1212         q_cols[n_query_cols] = &str_pres_id_col;        
1213         q_vals[n_query_cols].type = DB1_STR;
1214         q_vals[n_query_cols].nul = 0;
1215         q_vals[n_query_cols].val.str_val = pres_id;
1216         n_query_cols++;
1217
1218         q_cols[n_query_cols] = &str_pres_uri_col;
1219         q_vals[n_query_cols].type = DB1_STR;
1220         q_vals[n_query_cols].nul = 0;
1221         q_vals[n_query_cols].val.str_val.s = pres_uri->s;
1222         q_vals[n_query_cols].val.str_val.len = pres_uri->len;
1223         n_query_cols++;
1224
1225         if(pua_db == NULL)
1226         {
1227                 LM_ERR("null database connection\n");
1228                 return(NULL);
1229         }
1230
1231         if (pua_dbf.use_table(pua_db, &db_table) < 0)
1232         {
1233                 LM_ERR("error in use_table pua\n");
1234                 return(NULL);
1235         }
1236
1237         if(query_fn(pua_db, q_cols, 0, q_vals,
1238                                 NULL,n_query_cols,0,0,&res) < 0)
1239         {
1240                 LM_ERR("DB query error\n");
1241                 return(NULL);
1242         }
1243
1244         if (res == NULL)
1245         {
1246                 LM_ERR("bad result\n");
1247                 return(NULL);
1248         }
1249
1250         nr_rows = RES_ROW_N(res);
1251
1252         if (nr_rows == 0)
1253         {
1254                 /* no match */ 
1255                 LM_DBG("No rows found\n");
1256                 pua_dbf.free_result(pua_db, res);
1257                 return(NULL);
1258         }
1259         else if (nr_rows > 1)
1260         {
1261                 LM_ERR("Too many rows found (%d)... deleting\n", nr_rows);
1262                 pua_dbf.free_result(pua_db, res);
1263
1264                 if (pua_dbf.delete(pua_db, q_cols, 0, q_vals, n_query_cols) < 0) 
1265                         LM_ERR("deleting record(s)\n");
1266
1267                 return(NULL);
1268         }
1269
1270         /* get the results and fill in return data structure */
1271         rows = RES_ROWS(res);
1272         values = ROW_VALUES(rows);
1273
1274         extract_row( values, result );
1275
1276         /*pua_dbf.free_result(pua_db, res);*/
1277         *dbres = res;
1278
1279         return(result);
1280 }
1281
1282 /******************************************************************************/
1283
1284 int delete_dialog_puadb(ua_pres_t *pres)
1285 {
1286         db_key_t q_cols[3];
1287         db_val_t q_vals[3];
1288         int n_query_cols = 0;
1289
1290         if (pres==NULL)
1291         {
1292                 LM_ERR("called with NULL param\n");
1293                 return(-1);
1294         }
1295
1296         q_cols[n_query_cols] = &str_call_id_col;        
1297         q_vals[n_query_cols].type = DB1_STR;
1298         q_vals[n_query_cols].nul = 0;
1299         q_vals[n_query_cols].val.str_val = pres->call_id;
1300         n_query_cols++;
1301
1302         q_cols[n_query_cols] = &str_from_tag_col;       
1303         q_vals[n_query_cols].type = DB1_STR;
1304         q_vals[n_query_cols].nul = 0;
1305         q_vals[n_query_cols].val.str_val = pres->from_tag;
1306         n_query_cols++;
1307
1308         if (pres->to_tag.len > 0 && pres->to_tag.s != NULL)
1309         {
1310                 q_cols[n_query_cols] = &str_to_tag_col; 
1311                 q_vals[n_query_cols].type = DB1_STR;
1312                 q_vals[n_query_cols].nul = 0;
1313                 q_vals[n_query_cols].val.str_val = pres->to_tag;
1314                 n_query_cols++;
1315         }
1316         
1317         if(pua_db == NULL)
1318         {
1319                 LM_ERR("null database connection\n");
1320                 return(-1);
1321         }
1322
1323         if (pua_dbf.use_table(pua_db, &db_table) < 0)
1324         {
1325                 LM_ERR("error in use_table pua\n");
1326                 return(-1);
1327         }
1328
1329         if (pua_dbf.delete(pua_db, q_cols, 0, q_vals, n_query_cols) < 0) 
1330         {
1331                 LM_ERR("deleting record\n");
1332                 return -1;
1333         }
1334
1335         return 1;
1336 }
1337
1338 /******************************************************************************/
1339
1340 int update_dialog_puadb(ua_pres_t *pres, int expires, str *contact)
1341 {
1342         db_key_t q_cols[3], u_cols[4];
1343         db_val_t q_vals[3], u_vals[4];
1344         int n_query_cols = 0, n_update_cols = 0;
1345
1346         if (pres==NULL)
1347         {
1348                 LM_ERR("called with NULL param\n");
1349                 return(-1);
1350         }
1351
1352         q_cols[n_query_cols] = &str_call_id_col;        
1353         q_vals[n_query_cols].type = DB1_STR;
1354         q_vals[n_query_cols].nul = 0;
1355         q_vals[n_query_cols].val.str_val = pres->call_id;
1356         n_query_cols++;
1357
1358         q_cols[n_query_cols] = &str_from_tag_col;       
1359         q_vals[n_query_cols].type = DB1_STR;
1360         q_vals[n_query_cols].nul = 0;
1361         q_vals[n_query_cols].val.str_val = pres->from_tag;
1362         n_query_cols++;
1363
1364         q_cols[n_query_cols] = &str_to_tag_col; 
1365         q_vals[n_query_cols].type = DB1_STR;
1366         q_vals[n_query_cols].nul = 0;
1367         q_vals[n_query_cols].val.str_val = pres->to_tag;
1368         n_query_cols++;
1369
1370         u_cols[n_update_cols] = &str_desired_expires_col;
1371         u_vals[n_update_cols].type = DB1_INT;
1372         u_vals[n_update_cols].nul = 0;
1373         u_vals[n_update_cols].val.int_val = pres->desired_expires;
1374         n_update_cols++;
1375
1376         u_cols[n_update_cols] = &str_expires_col;
1377         u_vals[n_update_cols].type = DB1_INT;
1378         u_vals[n_update_cols].nul = 0;
1379         u_vals[n_update_cols].val.int_val = expires + (int) time(NULL);
1380         n_update_cols++;
1381
1382         u_cols[n_update_cols] = &str_cseq_col;
1383         u_vals[n_update_cols].type = DB1_INT;
1384         u_vals[n_update_cols].nul = 0;
1385         u_vals[n_update_cols].val.int_val = pres->cseq;
1386         n_update_cols++;
1387
1388         u_cols[n_update_cols] = &str_remote_contact_col;
1389         u_vals[n_update_cols].type = DB1_STR;
1390         u_vals[n_update_cols].nul = 0;
1391         u_vals[n_update_cols].val.str_val.s = contact->s;
1392         u_vals[n_update_cols].val.str_val.len = contact->len;
1393         n_update_cols++;
1394
1395         if(pua_db == NULL)
1396         {
1397                 LM_ERR("null database connection\n");
1398                 return(-1);
1399         }
1400
1401         if (pua_dbf.use_table(pua_db, &db_table) < 0)
1402         {
1403                 LM_ERR("error in use_table pua\n");
1404                 return(-1);
1405         }
1406
1407         if (pua_dbf.update(pua_db, q_cols, 0, q_vals, u_cols, u_vals,
1408                         n_query_cols, n_update_cols) < 0)
1409         {
1410                 LM_ERR("updating dialog\n");
1411                 return -1;
1412         }
1413
1414         return 1;
1415 }
1416
1417 /******************************************************************************/
1418
1419 int update_contact_puadb(ua_pres_t *pres, str *contact) 
1420
1421 {
1422         db_key_t q_cols[3], db_cols[1];
1423         db_val_t q_vals[3], db_vals[1];
1424         int n_query_cols= 0, n_update_cols=0;
1425
1426         if (pres==NULL)
1427         {
1428                 LM_ERR("called with NULL param\n");
1429                 return(-1);
1430         }
1431
1432         /* cols and values used for search query */
1433         q_cols[n_query_cols] = &str_call_id_col;        
1434         q_vals[n_query_cols].type = DB1_STR;
1435         q_vals[n_query_cols].nul = 0;
1436         q_vals[n_query_cols].val.str_val = pres->call_id;
1437         n_query_cols++;
1438
1439         q_cols[n_query_cols] = &str_to_tag_col; 
1440         q_vals[n_query_cols].type = DB1_STR;
1441         q_vals[n_query_cols].nul = 0;
1442         q_vals[n_query_cols].val.str_val = pres->to_tag;
1443         n_query_cols++;
1444
1445         q_cols[n_query_cols] = &str_from_tag_col;       
1446         q_vals[n_query_cols].type = DB1_STR;
1447         q_vals[n_query_cols].nul = 0;
1448         q_vals[n_query_cols].val.str_val = pres->from_tag;
1449         n_query_cols++;
1450
1451         /* we overwrite contact even if not changed */
1452         db_cols[n_update_cols] = &str_remote_contact_col;
1453         db_vals[n_update_cols].type = DB1_STR;
1454         db_vals[n_update_cols].nul = 0; 
1455         db_vals[n_update_cols].val.str_val.s = contact->s;
1456         db_vals[n_update_cols].val.str_val.len = contact->len;
1457         n_update_cols++;
1458
1459
1460         if(pua_db == NULL)
1461         {
1462                 LM_ERR("null database connection\n");
1463                 return(-1);
1464         }
1465
1466         if (pua_dbf.use_table(pua_db, &db_table) < 0)
1467         {
1468                 LM_ERR("error in use_table pua\n");
1469                 return(-1);
1470         }
1471
1472         if(pua_dbf.update(pua_db, q_cols, 0, q_vals,
1473                                 db_cols,db_vals,n_query_cols,n_update_cols) < 0)
1474         {
1475                 LM_ERR("DB update failed\n");
1476                 return(-1);
1477         }
1478
1479         return(0);
1480 }
1481
1482
1483 /******************************************************************************/
1484
1485 int update_version_puadb(ua_pres_t *pres) 
1486
1487 {
1488         db_key_t q_cols[3], db_cols[1];
1489         db_val_t q_vals[3], db_vals[1];
1490         int n_query_cols= 0, n_update_cols=0;
1491
1492         if (pres==NULL)
1493         {
1494                 LM_ERR("called with NULL param\n");
1495                 return(-1);
1496         }
1497
1498         /* cols and values used for search query */
1499         q_cols[n_query_cols] = &str_call_id_col;        
1500         q_vals[n_query_cols].type = DB1_STR;
1501         q_vals[n_query_cols].nul = 0;
1502         q_vals[n_query_cols].val.str_val = pres->call_id;
1503         n_query_cols++;
1504
1505         q_cols[n_query_cols] = &str_to_tag_col; 
1506         q_vals[n_query_cols].type = DB1_STR;
1507         q_vals[n_query_cols].nul = 0;
1508         q_vals[n_query_cols].val.str_val = pres->to_tag;
1509         n_query_cols++;
1510
1511         q_cols[n_query_cols] = &str_from_tag_col;       
1512         q_vals[n_query_cols].type = DB1_STR;
1513         q_vals[n_query_cols].nul = 0;
1514         q_vals[n_query_cols].val.str_val = pres->from_tag;
1515         n_query_cols++;
1516
1517         /* we overwrite contact even if not changed */
1518         db_cols[n_update_cols] = &str_version_col;
1519         db_vals[n_update_cols].type = DB1_INT;
1520         db_vals[n_update_cols].nul = 0;
1521         db_vals[n_update_cols].val.int_val = pres->version;
1522         n_update_cols++;
1523
1524         if(pua_db == NULL)
1525         {
1526                 LM_ERR("null database connection\n");
1527                 return(-1);
1528         }
1529
1530         if (pua_dbf.use_table(pua_db, &db_table) < 0)
1531         {
1532                 LM_ERR("error in use_table pua\n");
1533                 return(-1);
1534         }
1535
1536         if(pua_dbf.update(pua_db, q_cols, 0, q_vals,
1537                                 db_cols,db_vals,n_query_cols,n_update_cols) < 0)
1538
1539         {
1540                 LM_ERR("DB update failed\n");
1541                 return(-1);
1542         }
1543
1544         return(0);
1545 }
1546
1547 /******************************************************************************/
1548
1549 list_entry_t *get_subs_list_puadb(str *did)
1550 {
1551         list_entry_t *list = NULL;
1552         db_key_t q_cols[1], res_cols[1];
1553         db1_res_t *res= NULL;
1554         db_val_t q_vals[1];
1555         int n_query_cols= 0, n_res_cols = 0;
1556
1557         /* cols and values used for search query */
1558         q_cols[n_query_cols] = &str_pres_id_col;
1559         q_vals[n_query_cols].type = DB1_STR;
1560         q_vals[n_query_cols].nul = 0;
1561         q_vals[n_query_cols].val.str_val.s = did->s;
1562         q_vals[n_query_cols].val.str_val.len = did->len;
1563         n_query_cols++;
1564
1565         res_cols[n_res_cols] = &str_pres_uri_col;
1566         n_res_cols++;
1567
1568         if(pua_db == NULL)
1569         {
1570                 LM_ERR("null database connection\n");
1571                 return list;
1572         }
1573
1574         if (pua_dbf.use_table(pua_db, &db_table) < 0)
1575         {
1576                 LM_ERR("error in use_table pua\n");
1577                 return(list);
1578         }
1579
1580         if(db_fetch_query(&pua_dbf, pua_fetch_rows, pua_db, q_cols, 0,
1581                                 q_vals, res_cols, n_query_cols, n_res_cols, 0, &res) < 0)
1582         {
1583                 LM_ERR("DB query error\n");
1584                 return list;
1585         }
1586
1587         if (res == NULL)
1588         {
1589                 LM_ERR("bad result\n");
1590                 return list;
1591         }
1592
1593         if (RES_ROW_N(res) == 0)
1594         {
1595                 LM_INFO( "No records found\n");
1596                 pua_dbf.free_result(pua_db, res);
1597                 return list;
1598         }
1599
1600         do {
1601                 int i, nr_rows;
1602                 db_row_t *rows;
1603                 nr_rows = RES_ROW_N(res);
1604                 rows = RES_ROWS(res);
1605
1606                 for (i=0; i < nr_rows; i++)
1607                 {
1608                         str strng, *tmp_str;
1609                         strng.s = (char *) VAL_STRING(ROW_VALUES(rows+i));
1610                         strng.len = strlen(VAL_STRING(ROW_VALUES(rows+i)));
1611
1612                         if ((tmp_str = (str *)pkg_malloc(sizeof(str))) == NULL)
1613                         {
1614                                 LM_ERR("out of private memory\n");
1615                                 pua_dbf.free_result(pua_db, res);
1616                                 return list;
1617                         }
1618                         if ((tmp_str->s = (char *)pkg_malloc(sizeof(char) * strng.len + 1)) == NULL)
1619                         {
1620                                 pkg_free(tmp_str);
1621                                 LM_ERR("out of private memory\n");
1622                                 pua_dbf.free_result(pua_db, res);
1623                                 return list;
1624                         }
1625                         memcpy(tmp_str->s, strng.s, strng.len);
1626                         tmp_str->len = strng.len;
1627                         tmp_str->s[tmp_str->len] = '\0';
1628
1629                         list = list_insert(tmp_str, list, NULL);
1630                 }
1631         } while ((db_fetch_next(&pua_dbf, pua_fetch_rows, pua_db, &res)==1)
1632                         && (RES_ROWS(res)>0));
1633
1634         pua_dbf.free_result(pua_db, res);
1635         
1636         return list;
1637 }