ARI - implement allowMultiple for parameters
[asterisk/asterisk.git] / res / res_ari_bridges.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 Bridge resources
30  *
31  * \author David M. Lee, II <dlee@digium.com>
32  */
33
34 /*** MODULEINFO
35         <depend type="module">res_ari</depend>
36         <depend type="module">res_stasis</depend>
37         <support_level>core</support_level>
38  ***/
39
40 #include "asterisk.h"
41
42 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
43
44 #include "asterisk/app.h"
45 #include "asterisk/module.h"
46 #include "asterisk/stasis_app.h"
47 #include "ari/resource_bridges.h"
48 #if defined(AST_DEVMODE)
49 #include "ari/ari_model_validators.h"
50 #endif
51
52 #define MAX_VALS 128
53
54 /*!
55  * \brief Parameter parsing callback for /bridges.
56  * \param get_params GET parameters in the HTTP request.
57  * \param path_vars Path variables extracted from the request.
58  * \param headers HTTP headers.
59  * \param[out] response Response to the HTTP request.
60  */
61 static void ast_ari_get_bridges_cb(
62         struct ast_variable *get_params, struct ast_variable *path_vars,
63         struct ast_variable *headers, struct ast_ari_response *response)
64 {
65         struct ast_get_bridges_args args = {};
66 #if defined(AST_DEVMODE)
67         int is_valid;
68         int code;
69 #endif /* AST_DEVMODE */
70
71         ast_ari_get_bridges(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_bridge_fn());
87                 } else {
88                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges\n", code);
89                         is_valid = 0;
90                 }
91         }
92
93         if (!is_valid) {
94                 ast_log(LOG_ERROR, "Response validation failed for /bridges\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 /bridges.
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_new_bridge_cb(
111         struct ast_variable *get_params, struct ast_variable *path_vars,
112         struct ast_variable *headers, struct ast_ari_response *response)
113 {
114         struct ast_new_bridge_args args = {};
115         struct ast_variable *i;
116 #if defined(AST_DEVMODE)
117         int is_valid;
118         int code;
119 #endif /* AST_DEVMODE */
120
121         for (i = get_params; i; i = i->next) {
122                 if (strcmp(i->name, "type") == 0) {
123                         args.type = (i->value);
124                 } else
125                 {}
126         }
127         ast_ari_new_bridge(headers, &args, response);
128 #if defined(AST_DEVMODE)
129         code = response->response_code;
130
131         switch (code) {
132         case 0: /* Implementation is still a stub, or the code wasn't set */
133                 is_valid = response->message == NULL;
134                 break;
135         case 500: /* Internal Server Error */
136         case 501: /* Not Implemented */
137                 is_valid = 1;
138                 break;
139         default:
140                 if (200 <= code && code <= 299) {
141                         is_valid = ast_ari_validate_bridge(
142                                 response->message);
143                 } else {
144                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges\n", code);
145                         is_valid = 0;
146                 }
147         }
148
149         if (!is_valid) {
150                 ast_log(LOG_ERROR, "Response validation failed for /bridges\n");
151                 ast_ari_response_error(response, 500,
152                         "Internal Server Error", "Response validation failed");
153         }
154 #endif /* AST_DEVMODE */
155
156 fin: __attribute__((unused))
157         return;
158 }
159 /*!
160  * \brief Parameter parsing callback for /bridges/{bridgeId}.
161  * \param get_params GET parameters in the HTTP request.
162  * \param path_vars Path variables extracted from the request.
163  * \param headers HTTP headers.
164  * \param[out] response Response to the HTTP request.
165  */
166 static void ast_ari_get_bridge_cb(
167         struct ast_variable *get_params, struct ast_variable *path_vars,
168         struct ast_variable *headers, struct ast_ari_response *response)
169 {
170         struct ast_get_bridge_args args = {};
171         struct ast_variable *i;
172 #if defined(AST_DEVMODE)
173         int is_valid;
174         int code;
175 #endif /* AST_DEVMODE */
176
177         for (i = path_vars; i; i = i->next) {
178                 if (strcmp(i->name, "bridgeId") == 0) {
179                         args.bridge_id = (i->value);
180                 } else
181                 {}
182         }
183         ast_ari_get_bridge(headers, &args, response);
184 #if defined(AST_DEVMODE)
185         code = response->response_code;
186
187         switch (code) {
188         case 0: /* Implementation is still a stub, or the code wasn't set */
189                 is_valid = response->message == NULL;
190                 break;
191         case 500: /* Internal Server Error */
192         case 501: /* Not Implemented */
193         case 404: /* Bridge not found */
194                 is_valid = 1;
195                 break;
196         default:
197                 if (200 <= code && code <= 299) {
198                         is_valid = ast_ari_validate_bridge(
199                                 response->message);
200                 } else {
201                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}\n", code);
202                         is_valid = 0;
203                 }
204         }
205
206         if (!is_valid) {
207                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}\n");
208                 ast_ari_response_error(response, 500,
209                         "Internal Server Error", "Response validation failed");
210         }
211 #endif /* AST_DEVMODE */
212
213 fin: __attribute__((unused))
214         return;
215 }
216 /*!
217  * \brief Parameter parsing callback for /bridges/{bridgeId}.
218  * \param get_params GET parameters in the HTTP request.
219  * \param path_vars Path variables extracted from the request.
220  * \param headers HTTP headers.
221  * \param[out] response Response to the HTTP request.
222  */
223 static void ast_ari_delete_bridge_cb(
224         struct ast_variable *get_params, struct ast_variable *path_vars,
225         struct ast_variable *headers, struct ast_ari_response *response)
226 {
227         struct ast_delete_bridge_args args = {};
228         struct ast_variable *i;
229 #if defined(AST_DEVMODE)
230         int is_valid;
231         int code;
232 #endif /* AST_DEVMODE */
233
234         for (i = path_vars; i; i = i->next) {
235                 if (strcmp(i->name, "bridgeId") == 0) {
236                         args.bridge_id = (i->value);
237                 } else
238                 {}
239         }
240         ast_ari_delete_bridge(headers, &args, response);
241 #if defined(AST_DEVMODE)
242         code = response->response_code;
243
244         switch (code) {
245         case 0: /* Implementation is still a stub, or the code wasn't set */
246                 is_valid = response->message == NULL;
247                 break;
248         case 500: /* Internal Server Error */
249         case 501: /* Not Implemented */
250         case 404: /* Bridge not found */
251                 is_valid = 1;
252                 break;
253         default:
254                 if (200 <= code && code <= 299) {
255                         is_valid = ast_ari_validate_void(
256                                 response->message);
257                 } else {
258                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}\n", code);
259                         is_valid = 0;
260                 }
261         }
262
263         if (!is_valid) {
264                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}\n");
265                 ast_ari_response_error(response, 500,
266                         "Internal Server Error", "Response validation failed");
267         }
268 #endif /* AST_DEVMODE */
269
270 fin: __attribute__((unused))
271         return;
272 }
273 /*!
274  * \brief Parameter parsing callback for /bridges/{bridgeId}/addChannel.
275  * \param get_params GET parameters in the HTTP request.
276  * \param path_vars Path variables extracted from the request.
277  * \param headers HTTP headers.
278  * \param[out] response Response to the HTTP request.
279  */
280 static void ast_ari_add_channel_to_bridge_cb(
281         struct ast_variable *get_params, struct ast_variable *path_vars,
282         struct ast_variable *headers, struct ast_ari_response *response)
283 {
284         struct ast_add_channel_to_bridge_args args = {};
285         struct ast_variable *i;
286 #if defined(AST_DEVMODE)
287         int is_valid;
288         int code;
289 #endif /* AST_DEVMODE */
290
291         for (i = get_params; i; i = i->next) {
292                 if (strcmp(i->name, "channel") == 0) {
293                         /* Parse comma separated list */
294                         char *vals[MAX_VALS];
295                         size_t j;
296
297                         args.channel_parse = ast_strdup(i->value);
298                         if (!args.channel_parse) {
299                                 ast_ari_response_alloc_failed(response);
300                                 goto fin;
301                         }
302
303                         args.channel_count = ast_app_separate_args(
304                                 args.channel_parse, ',', vals, ARRAY_LEN(vals));
305                         if (args.channel_count == 0) {
306                                 ast_ari_response_alloc_failed(response);
307                                 goto fin;
308                         }
309
310                         if (args.channel_count >= MAX_VALS) {
311                                 ast_ari_response_error(response, 400,
312                                         "Bad Request",
313                                         "Too many values for channel");
314                                 goto fin;
315                         }
316
317                         args.channel = ast_malloc(sizeof(*args.channel) * args.channel_count);
318                         if (!args.channel) {
319                                 ast_ari_response_alloc_failed(response);
320                                 goto fin;
321                         }
322
323                         for (j = 0; j < args.channel_count; ++j) {
324                                 args.channel[j] = (vals[j]);
325                         }
326                 } else
327                 {}
328         }
329         for (i = path_vars; i; i = i->next) {
330                 if (strcmp(i->name, "bridgeId") == 0) {
331                         args.bridge_id = (i->value);
332                 } else
333                 {}
334         }
335         ast_ari_add_channel_to_bridge(headers, &args, response);
336 #if defined(AST_DEVMODE)
337         code = response->response_code;
338
339         switch (code) {
340         case 0: /* Implementation is still a stub, or the code wasn't set */
341                 is_valid = response->message == NULL;
342                 break;
343         case 500: /* Internal Server Error */
344         case 501: /* Not Implemented */
345         case 404: /* Bridge not found */
346         case 409: /* Bridge not in Stasis application */
347         case 422: /* Channel not found, or not in Stasis application */
348                 is_valid = 1;
349                 break;
350         default:
351                 if (200 <= code && code <= 299) {
352                         is_valid = ast_ari_validate_void(
353                                 response->message);
354                 } else {
355                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/addChannel\n", code);
356                         is_valid = 0;
357                 }
358         }
359
360         if (!is_valid) {
361                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/addChannel\n");
362                 ast_ari_response_error(response, 500,
363                         "Internal Server Error", "Response validation failed");
364         }
365 #endif /* AST_DEVMODE */
366
367 fin: __attribute__((unused))
368         ast_free(args.channel_parse);
369         ast_free(args.channel);
370         return;
371 }
372 /*!
373  * \brief Parameter parsing callback for /bridges/{bridgeId}/removeChannel.
374  * \param get_params GET parameters in the HTTP request.
375  * \param path_vars Path variables extracted from the request.
376  * \param headers HTTP headers.
377  * \param[out] response Response to the HTTP request.
378  */
379 static void ast_ari_remove_channel_from_bridge_cb(
380         struct ast_variable *get_params, struct ast_variable *path_vars,
381         struct ast_variable *headers, struct ast_ari_response *response)
382 {
383         struct ast_remove_channel_from_bridge_args args = {};
384         struct ast_variable *i;
385 #if defined(AST_DEVMODE)
386         int is_valid;
387         int code;
388 #endif /* AST_DEVMODE */
389
390         for (i = get_params; i; i = i->next) {
391                 if (strcmp(i->name, "channel") == 0) {
392                         /* Parse comma separated list */
393                         char *vals[MAX_VALS];
394                         size_t j;
395
396                         args.channel_parse = ast_strdup(i->value);
397                         if (!args.channel_parse) {
398                                 ast_ari_response_alloc_failed(response);
399                                 goto fin;
400                         }
401
402                         args.channel_count = ast_app_separate_args(
403                                 args.channel_parse, ',', vals, ARRAY_LEN(vals));
404                         if (args.channel_count == 0) {
405                                 ast_ari_response_alloc_failed(response);
406                                 goto fin;
407                         }
408
409                         if (args.channel_count >= MAX_VALS) {
410                                 ast_ari_response_error(response, 400,
411                                         "Bad Request",
412                                         "Too many values for channel");
413                                 goto fin;
414                         }
415
416                         args.channel = ast_malloc(sizeof(*args.channel) * args.channel_count);
417                         if (!args.channel) {
418                                 ast_ari_response_alloc_failed(response);
419                                 goto fin;
420                         }
421
422                         for (j = 0; j < args.channel_count; ++j) {
423                                 args.channel[j] = (vals[j]);
424                         }
425                 } else
426                 {}
427         }
428         for (i = path_vars; i; i = i->next) {
429                 if (strcmp(i->name, "bridgeId") == 0) {
430                         args.bridge_id = (i->value);
431                 } else
432                 {}
433         }
434         ast_ari_remove_channel_from_bridge(headers, &args, response);
435 #if defined(AST_DEVMODE)
436         code = response->response_code;
437
438         switch (code) {
439         case 0: /* Implementation is still a stub, or the code wasn't set */
440                 is_valid = response->message == NULL;
441                 break;
442         case 500: /* Internal Server Error */
443         case 501: /* Not Implemented */
444                 is_valid = 1;
445                 break;
446         default:
447                 if (200 <= code && code <= 299) {
448                         is_valid = ast_ari_validate_void(
449                                 response->message);
450                 } else {
451                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/removeChannel\n", code);
452                         is_valid = 0;
453                 }
454         }
455
456         if (!is_valid) {
457                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/removeChannel\n");
458                 ast_ari_response_error(response, 500,
459                         "Internal Server Error", "Response validation failed");
460         }
461 #endif /* AST_DEVMODE */
462
463 fin: __attribute__((unused))
464         ast_free(args.channel_parse);
465         ast_free(args.channel);
466         return;
467 }
468 /*!
469  * \brief Parameter parsing callback for /bridges/{bridgeId}/play.
470  * \param get_params GET parameters in the HTTP request.
471  * \param path_vars Path variables extracted from the request.
472  * \param headers HTTP headers.
473  * \param[out] response Response to the HTTP request.
474  */
475 static void ast_ari_play_on_bridge_cb(
476         struct ast_variable *get_params, struct ast_variable *path_vars,
477         struct ast_variable *headers, struct ast_ari_response *response)
478 {
479         struct ast_play_on_bridge_args args = {};
480         struct ast_variable *i;
481 #if defined(AST_DEVMODE)
482         int is_valid;
483         int code;
484 #endif /* AST_DEVMODE */
485
486         for (i = get_params; i; i = i->next) {
487                 if (strcmp(i->name, "media") == 0) {
488                         args.media = (i->value);
489                 } else
490                 if (strcmp(i->name, "lang") == 0) {
491                         args.lang = (i->value);
492                 } else
493                 if (strcmp(i->name, "offsetms") == 0) {
494                         args.offsetms = atoi(i->value);
495                 } else
496                 if (strcmp(i->name, "skipms") == 0) {
497                         args.skipms = atoi(i->value);
498                 } else
499                 {}
500         }
501         for (i = path_vars; i; i = i->next) {
502                 if (strcmp(i->name, "bridgeId") == 0) {
503                         args.bridge_id = (i->value);
504                 } else
505                 {}
506         }
507         ast_ari_play_on_bridge(headers, &args, response);
508 #if defined(AST_DEVMODE)
509         code = response->response_code;
510
511         switch (code) {
512         case 0: /* Implementation is still a stub, or the code wasn't set */
513                 is_valid = response->message == NULL;
514                 break;
515         case 500: /* Internal Server Error */
516         case 501: /* Not Implemented */
517         case 404: /* Bridge not found */
518         case 409: /* Bridge not in a Stasis application */
519                 is_valid = 1;
520                 break;
521         default:
522                 if (200 <= code && code <= 299) {
523                         is_valid = ast_ari_validate_playback(
524                                 response->message);
525                 } else {
526                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/play\n", code);
527                         is_valid = 0;
528                 }
529         }
530
531         if (!is_valid) {
532                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/play\n");
533                 ast_ari_response_error(response, 500,
534                         "Internal Server Error", "Response validation failed");
535         }
536 #endif /* AST_DEVMODE */
537
538 fin: __attribute__((unused))
539         return;
540 }
541 /*!
542  * \brief Parameter parsing callback for /bridges/{bridgeId}/record.
543  * \param get_params GET parameters in the HTTP request.
544  * \param path_vars Path variables extracted from the request.
545  * \param headers HTTP headers.
546  * \param[out] response Response to the HTTP request.
547  */
548 static void ast_ari_record_bridge_cb(
549         struct ast_variable *get_params, struct ast_variable *path_vars,
550         struct ast_variable *headers, struct ast_ari_response *response)
551 {
552         struct ast_record_bridge_args args = {};
553         struct ast_variable *i;
554 #if defined(AST_DEVMODE)
555         int is_valid;
556         int code;
557 #endif /* AST_DEVMODE */
558
559         for (i = get_params; i; i = i->next) {
560                 if (strcmp(i->name, "name") == 0) {
561                         args.name = (i->value);
562                 } else
563                 if (strcmp(i->name, "format") == 0) {
564                         args.format = (i->value);
565                 } else
566                 if (strcmp(i->name, "maxDurationSeconds") == 0) {
567                         args.max_duration_seconds = atoi(i->value);
568                 } else
569                 if (strcmp(i->name, "maxSilenceSeconds") == 0) {
570                         args.max_silence_seconds = atoi(i->value);
571                 } else
572                 if (strcmp(i->name, "ifExists") == 0) {
573                         args.if_exists = (i->value);
574                 } else
575                 if (strcmp(i->name, "beep") == 0) {
576                         args.beep = ast_true(i->value);
577                 } else
578                 if (strcmp(i->name, "terminateOn") == 0) {
579                         args.terminate_on = (i->value);
580                 } else
581                 {}
582         }
583         for (i = path_vars; i; i = i->next) {
584                 if (strcmp(i->name, "bridgeId") == 0) {
585                         args.bridge_id = (i->value);
586                 } else
587                 {}
588         }
589         ast_ari_record_bridge(headers, &args, response);
590 #if defined(AST_DEVMODE)
591         code = response->response_code;
592
593         switch (code) {
594         case 0: /* Implementation is still a stub, or the code wasn't set */
595                 is_valid = response->message == NULL;
596                 break;
597         case 500: /* Internal Server Error */
598         case 501: /* Not Implemented */
599                 is_valid = 1;
600                 break;
601         default:
602                 if (200 <= code && code <= 299) {
603                         is_valid = ast_ari_validate_live_recording(
604                                 response->message);
605                 } else {
606                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/record\n", code);
607                         is_valid = 0;
608                 }
609         }
610
611         if (!is_valid) {
612                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/record\n");
613                 ast_ari_response_error(response, 500,
614                         "Internal Server Error", "Response validation failed");
615         }
616 #endif /* AST_DEVMODE */
617
618 fin: __attribute__((unused))
619         return;
620 }
621
622 /*! \brief REST handler for /api-docs/bridges.{format} */
623 static struct stasis_rest_handlers bridges_bridgeId_addChannel = {
624         .path_segment = "addChannel",
625         .callbacks = {
626                 [AST_HTTP_POST] = ast_ari_add_channel_to_bridge_cb,
627         },
628         .num_children = 0,
629         .children = {  }
630 };
631 /*! \brief REST handler for /api-docs/bridges.{format} */
632 static struct stasis_rest_handlers bridges_bridgeId_removeChannel = {
633         .path_segment = "removeChannel",
634         .callbacks = {
635                 [AST_HTTP_POST] = ast_ari_remove_channel_from_bridge_cb,
636         },
637         .num_children = 0,
638         .children = {  }
639 };
640 /*! \brief REST handler for /api-docs/bridges.{format} */
641 static struct stasis_rest_handlers bridges_bridgeId_play = {
642         .path_segment = "play",
643         .callbacks = {
644                 [AST_HTTP_POST] = ast_ari_play_on_bridge_cb,
645         },
646         .num_children = 0,
647         .children = {  }
648 };
649 /*! \brief REST handler for /api-docs/bridges.{format} */
650 static struct stasis_rest_handlers bridges_bridgeId_record = {
651         .path_segment = "record",
652         .callbacks = {
653                 [AST_HTTP_POST] = ast_ari_record_bridge_cb,
654         },
655         .num_children = 0,
656         .children = {  }
657 };
658 /*! \brief REST handler for /api-docs/bridges.{format} */
659 static struct stasis_rest_handlers bridges_bridgeId = {
660         .path_segment = "bridgeId",
661         .is_wildcard = 1,
662         .callbacks = {
663                 [AST_HTTP_GET] = ast_ari_get_bridge_cb,
664                 [AST_HTTP_DELETE] = ast_ari_delete_bridge_cb,
665         },
666         .num_children = 4,
667         .children = { &bridges_bridgeId_addChannel,&bridges_bridgeId_removeChannel,&bridges_bridgeId_play,&bridges_bridgeId_record, }
668 };
669 /*! \brief REST handler for /api-docs/bridges.{format} */
670 static struct stasis_rest_handlers bridges = {
671         .path_segment = "bridges",
672         .callbacks = {
673                 [AST_HTTP_GET] = ast_ari_get_bridges_cb,
674                 [AST_HTTP_POST] = ast_ari_new_bridge_cb,
675         },
676         .num_children = 1,
677         .children = { &bridges_bridgeId, }
678 };
679
680 static int load_module(void)
681 {
682         int res = 0;
683         stasis_app_ref();
684         res |= ast_ari_add_handler(&bridges);
685         return res;
686 }
687
688 static int unload_module(void)
689 {
690         ast_ari_remove_handler(&bridges);
691         stasis_app_unref();
692         return 0;
693 }
694
695 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Bridge resources",
696         .load = load_module,
697         .unload = unload_module,
698         .nonoptreq = "res_ari,res_stasis",
699         );