f5b1732e8983b913d623f4bf2090b9b9791affd6
[sip-router] / src / modules / tsilo / tsilo.c
1 /**
2  *
3  * Copyright (C) 2015 Federico Cabiddu (federico.cabiddu@gmail.com)
4  *
5  * This file is part of Kamailio, a free SIP server.
6  *
7  * Kamailio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version
11  *
12  * Kamailio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25
26 #include "../../core/sr_module.h"
27 #include "../../core/dprint.h"
28 #include "../../core/mod_fix.h"
29 #include "../../core/route.h"
30 #include "../../core/script_cb.h"
31 #include "../../modules/tm/tm_load.h"
32 #include "../../modules/registrar/api.h"
33 #include "../../core/dset.h"
34 #include "../../core/rpc_lookup.h"
35
36 #include "ts_hash.h"
37 #include "ts_handlers.h"
38 #include "ts_append.h"
39 #include "ts_store.h"
40 #include "ts_rpc.h"
41
42 MODULE_VERSION
43
44
45 /** TM bind **/
46 struct tm_binds _tmb;
47 /** REGISTRAR bind **/
48 registrar_api_t _regapi;
49
50 /** parameters */
51 static int hash_size = 2048;
52 int use_domain = 0;
53
54 /** module functions */
55 static int mod_init(void);
56 static void destroy(void);
57
58 static int w_ts_append_to(struct sip_msg* msg, char *idx, char *lbl, char *d);
59 static int w_ts_append_to2(struct sip_msg* msg, char *idx, char *lbl, char *d, char *ruri);
60 static int fixup_ts_append_to(void** param, int param_no);
61 static int w_ts_append(struct sip_msg* _msg, char *_table, char *_ruri);
62 static int fixup_ts_append(void** param, int param_no);
63
64 static int w_ts_store(struct sip_msg* msg, char *p1, char *p2);
65 static int w_ts_store1(struct sip_msg* msg, char *_ruri, char *p2);
66
67 stat_var *stored_ruris;
68 stat_var *stored_transactions;
69 stat_var *total_ruris;
70 stat_var *total_transactions;
71 stat_var *added_branches;
72
73 static cmd_export_t cmds[]={
74         {"ts_append_to", (cmd_function)w_ts_append_to,  3,
75                 fixup_ts_append_to, 0, REQUEST_ROUTE | FAILURE_ROUTE },
76         {"ts_append_to", (cmd_function)w_ts_append_to2,  4,
77                 fixup_ts_append_to, 0, REQUEST_ROUTE | FAILURE_ROUTE },
78         {"ts_append", (cmd_function)w_ts_append,  2,
79                 fixup_ts_append, 0, REQUEST_ROUTE | FAILURE_ROUTE },
80         {"ts_store", (cmd_function)w_ts_store,  0,
81                 0 , 0, REQUEST_ROUTE | FAILURE_ROUTE },
82         {"ts_store", (cmd_function)w_ts_store1,  1,
83                 fixup_spve_null , 0, REQUEST_ROUTE | FAILURE_ROUTE },
84         {0,0,0,0,0,0}
85 };
86
87 static param_export_t params[]={
88         {"hash_size",   INT_PARAM,      &hash_size},
89         {"use_domain",  INT_PARAM,      &use_domain},
90         {0,0,0}
91 };
92
93 #ifdef STATISTICS
94 /*! \brief We expose internal variables via the statistic framework below.*/
95 stat_export_t mod_stats[] = {
96         {"stored_ruris",        STAT_NO_RESET,  &stored_ruris  },
97         {"stored_transactions", STAT_NO_RESET,  &stored_transactions  },
98         {"total_ruris",         STAT_NO_RESET,  &total_ruris  },
99         {"total_transactions",  STAT_NO_RESET,  &total_transactions  },
100         {"added_branches",      STAT_NO_RESET,  &added_branches  },
101         {0, 0, 0}
102 };
103 #endif
104
105 /** module exports */
106 struct module_exports exports = {
107         "tsilo",
108         DEFAULT_DLFLAGS,/* dlopen flags */
109         cmds,           /* Exported functions */
110         params,         /* Exported parameters */
111 #ifdef STATISTICS
112         mod_stats,      /* exported statistics */
113 #else
114         0,
115 #endif
116         0,              /* exported MI functions */
117         0,              /* exported pseudo-variables */
118         0,              /* extra processes */
119         mod_init,       /* module initialization function */
120         0,
121         destroy,        /* destroy function */
122         0,              /* Per-child init function */
123 };
124
125 /**
126  * init module function
127  */
128 static int mod_init(void)
129 {
130         unsigned int n;
131
132         /* register the RPC methods */
133         if(rpc_register_array(rpc_methods)!=0)
134         {
135         LM_ERR("failed to register RPC commands\n");
136         return -1;
137         }
138         /* load the TM API */
139         if (load_tm_api(&_tmb)!=0) {
140                 LM_ERR("can't load TM API\n");
141                 return -1;
142         }
143
144         /* load the REGISTRAR API */
145         if (registrar_load_api(&_regapi) != 0) {
146                 LM_ERR("cannot load REGISTRAR API\n");
147                 return -1;
148         }
149
150         /* sanitize hash_size */
151         if (hash_size < 1){
152                 LM_WARN("hash_size is smaller "
153                         "than 1  -> rounding from %d to 1\n",
154                         hash_size);
155                 hash_size = 1;
156         }
157
158         /* initialize the hash table */
159         for( n=0 ; n<(8*sizeof(n)) ; n++) {
160                 if (hash_size==(1<<n))
161                         break;
162                 if (n && hash_size<(1<<n)) {
163                         LM_WARN("hash_size is not a power "
164                                 "of 2 as it should be -> rounding from %d to %d (n=%d)\n",
165                                 hash_size, 1<<(n-1), n);
166                         hash_size = 1<<(n-1);
167                         break;
168                 }
169         }
170
171         LM_DBG("creating table with size %d", hash_size);
172         if ( init_ts_table(hash_size)<0 ) {
173                 LM_ERR("failed to create hash table\n");
174                 return -1;
175         }
176
177 #ifdef STATISTICS
178         /* register statistics */
179         if (register_module_stats(exports.name, mod_stats)!=0 ) {
180                 LM_ERR("failed to register core statistics\n");
181                 return -1;
182         }
183         return 0;
184 #endif
185
186 }
187
188 /**
189  * destroy function
190  */
191 static void destroy(void)
192 {
193         destroy_ts_table();
194         return;
195 }
196
197 static int ts_check_uri(str *uri)
198 {
199         struct sip_uri ruri;
200         if (parse_uri(uri->s, uri->len, &ruri)!=0)
201         {
202                 LM_ERR("bad uri [%.*s]\n",
203                                 uri->len,
204                                 uri->s);
205                 return -1;
206         }
207         return 0;
208 }
209 /**
210  *
211  */
212 static int fixup_ts_append_to(void** param, int param_no)
213 {
214         if (param_no==1 || param_no==2) {
215                 return fixup_igp_null(param, 1);
216         }
217
218         if (param_no==3) {
219                 if(strlen((char*)*param)<=1 && (*(char*)(*param)==0 || *(char*)(*param)=='0')) {
220                         *param = (void*)0;
221                         LM_ERR("empty table name\n");
222                         return -1;
223                 }
224         }
225
226         if (param_no==4) {
227                 return fixup_spve_null(param, 1);
228         }
229         return 0;
230 }
231
232 static int fixup_ts_append(void** param, int param_no)
233 {
234         if (param_no==1) {
235                 if(strlen((char*)*param)<=1 && (*(char*)(*param)==0 || *(char*)(*param)=='0')) {
236                         *param = (void*)0;
237                         LM_ERR("empty table name\n");
238                         return -1;
239                 }
240         }
241
242         if (param_no==2 || param_no==3) {
243                 return fixup_spve_null(param, 1);
244         }
245
246         return 0;
247 }
248 /**
249  *
250  */
251 static int w_ts_append(struct sip_msg* _msg, char *_table, char *_ruri)
252 {
253         str tmp  = STR_NULL;
254         str ruri = STR_NULL;
255         int rc;
256
257         if(_ruri==NULL || (fixup_get_svalue(_msg, (gparam_p)_ruri, &tmp)!=0 || tmp.len<=0)) {
258                 LM_ERR("invalid ruri parameter\n");
259                 return -1;
260         }
261         if(ts_check_uri(&tmp)<0)
262                 return -1;
263
264         if (pkg_str_dup(&ruri, &tmp) < 0)
265                 return -1;
266
267         rc = ts_append(_msg, &ruri, _table);
268
269         pkg_free(ruri.s);
270
271         return rc;
272 }
273 /**
274  *
275  */
276 static int w_ts_append_to(struct sip_msg* msg, char *idx, char *lbl, char *table)
277 {
278         unsigned int tindex;
279         unsigned int tlabel;
280
281         if(fixup_get_ivalue(msg, (gparam_p)idx, (int*)&tindex)<0) {
282                 LM_ERR("cannot get transaction index\n");
283                 return -1;
284         }
285
286         if(fixup_get_ivalue(msg, (gparam_p)lbl, (int*)&tlabel)<0) {
287                 LM_ERR("cannot get transaction label\n");
288                 return -1;
289         }
290
291         return ts_append_to(msg, tindex, tlabel, table, 0);
292 }
293
294 /**
295  *
296  */
297 static int w_ts_append_to2(struct sip_msg* msg, char *idx, char *lbl, char *table, char *ruri)
298 {
299         unsigned int tindex;
300         unsigned int tlabel;
301         str suri;
302
303         if(fixup_get_ivalue(msg, (gparam_p)idx, (int*)&tindex)<0) {
304                 LM_ERR("cannot get transaction index\n");
305                 return -1;
306         }
307
308         if(fixup_get_ivalue(msg, (gparam_p)lbl, (int*)&tlabel)<0) {
309                 LM_ERR("cannot get transaction label\n");
310                 return -1;
311         }
312
313         if(fixup_get_svalue(msg, (gparam_t*)ruri, &suri)!=0) {
314                 LM_ERR("failed to conert r-uri parameter\n");
315                 return -1;
316         }
317         if(ts_check_uri(&suri)<0)
318                 return -1;
319
320         return ts_append_to(msg, tindex, tlabel, table, &suri);
321 }
322
323 /**
324  *
325  */
326 static int w_ts_store(struct sip_msg* msg, char *p1, char *p2)
327 {
328         return ts_store(msg, 0);
329 }
330
331
332 /**
333  *
334  */
335 static int w_ts_store1(struct sip_msg* msg, char *_ruri, char *p2)
336 {
337         str suri;
338
339         if(fixup_get_svalue(msg, (gparam_t*)_ruri, &suri)!=0) {
340                 LM_ERR("failed to conert r-uri parameter\n");
341                 return -1;
342         }
343         return ts_store(msg, &suri);
344 }