loader: Add dependency fields to module structures.
[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/modules.
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_list_modules_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_list_modules_args args = {};
411 #if defined(AST_DEVMODE)
412         int is_valid;
413         int code;
414 #endif /* AST_DEVMODE */
415
416         ast_ari_asterisk_list_modules(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_list(response->message,
431                                 ast_ari_validate_module_fn());
432                 } else {
433                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/modules\n", code);
434                         is_valid = 0;
435                 }
436         }
437
438         if (!is_valid) {
439                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/modules\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/{moduleName}.
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_get_module_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_get_module_args args = {};
461         struct ast_variable *i;
462 #if defined(AST_DEVMODE)
463         int is_valid;
464         int code;
465 #endif /* AST_DEVMODE */
466
467         for (i = path_vars; i; i = i->next) {
468                 if (strcmp(i->name, "moduleName") == 0) {
469                         args.module_name = (i->value);
470                 } else
471                 {}
472         }
473         ast_ari_asterisk_get_module(headers, &args, response);
474 #if defined(AST_DEVMODE)
475         code = response->response_code;
476
477         switch (code) {
478         case 0: /* Implementation is still a stub, or the code wasn't set */
479                 is_valid = response->message == NULL;
480                 break;
481         case 500: /* Internal Server Error */
482         case 501: /* Not Implemented */
483         case 404: /* Module could not be found in running modules. */
484         case 409: /* Module information could not be retrieved. */
485                 is_valid = 1;
486                 break;
487         default:
488                 if (200 <= code && code <= 299) {
489                         is_valid = ast_ari_validate_module(
490                                 response->message);
491                 } else {
492                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/modules/{moduleName}\n", code);
493                         is_valid = 0;
494                 }
495         }
496
497         if (!is_valid) {
498                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/modules/{moduleName}\n");
499                 ast_ari_response_error(response, 500,
500                         "Internal Server Error", "Response validation failed");
501         }
502 #endif /* AST_DEVMODE */
503
504 fin: __attribute__((unused))
505         return;
506 }
507 /*!
508  * \brief Parameter parsing callback for /asterisk/modules/{moduleName}.
509  * \param get_params GET parameters in the HTTP request.
510  * \param path_vars Path variables extracted from the request.
511  * \param headers HTTP headers.
512  * \param[out] response Response to the HTTP request.
513  */
514 static void ast_ari_asterisk_load_module_cb(
515         struct ast_tcptls_session_instance *ser,
516         struct ast_variable *get_params, struct ast_variable *path_vars,
517         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
518 {
519         struct ast_ari_asterisk_load_module_args args = {};
520         struct ast_variable *i;
521 #if defined(AST_DEVMODE)
522         int is_valid;
523         int code;
524 #endif /* AST_DEVMODE */
525
526         for (i = path_vars; i; i = i->next) {
527                 if (strcmp(i->name, "moduleName") == 0) {
528                         args.module_name = (i->value);
529                 } else
530                 {}
531         }
532         ast_ari_asterisk_load_module(headers, &args, response);
533 #if defined(AST_DEVMODE)
534         code = response->response_code;
535
536         switch (code) {
537         case 0: /* Implementation is still a stub, or the code wasn't set */
538                 is_valid = response->message == NULL;
539                 break;
540         case 500: /* Internal Server Error */
541         case 501: /* Not Implemented */
542         case 409: /* Module could not be loaded. */
543                 is_valid = 1;
544                 break;
545         default:
546                 if (200 <= code && code <= 299) {
547                         is_valid = ast_ari_validate_void(
548                                 response->message);
549                 } else {
550                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/modules/{moduleName}\n", code);
551                         is_valid = 0;
552                 }
553         }
554
555         if (!is_valid) {
556                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/modules/{moduleName}\n");
557                 ast_ari_response_error(response, 500,
558                         "Internal Server Error", "Response validation failed");
559         }
560 #endif /* AST_DEVMODE */
561
562 fin: __attribute__((unused))
563         return;
564 }
565 /*!
566  * \brief Parameter parsing callback for /asterisk/modules/{moduleName}.
567  * \param get_params GET parameters in the HTTP request.
568  * \param path_vars Path variables extracted from the request.
569  * \param headers HTTP headers.
570  * \param[out] response Response to the HTTP request.
571  */
572 static void ast_ari_asterisk_unload_module_cb(
573         struct ast_tcptls_session_instance *ser,
574         struct ast_variable *get_params, struct ast_variable *path_vars,
575         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
576 {
577         struct ast_ari_asterisk_unload_module_args args = {};
578         struct ast_variable *i;
579 #if defined(AST_DEVMODE)
580         int is_valid;
581         int code;
582 #endif /* AST_DEVMODE */
583
584         for (i = path_vars; i; i = i->next) {
585                 if (strcmp(i->name, "moduleName") == 0) {
586                         args.module_name = (i->value);
587                 } else
588                 {}
589         }
590         ast_ari_asterisk_unload_module(headers, &args, response);
591 #if defined(AST_DEVMODE)
592         code = response->response_code;
593
594         switch (code) {
595         case 0: /* Implementation is still a stub, or the code wasn't set */
596                 is_valid = response->message == NULL;
597                 break;
598         case 500: /* Internal Server Error */
599         case 501: /* Not Implemented */
600         case 404: /* Module not found in running modules. */
601         case 409: /* Module could not be unloaded. */
602                 is_valid = 1;
603                 break;
604         default:
605                 if (200 <= code && code <= 299) {
606                         is_valid = ast_ari_validate_void(
607                                 response->message);
608                 } else {
609                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/modules/{moduleName}\n", code);
610                         is_valid = 0;
611                 }
612         }
613
614         if (!is_valid) {
615                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/modules/{moduleName}\n");
616                 ast_ari_response_error(response, 500,
617                         "Internal Server Error", "Response validation failed");
618         }
619 #endif /* AST_DEVMODE */
620
621 fin: __attribute__((unused))
622         return;
623 }
624 /*!
625  * \brief Parameter parsing callback for /asterisk/modules/{moduleName}.
626  * \param get_params GET parameters in the HTTP request.
627  * \param path_vars Path variables extracted from the request.
628  * \param headers HTTP headers.
629  * \param[out] response Response to the HTTP request.
630  */
631 static void ast_ari_asterisk_reload_module_cb(
632         struct ast_tcptls_session_instance *ser,
633         struct ast_variable *get_params, struct ast_variable *path_vars,
634         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
635 {
636         struct ast_ari_asterisk_reload_module_args args = {};
637         struct ast_variable *i;
638 #if defined(AST_DEVMODE)
639         int is_valid;
640         int code;
641 #endif /* AST_DEVMODE */
642
643         for (i = path_vars; i; i = i->next) {
644                 if (strcmp(i->name, "moduleName") == 0) {
645                         args.module_name = (i->value);
646                 } else
647                 {}
648         }
649         ast_ari_asterisk_reload_module(headers, &args, response);
650 #if defined(AST_DEVMODE)
651         code = response->response_code;
652
653         switch (code) {
654         case 0: /* Implementation is still a stub, or the code wasn't set */
655                 is_valid = response->message == NULL;
656                 break;
657         case 500: /* Internal Server Error */
658         case 501: /* Not Implemented */
659         case 404: /* Module not found in running modules. */
660         case 409: /* Module could not be reloaded. */
661                 is_valid = 1;
662                 break;
663         default:
664                 if (200 <= code && code <= 299) {
665                         is_valid = ast_ari_validate_void(
666                                 response->message);
667                 } else {
668                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/modules/{moduleName}\n", code);
669                         is_valid = 0;
670                 }
671         }
672
673         if (!is_valid) {
674                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/modules/{moduleName}\n");
675                 ast_ari_response_error(response, 500,
676                         "Internal Server Error", "Response validation failed");
677         }
678 #endif /* AST_DEVMODE */
679
680 fin: __attribute__((unused))
681         return;
682 }
683 /*!
684  * \brief Parameter parsing callback for /asterisk/logging.
685  * \param get_params GET parameters in the HTTP request.
686  * \param path_vars Path variables extracted from the request.
687  * \param headers HTTP headers.
688  * \param[out] response Response to the HTTP request.
689  */
690 static void ast_ari_asterisk_list_log_channels_cb(
691         struct ast_tcptls_session_instance *ser,
692         struct ast_variable *get_params, struct ast_variable *path_vars,
693         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
694 {
695         struct ast_ari_asterisk_list_log_channels_args args = {};
696 #if defined(AST_DEVMODE)
697         int is_valid;
698         int code;
699 #endif /* AST_DEVMODE */
700
701         ast_ari_asterisk_list_log_channels(headers, &args, response);
702 #if defined(AST_DEVMODE)
703         code = response->response_code;
704
705         switch (code) {
706         case 0: /* Implementation is still a stub, or the code wasn't set */
707                 is_valid = response->message == NULL;
708                 break;
709         case 500: /* Internal Server Error */
710         case 501: /* Not Implemented */
711                 is_valid = 1;
712                 break;
713         default:
714                 if (200 <= code && code <= 299) {
715                         is_valid = ast_ari_validate_list(response->message,
716                                 ast_ari_validate_log_channel_fn());
717                 } else {
718                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/logging\n", code);
719                         is_valid = 0;
720                 }
721         }
722
723         if (!is_valid) {
724                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/logging\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 int ast_ari_asterisk_add_log_parse_body(
734         struct ast_json *body,
735         struct ast_ari_asterisk_add_log_args *args)
736 {
737         struct ast_json *field;
738         /* Parse query parameters out of it */
739         field = ast_json_object_get(body, "configuration");
740         if (field) {
741                 args->configuration = ast_json_string_get(field);
742         }
743         return 0;
744 }
745
746 /*!
747  * \brief Parameter parsing callback for /asterisk/logging/{logChannelName}.
748  * \param get_params GET parameters in the HTTP request.
749  * \param path_vars Path variables extracted from the request.
750  * \param headers HTTP headers.
751  * \param[out] response Response to the HTTP request.
752  */
753 static void ast_ari_asterisk_add_log_cb(
754         struct ast_tcptls_session_instance *ser,
755         struct ast_variable *get_params, struct ast_variable *path_vars,
756         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
757 {
758         struct ast_ari_asterisk_add_log_args args = {};
759         struct ast_variable *i;
760 #if defined(AST_DEVMODE)
761         int is_valid;
762         int code;
763 #endif /* AST_DEVMODE */
764
765         for (i = get_params; i; i = i->next) {
766                 if (strcmp(i->name, "configuration") == 0) {
767                         args.configuration = (i->value);
768                 } else
769                 {}
770         }
771         for (i = path_vars; i; i = i->next) {
772                 if (strcmp(i->name, "logChannelName") == 0) {
773                         args.log_channel_name = (i->value);
774                 } else
775                 {}
776         }
777         if (ast_ari_asterisk_add_log_parse_body(body, &args)) {
778                 ast_ari_response_alloc_failed(response);
779                 goto fin;
780         }
781         ast_ari_asterisk_add_log(headers, &args, response);
782 #if defined(AST_DEVMODE)
783         code = response->response_code;
784
785         switch (code) {
786         case 0: /* Implementation is still a stub, or the code wasn't set */
787                 is_valid = response->message == NULL;
788                 break;
789         case 500: /* Internal Server Error */
790         case 501: /* Not Implemented */
791         case 400: /* Bad request body */
792         case 409: /* Log channel could not be created. */
793                 is_valid = 1;
794                 break;
795         default:
796                 if (200 <= code && code <= 299) {
797                         is_valid = ast_ari_validate_void(
798                                 response->message);
799                 } else {
800                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/logging/{logChannelName}\n", code);
801                         is_valid = 0;
802                 }
803         }
804
805         if (!is_valid) {
806                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/logging/{logChannelName}\n");
807                 ast_ari_response_error(response, 500,
808                         "Internal Server Error", "Response validation failed");
809         }
810 #endif /* AST_DEVMODE */
811
812 fin: __attribute__((unused))
813         return;
814 }
815 /*!
816  * \brief Parameter parsing callback for /asterisk/logging/{logChannelName}.
817  * \param get_params GET parameters in the HTTP request.
818  * \param path_vars Path variables extracted from the request.
819  * \param headers HTTP headers.
820  * \param[out] response Response to the HTTP request.
821  */
822 static void ast_ari_asterisk_delete_log_cb(
823         struct ast_tcptls_session_instance *ser,
824         struct ast_variable *get_params, struct ast_variable *path_vars,
825         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
826 {
827         struct ast_ari_asterisk_delete_log_args args = {};
828         struct ast_variable *i;
829 #if defined(AST_DEVMODE)
830         int is_valid;
831         int code;
832 #endif /* AST_DEVMODE */
833
834         for (i = path_vars; i; i = i->next) {
835                 if (strcmp(i->name, "logChannelName") == 0) {
836                         args.log_channel_name = (i->value);
837                 } else
838                 {}
839         }
840         ast_ari_asterisk_delete_log(headers, &args, response);
841 #if defined(AST_DEVMODE)
842         code = response->response_code;
843
844         switch (code) {
845         case 0: /* Implementation is still a stub, or the code wasn't set */
846                 is_valid = response->message == NULL;
847                 break;
848         case 500: /* Internal Server Error */
849         case 501: /* Not Implemented */
850         case 404: /* Log channel does not exist. */
851                 is_valid = 1;
852                 break;
853         default:
854                 if (200 <= code && code <= 299) {
855                         is_valid = ast_ari_validate_void(
856                                 response->message);
857                 } else {
858                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/logging/{logChannelName}\n", code);
859                         is_valid = 0;
860                 }
861         }
862
863         if (!is_valid) {
864                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/logging/{logChannelName}\n");
865                 ast_ari_response_error(response, 500,
866                         "Internal Server Error", "Response validation failed");
867         }
868 #endif /* AST_DEVMODE */
869
870 fin: __attribute__((unused))
871         return;
872 }
873 /*!
874  * \brief Parameter parsing callback for /asterisk/logging/{logChannelName}/rotate.
875  * \param get_params GET parameters in the HTTP request.
876  * \param path_vars Path variables extracted from the request.
877  * \param headers HTTP headers.
878  * \param[out] response Response to the HTTP request.
879  */
880 static void ast_ari_asterisk_rotate_log_cb(
881         struct ast_tcptls_session_instance *ser,
882         struct ast_variable *get_params, struct ast_variable *path_vars,
883         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
884 {
885         struct ast_ari_asterisk_rotate_log_args args = {};
886         struct ast_variable *i;
887 #if defined(AST_DEVMODE)
888         int is_valid;
889         int code;
890 #endif /* AST_DEVMODE */
891
892         for (i = path_vars; i; i = i->next) {
893                 if (strcmp(i->name, "logChannelName") == 0) {
894                         args.log_channel_name = (i->value);
895                 } else
896                 {}
897         }
898         ast_ari_asterisk_rotate_log(headers, &args, response);
899 #if defined(AST_DEVMODE)
900         code = response->response_code;
901
902         switch (code) {
903         case 0: /* Implementation is still a stub, or the code wasn't set */
904                 is_valid = response->message == NULL;
905                 break;
906         case 500: /* Internal Server Error */
907         case 501: /* Not Implemented */
908         case 404: /* Log channel does not exist. */
909                 is_valid = 1;
910                 break;
911         default:
912                 if (200 <= code && code <= 299) {
913                         is_valid = ast_ari_validate_void(
914                                 response->message);
915                 } else {
916                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/logging/{logChannelName}/rotate\n", code);
917                         is_valid = 0;
918                 }
919         }
920
921         if (!is_valid) {
922                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/logging/{logChannelName}/rotate\n");
923                 ast_ari_response_error(response, 500,
924                         "Internal Server Error", "Response validation failed");
925         }
926 #endif /* AST_DEVMODE */
927
928 fin: __attribute__((unused))
929         return;
930 }
931 int ast_ari_asterisk_get_global_var_parse_body(
932         struct ast_json *body,
933         struct ast_ari_asterisk_get_global_var_args *args)
934 {
935         struct ast_json *field;
936         /* Parse query parameters out of it */
937         field = ast_json_object_get(body, "variable");
938         if (field) {
939                 args->variable = ast_json_string_get(field);
940         }
941         return 0;
942 }
943
944 /*!
945  * \brief Parameter parsing callback for /asterisk/variable.
946  * \param get_params GET parameters in the HTTP request.
947  * \param path_vars Path variables extracted from the request.
948  * \param headers HTTP headers.
949  * \param[out] response Response to the HTTP request.
950  */
951 static void ast_ari_asterisk_get_global_var_cb(
952         struct ast_tcptls_session_instance *ser,
953         struct ast_variable *get_params, struct ast_variable *path_vars,
954         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
955 {
956         struct ast_ari_asterisk_get_global_var_args args = {};
957         struct ast_variable *i;
958 #if defined(AST_DEVMODE)
959         int is_valid;
960         int code;
961 #endif /* AST_DEVMODE */
962
963         for (i = get_params; i; i = i->next) {
964                 if (strcmp(i->name, "variable") == 0) {
965                         args.variable = (i->value);
966                 } else
967                 {}
968         }
969         if (ast_ari_asterisk_get_global_var_parse_body(body, &args)) {
970                 ast_ari_response_alloc_failed(response);
971                 goto fin;
972         }
973         ast_ari_asterisk_get_global_var(headers, &args, response);
974 #if defined(AST_DEVMODE)
975         code = response->response_code;
976
977         switch (code) {
978         case 0: /* Implementation is still a stub, or the code wasn't set */
979                 is_valid = response->message == NULL;
980                 break;
981         case 500: /* Internal Server Error */
982         case 501: /* Not Implemented */
983         case 400: /* Missing variable parameter. */
984                 is_valid = 1;
985                 break;
986         default:
987                 if (200 <= code && code <= 299) {
988                         is_valid = ast_ari_validate_variable(
989                                 response->message);
990                 } else {
991                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/variable\n", code);
992                         is_valid = 0;
993                 }
994         }
995
996         if (!is_valid) {
997                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/variable\n");
998                 ast_ari_response_error(response, 500,
999                         "Internal Server Error", "Response validation failed");
1000         }
1001 #endif /* AST_DEVMODE */
1002
1003 fin: __attribute__((unused))
1004         return;
1005 }
1006 int ast_ari_asterisk_set_global_var_parse_body(
1007         struct ast_json *body,
1008         struct ast_ari_asterisk_set_global_var_args *args)
1009 {
1010         struct ast_json *field;
1011         /* Parse query parameters out of it */
1012         field = ast_json_object_get(body, "variable");
1013         if (field) {
1014                 args->variable = ast_json_string_get(field);
1015         }
1016         field = ast_json_object_get(body, "value");
1017         if (field) {
1018                 args->value = ast_json_string_get(field);
1019         }
1020         return 0;
1021 }
1022
1023 /*!
1024  * \brief Parameter parsing callback for /asterisk/variable.
1025  * \param get_params GET parameters in the HTTP request.
1026  * \param path_vars Path variables extracted from the request.
1027  * \param headers HTTP headers.
1028  * \param[out] response Response to the HTTP request.
1029  */
1030 static void ast_ari_asterisk_set_global_var_cb(
1031         struct ast_tcptls_session_instance *ser,
1032         struct ast_variable *get_params, struct ast_variable *path_vars,
1033         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1034 {
1035         struct ast_ari_asterisk_set_global_var_args args = {};
1036         struct ast_variable *i;
1037 #if defined(AST_DEVMODE)
1038         int is_valid;
1039         int code;
1040 #endif /* AST_DEVMODE */
1041
1042         for (i = get_params; i; i = i->next) {
1043                 if (strcmp(i->name, "variable") == 0) {
1044                         args.variable = (i->value);
1045                 } else
1046                 if (strcmp(i->name, "value") == 0) {
1047                         args.value = (i->value);
1048                 } else
1049                 {}
1050         }
1051         if (ast_ari_asterisk_set_global_var_parse_body(body, &args)) {
1052                 ast_ari_response_alloc_failed(response);
1053                 goto fin;
1054         }
1055         ast_ari_asterisk_set_global_var(headers, &args, response);
1056 #if defined(AST_DEVMODE)
1057         code = response->response_code;
1058
1059         switch (code) {
1060         case 0: /* Implementation is still a stub, or the code wasn't set */
1061                 is_valid = response->message == NULL;
1062                 break;
1063         case 500: /* Internal Server Error */
1064         case 501: /* Not Implemented */
1065         case 400: /* Missing variable parameter. */
1066                 is_valid = 1;
1067                 break;
1068         default:
1069                 if (200 <= code && code <= 299) {
1070                         is_valid = ast_ari_validate_void(
1071                                 response->message);
1072                 } else {
1073                         ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/variable\n", code);
1074                         is_valid = 0;
1075                 }
1076         }
1077
1078         if (!is_valid) {
1079                 ast_log(LOG_ERROR, "Response validation failed for /asterisk/variable\n");
1080                 ast_ari_response_error(response, 500,
1081                         "Internal Server Error", "Response validation failed");
1082         }
1083 #endif /* AST_DEVMODE */
1084
1085 fin: __attribute__((unused))
1086         return;
1087 }
1088
1089 /*! \brief REST handler for /api-docs/asterisk.json */
1090 static struct stasis_rest_handlers asterisk_config_dynamic_configClass_objectType_id = {
1091         .path_segment = "id",
1092         .is_wildcard = 1,
1093         .callbacks = {
1094                 [AST_HTTP_GET] = ast_ari_asterisk_get_object_cb,
1095                 [AST_HTTP_PUT] = ast_ari_asterisk_update_object_cb,
1096                 [AST_HTTP_DELETE] = ast_ari_asterisk_delete_object_cb,
1097         },
1098         .num_children = 0,
1099         .children = {  }
1100 };
1101 /*! \brief REST handler for /api-docs/asterisk.json */
1102 static struct stasis_rest_handlers asterisk_config_dynamic_configClass_objectType = {
1103         .path_segment = "objectType",
1104         .is_wildcard = 1,
1105         .callbacks = {
1106         },
1107         .num_children = 1,
1108         .children = { &asterisk_config_dynamic_configClass_objectType_id, }
1109 };
1110 /*! \brief REST handler for /api-docs/asterisk.json */
1111 static struct stasis_rest_handlers asterisk_config_dynamic_configClass = {
1112         .path_segment = "configClass",
1113         .is_wildcard = 1,
1114         .callbacks = {
1115         },
1116         .num_children = 1,
1117         .children = { &asterisk_config_dynamic_configClass_objectType, }
1118 };
1119 /*! \brief REST handler for /api-docs/asterisk.json */
1120 static struct stasis_rest_handlers asterisk_config_dynamic = {
1121         .path_segment = "dynamic",
1122         .callbacks = {
1123         },
1124         .num_children = 1,
1125         .children = { &asterisk_config_dynamic_configClass, }
1126 };
1127 /*! \brief REST handler for /api-docs/asterisk.json */
1128 static struct stasis_rest_handlers asterisk_config = {
1129         .path_segment = "config",
1130         .callbacks = {
1131         },
1132         .num_children = 1,
1133         .children = { &asterisk_config_dynamic, }
1134 };
1135 /*! \brief REST handler for /api-docs/asterisk.json */
1136 static struct stasis_rest_handlers asterisk_info = {
1137         .path_segment = "info",
1138         .callbacks = {
1139                 [AST_HTTP_GET] = ast_ari_asterisk_get_info_cb,
1140         },
1141         .num_children = 0,
1142         .children = {  }
1143 };
1144 /*! \brief REST handler for /api-docs/asterisk.json */
1145 static struct stasis_rest_handlers asterisk_modules_moduleName = {
1146         .path_segment = "moduleName",
1147         .is_wildcard = 1,
1148         .callbacks = {
1149                 [AST_HTTP_GET] = ast_ari_asterisk_get_module_cb,
1150                 [AST_HTTP_POST] = ast_ari_asterisk_load_module_cb,
1151                 [AST_HTTP_DELETE] = ast_ari_asterisk_unload_module_cb,
1152                 [AST_HTTP_PUT] = ast_ari_asterisk_reload_module_cb,
1153         },
1154         .num_children = 0,
1155         .children = {  }
1156 };
1157 /*! \brief REST handler for /api-docs/asterisk.json */
1158 static struct stasis_rest_handlers asterisk_modules = {
1159         .path_segment = "modules",
1160         .callbacks = {
1161                 [AST_HTTP_GET] = ast_ari_asterisk_list_modules_cb,
1162         },
1163         .num_children = 1,
1164         .children = { &asterisk_modules_moduleName, }
1165 };
1166 /*! \brief REST handler for /api-docs/asterisk.json */
1167 static struct stasis_rest_handlers asterisk_logging_logChannelName_rotate = {
1168         .path_segment = "rotate",
1169         .callbacks = {
1170                 [AST_HTTP_PUT] = ast_ari_asterisk_rotate_log_cb,
1171         },
1172         .num_children = 0,
1173         .children = {  }
1174 };
1175 /*! \brief REST handler for /api-docs/asterisk.json */
1176 static struct stasis_rest_handlers asterisk_logging_logChannelName = {
1177         .path_segment = "logChannelName",
1178         .is_wildcard = 1,
1179         .callbacks = {
1180                 [AST_HTTP_POST] = ast_ari_asterisk_add_log_cb,
1181                 [AST_HTTP_DELETE] = ast_ari_asterisk_delete_log_cb,
1182         },
1183         .num_children = 1,
1184         .children = { &asterisk_logging_logChannelName_rotate, }
1185 };
1186 /*! \brief REST handler for /api-docs/asterisk.json */
1187 static struct stasis_rest_handlers asterisk_logging = {
1188         .path_segment = "logging",
1189         .callbacks = {
1190                 [AST_HTTP_GET] = ast_ari_asterisk_list_log_channels_cb,
1191         },
1192         .num_children = 1,
1193         .children = { &asterisk_logging_logChannelName, }
1194 };
1195 /*! \brief REST handler for /api-docs/asterisk.json */
1196 static struct stasis_rest_handlers asterisk_variable = {
1197         .path_segment = "variable",
1198         .callbacks = {
1199                 [AST_HTTP_GET] = ast_ari_asterisk_get_global_var_cb,
1200                 [AST_HTTP_POST] = ast_ari_asterisk_set_global_var_cb,
1201         },
1202         .num_children = 0,
1203         .children = {  }
1204 };
1205 /*! \brief REST handler for /api-docs/asterisk.json */
1206 static struct stasis_rest_handlers asterisk = {
1207         .path_segment = "asterisk",
1208         .callbacks = {
1209         },
1210         .num_children = 5,
1211         .children = { &asterisk_config,&asterisk_info,&asterisk_modules,&asterisk_logging,&asterisk_variable, }
1212 };
1213
1214 static int unload_module(void)
1215 {
1216         ast_ari_remove_handler(&asterisk);
1217         stasis_app_unref();
1218         return 0;
1219 }
1220
1221 static int load_module(void)
1222 {
1223         int res = 0;
1224
1225         CHECK_ARI_MODULE_LOADED();
1226
1227
1228         stasis_app_ref();
1229         res |= ast_ari_add_handler(&asterisk);
1230         if (res) {
1231                 unload_module();
1232                 return AST_MODULE_LOAD_DECLINE;
1233         }
1234
1235         return AST_MODULE_LOAD_SUCCESS;
1236 }
1237
1238 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Asterisk resources",
1239         .support_level = AST_MODULE_SUPPORT_CORE,
1240         .load = load_module,
1241         .unload = unload_module,
1242         .requires = "res_ari,res_ari_model,res_stasis",
1243 );