lost: adds HELD (RFC6155) and LOST (RFC5222) queries for location-based routing
[kamailio] / src / modules / lost / lost.c
1 /*\r
2  * lost module\r
3  *\r
4  * Copyright (C) 2019 Wolfgang Kampichler\r
5  * DEC112, FREQUENTIS AG\r
6  *\r
7  * This file is part of Kamailio, a free SIP server.\r
8  *\r
9  * Kamailio is free software; you can redistribute it and/or modify\r
10  * it under the terms of the GNU General Public License as published by\r
11  * the Free Software Foundation; either version 2 of the License, or\r
12  * (at your option) any later version\r
13  *\r
14  * Kamailio is distributed in the hope that it will be useful,\r
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
17  * GNU General Public License for more details.\r
18  *\r
19  * You should have received a copy of the GNU General Public License\r
20  * along with this program; if not, write to the Free Software\r
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\r
22  *\r
23  */\r
24 \r
25 /*!\r
26  * \file\r
27  * \brief Kamailio lost ::\r
28  * \ingroup lost\r
29  * Module: \ref lost\r
30  */\r
31 \r
32 #include "../../modules/http_client/curl_api.h"\r
33 \r
34 #include "../../core/mod_fix.h"\r
35 #include "../../core/sr_module.h"\r
36 #include "../../core/ut.h"\r
37 #include "../../core/locking.h"\r
38 \r
39 #include "../../core/pvar.h"\r
40 #include "../../core/mem/mem.h"\r
41 #include "../../core/dprint.h"\r
42 \r
43 #include "../../core/script_cb.h"\r
44 \r
45 #include "functions.h"\r
46 \r
47 MODULE_VERSION\r
48 \r
49 /* Module parameter variables */\r
50 httpc_api_t httpapi;\r
51 \r
52 /* Module management function prototypes */\r
53 static int mod_init(void);\r
54 static int child_init(int);\r
55 static void destroy(void);\r
56 \r
57 /* Fixup functions to be defined later */\r
58 static int fixup_lost_held_query(void **param, int param_no);\r
59 static int fixup_free_lost_held_query(void **param, int param_no);\r
60 static int fixup_lost_held_query_id(void **param, int param_no);\r
61 static int fixup_free_lost_held_query_id(void **param, int param_no);\r
62 \r
63 static int fixup_lost_query(void **param, int param_no);\r
64 static int fixup_free_lost_query(void **param, int param_no);\r
65 static int fixup_lost_query_all(void **param, int param_no);\r
66 static int fixup_free_lost_query_all(void **param, int param_no);\r
67 \r
68 /* Wrappers for http_query to be defined later */\r
69 static int w_lost_held_query(\r
70                 struct sip_msg *_m, char *_con, char *_pidf, char *_url, char *_err);\r
71 static int w_lost_held_query_id(struct sip_msg *_m, char *_con, char *_id,\r
72                 char *_pidf, char *_url, char *_err);\r
73 static int w_lost_query(\r
74                 struct sip_msg *_m, char *_con, char *_uri, char *_name, char *_err);\r
75 static int w_lost_query_all(struct sip_msg *_m, char *_con, char *_pidf,\r
76                 char *_urn, char *_uri, char *_name, char *_err);\r
77 \r
78 /* Exported functions */\r
79 static cmd_export_t cmds[] = {\r
80                 {"lost_held_query", (cmd_function)w_lost_held_query, 4,\r
81                                 fixup_lost_held_query, fixup_free_lost_held_query,\r
82                                 REQUEST_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE},\r
83                 {"lost_held_query", (cmd_function)w_lost_held_query_id, 5,\r
84                                 fixup_lost_held_query_id, fixup_free_lost_held_query_id,\r
85                                 REQUEST_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE},\r
86                 {"lost_query", (cmd_function)w_lost_query, 4, fixup_lost_query,\r
87                                 fixup_free_lost_query,\r
88                                 REQUEST_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE},\r
89                 {"lost_query", (cmd_function)w_lost_query_all, 6, fixup_lost_query_all,\r
90                                 fixup_free_lost_query_all,\r
91                                 REQUEST_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE},\r
92                 {0, 0, 0, 0, 0, 0}};\r
93 \r
94 \r
95 /* Module interface */\r
96 struct module_exports exports = {\r
97                 "lost",                  /* module name*/\r
98                 DEFAULT_DLFLAGS, /* dlopen flags */\r
99                 cmds,                    /* exported functions */\r
100                 0,                               /* exported parameters */\r
101                 0,                               /* RPC method exports */\r
102                 0,                               /* exported pseudo-variables */\r
103                 0,                               /* response handling function */\r
104                 mod_init,                /* module initialization function */\r
105                 child_init,              /* per-child init function */\r
106                 destroy                  /* module destroy function */\r
107 };\r
108 \r
109 /* Module initialization function */\r
110 static int mod_init(void)\r
111 {\r
112         LM_DBG("init lost module\n");\r
113 \r
114         if(httpc_load_api(&httpapi) != 0) {\r
115                 LM_ERR("Can not bind to http_client API \n");\r
116                 return -1;\r
117         }\r
118 \r
119         LM_DBG("**** init lost module done.\n");\r
120 \r
121         return 0;\r
122 }\r
123 \r
124 /* Child initialization function */\r
125 static int child_init(int rank)\r
126 {\r
127         if(rank == PROC_INIT || rank == PROC_MAIN || rank == PROC_TCP_MAIN) {\r
128                 return 0; /* do nothing for the main process */\r
129         }\r
130 \r
131         return 0;\r
132 }\r
133 \r
134 static void destroy(void)\r
135 {\r
136         ;\r
137         /* do nothing */\r
138 }\r
139 \r
140 /*\r
141  * Fix 4 lost_held_query params: con (string/pvar)\r
142  * and pidf, url, err (writable pvar).\r
143  */\r
144 static int fixup_lost_held_query(void **param, int param_no)\r
145 {\r
146         if(param_no == 1) {\r
147                 return fixup_spve_null(param, 1);\r
148         }\r
149         if((param_no == 2) || (param_no == 3) || (param_no == 4)) {\r
150                 if(fixup_pvar_null(param, 1) != 0) {\r
151                         LM_ERR("failed to fixup result pvar\n");\r
152                         return -1;\r
153                 }\r
154                 if(((pv_spec_t *)(*param))->setf == NULL) {\r
155                         LM_ERR("result pvar is not writeble\n");\r
156                         return -1;\r
157                 }\r
158                 return 0;\r
159         }\r
160         LM_ERR("invalid parameter number <%d>\n", param_no);\r
161         return -1;\r
162 }\r
163 \r
164 /*\r
165  * Free lost_held_query params.\r
166  */\r
167 static int fixup_free_lost_held_query(void **param, int param_no)\r
168 {\r
169         if(param_no == 1) {\r
170                 /* char strings don't need freeing */\r
171                 return 0;\r
172         }\r
173         if((param_no == 2) || (param_no == 3) || (param_no == 4)) {\r
174                 return fixup_free_pvar_null(param, 1);\r
175         }\r
176         LM_ERR("invalid parameter number <%d>\n", param_no);\r
177         return -1;\r
178 }\r
179 \r
180 /*\r
181  * Fix 5 lost_held_query_id params: con (string/pvar) id (string that may contain\r
182  * pvars) and pidf, url, err (writable pvar).\r
183  */\r
184 static int fixup_lost_held_query_id(void **param, int param_no)\r
185 {\r
186         if(param_no == 1) {\r
187                 return fixup_spve_null(param, 1);\r
188         }\r
189         if(param_no == 2) {\r
190                 return fixup_spve_null(param, 1);\r
191         }\r
192         if((param_no == 3) || (param_no == 4) || (param_no == 5)) {\r
193                 if(fixup_pvar_null(param, 1) != 0) {\r
194                         LM_ERR("failed to fixup result pvar\n");\r
195                         return -1;\r
196                 }\r
197                 if(((pv_spec_t *)(*param))->setf == NULL) {\r
198                         LM_ERR("result pvar is not writeble\n");\r
199                         return -1;\r
200                 }\r
201                 return 0;\r
202         }\r
203         LM_ERR("invalid parameter number <%d>\n", param_no);\r
204         return -1;\r
205 }\r
206 \r
207 /*\r
208  * Free lost_held_query_id params.\r
209  */\r
210 static int fixup_free_lost_held_query_id(void **param, int param_no)\r
211 {\r
212         if(param_no == 1) {\r
213                 return fixup_free_spve_null(param, 1);\r
214         }\r
215         if(param_no == 2) {\r
216                 return fixup_free_spve_null(param, 1);\r
217         }\r
218         if((param_no == 3) || (param_no == 4) || (param_no == 5)) {\r
219                 return fixup_free_pvar_null(param, 1);\r
220         }\r
221         LM_ERR("invalid parameter number <%d>\n", param_no);\r
222         return -1;\r
223 }\r
224 \r
225 /*\r
226  * Fix 4 lost_query params: con (string/pvar)\r
227  * and uri, name, err (writable pvar).\r
228  */\r
229 static int fixup_lost_query(void **param, int param_no)\r
230 {\r
231         if(param_no == 1) {\r
232                 return fixup_spve_null(param, 1);\r
233         }\r
234         if((param_no == 2) || (param_no == 3) || (param_no == 4)) {\r
235                 if(fixup_pvar_null(param, 1) != 0) {\r
236                         LM_ERR("failed to fixup result pvar\n");\r
237                         return -1;\r
238                 }\r
239                 if(((pv_spec_t *)(*param))->setf == NULL) {\r
240                         LM_ERR("result pvar is not writeble\n");\r
241                         return -1;\r
242                 }\r
243                 return 0;\r
244         }\r
245         LM_ERR("invalid parameter number <%d>\n", param_no);\r
246         return -1;\r
247 }\r
248 \r
249 /*\r
250  * Free lost_held_query_id params.\r
251  */\r
252 static int fixup_free_lost_query(void **param, int param_no)\r
253 {\r
254         if(param_no == 1) {\r
255                 return fixup_free_spve_null(param, 1);\r
256         }\r
257         if((param_no == 2) || (param_no == 3) || (param_no == 4)) {\r
258                 return fixup_free_pvar_null(param, 1);\r
259         }\r
260         LM_ERR("invalid parameter number <%d>\n", param_no);\r
261         return -1;\r
262 }\r
263 \r
264 /*\r
265  * Fix 6 lost_query params: con (string/pvar) pidf, urn (string that may contain\r
266  * pvars) and uri, name, err (writable pvar).\r
267  */\r
268 static int fixup_lost_query_all(void **param, int param_no)\r
269 {\r
270         if(param_no == 1) {\r
271                 return fixup_spve_null(param, 1);\r
272         }\r
273         if((param_no == 2) || (param_no == 3)) {\r
274                 return fixup_spve_null(param, 1);\r
275         }\r
276         if((param_no == 4) || (param_no == 5) || (param_no == 6)) {\r
277                 if(fixup_pvar_null(param, 1) != 0) {\r
278                         LM_ERR("failed to fixup result pvar\n");\r
279                         return -1;\r
280                 }\r
281                 if(((pv_spec_t *)(*param))->setf == NULL) {\r
282                         LM_ERR("result pvar is not writeble\n");\r
283                         return -1;\r
284                 }\r
285                 return 0;\r
286         }\r
287         LM_ERR("invalid parameter number <%d>\n", param_no);\r
288         return -1;\r
289 }\r
290 \r
291 /*\r
292  * Free lost_held_query_id params.\r
293  */\r
294 static int fixup_free_lost_query_all(void **param, int param_no)\r
295 {\r
296         if(param_no == 1) {\r
297                 return fixup_free_spve_null(param, 1);\r
298         }\r
299         if((param_no == 2) || (param_no == 3)) {\r
300                 return fixup_free_spve_null(param, 1);\r
301         }\r
302         if((param_no == 4) || (param_no == 5) || (param_no == 6)) {\r
303                 return fixup_free_pvar_null(param, 1);\r
304         }\r
305         LM_ERR("invalid parameter number <%d>\n", param_no);\r
306         return -1;\r
307 }\r
308 \r
309 /*\r
310  * Wrapper for lost_held_query w/o id\r
311  */\r
312 static int w_lost_held_query(\r
313                 struct sip_msg *_m, char *_con, char *_pidf, char *_url, char *_err)\r
314 {\r
315         return lost_function_held(_m, _con, _pidf, _url, _err, NULL);\r
316 }\r
317 \r
318 /*\r
319  * Wrapper for lost_held_query with id\r
320  */\r
321 static int w_lost_held_query_id(struct sip_msg *_m, char *_con, char *_id,\r
322                 char *_pidf, char *_url, char *_err)\r
323 {\r
324         return lost_function_held(_m, _con, _pidf, _url, _err, _id);\r
325 }\r
326 \r
327 /*\r
328  * Wrapper for lost_query w/o pudf, urn\r
329  */\r
330 static int w_lost_query(\r
331                 struct sip_msg *_m, char *_con, char *_uri, char *_name, char *_err)\r
332 {\r
333         return lost_function(_m, _con, _uri, _name, _err, NULL, NULL);\r
334 }\r
335 \r
336 /*\r
337  * Wrapper for lost_query with pidf, urn\r
338  */\r
339 static int w_lost_query_all(struct sip_msg *_m, char *_con, char *_pidf,\r
340                 char *_urn, char *_uri, char *_name, char *_err)\r
341 {\r
342         return lost_function(_m, _con, _uri, _name, _err, _pidf, _urn);\r
343 }\r