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