lost: adds HELD (RFC6155) and LOST (RFC5222) queries for location-based routing
[sip-router] / 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         return 0;\r
128 }\r
129 \r
130 static void destroy(void)\r
131 {\r
132         ;\r
133         /* do nothing */\r
134 }\r
135 \r
136 /*\r
137  * Fix 4 lost_held_query params: con (string/pvar)\r
138  * and pidf, url, err (writable pvar).\r
139  */\r
140 static int fixup_lost_held_query(void **param, int param_no)\r
141 {\r
142         if(param_no == 1) {\r
143                 return fixup_spve_null(param, 1);\r
144         }\r
145         if((param_no == 2) || (param_no == 3) || (param_no == 4)) {\r
146                 if(fixup_pvar_null(param, 1) != 0) {\r
147                         LM_ERR("failed to fixup result pvar\n");\r
148                         return -1;\r
149                 }\r
150                 if(((pv_spec_t *)(*param))->setf == NULL) {\r
151                         LM_ERR("result pvar is not writable\n");\r
152                         return -1;\r
153                 }\r
154                 return 0;\r
155         }\r
156         LM_ERR("invalid parameter number <%d>\n", param_no);\r
157         return -1;\r
158 }\r
159 \r
160 /*\r
161  * Free lost_held_query params.\r
162  */\r
163 static int fixup_free_lost_held_query(void **param, int param_no)\r
164 {\r
165         if(param_no == 1) {\r
166                 /* char strings don't need freeing */\r
167                 return 0;\r
168         }\r
169         if((param_no == 2) || (param_no == 3) || (param_no == 4)) {\r
170                 return fixup_free_pvar_null(param, 1);\r
171         }\r
172         LM_ERR("invalid parameter number <%d>\n", param_no);\r
173         return -1;\r
174 }\r
175 \r
176 /*\r
177  * Fix 5 lost_held_query_id params: con (string/pvar) id (string that may contain\r
178  * pvars) and pidf, url, err (writable pvar).\r
179  */\r
180 static int fixup_lost_held_query_id(void **param, int param_no)\r
181 {\r
182         if(param_no == 1) {\r
183                 return fixup_spve_null(param, 1);\r
184         }\r
185         if(param_no == 2) {\r
186                 return fixup_spve_null(param, 1);\r
187         }\r
188         if((param_no == 3) || (param_no == 4) || (param_no == 5)) {\r
189                 if(fixup_pvar_null(param, 1) != 0) {\r
190                         LM_ERR("failed to fixup result pvar\n");\r
191                         return -1;\r
192                 }\r
193                 if(((pv_spec_t *)(*param))->setf == NULL) {\r
194                         LM_ERR("result pvar is not writable\n");\r
195                         return -1;\r
196                 }\r
197                 return 0;\r
198         }\r
199         LM_ERR("invalid parameter number <%d>\n", param_no);\r
200         return -1;\r
201 }\r
202 \r
203 /*\r
204  * Free lost_held_query_id params.\r
205  */\r
206 static int fixup_free_lost_held_query_id(void **param, int param_no)\r
207 {\r
208         if(param_no == 1) {\r
209                 return fixup_free_spve_null(param, 1);\r
210         }\r
211         if(param_no == 2) {\r
212                 return fixup_free_spve_null(param, 1);\r
213         }\r
214         if((param_no == 3) || (param_no == 4) || (param_no == 5)) {\r
215                 return fixup_free_pvar_null(param, 1);\r
216         }\r
217         LM_ERR("invalid parameter number <%d>\n", param_no);\r
218         return -1;\r
219 }\r
220 \r
221 /*\r
222  * Fix 4 lost_query params: con (string/pvar)\r
223  * and uri, name, err (writable pvar).\r
224  */\r
225 static int fixup_lost_query(void **param, int param_no)\r
226 {\r
227         if(param_no == 1) {\r
228                 return fixup_spve_null(param, 1);\r
229         }\r
230         if((param_no == 2) || (param_no == 3) || (param_no == 4)) {\r
231                 if(fixup_pvar_null(param, 1) != 0) {\r
232                         LM_ERR("failed to fixup result pvar\n");\r
233                         return -1;\r
234                 }\r
235                 if(((pv_spec_t *)(*param))->setf == NULL) {\r
236                         LM_ERR("result pvar is not writable\n");\r
237                         return -1;\r
238                 }\r
239                 return 0;\r
240         }\r
241         LM_ERR("invalid parameter number <%d>\n", param_no);\r
242         return -1;\r
243 }\r
244 \r
245 /*\r
246  * Free lost_held_query_id params.\r
247  */\r
248 static int fixup_free_lost_query(void **param, int param_no)\r
249 {\r
250         if(param_no == 1) {\r
251                 return fixup_free_spve_null(param, 1);\r
252         }\r
253         if((param_no == 2) || (param_no == 3) || (param_no == 4)) {\r
254                 return fixup_free_pvar_null(param, 1);\r
255         }\r
256         LM_ERR("invalid parameter number <%d>\n", param_no);\r
257         return -1;\r
258 }\r
259 \r
260 /*\r
261  * Fix 6 lost_query params: con (string/pvar) pidf, urn (string that may contain\r
262  * pvars) and uri, name, err (writable pvar).\r
263  */\r
264 static int fixup_lost_query_all(void **param, int param_no)\r
265 {\r
266         if(param_no == 1) {\r
267                 return fixup_spve_null(param, 1);\r
268         }\r
269         if((param_no == 2) || (param_no == 3)) {\r
270                 return fixup_spve_null(param, 1);\r
271         }\r
272         if((param_no == 4) || (param_no == 5) || (param_no == 6)) {\r
273                 if(fixup_pvar_null(param, 1) != 0) {\r
274                         LM_ERR("failed to fixup result pvar\n");\r
275                         return -1;\r
276                 }\r
277                 if(((pv_spec_t *)(*param))->setf == NULL) {\r
278                         LM_ERR("result pvar is not writable\n");\r
279                         return -1;\r
280                 }\r
281                 return 0;\r
282         }\r
283         LM_ERR("invalid parameter number <%d>\n", param_no);\r
284         return -1;\r
285 }\r
286 \r
287 /*\r
288  * Free lost_held_query_id params.\r
289  */\r
290 static int fixup_free_lost_query_all(void **param, int param_no)\r
291 {\r
292         if(param_no == 1) {\r
293                 return fixup_free_spve_null(param, 1);\r
294         }\r
295         if((param_no == 2) || (param_no == 3)) {\r
296                 return fixup_free_spve_null(param, 1);\r
297         }\r
298         if((param_no == 4) || (param_no == 5) || (param_no == 6)) {\r
299                 return fixup_free_pvar_null(param, 1);\r
300         }\r
301         LM_ERR("invalid parameter number <%d>\n", param_no);\r
302         return -1;\r
303 }\r
304 \r
305 /*\r
306  * Wrapper for lost_held_query w/o id\r
307  */\r
308 static int w_lost_held_query(\r
309                 struct sip_msg *_m, char *_con, char *_pidf, char *_url, char *_err)\r
310 {\r
311         return lost_function_held(_m, _con, _pidf, _url, _err, NULL);\r
312 }\r
313 \r
314 /*\r
315  * Wrapper for lost_held_query with id\r
316  */\r
317 static int w_lost_held_query_id(struct sip_msg *_m, char *_con, char *_id,\r
318                 char *_pidf, char *_url, char *_err)\r
319 {\r
320         return lost_function_held(_m, _con, _pidf, _url, _err, _id);\r
321 }\r
322 \r
323 /*\r
324  * Wrapper for lost_query w/o pudf, urn\r
325  */\r
326 static int w_lost_query(\r
327                 struct sip_msg *_m, char *_con, char *_uri, char *_name, char *_err)\r
328 {\r
329         return lost_function(_m, _con, _uri, _name, _err, NULL, NULL);\r
330 }\r
331 \r
332 /*\r
333  * Wrapper for lost_query with pidf, urn\r
334  */\r
335 static int w_lost_query_all(struct sip_msg *_m, char *_con, char *_pidf,\r
336                 char *_urn, char *_uri, char *_name, char *_err)\r
337 {\r
338         return lost_function(_m, _con, _uri, _name, _err, _pidf, _urn);\r
339 }\r