Fix relative paths to tm header files.
[sip-router] / modules_k / rls / rls.c
1 /*
2  * $Id: rls.c 2230 2007-06-06 07:13:20Z anca_vamanu $
3  *
4  * rls module - resource list server
5  *
6  * Copyright (C) 2007 Voice Sistem S.R.L.
7  *
8  * This file is part of Kamailio, a free SIP server.
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  *  2007-09-11  initial version (anca)
27  */
28
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <sys/types.h>
33 #include <sys/ipc.h>
34 #include <unistd.h>
35 #include <fcntl.h>
36 #include <time.h>
37
38 #include "../../pt.h"
39 #include "../../lib/srdb1/db.h"
40 #include "../../sr_module.h"
41 #include "../../dprint.h"
42 #include "../../error.h"
43 #include "../../ut.h"
44 #include "../../mem/mem.h"
45 #include "../../mem/shm_mem.h"
46 #include "../../modules/tm/tm_load.h"
47 #include "../sl/sl_api.h"
48 #include "../presence/bind_presence.h"
49 #include "../presence/hash.h"
50 #include "../pua/pua_bind.h"
51 #include "../pua/pidf.h"
52 #include "../xcap_client/xcap_functions.h"
53 #include "rls.h"
54 #include "notify.h"
55 #include "resource_notify.h"
56
57 MODULE_VERSION
58
59 #define P_TABLE_VERSION 0
60 #define W_TABLE_VERSION 1
61
62 /** database connection */
63 db1_con_t *rls_db = NULL;
64 db_func_t rls_dbf;
65
66 /** modules variables */
67 str server_address= {0, 0};
68 int waitn_time= 10;
69 str rlsubs_table= str_init("rls_watchers");
70 str rlpres_table= str_init("rls_presentity");
71 str rls_xcap_table= str_init("xcap");
72
73 str db_url= str_init(DEFAULT_DB_URL);
74 int hash_size= 512;
75 shtable_t rls_table;
76 int pid;
77 contains_event_t pres_contains_event;
78 search_event_t pres_search_event;
79 get_event_list_t pres_get_ev_list;
80 int clean_period= 100;
81 char* xcap_root;
82 unsigned int xcap_port= 8000;
83 int rls_restore_db_subs(void);
84 int rls_integrated_xcap_server= 0;
85
86 /** libxml api */
87 xmlDocGetNodeByName_t XMLDocGetNodeByName;
88 xmlNodeGetNodeByName_t XMLNodeGetNodeByName;
89 xmlNodeGetNodeContentByName_t XMLNodeGetNodeContentByName;
90 xmlNodeGetAttrContentByName_t XMLNodeGetAttrContentByName;
91
92 /* functions imported from presence to handle subscribe hash table */
93 new_shtable_t pres_new_shtable;
94 insert_shtable_t pres_insert_shtable;
95 search_shtable_t pres_search_shtable;
96 update_shtable_t pres_update_shtable;
97 delete_shtable_t pres_delete_shtable;
98 destroy_shtable_t pres_destroy_shtable;
99 mem_copy_subs_t  pres_copy_subs;
100 update_db_subs_t pres_update_db_subs;
101 extract_sdialog_info_t pres_extract_sdialog_info;
102 int rls_events= EVENT_PRESENCE;
103 int to_presence_code= 1;
104 int rls_max_expires= 7200;
105
106 /* functions imported from xcap_client module */
107 xcapGetNewDoc_t xcap_GetNewDoc= 0;
108
109 /* functions imported from pua module*/
110 send_subscribe_t pua_send_subscribe;
111 get_record_id_t pua_get_record_id;
112
113 /* TM bind */
114 struct tm_binds tmb;
115 /* SL bind */
116 struct sl_binds slb;
117
118 str str_rlsubs_did_col = str_init("rlsubs_did");
119 str str_resource_uri_col = str_init("resource_uri");
120 str str_updated_col = str_init("updated");
121 str str_auth_state_col = str_init("auth_state");
122 str str_reason_col = str_init("reason");
123 str str_content_type_col = str_init("content_type");
124 str str_presence_state_col = str_init("presence_state");
125 str str_expires_col = str_init("expires");
126 str str_presentity_uri_col = str_init("presentity_uri");
127 str str_event_col = str_init("event");
128 str str_event_id_col = str_init("event_id");
129 str str_to_user_col = str_init("to_user");
130 str str_to_domain_col = str_init("to_domain");
131 str str_watcher_username_col = str_init("watcher_username");
132 str str_watcher_domain_col = str_init("watcher_domain");
133 str str_callid_col = str_init("callid");
134 str str_to_tag_col = str_init("to_tag");
135 str str_from_tag_col = str_init("from_tag");
136 str str_local_cseq_col = str_init("local_cseq");
137 str str_remote_cseq_col = str_init("remote_cseq");
138 str str_record_route_col = str_init("record_route");
139 str str_socket_info_col = str_init("socket_info");
140 str str_contact_col = str_init("contact");
141 str str_local_contact_col = str_init("local_contact");
142 str str_version_col = str_init("version");
143 str str_status_col = str_init("status");
144 str str_username_col = str_init("username");
145 str str_domain_col = str_init("domain");
146 str str_doc_type_col = str_init("doc_type");
147 str str_etag_col = str_init("etag");
148 str str_doc_col = str_init("doc");
149
150
151 /** module functions */
152
153 static int mod_init(void);
154 static int child_init(int);
155 int rls_handle_subscribe(struct sip_msg*, char*, char*);
156 void destroy(void);
157 int rlsubs_table_restore();
158 void rlsubs_table_update(unsigned int ticks,void *param);
159 int add_rls_event(modparam_t type, void* val);
160
161 static cmd_export_t cmds[]=
162 {
163         {"rls_handle_subscribe",  (cmd_function)rls_handle_subscribe,   0,
164                         0, 0, REQUEST_ROUTE},
165         {"rls_handle_notify",     (cmd_function)rls_handle_notify,      0,
166                         0, 0, REQUEST_ROUTE},
167         {0, 0, 0, 0, 0, 0 }
168 };
169
170 static param_export_t params[]={
171         { "server_address",         STR_PARAM,   &server_address.s                           },
172         { "db_url",                                     STR_PARAM,   &db_url.s                                       },
173         { "rlsubs_table",               STR_PARAM,   &rlsubs_table.s                         },
174         { "rlpres_table",                       STR_PARAM,   &rlpres_table.s                         },
175         { "xcap_table",                 STR_PARAM,   &rls_xcap_table.s                       },
176         { "waitn_time",                         INT_PARAM,   &waitn_time                                     },
177         { "clean_period",                       INT_PARAM,   &clean_period                                   },
178         { "max_expires",                        INT_PARAM,   &rls_max_expires                        },
179         { "hash_size",                      INT_PARAM,   &hash_size                                  },
180         { "integrated_xcap_server",     INT_PARAM,   &rls_integrated_xcap_server     }, 
181         { "to_presence_code",       INT_PARAM,   &to_presence_code               },
182         { "xcap_root",              STR_PARAM,   &xcap_root                      },
183         /*address and port(default: 80):"http://192.168.2.132:8000/xcap-root"*/
184         { "rls_event",              STR_PARAM|USE_FUNC_PARAM,(void*)add_rls_event},
185         {0,                                                     0,                              0                                                    }
186 };
187
188 /** module exports */
189 struct module_exports exports= {
190         "rls",                                          /* module name */
191         DEFAULT_DLFLAGS,                        /* dlopen flags */
192         cmds,                                           /* exported functions */
193         params,                                         /* exported parameters */
194         0,                                                      /* exported statistics */
195         0,                                              /* exported MI functions */
196         0,                                                      /* exported pseudo-variables */
197         0,                                                      /* extra processes */
198         mod_init,                                       /* module initialization function */
199         0,                                                      /* response handling function */
200         (destroy_function) destroy, /* destroy function */
201         child_init                  /* per-child init function */
202 };
203
204 /**
205  * init module function
206  */
207 static int mod_init(void)
208 {
209         bind_presence_t bind_presence;
210         presence_api_t pres;
211         bind_pua_t bind_pua;
212         pua_api_t pua;
213         bind_libxml_t bind_libxml;
214         libxml_api_t libxml_api;
215         bind_xcap_t bind_xcap;
216         xcap_api_t xcap_api;
217         char* sep;
218
219         LM_DBG("start\n");
220
221         if(!server_address.s)
222         {
223                 LM_DBG("server_address parameter not set in configuration file\n");
224         }       
225         else
226                 server_address.len= strlen(server_address.s);
227         
228         if(!rls_integrated_xcap_server && xcap_root== NULL)
229         {
230                 LM_ERR("xcap_root parameter not set\n");
231                 return -1;
232         }
233         /* extract port if any */
234         if(xcap_root)
235     {
236         sep= strchr(xcap_root, ':');
237         if(sep)
238         {
239             char* sep2= NULL;
240             sep2= strchr(sep+ 1, ':');
241             if(sep2)
242                 sep= sep2;
243
244             str port_str;
245
246             port_str.s= sep+ 1;
247             port_str.len= strlen(xcap_root)- (port_str.s-xcap_root);
248
249             if(str2int(&port_str, &xcap_port)< 0)
250             {
251                 LM_ERR("converting string to int [port]= %.*s\n",port_str.len,
252                         port_str.s);
253                 return -1;
254             }
255             if(xcap_port< 0 || xcap_port> 65535)
256             {
257                 LM_ERR("wrong xcap server port\n");
258                 return -1;
259             }
260             *sep= '\0';
261         }
262     }
263
264         /* load SL API */
265         if(load_sl_api(&slb)==-1)
266         {
267                 LM_ERR("can't load sl functions\n");
268                 return -1;
269         }
270
271         /* load all TM stuff */
272         if(load_tm_api(&tmb)==-1)
273         {
274                 LM_ERR("can't load tm functions\n");
275                 return -1;
276         }
277         bind_presence= (bind_presence_t)find_export("bind_presence", 1,0);
278         if (!bind_presence)
279         {
280                 LM_ERR("Can't bind presence\n");
281                 return -1;
282         }
283         if (bind_presence(&pres) < 0)
284         {
285                 LM_ERR("Can't bind presence\n");
286                 return -1;
287         }
288         pres_contains_event = pres.contains_event;
289         pres_search_event   = pres.search_event;
290         pres_get_ev_list    = pres.get_event_list;
291         pres_new_shtable    = pres.new_shtable;
292         pres_destroy_shtable= pres.destroy_shtable;
293         pres_insert_shtable = pres.insert_shtable;
294         pres_delete_shtable = pres.delete_shtable;
295         pres_update_shtable = pres.update_shtable;
296         pres_search_shtable = pres.search_shtable;
297         pres_copy_subs      = pres.mem_copy_subs;
298         pres_update_db_subs = pres.update_db_subs;
299         pres_extract_sdialog_info= pres.extract_sdialog_info;
300
301         if(!pres_contains_event || !pres_get_ev_list || !pres_new_shtable ||
302                 !pres_destroy_shtable || !pres_insert_shtable || !pres_delete_shtable
303                  || !pres_update_shtable || !pres_search_shtable || !pres_copy_subs
304                  || !pres_extract_sdialog_info)
305         {
306                 LM_ERR("importing functions from presence module\n");
307                 return -1;
308         }
309
310         rlsubs_table.len= strlen(rlsubs_table.s);
311         rlpres_table.len= strlen(rlpres_table.s);
312         rls_xcap_table.len= strlen(rls_xcap_table.s);
313         db_url.len = db_url.s ? strlen(db_url.s) : 0;
314         LM_DBG("db_url=%s/%d/%p\n", ZSW(db_url.s), db_url.len, db_url.s);
315         
316         /* binding to mysql module  */
317         if (db_bind_mod(&db_url, &rls_dbf))
318         {
319                 LM_ERR("Database module not found\n");
320                 return -1;
321         }
322         
323         if (!DB_CAPABILITY(rls_dbf, DB_CAP_ALL)) {
324                 LM_ERR("Database module does not implement all functions"
325                                 " needed by the module\n");
326                 return -1;
327         }
328
329         rls_db = rls_dbf.init(&db_url);
330         if (!rls_db)
331         {
332                 LM_ERR("while connecting database\n");
333                 return -1;
334         }
335         /* verify table version */
336         if((db_check_table_version(&rls_dbf, rls_db, &rlsubs_table, W_TABLE_VERSION) < 0) ||
337                 (db_check_table_version(&rls_dbf, rls_db, &rlpres_table, P_TABLE_VERSION) < 0)) {
338                         LM_ERR("error during table version check.\n");
339                         return -1;
340         }
341         
342         if(hash_size<=1)
343                 hash_size= 512;
344         else
345                 hash_size = 1<<hash_size;
346
347         rls_table= pres_new_shtable(hash_size);
348         if(rls_table== NULL)
349         {
350                 LM_ERR("while creating new hash table\n");
351                 return -1;
352         }
353         if(rls_restore_db_subs()< 0)
354         {
355                 LM_ERR("while restoring rl watchers table\n");
356                 return -1;
357         }
358
359         if(rls_db)
360                 rls_dbf.close(rls_db);
361         rls_db = NULL;
362
363         if(waitn_time<= 0)
364                 waitn_time= 5;
365         
366         if(waitn_time<= 0)
367                 waitn_time= 100;
368
369         /* bind libxml wrapper functions */
370
371         if((bind_libxml=(bind_libxml_t)find_export("bind_libxml_api", 1, 0))== NULL)
372         {
373                 LM_ERR("can't import bind_libxml_api\n");
374                 return -1;
375         }
376         if(bind_libxml(&libxml_api)< 0)
377         {
378                 LM_ERR("can not bind libxml api\n");
379                 return -1;
380         }
381         XMLNodeGetAttrContentByName= libxml_api.xmlNodeGetAttrContentByName;
382         XMLDocGetNodeByName= libxml_api.xmlDocGetNodeByName;
383         XMLNodeGetNodeByName= libxml_api.xmlNodeGetNodeByName;
384     XMLNodeGetNodeContentByName= libxml_api.xmlNodeGetNodeContentByName;
385
386         if(XMLNodeGetAttrContentByName== NULL || XMLDocGetNodeByName== NULL ||
387                         XMLNodeGetNodeByName== NULL || XMLNodeGetNodeContentByName== NULL)
388         {
389                 LM_ERR("libxml wrapper functions could not be bound\n");
390                 return -1;
391         }
392
393         /* bind pua */
394         bind_pua= (bind_pua_t)find_export("bind_pua", 1,0);
395         if (!bind_pua)
396         {
397                 LM_ERR("Can't bind pua\n");
398                 return -1;
399         }
400         
401         if (bind_pua(&pua) < 0)
402         {
403                 LM_ERR("mod_init Can't bind pua\n");
404                 return -1;
405         }
406         if(pua.send_subscribe == NULL)
407         {
408                 LM_ERR("Could not import send_subscribe\n");
409                 return -1;
410         }
411         pua_send_subscribe= pua.send_subscribe;
412         
413         if(pua.get_record_id == NULL)
414         {
415                 LM_ERR("Could not import send_subscribe\n");
416                 return -1;
417         }
418         pua_get_record_id= pua.get_record_id;
419
420         if(!rls_integrated_xcap_server)
421         {
422                 /* bind xcap */
423                 bind_xcap= (bind_xcap_t)find_export("bind_xcap", 1, 0);
424                 if (!bind_xcap)
425                 {
426                         LM_ERR("Can't bind xcap_client\n");
427                         return -1;
428                 }
429         
430                 if (bind_xcap(&xcap_api) < 0)
431                 {
432                         LM_ERR("Can't bind xcap\n");
433                         return -1;
434                 }
435                 xcap_GetNewDoc= xcap_api.getNewDoc;
436                 if(xcap_GetNewDoc== NULL)
437                 {
438                         LM_ERR("Can't import xcap_client functions\n");
439                         return -1;
440                 }
441         }
442         register_timer(timer_send_notify,0, waitn_time);
443         
444         register_timer(rls_presentity_clean, 0, clean_period);
445         
446         register_timer(rlsubs_table_update, 0, clean_period);
447         
448         return 0;
449 }
450
451 /**
452  * Initialize children
453  */
454 static int child_init(int rank)
455 {
456         LM_DBG("child [%d]  pid [%d]\n", rank, getpid());
457         if (rls_dbf.init==0)
458         {
459                 LM_CRIT("database not bound\n");
460                 return -1;
461         }
462         rls_db = rls_dbf.init(&db_url);
463         if (!rls_db)
464         {
465                 LM_ERR("child %d: Error while connecting database\n",
466                                 rank);
467                 return -1;
468         }
469         else
470         {
471                 if (rls_dbf.use_table(rls_db, &rlsubs_table) < 0)  
472                 {
473                         LM_ERR("child %d: Error in use_table rlsubs_table\n", rank);
474                         return -1;
475                 }
476                 if (rls_dbf.use_table(rls_db, &rlpres_table) < 0)  
477                 {
478                         LM_ERR("child %d: Error in use_table rlpres_table\n", rank);
479                         return -1;
480                 }
481
482                 LM_DBG("child %d: Database connection opened successfully\n", rank);
483         }
484
485         pid= my_pid();
486         return 0;
487 }
488
489 /*
490  * destroy function
491  */
492 void destroy(void)
493 {
494         LM_DBG("start\n");
495         
496         if(rls_table)
497         {
498                 if(rls_db)
499                         rlsubs_table_update(0, 0);
500                 pres_destroy_shtable(rls_table, hash_size);
501         }
502         if(rls_db && rls_dbf.close)
503                 rls_dbf.close(rls_db);
504 }
505
506 int handle_expired_record(subs_t* s)
507 {
508         /* send Notify with state terminated*/  
509         if( rls_send_notify(s, NULL, NULL, NULL)< 0)
510         {
511                 LM_ERR("in function send_notify\n");
512                 return -1;
513         }
514         
515         return 0;
516 }
517
518 void rlsubs_table_update(unsigned int ticks,void *param)
519 {
520         int no_lock= 0;
521
522         if(ticks== 0 && param == NULL)
523                 no_lock= 1;
524         
525         if(rls_dbf.use_table(rls_db, &rlsubs_table)< 0)
526         {
527                 LM_ERR("sql use table failed\n");
528                 return;
529         }
530         pres_update_db_subs(rls_db, rls_dbf, rls_table, hash_size, 
531                         no_lock, handle_expired_record);
532
533 }
534
535 int rls_restore_db_subs(void)
536 {
537         db_key_t result_cols[22]; 
538         db1_res_t *res= NULL;
539         db_row_t *row = NULL;   
540         db_val_t *row_vals= NULL;
541         int i;
542         int n_result_cols= 0;
543         int pres_uri_col, expires_col, from_user_col, from_domain_col,to_user_col; 
544         int callid_col,totag_col,fromtag_col,to_domain_col,sockinfo_col,reason_col;
545         int event_col,contact_col,record_route_col, event_id_col, status_col;
546         int remote_cseq_col, local_cseq_col, local_contact_col, version_col;
547         subs_t s;
548         str ev_sname;
549         pres_ev_t* event= NULL;
550         event_t parsed_event;
551         unsigned int expires;
552         unsigned int hash_code;
553
554         result_cols[pres_uri_col=n_result_cols++] = &str_presentity_uri_col;
555         result_cols[expires_col=n_result_cols++] = &str_expires_col;
556         result_cols[event_col=n_result_cols++] = &str_event_col;
557         result_cols[event_id_col=n_result_cols++] = &str_event_id_col;
558         result_cols[to_user_col=n_result_cols++] = &str_to_user_col;
559         result_cols[to_domain_col=n_result_cols++] = &str_to_domain_col;
560         result_cols[from_user_col=n_result_cols++] = &str_watcher_username_col;
561         result_cols[from_domain_col=n_result_cols++] = &str_watcher_domain_col;
562         result_cols[callid_col=n_result_cols++] = &str_callid_col;
563         result_cols[totag_col=n_result_cols++] = &str_to_tag_col;
564         result_cols[fromtag_col=n_result_cols++] = &str_from_tag_col;
565         result_cols[local_cseq_col= n_result_cols++] = &str_local_cseq_col;
566         result_cols[remote_cseq_col= n_result_cols++] = &str_remote_cseq_col;
567         result_cols[record_route_col= n_result_cols++] = &str_record_route_col;
568         result_cols[sockinfo_col= n_result_cols++] = &str_socket_info_col;
569         result_cols[contact_col= n_result_cols++] = &str_contact_col;
570         result_cols[local_contact_col= n_result_cols++] = &str_local_contact_col;
571         result_cols[version_col= n_result_cols++] = &str_version_col;
572         result_cols[status_col= n_result_cols++] = &str_status_col;
573         result_cols[reason_col= n_result_cols++] = &str_reason_col;
574         
575         if(!rls_db)
576         {
577                 LM_ERR("null database connection\n");
578                 return -1;
579         }
580         if(rls_dbf.use_table(rls_db, &rlsubs_table)< 0)
581         {
582                 LM_ERR("in use table\n");
583                 return -1;
584         }
585
586         if(rls_dbf.query(rls_db,0, 0, 0, result_cols,0, n_result_cols, 0,&res)< 0)
587         {
588                 LM_ERR("while querrying table\n");
589                 if(res)
590                 {
591                         rls_dbf.free_result(rls_db, res);
592                         res = NULL;
593                 }
594                 return -1;
595         }
596         if(res== NULL)
597                 return -1;
598
599         if(res->n<=0)
600         {
601                 LM_INFO("The query returned no result\n");
602                 rls_dbf.free_result(rls_db, res);
603                 res = NULL;
604                 return 0;
605         }
606
607         LM_DBG("found %d db entries\n", res->n);
608
609         for(i =0 ; i< res->n ; i++)
610         {
611                 row = &res->rows[i];
612                 row_vals = ROW_VALUES(row);
613                 memset(&s, 0, sizeof(subs_t));
614
615                 expires= row_vals[expires_col].val.int_val;
616                 
617                 if(expires< (int)time(NULL))
618                         continue;
619         
620                 s.pres_uri.s= (char*)row_vals[pres_uri_col].val.string_val;
621                 s.pres_uri.len= strlen(s.pres_uri.s);
622                 
623                 s.to_user.s=(char*)row_vals[to_user_col].val.string_val;
624                 s.to_user.len= strlen(s.to_user.s);
625
626                 s.to_domain.s=(char*)row_vals[to_domain_col].val.string_val;
627                 s.to_domain.len= strlen(s.to_domain.s);
628
629                 s.from_user.s=(char*)row_vals[from_user_col].val.string_val;
630                 s.from_user.len= strlen(s.from_user.s);
631                 
632                 s.from_domain.s=(char*)row_vals[from_domain_col].val.string_val;
633                 s.from_domain.len= strlen(s.from_domain.s);
634
635                 s.to_tag.s=(char*)row_vals[totag_col].val.string_val;
636                 s.to_tag.len= strlen(s.to_tag.s);
637
638                 s.from_tag.s=(char*)row_vals[fromtag_col].val.string_val;
639                 s.from_tag.len= strlen(s.from_tag.s);
640
641                 s.callid.s=(char*)row_vals[callid_col].val.string_val;
642                 s.callid.len= strlen(s.callid.s);
643
644                 ev_sname.s= (char*)row_vals[event_col].val.string_val;
645                 ev_sname.len= strlen(ev_sname.s);
646                 
647                 event= pres_contains_event(&ev_sname, &parsed_event);
648                 if(event== NULL)
649                 {
650                         LM_ERR("event not found in list\n");
651                         goto error;
652                 }
653                 s.event= event;
654
655                 s.event_id.s=(char*)row_vals[event_id_col].val.string_val;
656                 if(s.event_id.s)
657                         s.event_id.len= strlen(s.event_id.s);
658
659                 s.remote_cseq= row_vals[remote_cseq_col].val.int_val;
660                 s.local_cseq= row_vals[local_cseq_col].val.int_val;
661                 s.version= row_vals[version_col].val.int_val;
662                 
663                 s.expires= expires- (int)time(NULL);
664                 s.status= row_vals[status_col].val.int_val;
665
666                 s.reason.s= (char*)row_vals[reason_col].val.string_val;
667                 if(s.reason.s)
668                         s.reason.len= strlen(s.reason.s);
669
670                 s.contact.s=(char*)row_vals[contact_col].val.string_val;
671                 s.contact.len= strlen(s.contact.s);
672
673                 s.local_contact.s=(char*)row_vals[local_contact_col].val.string_val;
674                 s.local_contact.len= strlen(s.local_contact.s);
675         
676                 s.record_route.s=(char*)row_vals[record_route_col].val.string_val;
677                 if(s.record_route.s)
678                         s.record_route.len= strlen(s.record_route.s);
679         
680                 s.sockinfo_str.s=(char*)row_vals[sockinfo_col].val.string_val;
681                 s.sockinfo_str.len= strlen(s.sockinfo_str.s);
682
683                 hash_code= core_hash(&s.pres_uri, &s.event->name, hash_size);
684                 if(pres_insert_shtable(rls_table, hash_code, &s)< 0)
685                 {
686                         LM_ERR("adding new record in hash table\n");
687                         goto error;
688                 }
689         }
690
691         rls_dbf.free_result(rls_db, res);
692
693         /* delete all records */
694         if(rls_dbf.delete(rls_db, 0,0,0,0)< 0)
695         {
696                 LM_ERR("deleting all records from database table\n");
697                 return -1;
698         }
699
700         return 0;
701
702 error:
703         if(res)
704                 rls_dbf.free_result(rls_db, res);
705         return -1;
706
707 }
708
709 int add_rls_event(modparam_t type, void* val)
710 {
711         char* event= (char*)val;
712         event_t e;
713
714         if(event_parser(event, strlen(event), &e)< 0)
715         {
716                 LM_ERR("while parsing event = %s\n", event);
717                 return -1;
718         }
719         if(e.type & EVENT_OTHER)
720         {
721                 LM_ERR("wrong event= %s\n", event);
722                 return -1;
723         }
724
725         rls_events|= e.type;
726
727         return 0;
728
729 }