presence(k): avoid str* alloc for local contact
[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         contact_body_t *b;
925         struct to_body *pto, *pfrom = NULL, TO;
926         int lexpire;
927         str rtag_value;
928         struct sip_uri uri;
929
930         /* examine the expire header field */
931         if(msg->expires && msg->expires->body.len > 0)
932         {
933                 if (!msg->expires->parsed && (parse_expires(msg->expires) < 0))
934                 {
935                         LM_ERR("cannot parse Expires header\n");
936                         goto error;
937                 }
938                 lexpire = ((exp_body_t*)msg->expires->parsed)->val;
939                 LM_DBG("'Expires' header found, value= %d\n", lexpire);
940
941         }
942         else 
943         {
944                 LM_DBG("'expires' not found; default=%d\n",subs->event->default_expires);
945                 lexpire = subs->event->default_expires;
946         }
947         if(lexpire > mexp)
948                 lexpire = mexp;
949
950         subs->expires = lexpire;
951
952         if( msg->to==NULL || msg->to->body.s==NULL)
953         {
954                 LM_ERR("cannot parse TO header\n");
955                 goto error;
956         }
957         /* examine the to header */
958         if(msg->to->parsed != NULL)
959         {
960                 pto = (struct to_body*)msg->to->parsed;
961                 LM_DBG("'To' header ALREADY PARSED: <%.*s>\n",pto->uri.len,pto->uri.s);
962         }
963         else
964         {
965                 memset( &TO , 0, sizeof(TO) );
966                 parse_to(msg->to->body.s,msg->to->body.s + msg->to->body.len + 1, &TO);
967                 if( TO.uri.len <= 0 )
968                 {
969                         LM_DBG("'To' header NOT parsed\n");
970                         goto error;
971                 }
972                 pto = &TO;
973         }
974
975         if( pto->parsed_uri.user.s && pto->parsed_uri.host.s &&
976                 pto->parsed_uri.user.len && pto->parsed_uri.host.len)
977         {
978                 subs->to_user = pto->parsed_uri.user;
979                 subs->to_domain = pto->parsed_uri.host;
980         }
981         else
982         {
983                 if(parse_uri(pto->uri.s, pto->uri.len, &uri)< 0)
984                 {
985                         LM_ERR("while parsing uri\n");
986                         goto error;
987                 }
988                 subs->to_user = uri.user;
989                 subs->to_domain = uri.host;
990         }
991
992         /* examine the from header */
993         if (!msg->from || !msg->from->body.s)
994         {
995                 LM_DBG("cannot find 'from' header!\n");
996                 goto error;
997         }
998         if (msg->from->parsed == NULL)
999         {
1000                 LM_DBG("'From' header not parsed\n");
1001                 /* parsing from header */
1002                 if ( parse_from_header( msg )<0 ) 
1003                 {
1004                         LM_DBG("cannot parse From header\n");
1005                         goto error;
1006                 }
1007         }
1008         pfrom = (struct to_body*)msg->from->parsed;
1009         
1010         if( pfrom->parsed_uri.user.s && pfrom->parsed_uri.host.s && 
1011                 pfrom->parsed_uri.user.len && pfrom->parsed_uri.host.len)
1012         {
1013                 subs->from_user = pfrom->parsed_uri.user;
1014                 subs->from_domain = pfrom->parsed_uri.host;
1015         }
1016         else
1017         {
1018                 if(parse_uri(pfrom->uri.s, pfrom->uri.len, &uri)< 0)
1019                 {
1020                         LM_ERR("while parsing uri\n");
1021                         goto error;
1022                 }
1023                 subs->from_user = uri.user;
1024                 subs->from_domain = uri.host;
1025         }
1026
1027         /* get to_tag if the message does not have a to_tag*/
1028         if (pto->tag_value.s==NULL || pto->tag_value.len==0 )
1029         {  
1030                 LM_DBG("generating to_tag\n");
1031                 *to_tag_gen = 1;
1032                 rtag_value.len = 0;
1033                 if(slb.get_reply_totag(msg, &rtag_value)<0 || rtag_value.len <= 0)
1034                 {
1035                         LM_ERR("while creating to_tag\n");
1036                         goto error;
1037                 }
1038         }
1039         else
1040         {
1041                 *to_tag_gen = 0;
1042                 rtag_value=pto->tag_value;
1043         }
1044         subs->to_tag = rtag_value;
1045
1046         if( msg->callid==NULL || msg->callid->body.s==NULL)
1047         {
1048                 LM_ERR("cannot parse callid header\n");
1049                 goto error;
1050         }
1051         subs->callid = msg->callid->body;
1052
1053         if( msg->cseq==NULL || msg->cseq->body.s==NULL)
1054         {
1055                 LM_ERR("cannot parse cseq header\n");
1056                 goto error;
1057         }
1058         if (str2int( &(get_cseq(msg)->number), &subs->remote_cseq)!=0 )
1059         {
1060                 LM_ERR("cannot parse cseq number\n");
1061                 goto error;
1062         }
1063         if( msg->contact==NULL || msg->contact->body.s==NULL)
1064         {
1065                 LM_ERR("cannot parse contact header\n");
1066                 goto error;
1067         }
1068         if( parse_contact(msg->contact) <0 )
1069         {
1070                 LM_ERR(" cannot parse contact"
1071                                 " header\n");
1072                 goto error;
1073         }
1074         b= (contact_body_t* )msg->contact->parsed;
1075
1076         if(b == NULL)
1077         {
1078                 LM_ERR("cannot parse contact header\n");
1079                 goto error;
1080         }
1081         subs->contact = b->contacts->uri;
1082         
1083         LM_DBG("subs->contact= %.*s - len = %d\n",subs->contact.len,
1084                         subs->contact.s, subs->contact.len);    
1085
1086         if (EVENT_DIALOG_SLA(subs->event->evp))
1087     {
1088         /* user_contact@from_domain */
1089         if(parse_uri(subs->contact.s, subs->contact.len, &uri)< 0)
1090         {
1091             LM_ERR("failed to parse contact uri\n");
1092             goto error;
1093         }
1094         if(uandd_to_uri(uri.user, subs->from_domain, &subs->pres_uri)< 0)
1095         {
1096             LM_ERR("failed to construct uri\n");
1097             goto error;
1098         }
1099         LM_DBG("&&&&&&&&&&&&&&& dialog pres_uri= %.*s\n",subs->pres_uri.len, subs->pres_uri.s);
1100     }
1101
1102
1103         /*process record route and add it to a string*/
1104         if(*to_tag_gen && msg->record_route!=NULL)
1105         {
1106                 rt = print_rr_body(msg->record_route, &rec_route, 0, 0);
1107                 if(rt != 0)
1108                 {
1109                         LM_ERR("processing the record route [%d]\n", rt);       
1110                         rec_route.s=NULL;
1111                         rec_route.len=0;
1112                 //      goto error;
1113                 }
1114         }
1115         subs->record_route = rec_route;
1116                         
1117         subs->sockinfo_str= msg->rcv.bind_address->sock_str;
1118
1119         if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0)
1120         {
1121                 LM_ERR("no from tag value present\n");
1122                 goto error;
1123         }
1124         subs->from_tag = pfrom->tag_value;
1125
1126         subs->version = 0;
1127         
1128         if((!scontact.s) || (scontact.len== 0))
1129         {
1130                 if(ps_fill_local_contact(msg, &subs->local_contact)<0)
1131                 {
1132                         LM_ERR("cannot get local contact address\n");
1133                         goto error;
1134                 }
1135         }
1136         else
1137                 subs->local_contact= scontact;
1138         
1139         return 0;
1140         
1141 error:
1142
1143         return -1;
1144 }
1145
1146
1147 int get_stored_info(struct sip_msg* msg, subs_t* subs, int* reply_code,
1148                 str* reply_str)
1149 {       
1150         str pres_uri= {0, 0}, reason={0, 0};
1151         subs_t* s;
1152         int i;
1153         unsigned int hash_code;
1154
1155         /* first try to_user== pres_user and to_domain== pres_domain */
1156
1157     if(subs->pres_uri.s == NULL)
1158     {
1159             uandd_to_uri(subs->to_user, subs->to_domain, &pres_uri);
1160             if(pres_uri.s== NULL)
1161             {
1162                     LM_ERR("creating uri from user and domain\n");
1163                     return -1;
1164             }
1165     }
1166     else
1167         pres_uri = subs->pres_uri;
1168
1169         hash_code= core_hash(&pres_uri, &subs->event->name, shtable_size);
1170         lock_get(&subs_htable[hash_code].lock);
1171         i= hash_code;
1172         s= search_shtable(subs_htable, subs->callid, subs->to_tag,
1173                         subs->from_tag, hash_code);
1174         if(s)
1175         {
1176                 goto found_rec;
1177         }
1178         lock_release(&subs_htable[hash_code].lock);
1179
1180     if(subs->pres_uri.s)
1181         goto not_found;
1182         
1183     pkg_free(pres_uri.s);
1184         pres_uri.s= NULL;
1185         
1186
1187     LM_DBG("record not found using R-URI search iteratively\n");
1188         /* take one row at a time */
1189         for(i= 0; i< shtable_size; i++)
1190         {
1191                 lock_get(&subs_htable[i].lock);
1192                 s= search_shtable(subs_htable, subs->callid,subs->to_tag,subs->from_tag, i);
1193                 if (s)
1194                 {
1195                         if(!EVENT_DIALOG_SLA(s->event->evp))
1196                         {
1197                                 pres_uri.s= (char*)pkg_malloc(s->pres_uri.len* sizeof(char));
1198                                 if(pres_uri.s== NULL)
1199                                 {
1200                                         lock_release(&subs_htable[i].lock);
1201                                         ERR_MEM(PKG_MEM_STR);
1202                                 }
1203                                 memcpy(pres_uri.s, s->pres_uri.s, s->pres_uri.len);
1204                                 pres_uri.len= s->pres_uri.len;
1205                         }
1206                         goto found_rec;
1207                 }
1208                 lock_release(&subs_htable[i].lock);
1209         }
1210
1211         if(dbmode != DB_MEMORY_ONLY)
1212         {
1213                 return get_database_info(msg, subs, reply_code, reply_str);     
1214         }
1215
1216 not_found:
1217
1218         LM_ERR("record not found in hash_table\n");
1219         *reply_code= 481;
1220         *reply_str= pu_481_rpl;
1221
1222         return -1;
1223
1224 found_rec:
1225         
1226         LM_DBG("Record found in hash_table\n");
1227         
1228         if(!EVENT_DIALOG_SLA(s->event->evp))
1229                 subs->pres_uri= pres_uri;
1230         
1231         subs->version = s->version;
1232         subs->status= s->status;
1233         if(s->reason.s && s->reason.len)
1234         {       
1235                 reason.s= (char*)pkg_malloc(s->reason.len* sizeof(char));
1236                 if(reason.s== NULL)
1237                 {
1238                         lock_release(&subs_htable[i].lock);
1239                         ERR_MEM(PKG_MEM_STR);
1240                 }
1241                 memcpy(reason.s, s->reason.s, s->reason.len);
1242                 reason.len= s->reason.len;
1243                 subs->reason= reason;
1244         }
1245         if(s->record_route.s && s->record_route.len)
1246         {
1247                 subs->record_route.s= (char*)pkg_malloc
1248                         (s->record_route.len* sizeof(char));
1249                 if(subs->record_route.s== NULL)
1250                 {
1251                         ERR_MEM(PKG_MEM_STR);
1252                 }
1253                 memcpy(subs->record_route.s, s->record_route.s, s->record_route.len);
1254                 subs->record_route.len= s->record_route.len;
1255         }
1256
1257         subs->local_cseq= s->local_cseq;
1258         
1259         if(subs->remote_cseq<= s->remote_cseq)
1260         {
1261                 LM_ERR("wrong sequence number;received: %d - stored: %d\n",
1262                                 subs->remote_cseq, s->remote_cseq);
1263                 
1264                 *reply_code= 400;
1265                 *reply_str= pu_400_rpl;
1266
1267                 lock_release(&subs_htable[i].lock);
1268                 goto error;
1269         }       
1270         lock_release(&subs_htable[i].lock);
1271
1272         return 0;
1273
1274 error:
1275         if(subs->reason.s)
1276                 pkg_free(subs->reason.s);
1277         subs->reason.s= NULL;
1278         if(subs->record_route.s)
1279                 pkg_free(subs->record_route.s);
1280         subs->record_route.s= NULL;
1281         return -1;
1282 }
1283
1284 int get_database_info(struct sip_msg* msg, subs_t* subs, int* reply_code, str* reply_str)
1285 {       
1286         db_key_t query_cols[10];
1287         db_val_t query_vals[10];
1288         db_key_t result_cols[9];
1289         db1_res_t *result= NULL;
1290         db_row_t *row ; 
1291         db_val_t *row_vals ;
1292         int n_query_cols = 0;
1293         int n_result_cols = 0;
1294         int remote_cseq_col= 0, local_cseq_col= 0, status_col, reason_col;
1295         int record_route_col, version_col;
1296         int pres_uri_col;
1297         unsigned int remote_cseq;
1298         str pres_uri, record_route;
1299         str reason;
1300
1301         query_cols[n_query_cols] = &str_to_user_col;
1302         query_vals[n_query_cols].type = DB1_STR;
1303         query_vals[n_query_cols].nul = 0;
1304         query_vals[n_query_cols].val.str_val = subs->to_user;
1305         n_query_cols++;
1306         
1307         query_cols[n_query_cols] = &str_to_domain_col;
1308         query_vals[n_query_cols].type = DB1_STR;
1309         query_vals[n_query_cols].nul = 0;
1310         query_vals[n_query_cols].val.str_val = subs->to_domain;
1311         n_query_cols++;
1312
1313         query_cols[n_query_cols] = &str_watcher_username_col;
1314         query_vals[n_query_cols].type = DB1_STR;
1315         query_vals[n_query_cols].nul = 0;
1316         query_vals[n_query_cols].val.str_val = subs->from_user;
1317         n_query_cols++;
1318         
1319         query_cols[n_query_cols] = &str_watcher_domain_col;
1320         query_vals[n_query_cols].type = DB1_STR;
1321         query_vals[n_query_cols].nul = 0;
1322         query_vals[n_query_cols].val.str_val = subs->from_domain;
1323         n_query_cols++;
1324
1325         query_cols[n_query_cols] = &str_event_col;
1326         query_vals[n_query_cols].type = DB1_STR;
1327         query_vals[n_query_cols].nul = 0;
1328         query_vals[n_query_cols].val.str_val = subs->event->name;
1329         n_query_cols++;
1330
1331         query_cols[n_query_cols] = &str_event_id_col;
1332         query_vals[n_query_cols].type = DB1_STR;
1333         query_vals[n_query_cols].nul = 0;
1334         if( subs->event_id.s != NULL)
1335         {
1336                 query_vals[n_query_cols].val.str_val.s = subs->event_id.s;
1337                 query_vals[n_query_cols].val.str_val.len = subs->event_id.len;
1338         } else {
1339                 query_vals[n_query_cols].val.str_val.s = "";
1340                 query_vals[n_query_cols].val.str_val.len = 0;
1341         }
1342         n_query_cols++;
1343         
1344         query_cols[n_query_cols] = &str_callid_col;
1345         query_vals[n_query_cols].type = DB1_STR;
1346         query_vals[n_query_cols].nul = 0;
1347         query_vals[n_query_cols].val.str_val = subs->callid;
1348         n_query_cols++;
1349
1350         query_cols[n_query_cols] = &str_to_tag_col;
1351         query_vals[n_query_cols].type = DB1_STR;
1352         query_vals[n_query_cols].nul = 0;
1353         query_vals[n_query_cols].val.str_val = subs->to_tag;
1354         n_query_cols++;
1355
1356         query_cols[n_query_cols] = &str_from_tag_col;
1357         query_vals[n_query_cols].type = DB1_STR;
1358         query_vals[n_query_cols].nul = 0;
1359         query_vals[n_query_cols].val.str_val = subs->from_tag;
1360         n_query_cols++;
1361
1362         result_cols[pres_uri_col=n_result_cols++] = &str_presentity_uri_col;
1363         result_cols[remote_cseq_col=n_result_cols++] = &str_remote_cseq_col;
1364         result_cols[local_cseq_col=n_result_cols++] = &str_local_cseq_col;
1365         result_cols[status_col=n_result_cols++] = &str_status_col;
1366         result_cols[reason_col=n_result_cols++] = &str_reason_col;
1367         result_cols[record_route_col=n_result_cols++] = &str_record_route_col;
1368         result_cols[version_col=n_result_cols++] = &str_version_col;
1369         
1370         if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0) 
1371         {
1372                 LM_ERR("unsuccessful use_table sql operation\n");
1373                 return -1;
1374         }
1375         
1376         if (pa_dbf.query (pa_db, query_cols, 0, query_vals,
1377                  result_cols, n_query_cols, n_result_cols, 0,  &result) < 0) 
1378         {
1379                 LM_ERR("querying subscription dialog\n");
1380                 if(result)
1381                         pa_dbf.free_result(pa_db, result);
1382                 return -1;
1383         }
1384         if(result== NULL)
1385                 return -1;
1386
1387         if(result && result->n <=0)
1388         {
1389                 LM_ERR("No matching subscription dialog found in database\n");
1390                 
1391                 pa_dbf.free_result(pa_db, result);
1392                 *reply_code= 481;
1393                 *reply_str= pu_481_rpl;
1394
1395                 return -1;
1396         }
1397
1398         row = &result->rows[0];
1399         row_vals = ROW_VALUES(row);
1400         remote_cseq= row_vals[remote_cseq_col].val.int_val;
1401         
1402         if(subs->remote_cseq<= remote_cseq)
1403         {
1404                 LM_ERR("wrong sequence number received: %d - stored: %d\n",
1405                                 subs->remote_cseq, remote_cseq);
1406                 *reply_code= 400;
1407                 *reply_str= pu_400_rpl;
1408                 pa_dbf.free_result(pa_db, result);
1409                 return -1;
1410         }
1411         
1412         subs->status= row_vals[status_col].val.int_val;
1413         reason.s= (char*)row_vals[reason_col].val.string_val;
1414         if(reason.s)
1415         {
1416                 reason.len= strlen(reason.s);
1417                 subs->reason.s= (char*)pkg_malloc(reason.len* sizeof(char));
1418                 if(subs->reason.s== NULL)
1419                 {
1420                         ERR_MEM(PKG_MEM_STR);
1421                 }
1422                 memcpy(subs->reason.s, reason.s, reason.len);
1423                 subs->reason.len= reason.len;
1424         }
1425
1426         subs->local_cseq= row_vals[local_cseq_col].val.int_val;
1427         subs->version= row_vals[version_col].val.int_val;
1428
1429         if(!EVENT_DIALOG_SLA(subs->event->evp))
1430         {
1431                 pres_uri.s= (char*)row_vals[pres_uri_col].val.string_val;
1432                 pres_uri.len= strlen(pres_uri.s);
1433                 subs->pres_uri.s= (char*)pkg_malloc(pres_uri.len* sizeof(char));
1434                 if(subs->pres_uri.s== NULL)
1435                 {       
1436                         if(subs->reason.s)
1437                                 pkg_free(subs->reason.s);
1438                         ERR_MEM(PKG_MEM_STR);
1439                 }
1440                 memcpy(subs->pres_uri.s, pres_uri.s, pres_uri.len);
1441                 subs->pres_uri.len= pres_uri.len;
1442         }
1443
1444         record_route.s= (char*)row_vals[record_route_col].val.string_val;
1445         if(record_route.s)
1446         {
1447                 record_route.len= strlen(record_route.s);
1448                 subs->record_route.s= (char*)pkg_malloc(record_route.len*sizeof(char));
1449                 if(subs->record_route.s== NULL)
1450                 {
1451                         ERR_MEM(PKG_MEM_STR);
1452                 }
1453                 memcpy(subs->record_route.s, record_route.s, record_route.len);
1454                 subs->record_route.len= record_route.len;
1455         }
1456
1457         pa_dbf.free_result(pa_db, result);
1458         result= NULL;
1459
1460         return 0;
1461 error:
1462         if(result)
1463                 pa_dbf.free_result(pa_db, result);
1464
1465         return -1;
1466
1467 }
1468
1469
1470 int handle_expired_subs(subs_t* s)
1471 {
1472         /* send Notify with state=terminated;reason=timeout */
1473         
1474         s->status= TERMINATED_STATUS;
1475         s->reason.s= "timeout";
1476         s->reason.len= 7;
1477         s->expires= 0;
1478
1479         if(send_notify_request(s, NULL, NULL, 1)< 0)
1480         {
1481                 LM_ERR("send Notify not successful\n");
1482                 return -1;
1483         }
1484         
1485         return 0;
1486
1487 }
1488
1489 void timer_db_update(unsigned int ticks,void *param)
1490 {       
1491         int no_lock=0;
1492         LM_DBG("db_update timer\n");
1493         if(ticks== 0 && param == NULL)
1494                 no_lock= 1;
1495         
1496         if(pa_dbf.use_table(pa_db, &active_watchers_table)< 0)
1497         {
1498                 LM_ERR("sql use table failed\n");
1499                 return;
1500         }
1501
1502         update_db_subs(pa_db, pa_dbf, subs_htable, 
1503                         shtable_size, no_lock, handle_expired_subs);
1504
1505 }
1506
1507 void update_db_subs(db1_con_t *db,db_func_t dbf, shtable_t hash_table,
1508         int htable_size, int no_lock, handle_expired_func_t handle_expired_func)
1509 {       
1510         db_key_t query_cols[22], update_cols[7];
1511         db_val_t query_vals[22], update_vals[7];
1512         db_op_t update_ops[1];
1513         subs_t* del_s;
1514         int pres_uri_col, to_user_col, to_domain_col, from_user_col, from_domain_col,
1515                 callid_col, totag_col, fromtag_col, event_col,status_col, event_id_col, 
1516                 local_cseq_col, remote_cseq_col, expires_col, record_route_col, 
1517                 contact_col, local_contact_col, version_col,socket_info_col,reason_col;
1518         int u_expires_col, u_local_cseq_col, u_remote_cseq_col, u_version_col, 
1519                 u_reason_col, u_status_col; 
1520         int i;
1521         subs_t* s= NULL, *prev_s= NULL;
1522         int n_query_cols= 0, n_update_cols= 0;
1523         int n_query_update;
1524
1525         query_cols[pres_uri_col= n_query_cols] =&str_presentity_uri_col;
1526         query_vals[pres_uri_col].type = DB1_STR;
1527         query_vals[pres_uri_col].nul = 0;
1528         n_query_cols++;
1529         
1530         query_cols[callid_col= n_query_cols] =&str_callid_col;
1531         query_vals[callid_col].type = DB1_STR;
1532         query_vals[callid_col].nul = 0;
1533         n_query_cols++;
1534
1535         query_cols[totag_col= n_query_cols] =&str_to_tag_col;
1536         query_vals[totag_col].type = DB1_STR;
1537         query_vals[totag_col].nul = 0;
1538         n_query_cols++;
1539
1540         query_cols[fromtag_col= n_query_cols] =&str_from_tag_col;
1541         query_vals[fromtag_col].type = DB1_STR;
1542         query_vals[fromtag_col].nul = 0;
1543         n_query_cols++;
1544
1545         n_query_update= n_query_cols;
1546
1547         query_cols[to_user_col= n_query_cols] =&str_to_user_col;
1548         query_vals[to_user_col].type = DB1_STR;
1549         query_vals[to_user_col].nul = 0;
1550         n_query_cols++;
1551
1552         query_cols[to_domain_col= n_query_cols] =&str_to_domain_col;
1553         query_vals[to_domain_col].type = DB1_STR;
1554         query_vals[to_domain_col].nul = 0;
1555         n_query_cols++;
1556         
1557         query_cols[from_user_col= n_query_cols] =&str_watcher_username_col;
1558         query_vals[from_user_col].type = DB1_STR;
1559         query_vals[from_user_col].nul = 0;
1560         n_query_cols++;
1561
1562         query_cols[from_domain_col= n_query_cols] =&str_watcher_domain_col;
1563         query_vals[from_domain_col].type = DB1_STR;
1564         query_vals[from_domain_col].nul = 0;
1565         n_query_cols++;
1566
1567         query_cols[event_col= n_query_cols] =&str_event_col;
1568         query_vals[event_col].type = DB1_STR;
1569         query_vals[event_col].nul = 0;
1570         n_query_cols++; 
1571
1572         query_cols[event_id_col= n_query_cols] =&str_event_id_col;
1573         query_vals[event_id_col].type = DB1_STR;
1574         query_vals[event_id_col].nul = 0;
1575         n_query_cols++;
1576
1577         query_cols[local_cseq_col= n_query_cols]=&str_local_cseq_col;
1578         query_vals[local_cseq_col].type = DB1_INT;
1579         query_vals[local_cseq_col].nul = 0;
1580         n_query_cols++;
1581
1582         query_cols[remote_cseq_col= n_query_cols]=&str_remote_cseq_col;
1583         query_vals[remote_cseq_col].type = DB1_INT;
1584         query_vals[remote_cseq_col].nul = 0;
1585         n_query_cols++;
1586
1587         query_cols[expires_col= n_query_cols] =&str_expires_col;
1588         query_vals[expires_col].type = DB1_INT;
1589         query_vals[expires_col].nul = 0;
1590         n_query_cols++;
1591
1592         query_cols[status_col= n_query_cols] =&str_status_col;
1593         query_vals[status_col].type = DB1_INT;
1594         query_vals[status_col].nul = 0;
1595         n_query_cols++;
1596
1597         query_cols[reason_col= n_query_cols] =&str_reason_col;
1598         query_vals[reason_col].type = DB1_STR;
1599         query_vals[reason_col].nul = 0;
1600         n_query_cols++;
1601
1602         query_cols[record_route_col= n_query_cols] =&str_record_route_col;
1603         query_vals[record_route_col].type = DB1_STR;
1604         query_vals[record_route_col].nul = 0;
1605         n_query_cols++;
1606         
1607         query_cols[contact_col= n_query_cols] =&str_contact_col;
1608         query_vals[contact_col].type = DB1_STR;
1609         query_vals[contact_col].nul = 0;
1610         n_query_cols++;
1611
1612         query_cols[local_contact_col= n_query_cols] =&str_local_contact_col;
1613         query_vals[local_contact_col].type = DB1_STR;
1614         query_vals[local_contact_col].nul = 0;
1615         n_query_cols++;
1616
1617         query_cols[socket_info_col= n_query_cols] =&str_socket_info_col;
1618         query_vals[socket_info_col].type = DB1_STR;
1619         query_vals[socket_info_col].nul = 0;
1620         n_query_cols++;
1621
1622         query_cols[version_col= n_query_cols]=&str_version_col;
1623         query_vals[version_col].type = DB1_INT;
1624         query_vals[version_col].nul = 0;
1625         n_query_cols++;
1626
1627         /* cols and values used for update */
1628         update_cols[u_expires_col= n_update_cols]= &str_expires_col;
1629         update_vals[u_expires_col].type = DB1_INT;
1630         update_vals[u_expires_col].nul = 0;
1631         n_update_cols++;
1632
1633         update_cols[u_status_col= n_update_cols]= &str_status_col;
1634         update_vals[u_status_col].type = DB1_INT;
1635         update_vals[u_status_col].nul = 0;
1636         n_update_cols++;
1637
1638         update_cols[u_reason_col= n_update_cols]= &str_reason_col;
1639         update_vals[u_reason_col].type = DB1_STR;
1640         update_vals[u_reason_col].nul = 0;
1641         n_update_cols++;
1642
1643         update_cols[u_remote_cseq_col= n_update_cols]= &str_remote_cseq_col;
1644         update_vals[u_remote_cseq_col].type = DB1_INT;
1645         update_vals[u_remote_cseq_col].nul = 0;
1646         n_update_cols++;
1647
1648         update_cols[u_local_cseq_col= n_update_cols]= &str_local_cseq_col;
1649         update_vals[u_local_cseq_col].type = DB1_INT;
1650         update_vals[u_local_cseq_col].nul = 0;
1651         n_update_cols++;
1652         
1653         update_cols[u_version_col= n_update_cols]= &str_version_col;
1654         update_vals[u_version_col].type = DB1_INT;
1655         update_vals[u_version_col].nul = 0;
1656         n_update_cols++;
1657
1658
1659         if(db== NULL)
1660         {
1661                 LM_ERR("null database connection\n");
1662                 return;
1663         }
1664         
1665         /* if in dbonly mode, no update to database is required */
1666         if(dbmode == DB_ONLY)
1667         {
1668                 goto delete_expired_subs;
1669         }
1670         
1671         for(i=0; i<htable_size; i++) 
1672         {
1673                 if(!no_lock)
1674                         lock_get(&hash_table[i].lock);  
1675
1676                 prev_s= hash_table[i].entries;
1677                 s= prev_s->next;
1678         
1679                 while(s)
1680                 {
1681                         printf_subs(s);
1682                         if(s->expires < (int)time(NULL)- expires_offset)        
1683                         {
1684                                 LM_DBG("Found expired record\n");
1685                                 if(!no_lock)
1686                                 {
1687                                         if(handle_expired_func(s)< 0)
1688                                         {
1689                                                 LM_ERR("in function handle_expired_record\n");
1690                                                 if(!no_lock)
1691                                                         lock_release(&hash_table[i].lock);      
1692                                                 return ;
1693                                         }
1694                                 }
1695                                 del_s= s;       
1696                                 s= s->next;
1697                                 prev_s->next= s;
1698                                 
1699                                 /* need for a struct free/destroy? */
1700                                 if (del_s->contact.s)
1701                                         shm_free(del_s->contact.s);
1702
1703                                 shm_free(del_s);
1704                                 continue;
1705                         }
1706                         switch(s->db_flag)
1707                         {
1708                                 case NO_UPDATEDB_FLAG:
1709                                         LM_DBG("NO_UPDATEDB_FLAG\n");
1710                                         break;                    
1711
1712                                 case UPDATEDB_FLAG:
1713                                         LM_DBG("UPDATEDB_FLAG\n");
1714
1715                                         query_vals[pres_uri_col].val.str_val= s->pres_uri;
1716                                         query_vals[callid_col].val.str_val= s->callid;
1717                                         query_vals[totag_col].val.str_val= s->to_tag;
1718                                         query_vals[fromtag_col].val.str_val= s->from_tag;
1719                                 
1720                                         update_vals[u_expires_col].val.int_val= s->expires;
1721                                         update_vals[u_local_cseq_col].val.int_val= s->local_cseq;
1722                                         update_vals[u_remote_cseq_col].val.int_val= s->remote_cseq;
1723                                         update_vals[u_version_col].val.int_val= s->version;
1724                                         update_vals[u_status_col].val.int_val= s->status;
1725                                         update_vals[u_reason_col].val.str_val= s->reason;
1726
1727                                         if(dbf.update(db, query_cols, 0, query_vals, update_cols, 
1728                                                                 update_vals, n_query_update, n_update_cols)< 0)
1729                                         {
1730                                                 LM_ERR("updating in database\n");
1731                                         } else {
1732                                                 s->db_flag= NO_UPDATEDB_FLAG;   
1733                                         }
1734                                         break;
1735
1736                                 case  INSERTDB_FLAG:
1737                                         LM_DBG("INSERTDB_FLAG\n");
1738
1739                                         query_vals[pres_uri_col].val.str_val= s->pres_uri;
1740                                         query_vals[callid_col].val.str_val= s->callid;
1741                                         query_vals[totag_col].val.str_val= s->to_tag;
1742                                         query_vals[fromtag_col].val.str_val= s->from_tag;
1743                                         query_vals[to_user_col].val.str_val = s->to_user;
1744                                         query_vals[to_domain_col].val.str_val = s->to_domain;
1745                                         query_vals[from_user_col].val.str_val = s->from_user;
1746                                         query_vals[from_domain_col].val.str_val = s->from_domain;
1747                                         query_vals[event_col].val.str_val = s->event->name;
1748                                         query_vals[event_id_col].val.str_val = s->event_id;
1749                                         query_vals[local_cseq_col].val.int_val= s->local_cseq;
1750                                         query_vals[remote_cseq_col].val.int_val= s->remote_cseq;
1751                                         query_vals[expires_col].val.int_val = s->expires;
1752                                         query_vals[record_route_col].val.str_val = s->record_route;
1753                                         query_vals[contact_col].val.str_val = s->contact;
1754                                         query_vals[local_contact_col].val.str_val = s->local_contact;
1755                                         query_vals[version_col].val.int_val= s->version;
1756                                         query_vals[status_col].val.int_val= s->status;
1757                                         query_vals[reason_col].val.str_val= s->reason;
1758                                         query_vals[socket_info_col].val.str_val= s->sockinfo_str;
1759                                 
1760                                         if(dbf.insert(db,query_cols,query_vals,n_query_cols )<0)
1761                                         {
1762                                                 LM_ERR("unsuccessful sql insert\n");
1763                                         } else {
1764                                                 s->db_flag= NO_UPDATEDB_FLAG;   
1765                                         }
1766                                         break;                                                                          
1767                         } /* switch */
1768                         prev_s= s;
1769                         s= s->next;
1770                 }
1771                 if(!no_lock)
1772                         lock_release(&hash_table[i].lock);      
1773         }
1774
1775 delete_expired_subs:
1776         update_vals[0].val.int_val= (int)time(NULL) - expires_offset;
1777         update_ops[0]= OP_LT;
1778         if(dbf.delete(db, update_cols, update_ops, update_vals, 1) < 0)
1779         {
1780                 LM_ERR("deleting expired information from database\n");
1781         }
1782
1783 }
1784
1785 int restore_db_subs(void)
1786 {
1787         db_key_t result_cols[22]; 
1788         db1_res_t *result= NULL;
1789         db_row_t *rows = NULL;  
1790         db_val_t *row_vals= NULL;
1791         int i;
1792         int n_result_cols= 0;
1793         int pres_uri_col, expires_col, from_user_col, from_domain_col,to_user_col; 
1794         int callid_col,totag_col,fromtag_col,to_domain_col,sockinfo_col,reason_col;
1795         int event_col,contact_col,record_route_col, event_id_col, status_col;
1796         int remote_cseq_col, local_cseq_col, local_contact_col, version_col;
1797         subs_t s;
1798         str ev_sname;
1799         pres_ev_t* event= NULL;
1800         event_t parsed_event;
1801         unsigned int expires;
1802         unsigned int hash_code;
1803         int nr_rows;
1804
1805         result_cols[pres_uri_col=n_result_cols++]       =&str_presentity_uri_col;
1806         result_cols[expires_col=n_result_cols++]=&str_expires_col;
1807         result_cols[event_col=n_result_cols++]  =&str_event_col;
1808         result_cols[event_id_col=n_result_cols++]=&str_event_id_col;
1809         result_cols[to_user_col=n_result_cols++]        =&str_to_user_col;
1810         result_cols[to_domain_col=n_result_cols++]      =&str_to_domain_col;
1811         result_cols[from_user_col=n_result_cols++]      =&str_watcher_username_col;
1812         result_cols[from_domain_col=n_result_cols++]=&str_watcher_domain_col;
1813         result_cols[callid_col=n_result_cols++] =&str_callid_col;
1814         result_cols[totag_col=n_result_cols++]  =&str_to_tag_col;
1815         result_cols[fromtag_col=n_result_cols++]=&str_from_tag_col;
1816         result_cols[local_cseq_col= n_result_cols++]    =&str_local_cseq_col;
1817         result_cols[remote_cseq_col= n_result_cols++]   =&str_remote_cseq_col;
1818         result_cols[record_route_col= n_result_cols++]  =&str_record_route_col;
1819         result_cols[sockinfo_col= n_result_cols++]      =&str_socket_info_col;
1820         result_cols[contact_col= n_result_cols++]       =&str_contact_col;
1821         result_cols[local_contact_col= n_result_cols++] =&str_local_contact_col;
1822         result_cols[version_col= n_result_cols++]       =&str_version_col;
1823         result_cols[status_col= n_result_cols++]        =&str_status_col;
1824         result_cols[reason_col= n_result_cols++]        =&str_reason_col;
1825         
1826         if(!pa_db)
1827         {
1828                 LM_ERR("null database connection\n");
1829                 return -1;
1830         }
1831
1832         if(pa_dbf.use_table(pa_db, &active_watchers_table)< 0)
1833         {
1834                 LM_ERR("in use table\n");
1835                 return -1;
1836         }
1837
1838         /* select the whole table and all the columns */
1839         if (DB_CAPABILITY(pa_dbf, DB_CAP_FETCH)) 
1840         {
1841                 if(pa_dbf.query(pa_db,0,0,0,result_cols, 0,
1842                 n_result_cols, 0, 0) < 0) 
1843                 {
1844                         LM_ERR("Error while querying (fetch) database\n");
1845                         return -1;
1846                 }
1847                 if(pa_dbf.fetch_result(pa_db,&result,ACTW_FETCH_SIZE)<0)
1848                 {
1849                         LM_ERR("fetching rows failed\n");
1850                         return -1;
1851                 }
1852         } else 
1853         {
1854                 if (pa_dbf.query (pa_db, 0, 0, 0,result_cols,0, n_result_cols,
1855                                         0, &result) < 0)
1856                 {
1857                         LM_ERR("querying presentity\n");
1858                         goto error;
1859                 }
1860         }
1861
1862         nr_rows = RES_ROW_N(result);
1863
1864
1865         do {
1866                 LM_DBG("loading information from database %i records\n", nr_rows);
1867
1868                 rows = RES_ROWS(result);
1869
1870                 /* for every row */
1871                 for(i=0; i<nr_rows; i++)
1872                 {
1873
1874                         row_vals = ROW_VALUES(rows +i);
1875                         memset(&s, 0, sizeof(subs_t));
1876
1877                         expires= row_vals[expires_col].val.int_val;
1878                 
1879                         if(expires< (int)time(NULL))
1880                             continue;
1881         
1882                         s.pres_uri.s= (char*)row_vals[pres_uri_col].val.string_val;
1883                         s.pres_uri.len= strlen(s.pres_uri.s);
1884                 
1885                         s.to_user.s=(char*)row_vals[to_user_col].val.string_val;
1886                         s.to_user.len= strlen(s.to_user.s);
1887                         
1888                         s.to_domain.s=(char*)row_vals[to_domain_col].val.string_val;
1889                         s.to_domain.len= strlen(s.to_domain.s);
1890                         
1891                         s.from_user.s=(char*)row_vals[from_user_col].val.string_val;
1892                         s.from_user.len= strlen(s.from_user.s);
1893                         
1894                         s.from_domain.s=(char*)row_vals[from_domain_col].val.string_val;
1895                         s.from_domain.len= strlen(s.from_domain.s);
1896                         
1897                         s.to_tag.s=(char*)row_vals[totag_col].val.string_val;
1898                         s.to_tag.len= strlen(s.to_tag.s);
1899
1900                         s.from_tag.s=(char*)row_vals[fromtag_col].val.string_val;
1901                         s.from_tag.len= strlen(s.from_tag.s);
1902
1903                         s.callid.s=(char*)row_vals[callid_col].val.string_val;
1904                         s.callid.len= strlen(s.callid.s);
1905
1906                         ev_sname.s= (char*)row_vals[event_col].val.string_val;
1907                         ev_sname.len= strlen(ev_sname.s);
1908                 
1909                         event= contains_event(&ev_sname, &parsed_event);
1910                         if(event== NULL)
1911                             {
1912                                 LM_DBG("insert a new event structure in the list waiting"
1913                                        " to be filled in\n");
1914                                 
1915                                 /*insert a new event structure in the list waiting to be filled in*/
1916                                 event= (pres_ev_t*)shm_malloc(sizeof(pres_ev_t));
1917                                 if(event== NULL)
1918                                     {
1919                                         free_event_params(parsed_event.params.list, PKG_MEM_TYPE);
1920                                         ERR_MEM(SHM_MEM_STR);
1921                                     }
1922                                 memset(event, 0, sizeof(pres_ev_t));
1923                                 event->name.s= (char*)shm_malloc(ev_sname.len* sizeof(char));
1924                                 if(event->name.s== NULL)
1925                                     {
1926                                         free_event_params(parsed_event.params.list, PKG_MEM_TYPE);
1927                                         ERR_MEM(SHM_MEM_STR);
1928                                     }
1929                                 memcpy(event->name.s,ev_sname.s, ev_sname.len);
1930                                 event->name.len= ev_sname.len;
1931                                 
1932                                 event->evp= shm_copy_event(&parsed_event);
1933                                 if(event->evp== NULL)
1934                                     {
1935                                         LM_ERR("ERROR copying event_t structure\n");
1936                                         free_event_params(parsed_event.params.list, PKG_MEM_TYPE);
1937                                         goto error;
1938                                     }
1939                                 event->next= EvList->events;
1940                                 EvList->events= event;
1941                             }
1942                         
1943                         free_event_params(parsed_event.params.list, PKG_MEM_TYPE);
1944                         
1945                         s.event= event;
1946
1947                         s.event_id.s=(char*)row_vals[event_id_col].val.string_val;
1948                         if(s.event_id.s)
1949                             s.event_id.len= strlen(s.event_id.s);
1950                         
1951                         s.remote_cseq= row_vals[remote_cseq_col].val.int_val;
1952                         s.local_cseq= row_vals[local_cseq_col].val.int_val;
1953                         s.version= row_vals[version_col].val.int_val;
1954                 
1955                         s.expires= expires- (int)time(NULL);
1956                         s.status= row_vals[status_col].val.int_val;
1957
1958                         s.reason.s= (char*)row_vals[reason_col].val.string_val;
1959                         if(s.reason.s)
1960                             s.reason.len= strlen(s.reason.s);
1961
1962                         s.contact.s=(char*)row_vals[contact_col].val.string_val;
1963                         s.contact.len= strlen(s.contact.s);
1964                         
1965                         s.local_contact.s=(char*)row_vals[local_contact_col].val.string_val;
1966                         s.local_contact.len= strlen(s.local_contact.s);
1967                         
1968                         s.record_route.s=(char*)row_vals[record_route_col].val.string_val;
1969                         if(s.record_route.s)
1970                             s.record_route.len= strlen(s.record_route.s);
1971         
1972                         s.sockinfo_str.s=(char*)row_vals[sockinfo_col].val.string_val;
1973                         s.sockinfo_str.len= strlen(s.sockinfo_str.s);
1974
1975                         if(dbmode == DB_FALLBACK)
1976                                 s.db_flag = NO_UPDATEDB_FLAG;
1977                         hash_code= core_hash(&s.pres_uri, &s.event->name, shtable_size);
1978                         if(insert_shtable(subs_htable, hash_code, &s)< 0)
1979                         {
1980                                 LM_ERR("adding new record in hash table\n");
1981                                 goto error;
1982                         }
1983                 }
1984
1985                 /* any more data to be fetched ?*/
1986                 if (DB_CAPABILITY(pa_dbf, DB_CAP_FETCH)) {
1987                     if (pa_dbf.fetch_result( pa_db, &result,
1988                                              ACTW_FETCH_SIZE ) < 0) {
1989                         LM_ERR("fetching more rows failed\n");
1990                         goto error;
1991                     }
1992                     nr_rows = RES_ROW_N(result);
1993                 } else {
1994                     nr_rows = 0;
1995                 }
1996
1997         }while (nr_rows>0);
1998
1999         pa_dbf.free_result(pa_db, result);
2000
2001         /* delete all records */
2002         if(dbmode != DB_MEMORY_ONLY && pa_dbf.delete(pa_db, 0,0,0,0)< 0)
2003         {
2004                 LM_ERR("deleting all records from database table\n");
2005                 return -1;
2006         }
2007
2008         return 0;
2009
2010 error:
2011         if(result)
2012                 pa_dbf.free_result(pa_db, result);
2013         return -1;
2014
2015 }
2016
2017 int refresh_watcher(str* pres_uri, str* watcher_uri, str* event, 
2018                 int status, str* reason)
2019 {
2020         unsigned int hash_code;
2021         subs_t* s, *s_copy;
2022         pres_ev_t* ev;          
2023         struct sip_uri uri;
2024         str user, domain;
2025         /* refresh status in subs_htable and send notify */
2026
2027         ev=     contains_event(event, NULL);
2028         if(ev== NULL)
2029         {
2030                 LM_ERR("while searching event in list\n");
2031                 return -1;
2032         }
2033
2034         if(parse_uri(watcher_uri->s, watcher_uri->len, &uri)< 0)
2035         {
2036                 LM_ERR("parsing uri\n");
2037                 return -1;
2038         }
2039         user= uri.user;
2040         domain= uri.host;
2041
2042         hash_code= core_hash(pres_uri, event, shtable_size);
2043
2044         lock_get(&subs_htable[hash_code].lock);
2045
2046         s= subs_htable[hash_code].entries->next;
2047
2048         while(s)
2049         {
2050                 if(s->event== ev && s->pres_uri.len== pres_uri->len &&
2051                         strncmp(s->pres_uri.s, pres_uri->s, pres_uri->len)== 0 &&
2052                         s->from_user.len==user.len && strncmp(s->from_user.s,user.s, user.len)==0 &&
2053                         s->from_domain.len== domain.len && 
2054                         strncmp(s->from_domain.s, domain.s, domain.len)== 0)
2055                 {
2056                         s->status= status;
2057                         if(reason)
2058                                 s->reason= *reason;
2059                         
2060                         s_copy= mem_copy_subs(s, PKG_MEM_TYPE);
2061                         if(s_copy== NULL)
2062                         {
2063                                 LM_ERR("copying subs_t\n");
2064                                 lock_release(&subs_htable[hash_code].lock);
2065                                 return -1;
2066                         }
2067                         lock_release(&subs_htable[hash_code].lock);
2068                         if(notify(s_copy, NULL, NULL, 0)< 0)
2069                         {
2070                                 LM_ERR("in notify function\n");
2071                                 pkg_free(s_copy);
2072                                 return -1;
2073                         }
2074                         pkg_free(s_copy);
2075                         lock_get(&subs_htable[hash_code].lock);
2076                 }
2077                 s= s->next;
2078         }
2079         return 0;
2080 }
2081
2082 int get_db_subs_auth(subs_t* subs, int* found)
2083 {
2084         db_key_t db_keys[5];
2085         db_val_t db_vals[5];
2086         int n_query_cols= 0; 
2087         db_key_t result_cols[3];
2088         db1_res_t *result = NULL;
2089         db_row_t *row ; 
2090         db_val_t *row_vals ;
2091
2092         db_keys[n_query_cols] =&str_presentity_uri_col;
2093         db_vals[n_query_cols].type = DB1_STR;
2094         db_vals[n_query_cols].nul = 0;
2095         db_vals[n_query_cols].val.str_val= subs->pres_uri;
2096         n_query_cols++;
2097
2098         db_keys[n_query_cols] =&str_watcher_username_col;
2099         db_vals[n_query_cols].type = DB1_STR;
2100         db_vals[n_query_cols].nul = 0;
2101         db_vals[n_query_cols].val.str_val = subs->from_user;
2102         n_query_cols++;
2103
2104         db_keys[n_query_cols] =&str_watcher_domain_col;
2105         db_vals[n_query_cols].type = DB1_STR;
2106         db_vals[n_query_cols].nul = 0;
2107         db_vals[n_query_cols].val.str_val = subs->from_domain;
2108         n_query_cols++;
2109         
2110         db_keys[n_query_cols] =&str_event_col;
2111         db_vals[n_query_cols].type = DB1_STR;
2112         db_vals[n_query_cols].nul = 0;
2113         db_vals[n_query_cols].val.str_val = subs->event->name;
2114         n_query_cols++;
2115
2116         result_cols[0] = &str_status_col;
2117         result_cols[1] = &str_reason_col;
2118         
2119         if(pa_dbf.use_table(pa_db, &watchers_table)< 0)
2120         {
2121                 LM_ERR("in use table\n");
2122                 return -1;
2123         }       
2124
2125         if(pa_dbf.query(pa_db, db_keys, 0, db_vals, result_cols,
2126                                         n_query_cols, 2, 0, &result )< 0)
2127         {
2128                 LM_ERR("while querying watchers table\n");
2129                 if(result)
2130                         pa_dbf.free_result(pa_db, result);
2131                 return -1;
2132         }
2133         if(result== NULL)
2134                 return -1;
2135         
2136         if(result->n<= 0)
2137         {
2138                 *found= 0;
2139                 pa_dbf.free_result(pa_db, result);
2140                 return 0;
2141         }
2142
2143         *found= 1;
2144         row = &result->rows[0];
2145         row_vals = ROW_VALUES(row);
2146         subs->status= row_vals[0].val.int_val;
2147
2148         if(row_vals[1].val.string_val)
2149         {
2150
2151                 subs->reason.len= strlen(row_vals[1].val.string_val);
2152                 if(subs->reason.len== 0)
2153                         subs->reason.s= NULL;
2154                 else
2155                 {
2156                         subs->reason.s= (char*)pkg_malloc(subs->reason.len*sizeof(char));
2157                         if(subs->reason.s== NULL)
2158                         {
2159                                 pa_dbf.free_result(pa_db, result);
2160                                 ERR_MEM(PKG_MEM_STR);
2161                         }               
2162                         memcpy(subs->reason.s, row_vals[1].val.string_val, subs->reason.len);
2163                 }
2164         }
2165         
2166         pa_dbf.free_result(pa_db, result);
2167         return 0;
2168 error:
2169         return -1;
2170 }       
2171
2172 int insert_db_subs_auth(subs_t* subs)
2173 {
2174         db_key_t db_keys[10];
2175         db_val_t db_vals[10];
2176         int n_query_cols= 0; 
2177
2178         db_keys[n_query_cols] =&str_presentity_uri_col;
2179         db_vals[n_query_cols].type = DB1_STR;
2180         db_vals[n_query_cols].nul = 0;
2181         db_vals[n_query_cols].val.str_val= subs->pres_uri;
2182         n_query_cols++;
2183
2184         db_keys[n_query_cols] =&str_watcher_username_col;
2185         db_vals[n_query_cols].type = DB1_STR;
2186         db_vals[n_query_cols].nul = 0;
2187         db_vals[n_query_cols].val.str_val = subs->from_user;
2188         n_query_cols++;
2189
2190         db_keys[n_query_cols] =&str_watcher_domain_col;
2191         db_vals[n_query_cols].type = DB1_STR;
2192         db_vals[n_query_cols].nul = 0;
2193         db_vals[n_query_cols].val.str_val = subs->from_domain;
2194         n_query_cols++;
2195         
2196         db_keys[n_query_cols] =&str_event_col;
2197         db_vals[n_query_cols].type = DB1_STR;
2198         db_vals[n_query_cols].nul = 0;
2199         db_vals[n_query_cols].val.str_val = subs->event->name;
2200         n_query_cols++;
2201
2202         db_keys[n_query_cols] =&str_status_col;
2203         db_vals[n_query_cols].type = DB1_INT;
2204         db_vals[n_query_cols].nul = 0;
2205         db_vals[n_query_cols].val.int_val = subs->status;
2206         n_query_cols++;
2207                                                                 
2208         db_keys[n_query_cols] = &str_inserted_time_col;
2209         db_vals[n_query_cols].type = DB1_INT;
2210         db_vals[n_query_cols].nul = 0;
2211         db_vals[n_query_cols].val.int_val= (int)time(NULL);
2212         n_query_cols++;
2213         
2214         if(subs->reason.s && subs->reason.len)
2215         {
2216                 db_keys[n_query_cols] =&str_reason_col;
2217                 db_vals[n_query_cols].type = DB1_STR;
2218                 db_vals[n_query_cols].nul = 0;
2219                 db_vals[n_query_cols].val.str_val = subs->reason;
2220                 n_query_cols++; 
2221         }       
2222         
2223         if (pa_dbf.use_table(pa_db, &watchers_table) < 0) 
2224         {
2225                 LM_ERR("in use_table\n");
2226                 return -1;
2227         }
2228
2229         if(pa_dbf.insert(pa_db, db_keys, db_vals, n_query_cols )< 0)
2230         {       
2231                 LM_ERR("in sql insert\n");
2232                 return -1;
2233         }
2234
2235         return 0;
2236 }