ARI - implement allowMultiple for parameters
[asterisk/asterisk.git] / res / res_ari_asterisk.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2012 - 2013, Digium, Inc.
5  *
6  * David M. Lee, II <dlee@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*
20  * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
21  * !!!!!                               DO NOT EDIT                        !!!!!
22  * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
23  * This file is generated by a mustache template. Please see the original
24  * template in rest-api-templates/res_ari_resource.c.mustache
25  */
26
27 /*! \file
28  *
29  * \brief Asterisk resources
30  *
31  * \author David M. Lee, II <dlee@digium.com>
32  */
33
34 /*** MODULEINFO
35         <depend type="module">res_ari</depend>
36         <depend type="module">res_stasis</depend>
37         <support_level>core</support_level>
38  ***/
39
40 #include "asterisk.h"
41
42 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
43
44 #include "asterisk/app.h"
45 #include "asterisk/module.h"
46 #include "asterisk/stasis_app.h"
47 #include "ari/resource_asterisk.h"
48 #if defined(AST_DEVMODE)
49 #include "ari/ari_model_validators.h"
50 #endif
51
52 #define MAX_VALS 128
53
54 /*!
55  * \brief Parameter parsing callback for /asterisk/info.
56  * \param get_params GET parameters in the HTTP request.
57  * \param path_vars Path variables extracted from the request.
58  * \param headers HTTP headers.
59  * \param[out] response Response to the HTTP request.
60  */
61 static void ast_ari_get_asterisk_info_cb(
62         struct ast_variable *get_params, struct ast_variable *path_vars,
63         struct ast_variable *headers, struct ast_ari_response *response)
64 {
65         struct ast_get_asterisk_info_args args = {};
66         struct ast_variable *i;
67 #if defined(AST_DEVMODE)
68         int is_valid;
69         int code;
70 #endif /* AST_DEVMODE */
71
72         for (i = get_params; i; i = i->next) {
73                 if (strcmp(i->name, "only") == 0) {
74                         /* Parse comma separated list */
75                         char *vals[MAX_VALS];
76                         size_t j;
77
78                         args.only_parse = ast_strdup(i->value);
79                         if (!args.only_parse) {
80                                 ast_ari_response_alloc_failed(response);
81                                 goto fin;
82                         }
83
84                         args.only_count = ast_app_separate_args(
85                                 args.only_parse, ',', vals, ARRAY_LEN(vals));
86                         if (args.only_count == 0) {
87                                 ast_ari_response_alloc_failed(response);
88                                 goto fin;
89                         }
90
91                         if (args.only_count >= MAX_VALS) {
92                                 ast_ari_response_error(response, 400,
93                                         "Bad Request",
94                                         "Too many values for only");
95                                 goto fin;
96                         }
97
98                         args.only = ast_malloc(sizeof(*args.only) * args.only_count);
99                         if (!args.only) {
100                                 ast_ari_response_alloc_failed(response);
101                                 goto fin;
102                         }
103
104                         for (j = 0; j < args.only_count; ++j) {
105                                 args.only[j] = (vals[j]);
106                         }
107                 } else
108                 {}
109         }
110         ast_ari_get_asterisk_info(headers, &args, response);
111 #if defined(AST_DEVMODE)
112         code = response->response_code;
113
114         switch (code) {
115         case 0: /* Implementation is still a stub, or the code wasn't set */
116                 is_valid = response->message == NULL;
117                 break;
118         case 500: /* Internal Server Error */
119         case 501: /* Not Implemented */
120                 is_valid = 1;
121                 break;
122         default:
123                 if (200 <= code && code <= 299) {
124                         is_valid = ast_ari_validate_asterisk_info(
125                                 response->message);
126                 } else {
127                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/info\n", code);
128                         is_valid = 0;
129                 }
130         }
131
132         if (!is_valid) {
133                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/info\n");
134                 ast_ari_response_error(response, 500,
135                         "Internal Server Error", "Response validation failed");
136         }
137 #endif /* AST_DEVMODE */
138
139 fin: __attribute__((unused))
140         ast_free(args.only_parse);
141         ast_free(args.only);
142         return;
143 }
144 /*!
145  * \brief Parameter parsing callback for /asterisk/variable.
146  * \param get_params GET parameters in the HTTP request.
147  * \param path_vars Path variables extracted from the request.
148  * \param headers HTTP headers.
149  * \param[out] response Response to the HTTP request.
150  */
151 static void ast_ari_get_global_var_cb(
152         struct ast_variable *get_params, struct ast_variable *path_vars,
153         struct ast_variable *headers, struct ast_ari_response *response)
154 {
155         struct ast_get_global_var_args args = {};
156         struct ast_variable *i;
157 #if defined(AST_DEVMODE)
158         int is_valid;
159         int code;
160 #endif /* AST_DEVMODE */
161
162         for (i = get_params; i; i = i->next) {
163                 if (strcmp(i->name, "variable") == 0) {
164                         args.variable = (i->value);
165                 } else
166                 {}
167         }
168         ast_ari_get_global_var(headers, &args, response);
169 #if defined(AST_DEVMODE)
170         code = response->response_code;
171
172         switch (code) {
173         case 0: /* Implementation is still a stub, or the code wasn't set */
174                 is_valid = response->message == NULL;
175                 break;
176         case 500: /* Internal Server Error */
177         case 501: /* Not Implemented */
178                 is_valid = 1;
179                 break;
180         default:
181                 if (200 <= code && code <= 299) {
182                         is_valid = ast_ari_validate_variable(
183                                 response->message);
184                 } else {
185                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/variable\n", code);
186                         is_valid = 0;
187                 }
188         }
189
190         if (!is_valid) {
191                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/variable\n");
192                 ast_ari_response_error(response, 500,
193                         "Internal Server Error", "Response validation failed");
194         }
195 #endif /* AST_DEVMODE */
196
197 fin: __attribute__((unused))
198         return;
199 }
200 /*!
201  * \brief Parameter parsing callback for /asterisk/variable.
202  * \param get_params GET parameters in the HTTP request.
203  * \param path_vars Path variables extracted from the request.
204  * \param headers HTTP headers.
205  * \param[out] response Response to the HTTP request.
206  */
207 static void ast_ari_set_global_var_cb(
208         struct ast_variable *get_params, struct ast_variable *path_vars,
209         struct ast_variable *headers, struct ast_ari_response *response)
210 {
211         struct ast_set_global_var_args args = {};
212         struct ast_variable *i;
213 #if defined(AST_DEVMODE)
214         int is_valid;
215         int code;
216 #endif /* AST_DEVMODE */
217
218         for (i = get_params; i; i = i->next) {
219                 if (strcmp(i->name, "variable") == 0) {
220                         args.variable = (i->value);
221                 } else
222                 if (strcmp(i->name, "value") == 0) {
223                         args.value = (i->value);
224                 } else
225                 {}
226         }
227         ast_ari_set_global_var(headers, &args, response);
228 #if defined(AST_DEVMODE)
229         code = response->response_code;
230
231         switch (code) {
232         case 0: /* Implementation is still a stub, or the code wasn't set */
233                 is_valid = response->message == NULL;
234                 break;
235         case 500: /* Internal Server Error */
236         case 501: /* Not Implemented */
237                 is_valid = 1;
238                 break;
239         default:
240                 if (200 <= code && code <= 299) {
241                         is_valid = ast_ari_validate_void(
242                                 response->message);
243                 } else {
244                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/variable\n", code);
245                         is_valid = 0;
246                 }
247         }
248
249         if (!is_valid) {
250                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/variable\n");
251                 ast_ari_response_error(response, 500,
252                         "Internal Server Error", "Response validation failed");
253         }
254 #endif /* AST_DEVMODE */
255
256 fin: __attribute__((unused))
257         return;
258 }
259
260 /*! \brief REST handler for /api-docs/asterisk.{format} */
261 static struct stasis_rest_handlers asterisk_info = {
262         .path_segment = "info",
263         .callbacks = {
264                 [AST_HTTP_GET] = ast_ari_get_asterisk_info_cb,
265         },
266         .num_children = 0,
267         .children = {  }
268 };
269 /*! \brief REST handler for /api-docs/asterisk.{format} */
270 static struct stasis_rest_handlers asterisk_variable = {
271         .path_segment = "variable",
272         .callbacks = {
273                 [AST_HTTP_GET] = ast_ari_get_global_var_cb,
274                 [AST_HTTP_POST] = ast_ari_set_global_var_cb,
275         },
276         .num_children = 0,
277         .children = {  }
278 };
279 /*! \brief REST handler for /api-docs/asterisk.{format} */
280 static struct stasis_rest_handlers asterisk = {
281         .path_segment = "asterisk",
282         .callbacks = {
283         },
284         .num_children = 2,
285         .children = { &asterisk_info,&asterisk_variable, }
286 };
287
288 static int load_module(void)
289 {
290         int res = 0;
291         stasis_app_ref();
292         res |= ast_ari_add_handler(&asterisk);
293         return res;
294 }
295
296 static int unload_module(void)
297 {
298         ast_ari_remove_handler(&asterisk);
299         stasis_app_unref();
300         return 0;
301 }
302
303 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Asterisk resources",
304         .load = load_module,
305         .unload = unload_module,
306         .nonoptreq = "res_ari,res_stasis",
307         );