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