Merge "chan_ooh323: fix h323 log file path"
[asterisk/asterisk.git] / res / res_ari_applications.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 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 Stasis application 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_applications.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 /applications.
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_applications_list_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_applications_list_args args = {};
66 #if defined(AST_DEVMODE)
67         int is_valid;
68         int code;
69 #endif /* AST_DEVMODE */
70
71         ast_ari_applications_list(headers, &args, response);
72 #if defined(AST_DEVMODE)
73         code = response->response_code;
74
75         switch (code) {
76         case 0: /* Implementation is still a stub, or the code wasn't set */
77                 is_valid = response->message == NULL;
78                 break;
79         case 500: /* Internal Server Error */
80         case 501: /* Not Implemented */
81                 is_valid = 1;
82                 break;
83         default:
84                 if (200 <= code && code <= 299) {
85                         is_valid = ast_ari_validate_list(response->message,
86                                 ast_ari_validate_application_fn());
87                 } else {
88                         ast_log(LOG_ERROR, "Invalid error response %d for /applications\n", code);
89                         is_valid = 0;
90                 }
91         }
92
93         if (!is_valid) {
94                 ast_log(LOG_ERROR, "Response validation failed for /applications\n");
95                 ast_ari_response_error(response, 500,
96                         "Internal Server Error", "Response validation failed");
97         }
98 #endif /* AST_DEVMODE */
99
100 fin: __attribute__((unused))
101         return;
102 }
103 /*!
104  * \brief Parameter parsing callback for /applications/{applicationName}.
105  * \param get_params GET parameters in the HTTP request.
106  * \param path_vars Path variables extracted from the request.
107  * \param headers HTTP headers.
108  * \param[out] response Response to the HTTP request.
109  */
110 static void ast_ari_applications_get_cb(
111         struct ast_tcptls_session_instance *ser,
112         struct ast_variable *get_params, struct ast_variable *path_vars,
113         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
114 {
115         struct ast_ari_applications_get_args args = {};
116         struct ast_variable *i;
117 #if defined(AST_DEVMODE)
118         int is_valid;
119         int code;
120 #endif /* AST_DEVMODE */
121
122         for (i = path_vars; i; i = i->next) {
123                 if (strcmp(i->name, "applicationName") == 0) {
124                         args.application_name = (i->value);
125                 } else
126                 {}
127         }
128         ast_ari_applications_get(headers, &args, response);
129 #if defined(AST_DEVMODE)
130         code = response->response_code;
131
132         switch (code) {
133         case 0: /* Implementation is still a stub, or the code wasn't set */
134                 is_valid = response->message == NULL;
135                 break;
136         case 500: /* Internal Server Error */
137         case 501: /* Not Implemented */
138         case 404: /* Application does not exist. */
139                 is_valid = 1;
140                 break;
141         default:
142                 if (200 <= code && code <= 299) {
143                         is_valid = ast_ari_validate_application(
144                                 response->message);
145                 } else {
146                         ast_log(LOG_ERROR, "Invalid error response %d for /applications/{applicationName}\n", code);
147                         is_valid = 0;
148                 }
149         }
150
151         if (!is_valid) {
152                 ast_log(LOG_ERROR, "Response validation failed for /applications/{applicationName}\n");
153                 ast_ari_response_error(response, 500,
154                         "Internal Server Error", "Response validation failed");
155         }
156 #endif /* AST_DEVMODE */
157
158 fin: __attribute__((unused))
159         return;
160 }
161 int ast_ari_applications_subscribe_parse_body(
162         struct ast_json *body,
163         struct ast_ari_applications_subscribe_args *args)
164 {
165         struct ast_json *field;
166         /* Parse query parameters out of it */
167         field = ast_json_object_get(body, "eventSource");
168         if (field) {
169                 /* If they were silly enough to both pass in a query param and a
170                  * JSON body, free up the query value.
171                  */
172                 ast_free(args->event_source);
173                 if (ast_json_typeof(field) == AST_JSON_ARRAY) {
174                         /* Multiple param passed as array */
175                         size_t i;
176                         args->event_source_count = ast_json_array_size(field);
177                         args->event_source = ast_malloc(sizeof(*args->event_source) * args->event_source_count);
178
179                         if (!args->event_source) {
180                                 return -1;
181                         }
182
183                         for (i = 0; i < args->event_source_count; ++i) {
184                                 args->event_source[i] = ast_json_string_get(ast_json_array_get(field, i));
185                         }
186                 } else {
187                         /* Multiple param passed as single value */
188                         args->event_source_count = 1;
189                         args->event_source = ast_malloc(sizeof(*args->event_source) * args->event_source_count);
190                         if (!args->event_source) {
191                                 return -1;
192                         }
193                         args->event_source[0] = ast_json_string_get(field);
194                 }
195         }
196         return 0;
197 }
198
199 /*!
200  * \brief Parameter parsing callback for /applications/{applicationName}/subscription.
201  * \param get_params GET parameters in the HTTP request.
202  * \param path_vars Path variables extracted from the request.
203  * \param headers HTTP headers.
204  * \param[out] response Response to the HTTP request.
205  */
206 static void ast_ari_applications_subscribe_cb(
207         struct ast_tcptls_session_instance *ser,
208         struct ast_variable *get_params, struct ast_variable *path_vars,
209         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
210 {
211         struct ast_ari_applications_subscribe_args args = {};
212         struct ast_variable *i;
213 #if defined(AST_DEVMODE)
214         int is_valid;
215         int code;
216 #endif /* AST_DEVMODE */
217
218         for (i = get_params; i; i = i->next) {
219                 if (strcmp(i->name, "eventSource") == 0) {
220                         /* Parse comma separated list */
221                         char *vals[MAX_VALS];
222                         size_t j;
223
224                         args.event_source_parse = ast_strdup(i->value);
225                         if (!args.event_source_parse) {
226                                 ast_ari_response_alloc_failed(response);
227                                 goto fin;
228                         }
229
230                         if (strlen(args.event_source_parse) == 0) {
231                                 /* ast_app_separate_args can't handle "" */
232                                 args.event_source_count = 1;
233                                 vals[0] = args.event_source_parse;
234                         } else {
235                                 args.event_source_count = ast_app_separate_args(
236                                         args.event_source_parse, ',', vals,
237                                         ARRAY_LEN(vals));
238                         }
239
240                         if (args.event_source_count == 0) {
241                                 ast_ari_response_alloc_failed(response);
242                                 goto fin;
243                         }
244
245                         if (args.event_source_count >= MAX_VALS) {
246                                 ast_ari_response_error(response, 400,
247                                         "Bad Request",
248                                         "Too many values for event_source");
249                                 goto fin;
250                         }
251
252                         args.event_source = ast_malloc(sizeof(*args.event_source) * args.event_source_count);
253                         if (!args.event_source) {
254                                 ast_ari_response_alloc_failed(response);
255                                 goto fin;
256                         }
257
258                         for (j = 0; j < args.event_source_count; ++j) {
259                                 args.event_source[j] = (vals[j]);
260                         }
261                 } else
262                 {}
263         }
264         for (i = path_vars; i; i = i->next) {
265                 if (strcmp(i->name, "applicationName") == 0) {
266                         args.application_name = (i->value);
267                 } else
268                 {}
269         }
270         if (ast_ari_applications_subscribe_parse_body(body, &args)) {
271                 ast_ari_response_alloc_failed(response);
272                 goto fin;
273         }
274         ast_ari_applications_subscribe(headers, &args, response);
275 #if defined(AST_DEVMODE)
276         code = response->response_code;
277
278         switch (code) {
279         case 0: /* Implementation is still a stub, or the code wasn't set */
280                 is_valid = response->message == NULL;
281                 break;
282         case 500: /* Internal Server Error */
283         case 501: /* Not Implemented */
284         case 400: /* Missing parameter. */
285         case 404: /* Application does not exist. */
286         case 422: /* Event source does not exist. */
287                 is_valid = 1;
288                 break;
289         default:
290                 if (200 <= code && code <= 299) {
291                         is_valid = ast_ari_validate_application(
292                                 response->message);
293                 } else {
294                         ast_log(LOG_ERROR, "Invalid error response %d for /applications/{applicationName}/subscription\n", code);
295                         is_valid = 0;
296                 }
297         }
298
299         if (!is_valid) {
300                 ast_log(LOG_ERROR, "Response validation failed for /applications/{applicationName}/subscription\n");
301                 ast_ari_response_error(response, 500,
302                         "Internal Server Error", "Response validation failed");
303         }
304 #endif /* AST_DEVMODE */
305
306 fin: __attribute__((unused))
307         ast_free(args.event_source_parse);
308         ast_free(args.event_source);
309         return;
310 }
311 int ast_ari_applications_unsubscribe_parse_body(
312         struct ast_json *body,
313         struct ast_ari_applications_unsubscribe_args *args)
314 {
315         struct ast_json *field;
316         /* Parse query parameters out of it */
317         field = ast_json_object_get(body, "eventSource");
318         if (field) {
319                 /* If they were silly enough to both pass in a query param and a
320                  * JSON body, free up the query value.
321                  */
322                 ast_free(args->event_source);
323                 if (ast_json_typeof(field) == AST_JSON_ARRAY) {
324                         /* Multiple param passed as array */
325                         size_t i;
326                         args->event_source_count = ast_json_array_size(field);
327                         args->event_source = ast_malloc(sizeof(*args->event_source) * args->event_source_count);
328
329                         if (!args->event_source) {
330                                 return -1;
331                         }
332
333                         for (i = 0; i < args->event_source_count; ++i) {
334                                 args->event_source[i] = ast_json_string_get(ast_json_array_get(field, i));
335                         }
336                 } else {
337                         /* Multiple param passed as single value */
338                         args->event_source_count = 1;
339                         args->event_source = ast_malloc(sizeof(*args->event_source) * args->event_source_count);
340                         if (!args->event_source) {
341                                 return -1;
342                         }
343                         args->event_source[0] = ast_json_string_get(field);
344                 }
345         }
346         return 0;
347 }
348
349 /*!
350  * \brief Parameter parsing callback for /applications/{applicationName}/subscription.
351  * \param get_params GET parameters in the HTTP request.
352  * \param path_vars Path variables extracted from the request.
353  * \param headers HTTP headers.
354  * \param[out] response Response to the HTTP request.
355  */
356 static void ast_ari_applications_unsubscribe_cb(
357         struct ast_tcptls_session_instance *ser,
358         struct ast_variable *get_params, struct ast_variable *path_vars,
359         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
360 {
361         struct ast_ari_applications_unsubscribe_args args = {};
362         struct ast_variable *i;
363 #if defined(AST_DEVMODE)
364         int is_valid;
365         int code;
366 #endif /* AST_DEVMODE */
367
368         for (i = get_params; i; i = i->next) {
369                 if (strcmp(i->name, "eventSource") == 0) {
370                         /* Parse comma separated list */
371                         char *vals[MAX_VALS];
372                         size_t j;
373
374                         args.event_source_parse = ast_strdup(i->value);
375                         if (!args.event_source_parse) {
376                                 ast_ari_response_alloc_failed(response);
377                                 goto fin;
378                         }
379
380                         if (strlen(args.event_source_parse) == 0) {
381                                 /* ast_app_separate_args can't handle "" */
382                                 args.event_source_count = 1;
383                                 vals[0] = args.event_source_parse;
384                         } else {
385                                 args.event_source_count = ast_app_separate_args(
386                                         args.event_source_parse, ',', vals,
387                                         ARRAY_LEN(vals));
388                         }
389
390                         if (args.event_source_count == 0) {
391                                 ast_ari_response_alloc_failed(response);
392                                 goto fin;
393                         }
394
395                         if (args.event_source_count >= MAX_VALS) {
396                                 ast_ari_response_error(response, 400,
397                                         "Bad Request",
398                                         "Too many values for event_source");
399                                 goto fin;
400                         }
401
402                         args.event_source = ast_malloc(sizeof(*args.event_source) * args.event_source_count);
403                         if (!args.event_source) {
404                                 ast_ari_response_alloc_failed(response);
405                                 goto fin;
406                         }
407
408                         for (j = 0; j < args.event_source_count; ++j) {
409                                 args.event_source[j] = (vals[j]);
410                         }
411                 } else
412                 {}
413         }
414         for (i = path_vars; i; i = i->next) {
415                 if (strcmp(i->name, "applicationName") == 0) {
416                         args.application_name = (i->value);
417                 } else
418                 {}
419         }
420         if (ast_ari_applications_unsubscribe_parse_body(body, &args)) {
421                 ast_ari_response_alloc_failed(response);
422                 goto fin;
423         }
424         ast_ari_applications_unsubscribe(headers, &args, response);
425 #if defined(AST_DEVMODE)
426         code = response->response_code;
427
428         switch (code) {
429         case 0: /* Implementation is still a stub, or the code wasn't set */
430                 is_valid = response->message == NULL;
431                 break;
432         case 500: /* Internal Server Error */
433         case 501: /* Not Implemented */
434         case 400: /* Missing parameter; event source scheme not recognized. */
435         case 404: /* Application does not exist. */
436         case 409: /* Application not subscribed to event source. */
437         case 422: /* Event source does not exist. */
438                 is_valid = 1;
439                 break;
440         default:
441                 if (200 <= code && code <= 299) {
442                         is_valid = ast_ari_validate_application(
443                                 response->message);
444                 } else {
445                         ast_log(LOG_ERROR, "Invalid error response %d for /applications/{applicationName}/subscription\n", code);
446                         is_valid = 0;
447                 }
448         }
449
450         if (!is_valid) {
451                 ast_log(LOG_ERROR, "Response validation failed for /applications/{applicationName}/subscription\n");
452                 ast_ari_response_error(response, 500,
453                         "Internal Server Error", "Response validation failed");
454         }
455 #endif /* AST_DEVMODE */
456
457 fin: __attribute__((unused))
458         ast_free(args.event_source_parse);
459         ast_free(args.event_source);
460         return;
461 }
462 int ast_ari_applications_filter_parse_body(
463         struct ast_json *body,
464         struct ast_ari_applications_filter_args *args)
465 {
466         /* Parse query parameters out of it */
467         return 0;
468 }
469
470 /*!
471  * \brief Parameter parsing callback for /applications/{applicationName}/eventFilter.
472  * \param get_params GET parameters in the HTTP request.
473  * \param path_vars Path variables extracted from the request.
474  * \param headers HTTP headers.
475  * \param[out] response Response to the HTTP request.
476  */
477 static void ast_ari_applications_filter_cb(
478         struct ast_tcptls_session_instance *ser,
479         struct ast_variable *get_params, struct ast_variable *path_vars,
480         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
481 {
482         struct ast_ari_applications_filter_args args = {};
483         struct ast_variable *i;
484 #if defined(AST_DEVMODE)
485         int is_valid;
486         int code;
487 #endif /* AST_DEVMODE */
488
489         for (i = path_vars; i; i = i->next) {
490                 if (strcmp(i->name, "applicationName") == 0) {
491                         args.application_name = (i->value);
492                 } else
493                 {}
494         }
495         args.filter = body;
496         ast_ari_applications_filter(headers, &args, response);
497 #if defined(AST_DEVMODE)
498         code = response->response_code;
499
500         switch (code) {
501         case 0: /* Implementation is still a stub, or the code wasn't set */
502                 is_valid = response->message == NULL;
503                 break;
504         case 500: /* Internal Server Error */
505         case 501: /* Not Implemented */
506         case 400: /* Bad request. */
507         case 404: /* Application does not exist. */
508                 is_valid = 1;
509                 break;
510         default:
511                 if (200 <= code && code <= 299) {
512                         is_valid = ast_ari_validate_application(
513                                 response->message);
514                 } else {
515                         ast_log(LOG_ERROR, "Invalid error response %d for /applications/{applicationName}/eventFilter\n", code);
516                         is_valid = 0;
517                 }
518         }
519
520         if (!is_valid) {
521                 ast_log(LOG_ERROR, "Response validation failed for /applications/{applicationName}/eventFilter\n");
522                 ast_ari_response_error(response, 500,
523                         "Internal Server Error", "Response validation failed");
524         }
525 #endif /* AST_DEVMODE */
526
527 fin: __attribute__((unused))
528         return;
529 }
530
531 /*! \brief REST handler for /api-docs/applications.json */
532 static struct stasis_rest_handlers applications_applicationName_subscription = {
533         .path_segment = "subscription",
534         .callbacks = {
535                 [AST_HTTP_POST] = ast_ari_applications_subscribe_cb,
536                 [AST_HTTP_DELETE] = ast_ari_applications_unsubscribe_cb,
537         },
538         .num_children = 0,
539         .children = {  }
540 };
541 /*! \brief REST handler for /api-docs/applications.json */
542 static struct stasis_rest_handlers applications_applicationName_eventFilter = {
543         .path_segment = "eventFilter",
544         .callbacks = {
545                 [AST_HTTP_PUT] = ast_ari_applications_filter_cb,
546         },
547         .num_children = 0,
548         .children = {  }
549 };
550 /*! \brief REST handler for /api-docs/applications.json */
551 static struct stasis_rest_handlers applications_applicationName = {
552         .path_segment = "applicationName",
553         .is_wildcard = 1,
554         .callbacks = {
555                 [AST_HTTP_GET] = ast_ari_applications_get_cb,
556         },
557         .num_children = 2,
558         .children = { &applications_applicationName_subscription,&applications_applicationName_eventFilter, }
559 };
560 /*! \brief REST handler for /api-docs/applications.json */
561 static struct stasis_rest_handlers applications = {
562         .path_segment = "applications",
563         .callbacks = {
564                 [AST_HTTP_GET] = ast_ari_applications_list_cb,
565         },
566         .num_children = 1,
567         .children = { &applications_applicationName, }
568 };
569
570 static int unload_module(void)
571 {
572         ast_ari_remove_handler(&applications);
573         return 0;
574 }
575
576 static int load_module(void)
577 {
578         int res = 0;
579
580
581         res |= ast_ari_add_handler(&applications);
582         if (res) {
583                 unload_module();
584                 return AST_MODULE_LOAD_DECLINE;
585         }
586
587         return AST_MODULE_LOAD_SUCCESS;
588 }
589
590 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Stasis application resources",
591         .support_level = AST_MODULE_SUPPORT_CORE,
592         .load = load_module,
593         .unload = unload_module,
594         .requires = "res_ari,res_ari_model,res_stasis",
595 );