pbx.c: Properly parse labels with leading digits
[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_ari_model</depend>
37         <depend type="module">res_stasis</depend>
38         <support_level>core</support_level>
39  ***/
40
41 #include "asterisk.h"
42
43 #include "asterisk/app.h"
44 #include "asterisk/module.h"
45 #include "asterisk/stasis_app.h"
46 #include "ari/resource_asterisk.h"
47 #if defined(AST_DEVMODE)
48 #include "ari/ari_model_validators.h"
49 #endif
50
51 #define MAX_VALS 128
52
53 /*!
54  * \brief Parameter parsing callback for /asterisk/config/dynamic/{configClass}/{objectType}/{id}.
55  * \param get_params GET parameters in the HTTP request.
56  * \param path_vars Path variables extracted from the request.
57  * \param headers HTTP headers.
58  * \param[out] response Response to the HTTP request.
59  */
60 static void ast_ari_asterisk_get_object_cb(
61         struct ast_tcptls_session_instance *ser,
62         struct ast_variable *get_params, struct ast_variable *path_vars,
63         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
64 {
65         struct ast_ari_asterisk_get_object_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 = path_vars; i; i = i->next) {
73                 if (strcmp(i->name, "configClass") == 0) {
74                         args.config_class = (i->value);
75                 } else
76                 if (strcmp(i->name, "objectType") == 0) {
77                         args.object_type = (i->value);
78                 } else
79                 if (strcmp(i->name, "id") == 0) {
80                         args.id = (i->value);
81                 } else
82                 {}
83         }
84         ast_ari_asterisk_get_object(headers, &args, response);
85 #if defined(AST_DEVMODE)
86         code = response->response_code;
87
88         switch (code) {
89         case 0: /* Implementation is still a stub, or the code wasn't set */
90                 is_valid = response->message == NULL;
91                 break;
92         case 500: /* Internal Server Error */
93         case 501: /* Not Implemented */
94         case 404: /* {configClass|objectType|id} not found */
95                 is_valid = 1;
96                 break;
97         default:
98                 if (200 <= code && code <= 299) {
99                         is_valid = ast_ari_validate_list(response->message,
100                                 ast_ari_validate_config_tuple_fn());
101                 } else {
102                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/config/dynamic/{configClass}/{objectType}/{id}\n", code);
103                         is_valid = 0;
104                 }
105         }
106
107         if (!is_valid) {
108                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/config/dynamic/{configClass}/{objectType}/{id}\n");
109                 ast_ari_response_error(response, 500,
110                         "Internal Server Error", "Response validation failed");
111         }
112 #endif /* AST_DEVMODE */
113
114 fin: __attribute__((unused))
115         return;
116 }
117 int ast_ari_asterisk_update_object_parse_body(
118         struct ast_json *body,
119         struct ast_ari_asterisk_update_object_args *args)
120 {
121         /* Parse query parameters out of it */
122         return 0;
123 }
124
125 /*!
126  * \brief Parameter parsing callback for /asterisk/config/dynamic/{configClass}/{objectType}/{id}.
127  * \param get_params GET parameters in the HTTP request.
128  * \param path_vars Path variables extracted from the request.
129  * \param headers HTTP headers.
130  * \param[out] response Response to the HTTP request.
131  */
132 static void ast_ari_asterisk_update_object_cb(
133         struct ast_tcptls_session_instance *ser,
134         struct ast_variable *get_params, struct ast_variable *path_vars,
135         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
136 {
137         struct ast_ari_asterisk_update_object_args args = {};
138         struct ast_variable *i;
139 #if defined(AST_DEVMODE)
140         int is_valid;
141         int code;
142 #endif /* AST_DEVMODE */
143
144         for (i = path_vars; i; i = i->next) {
145                 if (strcmp(i->name, "configClass") == 0) {
146                         args.config_class = (i->value);
147                 } else
148                 if (strcmp(i->name, "objectType") == 0) {
149                         args.object_type = (i->value);
150                 } else
151                 if (strcmp(i->name, "id") == 0) {
152                         args.id = (i->value);
153                 } else
154                 {}
155         }
156         args.fields = body;
157         ast_ari_asterisk_update_object(headers, &args, response);
158 #if defined(AST_DEVMODE)
159         code = response->response_code;
160
161         switch (code) {
162         case 0: /* Implementation is still a stub, or the code wasn't set */
163                 is_valid = response->message == NULL;
164                 break;
165         case 500: /* Internal Server Error */
166         case 501: /* Not Implemented */
167         case 400: /* Bad request body */
168         case 403: /* Could not create or update object */
169         case 404: /* {configClass|objectType} not found */
170                 is_valid = 1;
171                 break;
172         default:
173                 if (200 <= code && code <= 299) {
174                         is_valid = ast_ari_validate_list(response->message,
175                                 ast_ari_validate_config_tuple_fn());
176                 } else {
177                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/config/dynamic/{configClass}/{objectType}/{id}\n", code);
178                         is_valid = 0;
179                 }
180         }
181
182         if (!is_valid) {
183                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/config/dynamic/{configClass}/{objectType}/{id}\n");
184                 ast_ari_response_error(response, 500,
185                         "Internal Server Error", "Response validation failed");
186         }
187 #endif /* AST_DEVMODE */
188
189 fin: __attribute__((unused))
190         return;
191 }
192 /*!
193  * \brief Parameter parsing callback for /asterisk/config/dynamic/{configClass}/{objectType}/{id}.
194  * \param get_params GET parameters in the HTTP request.
195  * \param path_vars Path variables extracted from the request.
196  * \param headers HTTP headers.
197  * \param[out] response Response to the HTTP request.
198  */
199 static void ast_ari_asterisk_delete_object_cb(
200         struct ast_tcptls_session_instance *ser,
201         struct ast_variable *get_params, struct ast_variable *path_vars,
202         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
203 {
204         struct ast_ari_asterisk_delete_object_args args = {};
205         struct ast_variable *i;
206 #if defined(AST_DEVMODE)
207         int is_valid;
208         int code;
209 #endif /* AST_DEVMODE */
210
211         for (i = path_vars; i; i = i->next) {
212                 if (strcmp(i->name, "configClass") == 0) {
213                         args.config_class = (i->value);
214                 } else
215                 if (strcmp(i->name, "objectType") == 0) {
216                         args.object_type = (i->value);
217                 } else
218                 if (strcmp(i->name, "id") == 0) {
219                         args.id = (i->value);
220                 } else
221                 {}
222         }
223         ast_ari_asterisk_delete_object(headers, &args, response);
224 #if defined(AST_DEVMODE)
225         code = response->response_code;
226
227         switch (code) {
228         case 0: /* Implementation is still a stub, or the code wasn't set */
229                 is_valid = response->message == NULL;
230                 break;
231         case 500: /* Internal Server Error */
232         case 501: /* Not Implemented */
233         case 403: /* Could not delete object */
234         case 404: /* {configClass|objectType|id} not found */
235                 is_valid = 1;
236                 break;
237         default:
238                 if (200 <= code && code <= 299) {
239                         is_valid = ast_ari_validate_void(
240                                 response->message);
241                 } else {
242                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/config/dynamic/{configClass}/{objectType}/{id}\n", code);
243                         is_valid = 0;
244                 }
245         }
246
247         if (!is_valid) {
248                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/config/dynamic/{configClass}/{objectType}/{id}\n");
249                 ast_ari_response_error(response, 500,
250                         "Internal Server Error", "Response validation failed");
251         }
252 #endif /* AST_DEVMODE */
253
254 fin: __attribute__((unused))
255         return;
256 }
257 int ast_ari_asterisk_get_info_parse_body(
258         struct ast_json *body,
259         struct ast_ari_asterisk_get_info_args *args)
260 {
261         struct ast_json *field;
262         /* Parse query parameters out of it */
263         field = ast_json_object_get(body, "only");
264         if (field) {
265                 /* If they were silly enough to both pass in a query param and a
266                  * JSON body, free up the query value.
267                  */
268                 ast_free(args->only);
269                 if (ast_json_typeof(field) == AST_JSON_ARRAY) {
270                         /* Multiple param passed as array */
271                         size_t i;
272                         args->only_count = ast_json_array_size(field);
273                         args->only = ast_malloc(sizeof(*args->only) * args->only_count);
274
275                         if (!args->only) {
276                                 return -1;
277                         }
278
279                         for (i = 0; i < args->only_count; ++i) {
280                                 args->only[i] = ast_json_string_get(ast_json_array_get(field, i));
281                         }
282                 } else {
283                         /* Multiple param passed as single value */
284                         args->only_count = 1;
285                         args->only = ast_malloc(sizeof(*args->only) * args->only_count);
286                         if (!args->only) {
287                                 return -1;
288                         }
289                         args->only[0] = ast_json_string_get(field);
290                 }
291         }
292         return 0;
293 }
294
295 /*!
296  * \brief Parameter parsing callback for /asterisk/info.
297  * \param get_params GET parameters in the HTTP request.
298  * \param path_vars Path variables extracted from the request.
299  * \param headers HTTP headers.
300  * \param[out] response Response to the HTTP request.
301  */
302 static void ast_ari_asterisk_get_info_cb(
303         struct ast_tcptls_session_instance *ser,
304         struct ast_variable *get_params, struct ast_variable *path_vars,
305         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
306 {
307         struct ast_ari_asterisk_get_info_args args = {};
308         struct ast_variable *i;
309 #if defined(AST_DEVMODE)
310         int is_valid;
311         int code;
312 #endif /* AST_DEVMODE */
313
314         for (i = get_params; i; i = i->next) {
315                 if (strcmp(i->name, "only") == 0) {
316                         /* Parse comma separated list */
317                         char *vals[MAX_VALS];
318                         size_t j;
319
320                         args.only_parse = ast_strdup(i->value);
321                         if (!args.only_parse) {
322                                 ast_ari_response_alloc_failed(response);
323                                 goto fin;
324                         }
325
326                         if (strlen(args.only_parse) == 0) {
327                                 /* ast_app_separate_args can't handle "" */
328                                 args.only_count = 1;
329                                 vals[0] = args.only_parse;
330                         } else {
331                                 args.only_count = ast_app_separate_args(
332                                         args.only_parse, ',', vals,
333                                         ARRAY_LEN(vals));
334                         }
335
336                         if (args.only_count == 0) {
337                                 ast_ari_response_alloc_failed(response);
338                                 goto fin;
339                         }
340
341                         if (args.only_count >= MAX_VALS) {
342                                 ast_ari_response_error(response, 400,
343                                         "Bad Request",
344                                         "Too many values for only");
345                                 goto fin;
346                         }
347
348                         args.only = ast_malloc(sizeof(*args.only) * args.only_count);
349                         if (!args.only) {
350                                 ast_ari_response_alloc_failed(response);
351                                 goto fin;
352                         }
353
354                         for (j = 0; j < args.only_count; ++j) {
355                                 args.only[j] = (vals[j]);
356                         }
357                 } else
358                 {}
359         }
360         if (ast_ari_asterisk_get_info_parse_body(body, &args)) {
361                 ast_ari_response_alloc_failed(response);
362                 goto fin;
363         }
364         ast_ari_asterisk_get_info(headers, &args, response);
365 #if defined(AST_DEVMODE)
366         code = response->response_code;
367
368         switch (code) {
369         case 0: /* Implementation is still a stub, or the code wasn't set */
370                 is_valid = response->message == NULL;
371                 break;
372         case 500: /* Internal Server Error */
373         case 501: /* Not Implemented */
374                 is_valid = 1;
375                 break;
376         default:
377                 if (200 <= code && code <= 299) {
378                         is_valid = ast_ari_validate_asterisk_info(
379                                 response->message);
380                 } else {
381                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/info\n", code);
382                         is_valid = 0;
383                 }
384         }
385
386         if (!is_valid) {
387                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/info\n");
388                 ast_ari_response_error(response, 500,
389                         "Internal Server Error", "Response validation failed");
390         }
391 #endif /* AST_DEVMODE */
392
393 fin: __attribute__((unused))
394         ast_free(args.only_parse);
395         ast_free(args.only);
396         return;
397 }
398 /*!
399  * \brief Parameter parsing callback for /asterisk/ping.
400  * \param get_params GET parameters in the HTTP request.
401  * \param path_vars Path variables extracted from the request.
402  * \param headers HTTP headers.
403  * \param[out] response Response to the HTTP request.
404  */
405 static void ast_ari_asterisk_ping_cb(
406         struct ast_tcptls_session_instance *ser,
407         struct ast_variable *get_params, struct ast_variable *path_vars,
408         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
409 {
410         struct ast_ari_asterisk_ping_args args = {};
411 #if defined(AST_DEVMODE)
412         int is_valid;
413         int code;
414 #endif /* AST_DEVMODE */
415
416         ast_ari_asterisk_ping(headers, &args, response);
417 #if defined(AST_DEVMODE)
418         code = response->response_code;
419
420         switch (code) {
421         case 0: /* Implementation is still a stub, or the code wasn't set */
422                 is_valid = response->message == NULL;
423                 break;
424         case 500: /* Internal Server Error */
425         case 501: /* Not Implemented */
426                 is_valid = 1;
427                 break;
428         default:
429                 if (200 <= code && code <= 299) {
430                         is_valid = ast_ari_validate_asterisk_ping(
431                                 response->message);
432                 } else {
433                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/ping\n", code);
434                         is_valid = 0;
435                 }
436         }
437
438         if (!is_valid) {
439                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/ping\n");
440                 ast_ari_response_error(response, 500,
441                         "Internal Server Error", "Response validation failed");
442         }
443 #endif /* AST_DEVMODE */
444
445 fin: __attribute__((unused))
446         return;
447 }
448 /*!
449  * \brief Parameter parsing callback for /asterisk/modules.
450  * \param get_params GET parameters in the HTTP request.
451  * \param path_vars Path variables extracted from the request.
452  * \param headers HTTP headers.
453  * \param[out] response Response to the HTTP request.
454  */
455 static void ast_ari_asterisk_list_modules_cb(
456         struct ast_tcptls_session_instance *ser,
457         struct ast_variable *get_params, struct ast_variable *path_vars,
458         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
459 {
460         struct ast_ari_asterisk_list_modules_args args = {};
461 #if defined(AST_DEVMODE)
462         int is_valid;
463         int code;
464 #endif /* AST_DEVMODE */
465
466         ast_ari_asterisk_list_modules(headers, &args, response);
467 #if defined(AST_DEVMODE)
468         code = response->response_code;
469
470         switch (code) {
471         case 0: /* Implementation is still a stub, or the code wasn't set */
472                 is_valid = response->message == NULL;
473                 break;
474         case 500: /* Internal Server Error */
475         case 501: /* Not Implemented */
476                 is_valid = 1;
477                 break;
478         default:
479                 if (200 <= code && code <= 299) {
480                         is_valid = ast_ari_validate_list(response->message,
481                                 ast_ari_validate_module_fn());
482                 } else {
483                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/modules\n", code);
484                         is_valid = 0;
485                 }
486         }
487
488         if (!is_valid) {
489                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/modules\n");
490                 ast_ari_response_error(response, 500,
491                         "Internal Server Error", "Response validation failed");
492         }
493 #endif /* AST_DEVMODE */
494
495 fin: __attribute__((unused))
496         return;
497 }
498 /*!
499  * \brief Parameter parsing callback for /asterisk/modules/{moduleName}.
500  * \param get_params GET parameters in the HTTP request.
501  * \param path_vars Path variables extracted from the request.
502  * \param headers HTTP headers.
503  * \param[out] response Response to the HTTP request.
504  */
505 static void ast_ari_asterisk_get_module_cb(
506         struct ast_tcptls_session_instance *ser,
507         struct ast_variable *get_params, struct ast_variable *path_vars,
508         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
509 {
510         struct ast_ari_asterisk_get_module_args args = {};
511         struct ast_variable *i;
512 #if defined(AST_DEVMODE)
513         int is_valid;
514         int code;
515 #endif /* AST_DEVMODE */
516
517         for (i = path_vars; i; i = i->next) {
518                 if (strcmp(i->name, "moduleName") == 0) {
519                         args.module_name = (i->value);
520                 } else
521                 {}
522         }
523         ast_ari_asterisk_get_module(headers, &args, response);
524 #if defined(AST_DEVMODE)
525         code = response->response_code;
526
527         switch (code) {
528         case 0: /* Implementation is still a stub, or the code wasn't set */
529                 is_valid = response->message == NULL;
530                 break;
531         case 500: /* Internal Server Error */
532         case 501: /* Not Implemented */
533         case 404: /* Module could not be found in running modules. */
534         case 409: /* Module information could not be retrieved. */
535                 is_valid = 1;
536                 break;
537         default:
538                 if (200 <= code && code <= 299) {
539                         is_valid = ast_ari_validate_module(
540                                 response->message);
541                 } else {
542                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/modules/{moduleName}\n", code);
543                         is_valid = 0;
544                 }
545         }
546
547         if (!is_valid) {
548                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/modules/{moduleName}\n");
549                 ast_ari_response_error(response, 500,
550                         "Internal Server Error", "Response validation failed");
551         }
552 #endif /* AST_DEVMODE */
553
554 fin: __attribute__((unused))
555         return;
556 }
557 /*!
558  * \brief Parameter parsing callback for /asterisk/modules/{moduleName}.
559  * \param get_params GET parameters in the HTTP request.
560  * \param path_vars Path variables extracted from the request.
561  * \param headers HTTP headers.
562  * \param[out] response Response to the HTTP request.
563  */
564 static void ast_ari_asterisk_load_module_cb(
565         struct ast_tcptls_session_instance *ser,
566         struct ast_variable *get_params, struct ast_variable *path_vars,
567         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
568 {
569         struct ast_ari_asterisk_load_module_args args = {};
570         struct ast_variable *i;
571 #if defined(AST_DEVMODE)
572         int is_valid;
573         int code;
574 #endif /* AST_DEVMODE */
575
576         for (i = path_vars; i; i = i->next) {
577                 if (strcmp(i->name, "moduleName") == 0) {
578                         args.module_name = (i->value);
579                 } else
580                 {}
581         }
582         ast_ari_asterisk_load_module(headers, &args, response);
583 #if defined(AST_DEVMODE)
584         code = response->response_code;
585
586         switch (code) {
587         case 0: /* Implementation is still a stub, or the code wasn't set */
588                 is_valid = response->message == NULL;
589                 break;
590         case 500: /* Internal Server Error */
591         case 501: /* Not Implemented */
592         case 409: /* Module could not be loaded. */
593                 is_valid = 1;
594                 break;
595         default:
596                 if (200 <= code && code <= 299) {
597                         is_valid = ast_ari_validate_void(
598                                 response->message);
599                 } else {
600                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/modules/{moduleName}\n", code);
601                         is_valid = 0;
602                 }
603         }
604
605         if (!is_valid) {
606                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/modules/{moduleName}\n");
607                 ast_ari_response_error(response, 500,
608                         "Internal Server Error", "Response validation failed");
609         }
610 #endif /* AST_DEVMODE */
611
612 fin: __attribute__((unused))
613         return;
614 }
615 /*!
616  * \brief Parameter parsing callback for /asterisk/modules/{moduleName}.
617  * \param get_params GET parameters in the HTTP request.
618  * \param path_vars Path variables extracted from the request.
619  * \param headers HTTP headers.
620  * \param[out] response Response to the HTTP request.
621  */
622 static void ast_ari_asterisk_unload_module_cb(
623         struct ast_tcptls_session_instance *ser,
624         struct ast_variable *get_params, struct ast_variable *path_vars,
625         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
626 {
627         struct ast_ari_asterisk_unload_module_args args = {};
628         struct ast_variable *i;
629 #if defined(AST_DEVMODE)
630         int is_valid;
631         int code;
632 #endif /* AST_DEVMODE */
633
634         for (i = path_vars; i; i = i->next) {
635                 if (strcmp(i->name, "moduleName") == 0) {
636                         args.module_name = (i->value);
637                 } else
638                 {}
639         }
640         ast_ari_asterisk_unload_module(headers, &args, response);
641 #if defined(AST_DEVMODE)
642         code = response->response_code;
643
644         switch (code) {
645         case 0: /* Implementation is still a stub, or the code wasn't set */
646                 is_valid = response->message == NULL;
647                 break;
648         case 500: /* Internal Server Error */
649         case 501: /* Not Implemented */
650         case 404: /* Module not found in running modules. */
651         case 409: /* Module could not be unloaded. */
652                 is_valid = 1;
653                 break;
654         default:
655                 if (200 <= code && code <= 299) {
656                         is_valid = ast_ari_validate_void(
657                                 response->message);
658                 } else {
659                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/modules/{moduleName}\n", code);
660                         is_valid = 0;
661                 }
662         }
663
664         if (!is_valid) {
665                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/modules/{moduleName}\n");
666                 ast_ari_response_error(response, 500,
667                         "Internal Server Error", "Response validation failed");
668         }
669 #endif /* AST_DEVMODE */
670
671 fin: __attribute__((unused))
672         return;
673 }
674 /*!
675  * \brief Parameter parsing callback for /asterisk/modules/{moduleName}.
676  * \param get_params GET parameters in the HTTP request.
677  * \param path_vars Path variables extracted from the request.
678  * \param headers HTTP headers.
679  * \param[out] response Response to the HTTP request.
680  */
681 static void ast_ari_asterisk_reload_module_cb(
682         struct ast_tcptls_session_instance *ser,
683         struct ast_variable *get_params, struct ast_variable *path_vars,
684         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
685 {
686         struct ast_ari_asterisk_reload_module_args args = {};
687         struct ast_variable *i;
688 #if defined(AST_DEVMODE)
689         int is_valid;
690         int code;
691 #endif /* AST_DEVMODE */
692
693         for (i = path_vars; i; i = i->next) {
694                 if (strcmp(i->name, "moduleName") == 0) {
695                         args.module_name = (i->value);
696                 } else
697                 {}
698         }
699         ast_ari_asterisk_reload_module(headers, &args, response);
700 #if defined(AST_DEVMODE)
701         code = response->response_code;
702
703         switch (code) {
704         case 0: /* Implementation is still a stub, or the code wasn't set */
705                 is_valid = response->message == NULL;
706                 break;
707         case 500: /* Internal Server Error */
708         case 501: /* Not Implemented */
709         case 404: /* Module not found in running modules. */
710         case 409: /* Module could not be reloaded. */
711                 is_valid = 1;
712                 break;
713         default:
714                 if (200 <= code && code <= 299) {
715                         is_valid = ast_ari_validate_void(
716                                 response->message);
717                 } else {
718                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/modules/{moduleName}\n", code);
719                         is_valid = 0;
720                 }
721         }
722
723         if (!is_valid) {
724                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/modules/{moduleName}\n");
725                 ast_ari_response_error(response, 500,
726                         "Internal Server Error", "Response validation failed");
727         }
728 #endif /* AST_DEVMODE */
729
730 fin: __attribute__((unused))
731         return;
732 }
733 /*!
734  * \brief Parameter parsing callback for /asterisk/logging.
735  * \param get_params GET parameters in the HTTP request.
736  * \param path_vars Path variables extracted from the request.
737  * \param headers HTTP headers.
738  * \param[out] response Response to the HTTP request.
739  */
740 static void ast_ari_asterisk_list_log_channels_cb(
741         struct ast_tcptls_session_instance *ser,
742         struct ast_variable *get_params, struct ast_variable *path_vars,
743         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
744 {
745         struct ast_ari_asterisk_list_log_channels_args args = {};
746 #if defined(AST_DEVMODE)
747         int is_valid;
748         int code;
749 #endif /* AST_DEVMODE */
750
751         ast_ari_asterisk_list_log_channels(headers, &args, response);
752 #if defined(AST_DEVMODE)
753         code = response->response_code;
754
755         switch (code) {
756         case 0: /* Implementation is still a stub, or the code wasn't set */
757                 is_valid = response->message == NULL;
758                 break;
759         case 500: /* Internal Server Error */
760         case 501: /* Not Implemented */
761                 is_valid = 1;
762                 break;
763         default:
764                 if (200 <= code && code <= 299) {
765                         is_valid = ast_ari_validate_list(response->message,
766                                 ast_ari_validate_log_channel_fn());
767                 } else {
768                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/logging\n", code);
769                         is_valid = 0;
770                 }
771         }
772
773         if (!is_valid) {
774                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/logging\n");
775                 ast_ari_response_error(response, 500,
776                         "Internal Server Error", "Response validation failed");
777         }
778 #endif /* AST_DEVMODE */
779
780 fin: __attribute__((unused))
781         return;
782 }
783 int ast_ari_asterisk_add_log_parse_body(
784         struct ast_json *body,
785         struct ast_ari_asterisk_add_log_args *args)
786 {
787         struct ast_json *field;
788         /* Parse query parameters out of it */
789         field = ast_json_object_get(body, "configuration");
790         if (field) {
791                 args->configuration = ast_json_string_get(field);
792         }
793         return 0;
794 }
795
796 /*!
797  * \brief Parameter parsing callback for /asterisk/logging/{logChannelName}.
798  * \param get_params GET parameters in the HTTP request.
799  * \param path_vars Path variables extracted from the request.
800  * \param headers HTTP headers.
801  * \param[out] response Response to the HTTP request.
802  */
803 static void ast_ari_asterisk_add_log_cb(
804         struct ast_tcptls_session_instance *ser,
805         struct ast_variable *get_params, struct ast_variable *path_vars,
806         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
807 {
808         struct ast_ari_asterisk_add_log_args args = {};
809         struct ast_variable *i;
810 #if defined(AST_DEVMODE)
811         int is_valid;
812         int code;
813 #endif /* AST_DEVMODE */
814
815         for (i = get_params; i; i = i->next) {
816                 if (strcmp(i->name, "configuration") == 0) {
817                         args.configuration = (i->value);
818                 } else
819                 {}
820         }
821         for (i = path_vars; i; i = i->next) {
822                 if (strcmp(i->name, "logChannelName") == 0) {
823                         args.log_channel_name = (i->value);
824                 } else
825                 {}
826         }
827         if (ast_ari_asterisk_add_log_parse_body(body, &args)) {
828                 ast_ari_response_alloc_failed(response);
829                 goto fin;
830         }
831         ast_ari_asterisk_add_log(headers, &args, response);
832 #if defined(AST_DEVMODE)
833         code = response->response_code;
834
835         switch (code) {
836         case 0: /* Implementation is still a stub, or the code wasn't set */
837                 is_valid = response->message == NULL;
838                 break;
839         case 500: /* Internal Server Error */
840         case 501: /* Not Implemented */
841         case 400: /* Bad request body */
842         case 409: /* Log channel could not be created. */
843                 is_valid = 1;
844                 break;
845         default:
846                 if (200 <= code && code <= 299) {
847                         is_valid = ast_ari_validate_void(
848                                 response->message);
849                 } else {
850                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/logging/{logChannelName}\n", code);
851                         is_valid = 0;
852                 }
853         }
854
855         if (!is_valid) {
856                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/logging/{logChannelName}\n");
857                 ast_ari_response_error(response, 500,
858                         "Internal Server Error", "Response validation failed");
859         }
860 #endif /* AST_DEVMODE */
861
862 fin: __attribute__((unused))
863         return;
864 }
865 /*!
866  * \brief Parameter parsing callback for /asterisk/logging/{logChannelName}.
867  * \param get_params GET parameters in the HTTP request.
868  * \param path_vars Path variables extracted from the request.
869  * \param headers HTTP headers.
870  * \param[out] response Response to the HTTP request.
871  */
872 static void ast_ari_asterisk_delete_log_cb(
873         struct ast_tcptls_session_instance *ser,
874         struct ast_variable *get_params, struct ast_variable *path_vars,
875         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
876 {
877         struct ast_ari_asterisk_delete_log_args args = {};
878         struct ast_variable *i;
879 #if defined(AST_DEVMODE)
880         int is_valid;
881         int code;
882 #endif /* AST_DEVMODE */
883
884         for (i = path_vars; i; i = i->next) {
885                 if (strcmp(i->name, "logChannelName") == 0) {
886                         args.log_channel_name = (i->value);
887                 } else
888                 {}
889         }
890         ast_ari_asterisk_delete_log(headers, &args, response);
891 #if defined(AST_DEVMODE)
892         code = response->response_code;
893
894         switch (code) {
895         case 0: /* Implementation is still a stub, or the code wasn't set */
896                 is_valid = response->message == NULL;
897                 break;
898         case 500: /* Internal Server Error */
899         case 501: /* Not Implemented */
900         case 404: /* Log channel does not exist. */
901                 is_valid = 1;
902                 break;
903         default:
904                 if (200 <= code && code <= 299) {
905                         is_valid = ast_ari_validate_void(
906                                 response->message);
907                 } else {
908                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/logging/{logChannelName}\n", code);
909                         is_valid = 0;
910                 }
911         }
912
913         if (!is_valid) {
914                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/logging/{logChannelName}\n");
915                 ast_ari_response_error(response, 500,
916                         "Internal Server Error", "Response validation failed");
917         }
918 #endif /* AST_DEVMODE */
919
920 fin: __attribute__((unused))
921         return;
922 }
923 /*!
924  * \brief Parameter parsing callback for /asterisk/logging/{logChannelName}/rotate.
925  * \param get_params GET parameters in the HTTP request.
926  * \param path_vars Path variables extracted from the request.
927  * \param headers HTTP headers.
928  * \param[out] response Response to the HTTP request.
929  */
930 static void ast_ari_asterisk_rotate_log_cb(
931         struct ast_tcptls_session_instance *ser,
932         struct ast_variable *get_params, struct ast_variable *path_vars,
933         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
934 {
935         struct ast_ari_asterisk_rotate_log_args args = {};
936         struct ast_variable *i;
937 #if defined(AST_DEVMODE)
938         int is_valid;
939         int code;
940 #endif /* AST_DEVMODE */
941
942         for (i = path_vars; i; i = i->next) {
943                 if (strcmp(i->name, "logChannelName") == 0) {
944                         args.log_channel_name = (i->value);
945                 } else
946                 {}
947         }
948         ast_ari_asterisk_rotate_log(headers, &args, response);
949 #if defined(AST_DEVMODE)
950         code = response->response_code;
951
952         switch (code) {
953         case 0: /* Implementation is still a stub, or the code wasn't set */
954                 is_valid = response->message == NULL;
955                 break;
956         case 500: /* Internal Server Error */
957         case 501: /* Not Implemented */
958         case 404: /* Log channel does not exist. */
959                 is_valid = 1;
960                 break;
961         default:
962                 if (200 <= code && code <= 299) {
963                         is_valid = ast_ari_validate_void(
964                                 response->message);
965                 } else {
966                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/logging/{logChannelName}/rotate\n", code);
967                         is_valid = 0;
968                 }
969         }
970
971         if (!is_valid) {
972                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/logging/{logChannelName}/rotate\n");
973                 ast_ari_response_error(response, 500,
974                         "Internal Server Error", "Response validation failed");
975         }
976 #endif /* AST_DEVMODE */
977
978 fin: __attribute__((unused))
979         return;
980 }
981 int ast_ari_asterisk_get_global_var_parse_body(
982         struct ast_json *body,
983         struct ast_ari_asterisk_get_global_var_args *args)
984 {
985         struct ast_json *field;
986         /* Parse query parameters out of it */
987         field = ast_json_object_get(body, "variable");
988         if (field) {
989                 args->variable = ast_json_string_get(field);
990         }
991         return 0;
992 }
993
994 /*!
995  * \brief Parameter parsing callback for /asterisk/variable.
996  * \param get_params GET parameters in the HTTP request.
997  * \param path_vars Path variables extracted from the request.
998  * \param headers HTTP headers.
999  * \param[out] response Response to the HTTP request.
1000  */
1001 static void ast_ari_asterisk_get_global_var_cb(
1002         struct ast_tcptls_session_instance *ser,
1003         struct ast_variable *get_params, struct ast_variable *path_vars,
1004         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1005 {
1006         struct ast_ari_asterisk_get_global_var_args args = {};
1007         struct ast_variable *i;
1008 #if defined(AST_DEVMODE)
1009         int is_valid;
1010         int code;
1011 #endif /* AST_DEVMODE */
1012
1013         for (i = get_params; i; i = i->next) {
1014                 if (strcmp(i->name, "variable") == 0) {
1015                         args.variable = (i->value);
1016                 } else
1017                 {}
1018         }
1019         if (ast_ari_asterisk_get_global_var_parse_body(body, &args)) {
1020                 ast_ari_response_alloc_failed(response);
1021                 goto fin;
1022         }
1023         ast_ari_asterisk_get_global_var(headers, &args, response);
1024 #if defined(AST_DEVMODE)
1025         code = response->response_code;
1026
1027         switch (code) {
1028         case 0: /* Implementation is still a stub, or the code wasn't set */
1029                 is_valid = response->message == NULL;
1030                 break;
1031         case 500: /* Internal Server Error */
1032         case 501: /* Not Implemented */
1033         case 400: /* Missing variable parameter. */
1034                 is_valid = 1;
1035                 break;
1036         default:
1037                 if (200 <= code && code <= 299) {
1038                         is_valid = ast_ari_validate_variable(
1039                                 response->message);
1040                 } else {
1041                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/variable\n", code);
1042                         is_valid = 0;
1043                 }
1044         }
1045
1046         if (!is_valid) {
1047                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/variable\n");
1048                 ast_ari_response_error(response, 500,
1049                         "Internal Server Error", "Response validation failed");
1050         }
1051 #endif /* AST_DEVMODE */
1052
1053 fin: __attribute__((unused))
1054         return;
1055 }
1056 int ast_ari_asterisk_set_global_var_parse_body(
1057         struct ast_json *body,
1058         struct ast_ari_asterisk_set_global_var_args *args)
1059 {
1060         struct ast_json *field;
1061         /* Parse query parameters out of it */
1062         field = ast_json_object_get(body, "variable");
1063         if (field) {
1064                 args->variable = ast_json_string_get(field);
1065         }
1066         field = ast_json_object_get(body, "value");
1067         if (field) {
1068                 args->value = ast_json_string_get(field);
1069         }
1070         return 0;
1071 }
1072
1073 /*!
1074  * \brief Parameter parsing callback for /asterisk/variable.
1075  * \param get_params GET parameters in the HTTP request.
1076  * \param path_vars Path variables extracted from the request.
1077  * \param headers HTTP headers.
1078  * \param[out] response Response to the HTTP request.
1079  */
1080 static void ast_ari_asterisk_set_global_var_cb(
1081         struct ast_tcptls_session_instance *ser,
1082         struct ast_variable *get_params, struct ast_variable *path_vars,
1083         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1084 {
1085         struct ast_ari_asterisk_set_global_var_args args = {};
1086         struct ast_variable *i;
1087 #if defined(AST_DEVMODE)
1088         int is_valid;
1089         int code;
1090 #endif /* AST_DEVMODE */
1091
1092         for (i = get_params; i; i = i->next) {
1093                 if (strcmp(i->name, "variable") == 0) {
1094                         args.variable = (i->value);
1095                 } else
1096                 if (strcmp(i->name, "value") == 0) {
1097                         args.value = (i->value);
1098                 } else
1099                 {}
1100         }
1101         if (ast_ari_asterisk_set_global_var_parse_body(body, &args)) {
1102                 ast_ari_response_alloc_failed(response);
1103                 goto fin;
1104         }
1105         ast_ari_asterisk_set_global_var(headers, &args, response);
1106 #if defined(AST_DEVMODE)
1107         code = response->response_code;
1108
1109         switch (code) {
1110         case 0: /* Implementation is still a stub, or the code wasn't set */
1111                 is_valid = response->message == NULL;
1112                 break;
1113         case 500: /* Internal Server Error */
1114         case 501: /* Not Implemented */
1115         case 400: /* Missing variable parameter. */
1116                 is_valid = 1;
1117                 break;
1118         default:
1119                 if (200 <= code && code <= 299) {
1120                         is_valid = ast_ari_validate_void(
1121                                 response->message);
1122                 } else {
1123                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/variable\n", code);
1124                         is_valid = 0;
1125                 }
1126         }
1127
1128         if (!is_valid) {
1129                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/variable\n");
1130                 ast_ari_response_error(response, 500,
1131                         "Internal Server Error", "Response validation failed");
1132         }
1133 #endif /* AST_DEVMODE */
1134
1135 fin: __attribute__((unused))
1136         return;
1137 }
1138
1139 /*! \brief REST handler for /api-docs/asterisk.json */
1140 static struct stasis_rest_handlers asterisk_config_dynamic_configClass_objectType_id = {
1141         .path_segment = "id",
1142         .is_wildcard = 1,
1143         .callbacks = {
1144                 [AST_HTTP_GET] = ast_ari_asterisk_get_object_cb,
1145                 [AST_HTTP_PUT] = ast_ari_asterisk_update_object_cb,
1146                 [AST_HTTP_DELETE] = ast_ari_asterisk_delete_object_cb,
1147         },
1148         .num_children = 0,
1149         .children = {  }
1150 };
1151 /*! \brief REST handler for /api-docs/asterisk.json */
1152 static struct stasis_rest_handlers asterisk_config_dynamic_configClass_objectType = {
1153         .path_segment = "objectType",
1154         .is_wildcard = 1,
1155         .callbacks = {
1156         },
1157         .num_children = 1,
1158         .children = { &asterisk_config_dynamic_configClass_objectType_id, }
1159 };
1160 /*! \brief REST handler for /api-docs/asterisk.json */
1161 static struct stasis_rest_handlers asterisk_config_dynamic_configClass = {
1162         .path_segment = "configClass",
1163         .is_wildcard = 1,
1164         .callbacks = {
1165         },
1166         .num_children = 1,
1167         .children = { &asterisk_config_dynamic_configClass_objectType, }
1168 };
1169 /*! \brief REST handler for /api-docs/asterisk.json */
1170 static struct stasis_rest_handlers asterisk_config_dynamic = {
1171         .path_segment = "dynamic",
1172         .callbacks = {
1173         },
1174         .num_children = 1,
1175         .children = { &asterisk_config_dynamic_configClass, }
1176 };
1177 /*! \brief REST handler for /api-docs/asterisk.json */
1178 static struct stasis_rest_handlers asterisk_config = {
1179         .path_segment = "config",
1180         .callbacks = {
1181         },
1182         .num_children = 1,
1183         .children = { &asterisk_config_dynamic, }
1184 };
1185 /*! \brief REST handler for /api-docs/asterisk.json */
1186 static struct stasis_rest_handlers asterisk_info = {
1187         .path_segment = "info",
1188         .callbacks = {
1189                 [AST_HTTP_GET] = ast_ari_asterisk_get_info_cb,
1190         },
1191         .num_children = 0,
1192         .children = {  }
1193 };
1194 /*! \brief REST handler for /api-docs/asterisk.json */
1195 static struct stasis_rest_handlers asterisk_ping = {
1196         .path_segment = "ping",
1197         .callbacks = {
1198                 [AST_HTTP_GET] = ast_ari_asterisk_ping_cb,
1199         },
1200         .num_children = 0,
1201         .children = {  }
1202 };
1203 /*! \brief REST handler for /api-docs/asterisk.json */
1204 static struct stasis_rest_handlers asterisk_modules_moduleName = {
1205         .path_segment = "moduleName",
1206         .is_wildcard = 1,
1207         .callbacks = {
1208                 [AST_HTTP_GET] = ast_ari_asterisk_get_module_cb,
1209                 [AST_HTTP_POST] = ast_ari_asterisk_load_module_cb,
1210                 [AST_HTTP_DELETE] = ast_ari_asterisk_unload_module_cb,
1211                 [AST_HTTP_PUT] = ast_ari_asterisk_reload_module_cb,
1212         },
1213         .num_children = 0,
1214         .children = {  }
1215 };
1216 /*! \brief REST handler for /api-docs/asterisk.json */
1217 static struct stasis_rest_handlers asterisk_modules = {
1218         .path_segment = "modules",
1219         .callbacks = {
1220                 [AST_HTTP_GET] = ast_ari_asterisk_list_modules_cb,
1221         },
1222         .num_children = 1,
1223         .children = { &asterisk_modules_moduleName, }
1224 };
1225 /*! \brief REST handler for /api-docs/asterisk.json */
1226 static struct stasis_rest_handlers asterisk_logging_logChannelName_rotate = {
1227         .path_segment = "rotate",
1228         .callbacks = {
1229                 [AST_HTTP_PUT] = ast_ari_asterisk_rotate_log_cb,
1230         },
1231         .num_children = 0,
1232         .children = {  }
1233 };
1234 /*! \brief REST handler for /api-docs/asterisk.json */
1235 static struct stasis_rest_handlers asterisk_logging_logChannelName = {
1236         .path_segment = "logChannelName",
1237         .is_wildcard = 1,
1238         .callbacks = {
1239                 [AST_HTTP_POST] = ast_ari_asterisk_add_log_cb,
1240                 [AST_HTTP_DELETE] = ast_ari_asterisk_delete_log_cb,
1241         },
1242         .num_children = 1,
1243         .children = { &asterisk_logging_logChannelName_rotate, }
1244 };
1245 /*! \brief REST handler for /api-docs/asterisk.json */
1246 static struct stasis_rest_handlers asterisk_logging = {
1247         .path_segment = "logging",
1248         .callbacks = {
1249                 [AST_HTTP_GET] = ast_ari_asterisk_list_log_channels_cb,
1250         },
1251         .num_children = 1,
1252         .children = { &asterisk_logging_logChannelName, }
1253 };
1254 /*! \brief REST handler for /api-docs/asterisk.json */
1255 static struct stasis_rest_handlers asterisk_variable = {
1256         .path_segment = "variable",
1257         .callbacks = {
1258                 [AST_HTTP_GET] = ast_ari_asterisk_get_global_var_cb,
1259                 [AST_HTTP_POST] = ast_ari_asterisk_set_global_var_cb,
1260         },
1261         .num_children = 0,
1262         .children = {  }
1263 };
1264 /*! \brief REST handler for /api-docs/asterisk.json */
1265 static struct stasis_rest_handlers asterisk = {
1266         .path_segment = "asterisk",
1267         .callbacks = {
1268         },
1269         .num_children = 6,
1270         .children = { &asterisk_config,&asterisk_info,&asterisk_ping,&asterisk_modules,&asterisk_logging,&asterisk_variable, }
1271 };
1272
1273 static int unload_module(void)
1274 {
1275         ast_ari_remove_handler(&asterisk);
1276         return 0;
1277 }
1278
1279 static int load_module(void)
1280 {
1281         int res = 0;
1282
1283
1284         res |= ast_ari_add_handler(&asterisk);
1285         if (res) {
1286                 unload_module();
1287                 return AST_MODULE_LOAD_DECLINE;
1288         }
1289
1290         return AST_MODULE_LOAD_SUCCESS;
1291 }
1292
1293 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Asterisk resources",
1294         .support_level = AST_MODULE_SUPPORT_CORE,
1295         .load = load_module,
1296         .unload = unload_module,
1297         .requires = "res_ari,res_ari_model,res_stasis",
1298 );