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