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