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