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