- support for SCTP in contact building
[sip-router] / modules_k / presence / subscribe.c
1 /*
2  * $Id$
3  *
4  * presence module - presence server implementation
5  *
6  * Copyright (C) 2006 Voice Sistem S.R.L.
7  *
8  * This file is part of openser, a free SIP serves.
9  *
10  * Kamailio is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version
14  *
15  * Kamailio is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License 
21  * along with this program; if not, write to the Free Software 
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  *
24  * History:
25  * --------
26  *  2006-08-15  initial version (anca)
27  */
28
29 /*! \file
30  * \brief Kamailio presence module :: Support for SUBSCRIBE handling
31  * \ingroup presence 
32  */
33
34
35 #include "../../ut.h"
36 #include "../../usr_avp.h"
37 #include "../../data_lump_rpl.h"
38 #include "../../parser/parse_expires.h"
39 #include "../../parser/parse_event.h"
40 #include "../../parser/contact/parse_contact.h"
41 #include "presence.h"
42 #include "subscribe.h"
43 #include "utils_func.h"
44 #include "notify.h"
45 #include "../pua/hash.h"
46
47 int get_stored_info(struct sip_msg* msg, subs_t* subs, int* error_ret,
48                 str* reply_str);
49 int get_database_info(struct sip_msg* msg, subs_t* subs, int* error_ret,
50                 str* reply_str);
51 int get_db_subs_auth(subs_t* subs, int* found);
52 int insert_db_subs_auth(subs_t* subs);
53
54 static str su_200_rpl  = str_init("OK");
55 static str pu_481_rpl  = str_init("Subscription does not exist");
56 static str pu_400_rpl  = str_init("Bad request");
57 static str pu_500_rpl  = str_init("Server Internal Error");
58 static str pu_489_rpl  = str_init("Bad Event");
59
60
61 int send_2XX_reply(struct sip_msg * msg, int reply_code, int lexpire,
62                 str* local_contact)
63 {
64         str hdr_append = {0, 0};
65         str tmp;
66         char *t = NULL;
67         
68         tmp.s = int2str((unsigned long)lexpire, &tmp.len);
69         hdr_append.len = 9 + tmp.len + CRLF_LEN
70                 + 10 + local_contact->len + 16 + CRLF_LEN;
71         hdr_append.s = (char *)pkg_malloc(sizeof(char)*(hdr_append.len+1));
72         if(hdr_append.s == NULL)
73         {
74                 ERR_MEM(PKG_MEM_STR);
75         }
76         strncpy(hdr_append.s, "Expires: ", 9);
77         strncpy(hdr_append.s+9, tmp.s, tmp.len);
78         tmp.s = hdr_append.s+9+tmp.len;
79         strncpy(tmp.s, CRLF, CRLF_LEN);
80         tmp.s += CRLF_LEN;
81         strncpy(tmp.s, "Contact: <", 10);
82         tmp.s += 10;
83         strncpy(tmp.s, local_contact->s, local_contact->len);
84         tmp.s[local_contact->len] = '\0';
85         t = strstr(tmp.s, ";transport=");
86         tmp.s += local_contact->len;
87         if(t==NULL)
88         {
89                 switch (msg->rcv.proto)
90                 {
91                         case PROTO_TCP:
92                                 strncpy(tmp.s, ";transport=tcp", 14);
93                                 tmp.s += 14;
94                                 hdr_append.len -= 1;
95                         break;
96                         case PROTO_TLS:
97                                 strncpy(tmp.s, ";transport=tls", 14);
98                                 tmp.s += 14;
99                                 hdr_append.len -= 1;
100                         break;
101                         case PROTO_SCTP:
102                                 strncpy(tmp.s, ";transport=sctp", 15);
103                                 tmp.s += 15;
104                         break;
105                         default:
106                                 hdr_append.len -= 15;
107                 }
108         } else {
109                 hdr_append.len -= 15;
110         }
111         *tmp.s = '>';
112         strncpy(tmp.s+1, CRLF, CRLF_LEN);
113
114         hdr_append.s[hdr_append.len]= '\0';
115         
116         if (add_lump_rpl( msg, hdr_append.s, hdr_append.len, LUMP_RPL_HDR)==0 )
117         {
118                 LM_ERR("unable to add lump_rl\n");
119                 goto error;
120         }
121
122         if( slb.send_reply(msg, reply_code, &su_200_rpl)== -1)
123         {
124                 LM_ERR("sending reply\n");
125                 goto error;
126         }
127         
128         pkg_free(hdr_append.s);
129         return 0;
130
131 error:
132
133         if(hdr_append.s!=NULL)
134                 pkg_free(hdr_append.s);
135         return -1;
136 }
137
138
139 int delete_db_subs(str pres_uri, str ev_stored_name, str to_tag)
140 {
141         db_key_t query_cols[5];
142         db_val_t query_vals[5];
143         int n_query_cols= 0;
144
145         query_cols[n_query_cols] = &str_presentity_uri_col;
146         query_vals[n_query_cols].type = DB_STR;
147         query_vals[n_query_cols].nul = 0;
148         query_vals[n_query_cols].val.str_val = pres_uri;
149         n_query_cols++;
150
151         query_cols[n_query_cols] = &str_event_col;
152         query_vals[n_query_cols].type = DB_STR;
153         query_vals[n_query_cols].nul = 0;
154         query_vals[n_query_cols].val.str_val = ev_stored_name;
155         n_query_cols++;
156
157         query_cols[n_query_cols] = &str_to_tag_col;
158         query_vals[n_query_cols].type = DB_STR;
159         query_vals[n_query_cols].nul = 0;
160         query_vals[n_query_cols].val.str_val = to_tag;
161         n_query_cols++;
162         
163         if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0) 
164         {
165                 LM_ERR("in use table sql operation\n");
166                 return -1;
167         }
168
169         if(pa_dbf.delete(pa_db, query_cols, 0, query_vals,
170                                 n_query_cols)< 0 )
171         {
172                 LM_ERR("sql delete failed\n");
173                 return -1;
174         }
175
176         return 0;
177 }
178
179 int update_subs_db(subs_t* subs, int type)
180 {
181         db_key_t query_cols[22], update_keys[7];
182         db_val_t query_vals[22], update_vals[7];
183         int n_update_cols= 0;
184         int n_query_cols = 0;
185
186         query_cols[n_query_cols] = &str_presentity_uri_col;
187         query_vals[n_query_cols].type = DB_STR;
188         query_vals[n_query_cols].nul = 0;
189         query_vals[n_query_cols].val.str_val = subs->pres_uri;
190         n_query_cols++;
191         
192         query_cols[n_query_cols] = &str_watcher_username_col;
193         query_vals[n_query_cols].type = DB_STR;
194         query_vals[n_query_cols].nul = 0;
195         query_vals[n_query_cols].val.str_val = subs->from_user;
196         n_query_cols++;
197         
198         query_cols[n_query_cols] = &str_watcher_domain_col;
199         query_vals[n_query_cols].type = DB_STR;
200         query_vals[n_query_cols].nul = 0;
201         query_vals[n_query_cols].val.str_val = subs->from_domain;
202         n_query_cols++;
203
204         query_cols[n_query_cols] = &str_event_col;
205         query_vals[n_query_cols].type = DB_STR;
206         query_vals[n_query_cols].nul = 0;
207         query_vals[n_query_cols].val.str_val = subs->event->name;
208         n_query_cols++;
209
210         if(subs->event_id.s)
211         {
212                 query_cols[n_query_cols] = &str_event_id_col;
213                 query_vals[n_query_cols].type = DB_STR;
214                 query_vals[n_query_cols].nul = 0;
215                 query_vals[n_query_cols].val.str_val = subs->event_id;
216                 n_query_cols++;
217         }
218         query_cols[n_query_cols] = &str_callid_col;
219         query_vals[n_query_cols].type = DB_STR;
220         query_vals[n_query_cols].nul = 0;
221         query_vals[n_query_cols].val.str_val = subs->callid;
222         n_query_cols++;
223
224         query_cols[n_query_cols] = &str_to_tag_col;
225         query_vals[n_query_cols].type = DB_STR;
226         query_vals[n_query_cols].nul = 0;
227         query_vals[n_query_cols].val.str_val = subs->to_tag;
228         n_query_cols++;
229
230         query_cols[n_query_cols] = &str_from_tag_col;
231         query_vals[n_query_cols].type = DB_STR;
232         query_vals[n_query_cols].nul = 0;
233         query_vals[n_query_cols].val.str_val = subs->from_tag;
234         n_query_cols++;
235
236         if(type & REMOTE_TYPE)
237         {
238                 update_keys[n_update_cols] = &str_expires_col;
239                 update_vals[n_update_cols].type = DB_INT;
240                 update_vals[n_update_cols].nul = 0;
241                 update_vals[n_update_cols].val.int_val = subs->expires + (int)time(NULL);
242                 n_update_cols++;
243         
244                 update_keys[n_update_cols] = &str_remote_cseq_col;
245                 update_vals[n_update_cols].type = DB_INT;
246                 update_vals[n_update_cols].nul = 0;
247                 update_vals[n_update_cols].val.int_val = subs->remote_cseq; 
248                 n_update_cols++;
249         }
250         else
251         {       
252                 update_keys[n_update_cols] = &str_local_cseq_col;
253                 update_vals[n_update_cols].type = DB_INT;
254                 update_vals[n_update_cols].nul = 0;
255                 update_vals[n_update_cols].val.int_val = subs->local_cseq+ 1;
256                 n_update_cols++;
257         
258                 update_keys[n_update_cols] = &str_version_col;
259                 update_vals[n_update_cols].type = DB_INT;
260                 update_vals[n_update_cols].nul = 0;
261                 update_vals[n_update_cols].val.int_val = subs->version+ 1;
262                 n_update_cols++;
263         }
264
265         update_keys[n_update_cols] = &str_status_col;
266         update_vals[n_update_cols].type = DB_INT;
267         update_vals[n_update_cols].nul = 0;
268         update_vals[n_update_cols].val.int_val = subs->status;
269         n_update_cols++;
270
271         update_keys[n_update_cols] = &str_reason_col;
272         update_vals[n_update_cols].type = DB_STR;
273         update_vals[n_update_cols].nul = 0;
274         update_vals[n_update_cols].val.str_val = subs->reason;
275         n_update_cols++;
276         
277         if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0)
278         {
279                 LM_ERR("in use table sql operation\n"); 
280                 return -1;
281         }
282                 
283         if( pa_dbf.update( pa_db,query_cols, 0, query_vals,
284                                 update_keys, update_vals, n_query_cols,n_update_cols)<0) 
285         {
286                 LM_ERR("updating presence information\n");
287                 return -1;
288         }
289         return 0;
290 }
291
292 int update_subscription(struct sip_msg* msg, subs_t* subs, int to_tag_gen,
293                 int* sent_reply)
294 {       
295         unsigned int hash_code;
296         
297         printf_subs(subs);      
298         
299         *sent_reply= 0;
300
301         hash_code= core_hash(&subs->pres_uri, &subs->event->name, shtable_size);
302
303         if( to_tag_gen ==0) /*if a SUBSCRIBE within a dialog */
304         {
305                 if(subs->expires == 0)
306                 {
307                         LM_DBG("expires =0 -> deleting record\n");
308                 
309                         if( delete_db_subs(subs->pres_uri, 
310                                                 subs->event->name, subs->to_tag)< 0)
311                         {
312                                 LM_ERR("deleting subscription record from database\n");
313                                 goto error;
314                         }
315                         /* delete record from hash table also */
316
317                         subs->local_cseq= delete_shtable(subs_htable,hash_code,
318                                         subs->to_tag);
319                 
320                         if(subs->event->type & PUBL_TYPE)
321                         {       
322                                 if( send_2XX_reply(msg, 202, subs->expires,
323                                                         &subs->local_contact) <0)
324                                 {
325                                         LM_ERR("sending 202 OK\n");
326                                         goto error;
327                                 }
328                                 *sent_reply= 1;
329                                 if(subs->event->wipeer)
330                                 {
331                                         if(query_db_notify(&subs->pres_uri,
332                                                                 subs->event->wipeer, NULL)< 0)
333                                         {
334                                                 LM_ERR("Could not send notify for winfo\n");
335                                                 goto error;
336                                         }
337                                 }
338
339                         }       
340                         else /* if unsubscribe for winfo */
341                         {
342                                 if( send_2XX_reply(msg, 200, subs->expires,
343                                                         &subs->local_contact) <0)
344                                 {
345                                         LM_ERR("sending 200 OK reply\n");
346                                         goto error;
347                                 }
348                                 *sent_reply= 1;
349                         }
350                 
351                         if(notify(subs, NULL, NULL, 0)< 0)
352                         {
353                                 LM_ERR("Could not send notify\n");
354                                 goto error;
355                         }
356                         return 1;
357                 }
358
359                 if(update_shtable(subs_htable, hash_code, subs, REMOTE_TYPE)< 0)
360                 {
361                         if(fallback2db)
362                         {
363                                 /* update in database table */
364                                 if(update_subs_db(subs, REMOTE_TYPE)< 0)
365                                 {
366                                         LM_ERR("updating subscription in database table\n");
367                                         goto error;
368                                 }
369                         }
370                         else
371                         {
372                                 LM_ERR("updating subscription record in hash table\n");
373                                 goto error;
374                         }
375                 }
376         }
377         else
378         {
379                 if(subs->expires!= 0)
380                 {       
381                         if(insert_shtable(subs_htable,hash_code,subs)< 0)
382                         {
383                                 LM_ERR("inserting new record in subs_htable\n");
384                                 goto error;
385                         }
386                 }
387                 /*otherwise there is a subscription outside a dialog with expires= 0 
388                  * no update in database, but should try to send Notify */
389         }
390
391 /* reply_and_notify  */
392
393         if(subs->event->type & PUBL_TYPE)
394         {       
395                 if(send_2XX_reply(msg, 202, subs->expires,
396                                         &subs->local_contact)<0)
397                 {
398                         LM_ERR("sending 202 OK reply\n");
399                         goto error;
400                 }
401                 *sent_reply= 1;
402                 
403                 if(subs->expires!= 0 && subs->event->wipeer)
404                 {       
405                         LM_DBG("send Notify with winfo\n");
406                         if(query_db_notify(&subs->pres_uri, subs->event->wipeer, subs)< 0)
407                         {
408                                 LM_ERR("Could not send notify winfo\n");
409                                 goto error;
410                         }       
411                         if(subs->send_on_cback== 0)
412                         {       
413                                 if(notify(subs, NULL, NULL, 0)< 0)
414                                 {
415                                         LM_ERR("Could not send notify\n");
416                                         goto error;
417                                 }
418                         }
419                 }
420                 else
421                 {
422                         if(notify(subs, NULL, NULL, 0)< 0)
423                         {
424                                 LM_ERR("Could not send notify\n");
425                                 goto error;
426                         }
427                 }       
428                         
429         }
430         else 
431         {
432                 if( send_2XX_reply(msg, 200, subs->expires,
433                                         &subs->local_contact)<0)
434                 {
435                         LM_ERR("sending 200 OK reply\n");
436                         goto error;
437                 }               
438                 *sent_reply= 1;
439                 
440                 if(notify(subs, NULL, NULL, 0 )< 0)
441                 {
442                         LM_ERR("sending notify request\n");
443                         goto error;
444                 }
445         }
446         return 0;
447         
448 error:
449
450         LM_ERR("occured\n");
451         return -1;
452
453 }
454
455 void msg_watchers_clean(unsigned int ticks,void *param)
456 {
457         db_key_t db_keys[3], result_cols[1];
458         db_val_t db_vals[3];
459         db_op_t  db_ops[3] ;
460         db_res_t *result= NULL;
461
462         LM_DBG("cleaning pending subscriptions\n");
463         
464         db_keys[0] = &str_inserted_time_col;
465         db_ops[0] = OP_LT;
466         db_vals[0].type = DB_INT;
467         db_vals[0].nul = 0;
468         db_vals[0].val.int_val = (int)time(NULL)- 24*3600 ;
469
470         db_keys[1] = &str_status_col;
471         db_ops [1] = OP_EQ;
472         db_vals[1].type = DB_INT;
473         db_vals[1].nul = 0;
474         db_vals[1].val.int_val = PENDING_STATUS;
475         
476         result_cols[0]= &str_id_col;
477
478         if (pa_dbf.use_table(pa_db, &watchers_table) < 0) 
479         {
480                 LM_ERR("unsuccessful use table sql operation\n");
481                 return ;
482         }
483         
484         if(pa_dbf.query(pa_db, db_keys, db_ops, db_vals, result_cols, 2, 1, 0, &result )< 0)
485         {
486                 LM_ERR("querying database for expired messages\n");
487                 if(result)
488                         pa_dbf.free_result(pa_db, result);
489                 return;
490         }
491         if(result == NULL)
492                 return;
493         if(result->n <= 0)
494         {
495                 pa_dbf.free_result(pa_db, result);
496                 return;
497         }
498         pa_dbf.free_result(pa_db, result);
499
500         if (pa_dbf.delete(pa_db, db_keys, db_ops, db_vals, 2) < 0) 
501                 LM_ERR("cleaning pending subscriptions\n");
502 }
503
504 int handle_subscribe(struct sip_msg* msg, char* str1, char* str2)
505 {
506         int  to_tag_gen = 0;
507         subs_t subs;
508         pres_ev_t* event= NULL;
509         event_t* parsed_event= NULL;
510         param_t* ev_param= NULL;
511         int found;
512         str reason= {0, 0};
513         struct sip_uri uri;
514         int reply_code;
515         str reply_str;
516         int sent_reply= 0;
517
518         /* ??? rename to avoid collisions with other symbols */
519         counter++;
520
521         memset(&subs, 0, sizeof(subs_t));
522         
523         reply_code= 500;
524         reply_str= pu_500_rpl;
525
526         if( parse_headers(msg,HDR_EOH_F, 0)==-1 )
527         {
528                 LM_ERR("parsing headers\n");
529                 reply_code= 400;
530                 reply_str= pu_400_rpl;
531                 goto error;
532         }
533         
534         /* inspecting the Event header field */
535         if(msg->event && msg->event->body.len > 0)
536         {
537                 if (!msg->event->parsed && (parse_event(msg->event) < 0))
538                 {
539                         reply_code= 400;
540                         reply_str= pu_400_rpl;
541                         goto error;
542                 }
543                 if(((event_t*)msg->event->parsed)->parsed == EVENT_OTHER)
544                 {       
545                         goto bad_event;
546                 }
547         }
548         else
549                 goto bad_event;
550
551         /* search event in the list */
552         parsed_event= (event_t*)msg->event->parsed;
553         event= search_event(parsed_event);
554         if(event== NULL)
555         {
556                 goto bad_event;
557         }
558         subs.event= event;
559         
560         /* extract the id if any*/
561         ev_param= parsed_event->params;
562         while(ev_param)
563         {
564                 if(ev_param->name.len== 2 && strncmp(ev_param->name.s, "id", 2)== 0)
565                 {
566                         subs.event_id= ev_param->body;
567                         break;
568                 }
569                 ev_param= ev_param->next;
570         }               
571         
572         if(extract_sdialog_info(&subs, msg, max_expires, &to_tag_gen,
573                                 server_address)< 0)
574         {
575                 LM_ERR("failed to extract dialog information\n");
576                 goto error;
577         }
578
579         /* getting presentity uri from Request-URI if initial subscribe - or else from database*/
580         if(to_tag_gen)
581         {
582                 if(parsed_event->parsed!= EVENT_DIALOG_SLA)
583                 {
584                         if( parse_sip_msg_uri(msg)< 0)
585                         {
586                                 LM_ERR("failed to parse R-URI\n");
587                                 return -1;
588                         }
589                         if(uandd_to_uri(msg->parsed_uri.user, msg->parsed_uri.host,
590                                         &subs.pres_uri)< 0)
591                         {
592                                 LM_ERR("failed to construct uri from user and domain\n");
593                                 goto error;
594                         }
595                 }
596         }
597         else
598         {
599                 if(get_stored_info(msg, &subs, &reply_code, &reply_str )< 0)
600                 {
601                         LM_ERR("getting stored info\n");
602                         goto error;
603                 }
604                 reason= subs.reason;
605         }       
606
607         /* call event specific subscription handling */
608         if(event->evs_subs_handl)
609         {
610                 if(event->evs_subs_handl(msg)< 0)
611                 {
612                         LM_ERR("in event specific subscription handling\n");
613                         goto error;
614                 }
615         }       
616
617
618         /* if dialog initiation Subscribe - get subscription state */
619         if(to_tag_gen)
620         {
621                 if(!event->req_auth) 
622                         subs.status = ACTIVE_STATUS;
623                 else   
624                 {
625                         /* query in watchers_table */
626                         if(get_db_subs_auth(&subs, &found)< 0)
627                         {
628                                 LM_ERR("getting subscription status from watchers table\n");
629                                 goto error;
630                         }
631                         if(found== 0)
632                         {
633                                 /*default 'pending' status */
634                                 subs.status= PENDING_STATUS;
635                                 subs.reason.s= NULL;
636                                 subs.reason.len= 0;
637                                 /* here a query to xcap server must be done -> new process maybe */
638                         
639                                 if(parse_uri(subs.pres_uri.s, subs.pres_uri.len, &uri)< 0)
640                                 {
641                                         LM_ERR("parsing uri\n");
642                                         goto error;
643
644                                 }
645                                 if(subs.event->get_rules_doc(&uri.user, &uri.host, &subs.auth_rules_doc)< 0)
646                                 {
647                                         LM_ERR("getting rules doc\n");
648                                         goto error;
649                                 }
650                                 
651                                 if(subs.event->get_auth_status(&subs)< 0)
652                                 {
653                                         LM_ERR("in event specific function is_watcher_allowed\n");
654                                         goto error;
655                                 }
656                                 if(get_status_str(subs.status)== NULL)
657                                 {
658                                         LM_ERR("wrong status= %d\n", subs.status);
659                                         goto error;
660                                 }
661
662                                 if(insert_db_subs_auth(&subs)< 0)
663                                 {
664                                         LM_ERR("while inserting record in watchers table\n");
665                                         goto error;
666                                 }
667                         }
668                         else
669                         {
670                                 reason= subs.reason;
671                         }
672                 }
673         }
674
675         /* check if correct status */
676         if(get_status_str(subs.status)== NULL)
677         {
678                 LM_ERR("wrong status\n");
679                 goto error;
680         }
681     LM_DBG("subscription status= %s - %s\n", get_status_str(subs.status), 
682             found==0?"inserted":"found in watcher table");
683         
684         if(update_subscription(msg, &subs, to_tag_gen, &sent_reply) <0)
685         {       
686                 LM_ERR("in update_subscription\n");
687                 goto error;
688         }
689         if(subs.auth_rules_doc)
690         {
691                 pkg_free(subs.auth_rules_doc->s);
692                 pkg_free(subs.auth_rules_doc);
693         }
694         if(reason.s)
695                 pkg_free(reason.s);
696         
697         if(subs.pres_uri.s)
698                 pkg_free(subs.pres_uri.s);
699         
700         if((!server_address.s) || (server_address.len== 0))
701         {
702                 pkg_free(subs.local_contact.s);
703         }
704         if(subs.record_route.s)
705                 pkg_free(subs.record_route.s);
706
707         return 1;
708
709 bad_event:
710
711         LM_ERR("Missing or unsupported event header field value\n");
712                 
713         if(parsed_event && parsed_event->text.s)
714                 LM_ERR("\tevent= %.*s\n",parsed_event->text.len,parsed_event->text.s);
715         
716         reply_code= BAD_EVENT_CODE;
717         reply_str= pu_489_rpl;
718
719 error:
720         
721         if(sent_reply== 0)
722         {
723                 if(send_error_reply(msg, reply_code, reply_str)< 0)
724                 {
725                         LM_ERR("failed to send reply on error case\n");
726                 }
727         }
728
729         if(subs.pres_uri.s)     
730                 pkg_free(subs.pres_uri.s);
731         
732         if(subs.auth_rules_doc)
733         {
734                 if(subs.auth_rules_doc->s)
735                         pkg_free(subs.auth_rules_doc->s);
736                 pkg_free(subs.auth_rules_doc);
737         }
738         if(reason.s)
739                 pkg_free(reason.s);
740
741         if(((!server_address.s) ||(server_address.len== 0))&& subs.local_contact.s)
742         {
743                 pkg_free(subs.local_contact.s);
744         }
745         if(subs.record_route.s)
746                 pkg_free(subs.record_route.s);
747
748         return -1;
749
750 }
751
752
753 int extract_sdialog_info(subs_t* subs,struct sip_msg* msg, int mexp,
754                 int* to_tag_gen, str scontact)
755 {
756         str rec_route= {0, 0};
757         int rt  = 0;
758         str* contact= NULL;
759         contact_body_t *b;
760         struct to_body *pto, *pfrom = NULL, TO;
761         int lexpire;
762         str rtag_value;
763         struct sip_uri uri;
764
765         /* examine the expire header field */
766         if(msg->expires && msg->expires->body.len > 0)
767         {
768                 if (!msg->expires->parsed && (parse_expires(msg->expires) < 0))
769                 {
770                         LM_ERR("cannot parse Expires header\n");
771                         goto error;
772                 }
773                 lexpire = ((exp_body_t*)msg->expires->parsed)->val;
774                 LM_DBG("'Expires' header found, value= %d\n", lexpire);
775
776         }
777         else 
778         {
779                 LM_DBG("'expires' not found; default=%d\n",subs->event->default_expires);
780                 lexpire = subs->event->default_expires;
781         }
782         if(lexpire > mexp)
783                 lexpire = mexp;
784
785         subs->expires = lexpire;
786
787         if( msg->to==NULL || msg->to->body.s==NULL)
788         {
789                 LM_ERR("cannot parse TO header\n");
790                 goto error;
791         }
792         /* examine the to header */
793         if(msg->to->parsed != NULL)
794         {
795                 pto = (struct to_body*)msg->to->parsed;
796                 LM_DBG("'To' header ALREADY PARSED: <%.*s>\n",pto->uri.len,pto->uri.s);
797         }
798         else
799         {
800                 memset( &TO , 0, sizeof(TO) );
801                 if( !parse_to(msg->to->body.s,msg->to->body.s + msg->to->body.len + 1, &TO));
802                 {
803                         LM_DBG("'To' header NOT parsed\n");
804                         goto error;
805                 }
806                 pto = &TO;
807         }
808
809         if( pto->parsed_uri.user.s && pto->parsed_uri.host.s &&
810                 pto->parsed_uri.user.len && pto->parsed_uri.host.len)
811         {
812                 subs->to_user = pto->parsed_uri.user;
813                 subs->to_domain = pto->parsed_uri.host;
814         }
815         else
816         {
817                 if(parse_uri(pto->uri.s, pto->uri.len, &uri)< 0)
818                 {
819                         LM_ERR("while parsing uri\n");
820                         goto error;
821                 }
822                 subs->to_user = uri.user;
823                 subs->to_domain = uri.host;
824         }
825
826         /* examine the from header */
827         if (!msg->from || !msg->from->body.s)
828         {
829                 LM_DBG("cannot find 'from' header!\n");
830                 goto error;
831         }
832         if (msg->from->parsed == NULL)
833         {
834                 LM_DBG("'From' header not parsed\n");
835                 /* parsing from header */
836                 if ( parse_from_header( msg )<0 ) 
837                 {
838                         LM_DBG("cannot parse From header\n");
839                         goto error;
840                 }
841         }
842         pfrom = (struct to_body*)msg->from->parsed;
843         
844         if( pfrom->parsed_uri.user.s && pfrom->parsed_uri.host.s && 
845                 pfrom->parsed_uri.user.len && pfrom->parsed_uri.host.len)
846         {
847                 subs->from_user = pfrom->parsed_uri.user;
848                 subs->from_domain = pfrom->parsed_uri.host;
849         }
850         else
851         {
852                 if(parse_uri(pfrom->uri.s, pfrom->uri.len, &uri)< 0)
853                 {
854                         LM_ERR("while parsing uri\n");
855                         goto error;
856                 }
857                 subs->from_user = uri.user;
858                 subs->from_domain = uri.host;
859         }
860
861         /* get to_tag if the message does not have a to_tag*/
862         if (pto->tag_value.s==NULL || pto->tag_value.len==0 )
863         {  
864                 LM_DBG("generating to_tag\n");
865                 *to_tag_gen = 1;
866                 rtag_value.len = 0;
867                 if(slb.get_reply_totag(msg, &rtag_value)<0 || rtag_value.len <= 0)
868                 {
869                         LM_ERR("while creating to_tag\n");
870                         goto error;
871                 }
872         }
873         else
874         {
875                 *to_tag_gen = 0;
876                 rtag_value=pto->tag_value;
877         }
878         subs->to_tag = rtag_value;
879
880         if( msg->callid==NULL || msg->callid->body.s==NULL)
881         {
882                 LM_ERR("cannot parse callid header\n");
883                 goto error;
884         }
885         subs->callid = msg->callid->body;
886
887         if( msg->cseq==NULL || msg->cseq->body.s==NULL)
888         {
889                 LM_ERR("cannot parse cseq header\n");
890                 goto error;
891         }
892         if (str2int( &(get_cseq(msg)->number), &subs->remote_cseq)!=0 )
893         {
894                 LM_ERR("cannot parse cseq number\n");
895                 goto error;
896         }
897         if( msg->contact==NULL || msg->contact->body.s==NULL)
898         {
899                 LM_ERR("cannot parse contact header\n");
900                 goto error;
901         }
902         if( parse_contact(msg->contact) <0 )
903         {
904                 LM_ERR(" cannot parse contact"
905                                 " header\n");
906                 goto error;
907         }
908         b= (contact_body_t* )msg->contact->parsed;
909
910         if(b == NULL)
911         {
912                 LM_ERR("cannot parse contact header\n");
913                 goto error;
914         }
915         subs->contact = b->contacts->uri;
916         
917         LM_DBG("subs->contact= %.*s - len = %d\n",subs->contact.len,
918                         subs->contact.s, subs->contact.len);    
919
920     if(subs->event->evp->parsed== EVENT_DIALOG_SLA)
921     {
922         /* user_contact@from_domain */
923         if(parse_uri(subs->contact.s, subs->contact.len, &uri)< 0)
924         {
925             LM_ERR("failed to parse contact uri\n");
926             goto error;
927         }
928         if(uandd_to_uri(uri.user, subs->from_domain, &subs->pres_uri)< 0)
929         {
930             LM_ERR("failed to construct uri\n");
931             goto error;
932         }
933         LM_DBG("&&&&&&&&&&&&&&& dialog pres_uri= %.*s\n",subs->pres_uri.len, subs->pres_uri.s);
934     }
935
936
937         /*process record route and add it to a string*/
938         if(*to_tag_gen && msg->record_route!=NULL)
939         {
940                 rt = print_rr_body(msg->record_route, &rec_route, 0, 0);
941                 if(rt != 0)
942                 {
943                         LM_ERR("processing the record route [%d]\n", rt);       
944                         rec_route.s=NULL;
945                         rec_route.len=0;
946                 //      goto error;
947                 }
948         }
949         subs->record_route = rec_route;
950                         
951         subs->sockinfo_str= msg->rcv.bind_address->sock_str;
952
953         if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0)
954         {
955                 LM_ERR("no from tag value present\n");
956                 goto error;
957         }
958         subs->from_tag = pfrom->tag_value;
959
960         subs->version = 0;
961         
962         if((!scontact.s) || (scontact.len== 0))
963         {
964                 contact= get_local_contact(msg);
965                 if(contact== NULL)
966                 {
967                         LM_ERR("in function get_local_contact\n");
968                         goto error;
969                 }
970                 subs->local_contact= *contact;
971         }
972         else
973                 subs->local_contact= scontact;
974         
975         return 0;
976         
977 error:
978
979         return -1;
980 }
981
982
983 int get_stored_info(struct sip_msg* msg, subs_t* subs, int* reply_code,
984                 str* reply_str)
985 {       
986         str pres_uri= {0, 0}, reason={0, 0};
987         subs_t* s;
988         int i;
989         unsigned int hash_code;
990
991         /* first try to_user== pres_user and to_domain== pres_domain */
992
993     if(subs->pres_uri.s == NULL)
994     {
995             uandd_to_uri(subs->to_user, subs->to_domain, &pres_uri);
996             if(pres_uri.s== NULL)
997             {
998                     LM_ERR("creating uri from user and domain\n");
999                     return -1;
1000             }
1001     }
1002     else
1003         pres_uri = subs->pres_uri;
1004
1005         hash_code= core_hash(&pres_uri, &subs->event->name, shtable_size);
1006         lock_get(&subs_htable[hash_code].lock);
1007         i= hash_code;
1008         s= search_shtable(subs_htable, subs->callid, subs->to_tag,
1009                         subs->from_tag, hash_code);
1010         if(s)
1011         {
1012                 goto found_rec;
1013         }
1014         lock_release(&subs_htable[hash_code].lock);
1015
1016     if(subs->pres_uri.s)
1017         goto not_found;
1018         
1019     pkg_free(pres_uri.s);
1020         pres_uri.s= NULL;
1021         
1022
1023     LM_DBG("record not found using R-URI search iteratively\n");
1024         /* take one row at a time */
1025         for(i= 0; i< shtable_size; i++)
1026         {
1027                 lock_get(&subs_htable[i].lock);
1028                 s= search_shtable(subs_htable, subs->callid,subs->to_tag,subs->from_tag, i);
1029                 if(s && s->event->evp->parsed!= EVENT_DIALOG_SLA)
1030                 {
1031                         pres_uri.s= (char*)pkg_malloc(s->pres_uri.len* sizeof(char));
1032                         if(pres_uri.s== NULL)
1033                         {
1034                                 lock_release(&subs_htable[i].lock);
1035                                 ERR_MEM(PKG_MEM_STR);
1036                         }
1037                         memcpy(pres_uri.s, s->pres_uri.s, s->pres_uri.len);
1038                         pres_uri.len= s->pres_uri.len;
1039                         goto found_rec;
1040                 }
1041                 lock_release(&subs_htable[i].lock);
1042         }
1043
1044         if(fallback2db)
1045         {
1046                 return get_database_info(msg, subs, reply_code, reply_str);     
1047         }
1048
1049 not_found:
1050
1051         LM_ERR("record not found in hash_table\n");
1052         *reply_code= 481;
1053         *reply_str= pu_481_rpl;
1054
1055         return -1;
1056
1057 found_rec:
1058         
1059         LM_DBG("Record found in hash_table\n");
1060         
1061         if(s->event->evp->parsed!= EVENT_DIALOG_SLA)
1062                 subs->pres_uri= pres_uri;
1063         
1064         subs->version = s->version;
1065         subs->status= s->status;
1066         if(s->reason.s && s->reason.len)
1067         {       
1068                 reason.s= (char*)pkg_malloc(s->reason.len* sizeof(char));
1069                 if(reason.s== NULL)
1070                 {
1071                         lock_release(&subs_htable[i].lock);
1072                         ERR_MEM(PKG_MEM_STR);
1073                 }
1074                 memcpy(reason.s, s->reason.s, s->reason.len);
1075                 reason.len= s->reason.len;
1076                 subs->reason= reason;
1077         }
1078         if(s->record_route.s && s->record_route.len)
1079         {
1080                 subs->record_route.s= (char*)pkg_malloc
1081                         (s->record_route.len* sizeof(char));
1082                 if(subs->record_route.s== NULL)
1083                 {
1084                         ERR_MEM(PKG_MEM_STR);
1085                 }
1086                 memcpy(subs->record_route.s, s->record_route.s, s->record_route.len);
1087                 subs->record_route.len= s->record_route.len;
1088         }
1089
1090         subs->local_cseq= s->local_cseq;
1091         
1092         if(subs->remote_cseq<= s->remote_cseq)
1093         {
1094                 LM_ERR("wrong sequence number;received: %d - stored: %d\n",
1095                                 subs->remote_cseq, s->remote_cseq);
1096                 
1097                 *reply_code= 400;
1098                 *reply_str= pu_400_rpl;
1099
1100                 lock_release(&subs_htable[i].lock);
1101                 goto error;
1102         }       
1103         lock_release(&subs_htable[i].lock);
1104
1105         return 0;
1106
1107 error:
1108         if(subs->reason.s)
1109                 pkg_free(subs->reason.s);
1110         subs->reason.s= NULL;
1111         if(subs->record_route.s)
1112                 pkg_free(subs->record_route.s);
1113         subs->record_route.s= NULL;
1114         return -1;
1115 }
1116
1117 int get_database_info(struct sip_msg* msg, subs_t* subs, int* reply_code, str* reply_str)
1118 {       
1119         db_key_t query_cols[10];
1120         db_val_t query_vals[10];
1121         db_key_t result_cols[9];
1122         db_res_t *result= NULL;
1123         db_row_t *row ; 
1124         db_val_t *row_vals ;
1125         int n_query_cols = 0;
1126         int n_result_cols = 0;
1127         int remote_cseq_col= 0, local_cseq_col= 0, status_col, reason_col;
1128         int record_route_col, version_col;
1129         int pres_uri_col;
1130         unsigned int remote_cseq;
1131         str pres_uri, record_route;
1132         str reason;
1133
1134         query_cols[n_query_cols] = &str_to_user_col;
1135         query_vals[n_query_cols].type = DB_STR;
1136         query_vals[n_query_cols].nul = 0;
1137         query_vals[n_query_cols].val.str_val = subs->to_user;
1138         n_query_cols++;
1139         
1140         query_cols[n_query_cols] = &str_to_domain_col;
1141         query_vals[n_query_cols].type = DB_STR;
1142         query_vals[n_query_cols].nul = 0;
1143         query_vals[n_query_cols].val.str_val = subs->to_domain;
1144         n_query_cols++;
1145
1146         query_cols[n_query_cols] = &str_watcher_username_col;
1147         query_vals[n_query_cols].type = DB_STR;
1148         query_vals[n_query_cols].nul = 0;
1149         query_vals[n_query_cols].val.str_val = subs->from_user;
1150         n_query_cols++;
1151         
1152         query_cols[n_query_cols] = &str_watcher_domain_col;
1153         query_vals[n_query_cols].type = DB_STR;
1154         query_vals[n_query_cols].nul = 0;
1155         query_vals[n_query_cols].val.str_val = subs->from_domain;
1156         n_query_cols++;
1157
1158         query_cols[n_query_cols] = &str_event_col;
1159         query_vals[n_query_cols].type = DB_STR;
1160         query_vals[n_query_cols].nul = 0;
1161         query_vals[n_query_cols].val.str_val = subs->event->name;
1162         n_query_cols++;
1163
1164         query_cols[n_query_cols] = &str_event_id_col;
1165         query_vals[n_query_cols].type = DB_STR;
1166         query_vals[n_query_cols].nul = 0;
1167         if( subs->event_id.s != NULL)
1168         {
1169                 query_vals[n_query_cols].val.str_val.s = subs->event_id.s;
1170                 query_vals[n_query_cols].val.str_val.len = subs->event_id.len;
1171         } else {
1172                 query_vals[n_query_cols].val.str_val.s = "";
1173                 query_vals[n_query_cols].val.str_val.len = 0;
1174         }
1175         n_query_cols++;
1176         
1177         query_cols[n_query_cols] = &str_callid_col;
1178         query_vals[n_query_cols].type = DB_STR;
1179         query_vals[n_query_cols].nul = 0;
1180         query_vals[n_query_cols].val.str_val = subs->callid;
1181         n_query_cols++;
1182
1183         query_cols[n_query_cols] = &str_to_tag_col;
1184         query_vals[n_query_cols].type = DB_STR;
1185         query_vals[n_query_cols].nul = 0;
1186         query_vals[n_query_cols].val.str_val = subs->to_tag;
1187         n_query_cols++;
1188
1189         query_cols[n_query_cols] = &str_from_tag_col;
1190         query_vals[n_query_cols].type = DB_STR;
1191         query_vals[n_query_cols].nul = 0;
1192         query_vals[n_query_cols].val.str_val = subs->from_tag;
1193         n_query_cols++;
1194
1195         result_cols[pres_uri_col=n_result_cols++] = &str_presentity_uri_col;
1196         result_cols[remote_cseq_col=n_result_cols++] = &str_remote_cseq_col;
1197         result_cols[local_cseq_col=n_result_cols++] = &str_local_cseq_col;
1198         result_cols[status_col=n_result_cols++] = &str_status_col;
1199         result_cols[reason_col=n_result_cols++] = &str_reason_col;
1200         result_cols[record_route_col=n_result_cols++] = &str_record_route_col;
1201         result_cols[version_col=n_result_cols++] = &str_version_col;
1202         
1203         if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0) 
1204         {
1205                 LM_ERR("unsuccessful use_table sql operation\n");
1206                 return -1;
1207         }
1208         
1209         if (pa_dbf.query (pa_db, query_cols, 0, query_vals,
1210                  result_cols, n_query_cols, n_result_cols, 0,  &result) < 0) 
1211         {
1212                 LM_ERR("querying subscription dialog\n");
1213                 if(result)
1214                         pa_dbf.free_result(pa_db, result);
1215                 return -1;
1216         }
1217         if(result== NULL)
1218                 return -1;
1219
1220         if(result && result->n <=0)
1221         {
1222                 LM_ERR("No matching subscription dialog found in database\n");
1223                 
1224                 pa_dbf.free_result(pa_db, result);
1225                 *reply_code= 481;
1226                 *reply_str= pu_481_rpl;
1227
1228                 return -1;
1229         }
1230
1231         row = &result->rows[0];
1232         row_vals = ROW_VALUES(row);
1233         remote_cseq= row_vals[remote_cseq_col].val.int_val;
1234         
1235         if(subs->remote_cseq<= remote_cseq)
1236         {
1237                 LM_ERR("wrong sequence number received: %d - stored: %d\n",
1238                                 subs->remote_cseq, remote_cseq);
1239                 *reply_code= 400;
1240                 *reply_str= pu_400_rpl;
1241                 pa_dbf.free_result(pa_db, result);
1242                 return -1;
1243         }
1244         
1245         subs->status= row_vals[status_col].val.int_val;
1246         reason.s= (char*)row_vals[reason_col].val.string_val;
1247         if(reason.s)
1248         {
1249                 reason.len= strlen(reason.s);
1250                 subs->reason.s= (char*)pkg_malloc(reason.len* sizeof(char));
1251                 if(subs->reason.s== NULL)
1252                 {
1253                         ERR_MEM(PKG_MEM_STR);
1254                 }
1255                 memcpy(subs->reason.s, reason.s, reason.len);
1256                 subs->reason.len= reason.len;
1257         }
1258
1259         subs->local_cseq= row_vals[local_cseq_col].val.int_val;
1260         subs->version= row_vals[version_col].val.int_val;
1261
1262         if(subs->event->evp->parsed!= EVENT_DIALOG_SLA)
1263         {
1264                 pres_uri.s= (char*)row_vals[pres_uri_col].val.string_val;
1265                 pres_uri.len= strlen(pres_uri.s);
1266                 subs->pres_uri.s= (char*)pkg_malloc(pres_uri.len* sizeof(char));
1267                 if(subs->pres_uri.s== NULL)
1268                 {       
1269                         if(subs->reason.s)
1270                                 pkg_free(subs->reason.s);
1271                         ERR_MEM(PKG_MEM_STR);
1272                 }
1273                 memcpy(subs->pres_uri.s, pres_uri.s, pres_uri.len);
1274                 subs->pres_uri.len= pres_uri.len;
1275         }
1276
1277         record_route.s= (char*)row_vals[record_route_col].val.string_val;
1278         if(record_route.s)
1279         {
1280                 record_route.len= strlen(record_route.s);
1281                 subs->record_route.s= (char*)pkg_malloc(record_route.len*sizeof(char));
1282                 if(subs->record_route.s== NULL)
1283                 {
1284                         ERR_MEM(PKG_MEM_STR);
1285                 }
1286                 memcpy(subs->record_route.s, record_route.s, record_route.len);
1287                 subs->record_route.len= record_route.len;
1288         }
1289
1290         pa_dbf.free_result(pa_db, result);
1291         result= NULL;
1292
1293         return 0;
1294 error:
1295         if(result)
1296                 pa_dbf.free_result(pa_db, result);
1297
1298         return -1;
1299
1300 }
1301
1302
1303 int handle_expired_subs(subs_t* s)
1304 {
1305         /* send Notify with state=terminated;reason=timeout */
1306         
1307         s->status= TERMINATED_STATUS;
1308         s->reason.s= "timeout";
1309         s->reason.len= 7;
1310         s->expires= 0;
1311
1312         if(send_notify_request(s, NULL, NULL, 1)< 0)
1313         {
1314                 LM_ERR("send Notify not successful\n");
1315                 return -1;
1316         }
1317         
1318         return 0;
1319
1320 }
1321
1322 void timer_db_update(unsigned int ticks,void *param)
1323 {       
1324         int no_lock=0;
1325
1326         if(ticks== 0 && param == NULL)
1327                 no_lock= 1;
1328         
1329         if(pa_dbf.use_table(pa_db, &active_watchers_table)< 0)
1330         {
1331                 LM_ERR("sql use table failed\n");
1332                 return;
1333         }
1334
1335         update_db_subs(pa_db, pa_dbf, subs_htable, 
1336                         shtable_size, no_lock, handle_expired_subs);
1337
1338 }
1339
1340 void update_db_subs(db_con_t *db,db_func_t dbf, shtable_t hash_table,
1341         int htable_size, int no_lock, handle_expired_func_t handle_expired_func)
1342 {       
1343         db_key_t query_cols[22], update_cols[7];
1344         db_val_t query_vals[22], update_vals[7];
1345         db_op_t update_ops[1];
1346         subs_t* del_s;
1347         int pres_uri_col, to_user_col, to_domain_col, from_user_col, from_domain_col,
1348                 callid_col, totag_col, fromtag_col, event_col,status_col, event_id_col, 
1349                 local_cseq_col, remote_cseq_col, expires_col, record_route_col, 
1350                 contact_col, local_contact_col, version_col,socket_info_col,reason_col;
1351         int u_expires_col, u_local_cseq_col, u_remote_cseq_col, u_version_col, 
1352                 u_reason_col, u_status_col; 
1353         int i;
1354         subs_t* s= NULL, *prev_s= NULL;
1355         int n_query_cols= 0, n_update_cols= 0;
1356         int n_query_update;
1357
1358         query_cols[pres_uri_col= n_query_cols] =&str_presentity_uri_col;
1359         query_vals[pres_uri_col].type = DB_STR;
1360         query_vals[pres_uri_col].nul = 0;
1361         n_query_cols++;
1362         
1363         query_cols[callid_col= n_query_cols] =&str_callid_col;
1364         query_vals[callid_col].type = DB_STR;
1365         query_vals[callid_col].nul = 0;
1366         n_query_cols++;
1367
1368         query_cols[totag_col= n_query_cols] =&str_to_tag_col;
1369         query_vals[totag_col].type = DB_STR;
1370         query_vals[totag_col].nul = 0;
1371         n_query_cols++;
1372
1373         query_cols[fromtag_col= n_query_cols] =&str_from_tag_col;
1374         query_vals[fromtag_col].type = DB_STR;
1375         query_vals[fromtag_col].nul = 0;
1376         n_query_cols++;
1377
1378         n_query_update= n_query_cols;
1379
1380         query_cols[to_user_col= n_query_cols] =&str_to_user_col;
1381         query_vals[to_user_col].type = DB_STR;
1382         query_vals[to_user_col].nul = 0;
1383         n_query_cols++;
1384
1385         query_cols[to_domain_col= n_query_cols] =&str_to_domain_col;
1386         query_vals[to_domain_col].type = DB_STR;
1387         query_vals[to_domain_col].nul = 0;
1388         n_query_cols++;
1389         
1390         query_cols[from_user_col= n_query_cols] =&str_watcher_username_col;
1391         query_vals[from_user_col].type = DB_STR;
1392         query_vals[from_user_col].nul = 0;
1393         n_query_cols++;
1394
1395         query_cols[from_domain_col= n_query_cols] =&str_watcher_domain_col;
1396         query_vals[from_domain_col].type = DB_STR;
1397         query_vals[from_domain_col].nul = 0;
1398         n_query_cols++;
1399
1400         query_cols[event_col= n_query_cols] =&str_event_col;
1401         query_vals[event_col].type = DB_STR;
1402         query_vals[event_col].nul = 0;
1403         n_query_cols++; 
1404
1405         query_cols[event_id_col= n_query_cols] =&str_event_id_col;
1406         query_vals[event_id_col].type = DB_STR;
1407         query_vals[event_id_col].nul = 0;
1408         n_query_cols++;
1409
1410         query_cols[local_cseq_col= n_query_cols]=&str_local_cseq_col;
1411         query_vals[local_cseq_col].type = DB_INT;
1412         query_vals[local_cseq_col].nul = 0;
1413         n_query_cols++;
1414
1415         query_cols[remote_cseq_col= n_query_cols]=&str_remote_cseq_col;
1416         query_vals[remote_cseq_col].type = DB_INT;
1417         query_vals[remote_cseq_col].nul = 0;
1418         n_query_cols++;
1419
1420         query_cols[expires_col= n_query_cols] =&str_expires_col;
1421         query_vals[expires_col].type = DB_INT;
1422         query_vals[expires_col].nul = 0;
1423         n_query_cols++;
1424
1425         query_cols[status_col= n_query_cols] =&str_status_col;
1426         query_vals[status_col].type = DB_INT;
1427         query_vals[status_col].nul = 0;
1428         n_query_cols++;
1429
1430         query_cols[reason_col= n_query_cols] =&str_reason_col;
1431         query_vals[reason_col].type = DB_STR;
1432         query_vals[reason_col].nul = 0;
1433         n_query_cols++;
1434
1435         query_cols[record_route_col= n_query_cols] =&str_record_route_col;
1436         query_vals[record_route_col].type = DB_STR;
1437         query_vals[record_route_col].nul = 0;
1438         n_query_cols++;
1439         
1440         query_cols[contact_col= n_query_cols] =&str_contact_col;
1441         query_vals[contact_col].type = DB_STR;
1442         query_vals[contact_col].nul = 0;
1443         n_query_cols++;
1444
1445         query_cols[local_contact_col= n_query_cols] =&str_local_contact_col;
1446         query_vals[local_contact_col].type = DB_STR;
1447         query_vals[local_contact_col].nul = 0;
1448         n_query_cols++;
1449
1450         query_cols[socket_info_col= n_query_cols] =&str_socket_info_col;
1451         query_vals[socket_info_col].type = DB_STR;
1452         query_vals[socket_info_col].nul = 0;
1453         n_query_cols++;
1454
1455         query_cols[version_col= n_query_cols]=&str_version_col;
1456         query_vals[version_col].type = DB_INT;
1457         query_vals[version_col].nul = 0;
1458         n_query_cols++;
1459
1460         /* cols and values used for update */
1461         update_cols[u_expires_col= n_update_cols]= &str_expires_col;
1462         update_vals[u_expires_col].type = DB_INT;
1463         update_vals[u_expires_col].nul = 0;
1464         n_update_cols++;
1465
1466         update_cols[u_status_col= n_update_cols]= &str_status_col;
1467         update_vals[u_status_col].type = DB_INT;
1468         update_vals[u_status_col].nul = 0;
1469         n_update_cols++;
1470
1471         update_cols[u_reason_col= n_update_cols]= &str_reason_col;
1472         update_vals[u_reason_col].type = DB_STR;
1473         update_vals[u_reason_col].nul = 0;
1474         n_update_cols++;
1475
1476         update_cols[u_remote_cseq_col= n_update_cols]= &str_remote_cseq_col;
1477         update_vals[u_remote_cseq_col].type = DB_INT;
1478         update_vals[u_remote_cseq_col].nul = 0;
1479         n_update_cols++;
1480
1481         update_cols[u_local_cseq_col= n_update_cols]= &str_local_cseq_col;
1482         update_vals[u_local_cseq_col].type = DB_INT;
1483         update_vals[u_local_cseq_col].nul = 0;
1484         n_update_cols++;
1485         
1486         update_cols[u_version_col= n_update_cols]= &str_version_col;
1487         update_vals[u_version_col].type = DB_INT;
1488         update_vals[u_version_col].nul = 0;
1489         n_update_cols++;
1490
1491
1492         if(db== NULL)
1493         {
1494                 LM_ERR("null database connection\n");
1495                 return;
1496         }
1497         for(i=0; i<htable_size; i++) 
1498         {
1499                 if(!no_lock)
1500                         lock_get(&hash_table[i].lock);  
1501
1502                 prev_s= hash_table[i].entries;
1503                 s= prev_s->next;
1504         
1505                 while(s)
1506                 {
1507                         printf_subs(s);
1508                         if(s->expires < (int)time(NULL)- 50)    
1509                         {
1510                                 LM_DBG("Found expired record\n");
1511                                 if(!no_lock)
1512                                 {
1513                                         if(handle_expired_func(s)< 0)
1514                                         {
1515                                                 LM_ERR("in function handle_expired_record\n");
1516                                                 if(!no_lock)
1517                                                         lock_release(&hash_table[i].lock);      
1518                                                 return ;
1519                                         }
1520                                 }
1521                                 del_s= s;       
1522                                 s= s->next;
1523                                 prev_s->next= s;
1524                                 
1525                                 /* need for a struct free/destroy? */
1526                                 if (del_s->contact.s)
1527                                         shm_free(del_s->contact.s);
1528
1529                                 shm_free(del_s);
1530                                 continue;
1531                         }
1532                         switch(s->db_flag)
1533                         {
1534                                 case NO_UPDATEDB_FLAG:
1535                                 {
1536                                         LM_DBG("NO_UPDATEDB_FLAG\n");
1537                                         break;                    
1538                                 }
1539                                 case UPDATEDB_FLAG:
1540                                 {
1541                                         LM_DBG("UPDATEDB_FLAG\n");
1542
1543                                         query_vals[pres_uri_col].val.str_val= s->pres_uri;
1544                                         query_vals[callid_col].val.str_val= s->callid;
1545                                         query_vals[totag_col].val.str_val= s->to_tag;
1546                                         query_vals[fromtag_col].val.str_val= s->from_tag;
1547                                 
1548                                         update_vals[u_expires_col].val.int_val= s->expires;
1549                                         update_vals[u_local_cseq_col].val.int_val= s->local_cseq;
1550                                         update_vals[u_remote_cseq_col].val.int_val= s->remote_cseq;
1551                                         update_vals[u_version_col].val.int_val= s->version;
1552                                         update_vals[u_status_col].val.int_val= s->status;
1553                                         update_vals[u_reason_col].val.str_val= s->reason;
1554
1555                                         if(dbf.update(db, query_cols, 0, query_vals, update_cols, 
1556                                                                 update_vals, n_query_update, n_update_cols)< 0)
1557                                         {
1558                                                 LM_ERR("updating in database\n");
1559                                                 if(!no_lock)
1560                                                         lock_release(&hash_table[i].lock);      
1561                                                 return ;
1562                                         }
1563                                         break;
1564                                 }
1565                                 case  INSERTDB_FLAG:
1566                                 {
1567                                         LM_DBG("INSERTDB_FLAG\n");
1568
1569                                         query_vals[pres_uri_col].val.str_val= s->pres_uri;
1570                                         query_vals[callid_col].val.str_val= s->callid;
1571                                         query_vals[totag_col].val.str_val= s->to_tag;
1572                                         query_vals[fromtag_col].val.str_val= s->from_tag;
1573                                         query_vals[to_user_col].val.str_val = s->to_user;
1574                                         query_vals[to_domain_col].val.str_val = s->to_domain;
1575                                         query_vals[from_user_col].val.str_val = s->from_user;
1576                                         query_vals[from_domain_col].val.str_val = s->from_domain;
1577                                         query_vals[event_col].val.str_val = s->event->name;
1578                                         query_vals[event_id_col].val.str_val = s->event_id;
1579                                         query_vals[local_cseq_col].val.int_val= s->local_cseq;
1580                                         query_vals[remote_cseq_col].val.int_val= s->remote_cseq;
1581                                         query_vals[expires_col].val.int_val = s->expires;
1582                                         query_vals[record_route_col].val.str_val = s->record_route;
1583                                         query_vals[contact_col].val.str_val = s->contact;
1584                                         query_vals[local_contact_col].val.str_val = s->local_contact;
1585                                         query_vals[version_col].val.int_val= s->version;
1586                                         query_vals[status_col].val.int_val= s->status;
1587                                         query_vals[reason_col].val.str_val= s->reason;
1588                                         query_vals[socket_info_col].val.str_val= s->sockinfo_str;
1589                                 
1590                                         if(dbf.insert(db,query_cols,query_vals,n_query_cols )<0)
1591                                         {
1592                                                 LM_ERR("unsuccessful sql insert\n");
1593                                                 if(!no_lock)
1594                                                         lock_release(&hash_table[i].lock);
1595                                                 return ;
1596                                         }
1597                                         break;                                                                          
1598                                 }
1599
1600                         }
1601                         s->db_flag= NO_UPDATEDB_FLAG;   
1602                         prev_s= s;
1603                         s= s->next;
1604                 }
1605                 if(!no_lock)
1606                         lock_release(&hash_table[i].lock);      
1607         }
1608
1609         update_vals[0].val.int_val= (int)time(NULL)- 10;
1610         update_ops[0]= OP_LT;
1611         if(dbf.delete(db, update_cols, update_ops, update_vals, 1) < 0)
1612         {
1613                 LM_ERR("deleting expired information from database\n");
1614         }
1615
1616 }
1617
1618 int restore_db_subs(void)
1619 {
1620         db_key_t result_cols[22]; 
1621         db_res_t *res= NULL;
1622         db_row_t *row = NULL;   
1623         db_val_t *row_vals= NULL;
1624         int i;
1625         int n_result_cols= 0;
1626         int pres_uri_col, expires_col, from_user_col, from_domain_col,to_user_col; 
1627         int callid_col,totag_col,fromtag_col,to_domain_col,sockinfo_col,reason_col;
1628         int event_col,contact_col,record_route_col, event_id_col, status_col;
1629         int remote_cseq_col, local_cseq_col, local_contact_col, version_col;
1630         subs_t s;
1631         str ev_sname;
1632         pres_ev_t* event= NULL;
1633         event_t parsed_event;
1634         unsigned int expires;
1635         unsigned int hash_code;
1636
1637         result_cols[pres_uri_col=n_result_cols++]       =&str_presentity_uri_col;
1638         result_cols[expires_col=n_result_cols++]=&str_expires_col;
1639         result_cols[event_col=n_result_cols++]  =&str_event_col;
1640         result_cols[event_id_col=n_result_cols++]=&str_event_id_col;
1641         result_cols[to_user_col=n_result_cols++]        =&str_to_user_col;
1642         result_cols[to_domain_col=n_result_cols++]      =&str_to_domain_col;
1643         result_cols[from_user_col=n_result_cols++]      =&str_watcher_username_col;
1644         result_cols[from_domain_col=n_result_cols++]=&str_watcher_domain_col;
1645         result_cols[callid_col=n_result_cols++] =&str_callid_col;
1646         result_cols[totag_col=n_result_cols++]  =&str_to_tag_col;
1647         result_cols[fromtag_col=n_result_cols++]=&str_from_tag_col;
1648         result_cols[local_cseq_col= n_result_cols++]    =&str_local_cseq_col;
1649         result_cols[remote_cseq_col= n_result_cols++]   =&str_remote_cseq_col;
1650         result_cols[record_route_col= n_result_cols++]  =&str_record_route_col;
1651         result_cols[sockinfo_col= n_result_cols++]      =&str_socket_info_col;
1652         result_cols[contact_col= n_result_cols++]       =&str_contact_col;
1653         result_cols[local_contact_col= n_result_cols++] =&str_local_contact_col;
1654         result_cols[version_col= n_result_cols++]       =&str_version_col;
1655         result_cols[status_col= n_result_cols++]        =&str_status_col;
1656         result_cols[reason_col= n_result_cols++]        =&str_reason_col;
1657         
1658         if(!pa_db)
1659         {
1660                 LM_ERR("null database connection\n");
1661                 return -1;
1662         }
1663
1664         if(pa_dbf.use_table(pa_db, &active_watchers_table)< 0)
1665         {
1666                 LM_ERR("in use table\n");
1667                 return -1;
1668         }
1669
1670         if(pa_dbf.query(pa_db,0, 0, 0, result_cols,0, n_result_cols, 0,&res)< 0)
1671         {
1672                 LM_ERR("while querrying table\n");
1673                 if(res)
1674                 {
1675                         pa_dbf.free_result(pa_db, res);
1676                         res = NULL;
1677                 }
1678                 return -1;
1679         }
1680         if(res== NULL)
1681                 return -1;
1682
1683         if(res->n<=0)
1684         {
1685                 LM_INFO("The query returned no result\n");
1686                 pa_dbf.free_result(pa_db, res);
1687                 res = NULL;
1688                 return 0;
1689         }
1690
1691         LM_DBG("found %d db entries\n", res->n);
1692
1693         for(i =0 ; i< res->n ; i++)
1694         {
1695                 row = &res->rows[i];
1696                 row_vals = ROW_VALUES(row);
1697                 memset(&s, 0, sizeof(subs_t));
1698
1699                 expires= row_vals[expires_col].val.int_val;
1700                 
1701                 if(expires< (int)time(NULL))
1702                         continue;
1703         
1704                 s.pres_uri.s= (char*)row_vals[pres_uri_col].val.string_val;
1705                 s.pres_uri.len= strlen(s.pres_uri.s);
1706                 
1707                 s.to_user.s=(char*)row_vals[to_user_col].val.string_val;
1708                 s.to_user.len= strlen(s.to_user.s);
1709
1710                 s.to_domain.s=(char*)row_vals[to_domain_col].val.string_val;
1711                 s.to_domain.len= strlen(s.to_domain.s);
1712
1713                 s.from_user.s=(char*)row_vals[from_user_col].val.string_val;
1714                 s.from_user.len= strlen(s.from_user.s);
1715                 
1716                 s.from_domain.s=(char*)row_vals[from_domain_col].val.string_val;
1717                 s.from_domain.len= strlen(s.from_domain.s);
1718
1719                 s.to_tag.s=(char*)row_vals[totag_col].val.string_val;
1720                 s.to_tag.len= strlen(s.to_tag.s);
1721
1722                 s.from_tag.s=(char*)row_vals[fromtag_col].val.string_val;
1723                 s.from_tag.len= strlen(s.from_tag.s);
1724
1725                 s.callid.s=(char*)row_vals[callid_col].val.string_val;
1726                 s.callid.len= strlen(s.callid.s);
1727
1728                 ev_sname.s= (char*)row_vals[event_col].val.string_val;
1729                 ev_sname.len= strlen(ev_sname.s);
1730                 
1731                 event= contains_event(&ev_sname, &parsed_event);
1732                 if(event== NULL)
1733                 {
1734                         LM_DBG("insert a new event structure in the list waiting"
1735                                         " to be filled in\n");
1736         
1737                         /*insert a new event structure in the list waiting to be filled in*/
1738                         event= (pres_ev_t*)shm_malloc(sizeof(pres_ev_t));
1739                         if(event== NULL)
1740                         {
1741                                 free_event_params(parsed_event.params, PKG_MEM_TYPE);
1742                                 ERR_MEM(SHM_MEM_STR);
1743                         }
1744                         memset(event, 0, sizeof(pres_ev_t));
1745                         event->name.s= (char*)shm_malloc(ev_sname.len* sizeof(char));
1746                         if(event->name.s== NULL)
1747                         {
1748                                 free_event_params(parsed_event.params, PKG_MEM_TYPE);
1749                                 ERR_MEM(SHM_MEM_STR);
1750                         }
1751                         memcpy(event->name.s,ev_sname.s, ev_sname.len);
1752                         event->name.len= ev_sname.len;
1753                         
1754                         event->evp= shm_copy_event(&parsed_event);
1755                         if(event->evp== NULL)
1756                         {
1757                                 LM_ERR("ERROR copying event_t structure\n");
1758                                 free_event_params(parsed_event.params, PKG_MEM_TYPE);
1759                                 goto error;
1760                         }
1761                         event->next= EvList->events;
1762                         EvList->events= event;
1763                 }
1764                         
1765                 free_event_params(parsed_event.params, PKG_MEM_TYPE);
1766
1767                 s.event= event;
1768
1769                 s.event_id.s=(char*)row_vals[event_id_col].val.string_val;
1770                 if(s.event_id.s)
1771                         s.event_id.len= strlen(s.event_id.s);
1772
1773                 s.remote_cseq= row_vals[remote_cseq_col].val.int_val;
1774                 s.local_cseq= row_vals[local_cseq_col].val.int_val;
1775                 s.version= row_vals[version_col].val.int_val;
1776                 
1777                 s.expires= expires- (int)time(NULL);
1778                 s.status= row_vals[status_col].val.int_val;
1779
1780                 s.reason.s= (char*)row_vals[reason_col].val.string_val;
1781                 if(s.reason.s)
1782                         s.reason.len= strlen(s.reason.s);
1783
1784                 s.contact.s=(char*)row_vals[contact_col].val.string_val;
1785                 s.contact.len= strlen(s.contact.s);
1786
1787                 s.local_contact.s=(char*)row_vals[local_contact_col].val.string_val;
1788                 s.local_contact.len= strlen(s.local_contact.s);
1789         
1790                 s.record_route.s=(char*)row_vals[record_route_col].val.string_val;
1791                 if(s.record_route.s)
1792                         s.record_route.len= strlen(s.record_route.s);
1793         
1794                 s.sockinfo_str.s=(char*)row_vals[sockinfo_col].val.string_val;
1795                 s.sockinfo_str.len= strlen(s.sockinfo_str.s);
1796
1797                 hash_code= core_hash(&s.pres_uri, &s.event->name, shtable_size);
1798                 if(insert_shtable(subs_htable, hash_code, &s)< 0)
1799                 {
1800                         LM_ERR("adding new record in hash table\n");
1801                         goto error;
1802                 }
1803         }
1804
1805         pa_dbf.free_result(pa_db, res);
1806
1807         /* delete all records */
1808         if(pa_dbf.delete(pa_db, 0,0,0,0)< 0)
1809         {
1810                 LM_ERR("deleting all records from database table\n");
1811                 return -1;
1812         }
1813
1814         return 0;
1815
1816 error:
1817         if(res)
1818                 pa_dbf.free_result(pa_db, res);
1819         return -1;
1820
1821 }
1822
1823 int refresh_watcher(str* pres_uri, str* watcher_uri, str* event, 
1824                 int status, str* reason)
1825 {
1826         unsigned int hash_code;
1827         subs_t* s, *s_copy;
1828         pres_ev_t* ev;          
1829         struct sip_uri uri;
1830         str user, domain;
1831         /* refresh status in subs_htable and send notify */
1832
1833         ev=     contains_event(event, NULL);
1834         if(ev== NULL)
1835         {
1836                 LM_ERR("while searching event in list\n");
1837                 return -1;
1838         }
1839
1840         if(parse_uri(watcher_uri->s, watcher_uri->len, &uri)< 0)
1841         {
1842                 LM_ERR("parsing uri\n");
1843                 return -1;
1844         }
1845         user= uri.user;
1846         domain= uri.host;
1847
1848         hash_code= core_hash(pres_uri, event, shtable_size);
1849
1850         lock_get(&subs_htable[hash_code].lock);
1851
1852         s= subs_htable[hash_code].entries->next;
1853
1854         while(s)
1855         {
1856                 if(s->event== ev && s->pres_uri.len== pres_uri->len &&
1857                         strncmp(s->pres_uri.s, pres_uri->s, pres_uri->len)== 0 &&
1858                         s->from_user.len==user.len && strncmp(s->from_user.s,user.s, user.len)==0 &&
1859                         s->from_domain.len== domain.len && 
1860                         strncmp(s->from_domain.s, domain.s, domain.len)== 0)
1861                 {
1862                         s->status= status;
1863                         if(reason)
1864                                 s->reason= *reason;
1865                         
1866                         s_copy= mem_copy_subs(s, PKG_MEM_TYPE);
1867                         if(s_copy== NULL)
1868                         {
1869                                 LM_ERR("copying subs_t\n");
1870                                 lock_release(&subs_htable[hash_code].lock);
1871                                 return -1;
1872                         }
1873                         lock_release(&subs_htable[hash_code].lock);
1874                         if(notify(s_copy, NULL, NULL, 0)< 0)
1875                         {
1876                                 LM_ERR("in notify function\n");
1877                                 pkg_free(s_copy);
1878                                 return -1;
1879                         }
1880                         pkg_free(s_copy);
1881                         lock_get(&subs_htable[hash_code].lock);
1882                 }
1883                 s= s->next;
1884         }
1885         return 0;
1886 }
1887
1888 int get_db_subs_auth(subs_t* subs, int* found)
1889 {
1890         db_key_t db_keys[5];
1891         db_val_t db_vals[5];
1892         int n_query_cols= 0; 
1893         db_key_t result_cols[3];
1894         db_res_t *result = NULL;
1895         db_row_t *row ; 
1896         db_val_t *row_vals ;
1897
1898         db_keys[n_query_cols] =&str_presentity_uri_col;
1899         db_vals[n_query_cols].type = DB_STR;
1900         db_vals[n_query_cols].nul = 0;
1901         db_vals[n_query_cols].val.str_val= subs->pres_uri;
1902         n_query_cols++;
1903
1904         db_keys[n_query_cols] =&str_watcher_username_col;
1905         db_vals[n_query_cols].type = DB_STR;
1906         db_vals[n_query_cols].nul = 0;
1907         db_vals[n_query_cols].val.str_val = subs->from_user;
1908         n_query_cols++;
1909
1910         db_keys[n_query_cols] =&str_watcher_domain_col;
1911         db_vals[n_query_cols].type = DB_STR;
1912         db_vals[n_query_cols].nul = 0;
1913         db_vals[n_query_cols].val.str_val = subs->from_domain;
1914         n_query_cols++;
1915         
1916         db_keys[n_query_cols] =&str_event_col;
1917         db_vals[n_query_cols].type = DB_STR;
1918         db_vals[n_query_cols].nul = 0;
1919         db_vals[n_query_cols].val.str_val = subs->event->name;
1920         n_query_cols++;
1921
1922         result_cols[0] = &str_status_col;
1923         result_cols[1] = &str_reason_col;
1924         
1925         if(pa_dbf.use_table(pa_db, &watchers_table)< 0)
1926         {
1927                 LM_ERR("in use table\n");
1928                 return -1;
1929         }       
1930
1931         if(pa_dbf.query(pa_db, db_keys, 0, db_vals, result_cols,
1932                                         n_query_cols, 2, 0, &result )< 0)
1933         {
1934                 LM_ERR("while querying watchers table\n");
1935                 if(result)
1936                         pa_dbf.free_result(pa_db, result);
1937                 return -1;
1938         }
1939         if(result== NULL)
1940                 return -1;
1941         
1942         if(result->n<= 0)
1943         {
1944                 *found= 0;
1945                 pa_dbf.free_result(pa_db, result);
1946                 return 0;
1947         }
1948
1949         *found= 1;
1950         row = &result->rows[0];
1951         row_vals = ROW_VALUES(row);
1952         subs->status= row_vals[0].val.int_val;
1953
1954         if(row_vals[1].val.string_val)
1955         {
1956
1957                 subs->reason.len= strlen(row_vals[1].val.string_val);
1958                 if(subs->reason.len== 0)
1959                         subs->reason.s= NULL;
1960                 else
1961                 {
1962                         subs->reason.s= (char*)pkg_malloc(subs->reason.len*sizeof(char));
1963                         if(subs->reason.s== NULL)
1964                         {
1965                                 pa_dbf.free_result(pa_db, result);
1966                                 ERR_MEM(PKG_MEM_STR);
1967                         }               
1968                         memcpy(subs->reason.s, row_vals[1].val.string_val, subs->reason.len);
1969                 }
1970         }
1971         
1972         pa_dbf.free_result(pa_db, result);
1973         return 0;
1974 error:
1975         return -1;
1976 }       
1977
1978 int insert_db_subs_auth(subs_t* subs)
1979 {
1980         db_key_t db_keys[10];
1981         db_val_t db_vals[10];
1982         int n_query_cols= 0; 
1983
1984         db_keys[n_query_cols] =&str_presentity_uri_col;
1985         db_vals[n_query_cols].type = DB_STR;
1986         db_vals[n_query_cols].nul = 0;
1987         db_vals[n_query_cols].val.str_val= subs->pres_uri;
1988         n_query_cols++;
1989
1990         db_keys[n_query_cols] =&str_watcher_username_col;
1991         db_vals[n_query_cols].type = DB_STR;
1992         db_vals[n_query_cols].nul = 0;
1993         db_vals[n_query_cols].val.str_val = subs->from_user;
1994         n_query_cols++;
1995
1996         db_keys[n_query_cols] =&str_watcher_domain_col;
1997         db_vals[n_query_cols].type = DB_STR;
1998         db_vals[n_query_cols].nul = 0;
1999         db_vals[n_query_cols].val.str_val = subs->from_domain;
2000         n_query_cols++;
2001         
2002         db_keys[n_query_cols] =&str_event_col;
2003         db_vals[n_query_cols].type = DB_STR;
2004         db_vals[n_query_cols].nul = 0;
2005         db_vals[n_query_cols].val.str_val = subs->event->name;
2006         n_query_cols++;
2007
2008         db_keys[n_query_cols] =&str_status_col;
2009         db_vals[n_query_cols].type = DB_INT;
2010         db_vals[n_query_cols].nul = 0;
2011         db_vals[n_query_cols].val.int_val = subs->status;
2012         n_query_cols++;
2013                                                                 
2014         db_keys[n_query_cols] = &str_inserted_time_col;
2015         db_vals[n_query_cols].type = DB_INT;
2016         db_vals[n_query_cols].nul = 0;
2017         db_vals[n_query_cols].val.int_val= (int)time(NULL);
2018         n_query_cols++;
2019         
2020         if(subs->reason.s && subs->reason.len)
2021         {
2022                 db_keys[n_query_cols] =&str_reason_col;
2023                 db_vals[n_query_cols].type = DB_STR;
2024                 db_vals[n_query_cols].nul = 0;
2025                 db_vals[n_query_cols].val.str_val = subs->reason;
2026                 n_query_cols++; 
2027         }       
2028         
2029         if (pa_dbf.use_table(pa_db, &watchers_table) < 0) 
2030         {
2031                 LM_ERR("in use_table\n");
2032                 return -1;
2033         }
2034
2035         if(pa_dbf.insert(pa_db, db_keys, db_vals, n_query_cols )< 0)
2036         {       
2037                 LM_ERR("in sql insert\n");
2038                 return -1;
2039         }
2040
2041         return 0;
2042 }