1a91af95bc57cf5e114d425c0032cca55109004e
[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_bridges_list_cb(
62         struct ast_tcptls_session_instance *ser,
63         struct ast_variable *get_params, struct ast_variable *path_vars,
64         struct ast_variable *headers, struct ast_ari_response *response)
65 {
66         struct ast_ari_bridges_list_args args = {};
67         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
68 #if defined(AST_DEVMODE)
69         int is_valid;
70         int code;
71 #endif /* AST_DEVMODE */
72
73         ast_ari_bridges_list(headers, &args, response);
74 #if defined(AST_DEVMODE)
75         code = response->response_code;
76
77         switch (code) {
78         case 0: /* Implementation is still a stub, or the code wasn't set */
79                 is_valid = response->message == NULL;
80                 break;
81         case 500: /* Internal Server Error */
82         case 501: /* Not Implemented */
83                 is_valid = 1;
84                 break;
85         default:
86                 if (200 <= code && code <= 299) {
87                         is_valid = ast_ari_validate_list(response->message,
88                                 ast_ari_validate_bridge_fn());
89                 } else {
90                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges\n", code);
91                         is_valid = 0;
92                 }
93         }
94
95         if (!is_valid) {
96                 ast_log(LOG_ERROR, "Response validation failed for /bridges\n");
97                 ast_ari_response_error(response, 500,
98                         "Internal Server Error", "Response validation failed");
99         }
100 #endif /* AST_DEVMODE */
101
102 fin: __attribute__((unused))
103         return;
104 }
105 int ast_ari_bridges_create_parse_body(
106         struct ast_json *body,
107         struct ast_ari_bridges_create_args *args)
108 {
109         struct ast_json *field;
110         /* Parse query parameters out of it */
111         field = ast_json_object_get(body, "type");
112         if (field) {
113                 args->type = ast_json_string_get(field);
114         }
115         field = ast_json_object_get(body, "bridgeId");
116         if (field) {
117                 args->bridge_id = ast_json_string_get(field);
118         }
119         field = ast_json_object_get(body, "name");
120         if (field) {
121                 args->name = ast_json_string_get(field);
122         }
123         return 0;
124 }
125
126 /*!
127  * \brief Parameter parsing callback for /bridges.
128  * \param get_params GET parameters in the HTTP request.
129  * \param path_vars Path variables extracted from the request.
130  * \param headers HTTP headers.
131  * \param[out] response Response to the HTTP request.
132  */
133 static void ast_ari_bridges_create_cb(
134         struct ast_tcptls_session_instance *ser,
135         struct ast_variable *get_params, struct ast_variable *path_vars,
136         struct ast_variable *headers, struct ast_ari_response *response)
137 {
138         struct ast_ari_bridges_create_args args = {};
139         struct ast_variable *i;
140         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
141 #if defined(AST_DEVMODE)
142         int is_valid;
143         int code;
144 #endif /* AST_DEVMODE */
145
146         for (i = get_params; i; i = i->next) {
147                 if (strcmp(i->name, "type") == 0) {
148                         args.type = (i->value);
149                 } else
150                 if (strcmp(i->name, "bridgeId") == 0) {
151                         args.bridge_id = (i->value);
152                 } else
153                 if (strcmp(i->name, "name") == 0) {
154                         args.name = (i->value);
155                 } else
156                 {}
157         }
158         /* Look for a JSON request entity */
159         body = ast_http_get_json(ser, headers);
160         if (!body) {
161                 switch (errno) {
162                 case EFBIG:
163                         ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
164                         goto fin;
165                 case ENOMEM:
166                         ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
167                         goto fin;
168                 case EIO:
169                         ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
170                         goto fin;
171                 }
172         }
173         if (ast_ari_bridges_create_parse_body(body, &args)) {
174                 ast_ari_response_alloc_failed(response);
175                 goto fin;
176         }
177         ast_ari_bridges_create(headers, &args, response);
178 #if defined(AST_DEVMODE)
179         code = response->response_code;
180
181         switch (code) {
182         case 0: /* Implementation is still a stub, or the code wasn't set */
183                 is_valid = response->message == NULL;
184                 break;
185         case 500: /* Internal Server Error */
186         case 501: /* Not Implemented */
187                 is_valid = 1;
188                 break;
189         default:
190                 if (200 <= code && code <= 299) {
191                         is_valid = ast_ari_validate_bridge(
192                                 response->message);
193                 } else {
194                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges\n", code);
195                         is_valid = 0;
196                 }
197         }
198
199         if (!is_valid) {
200                 ast_log(LOG_ERROR, "Response validation failed for /bridges\n");
201                 ast_ari_response_error(response, 500,
202                         "Internal Server Error", "Response validation failed");
203         }
204 #endif /* AST_DEVMODE */
205
206 fin: __attribute__((unused))
207         return;
208 }
209 int ast_ari_bridges_create_or_update_with_id_parse_body(
210         struct ast_json *body,
211         struct ast_ari_bridges_create_or_update_with_id_args *args)
212 {
213         struct ast_json *field;
214         /* Parse query parameters out of it */
215         field = ast_json_object_get(body, "type");
216         if (field) {
217                 args->type = ast_json_string_get(field);
218         }
219         field = ast_json_object_get(body, "name");
220         if (field) {
221                 args->name = ast_json_string_get(field);
222         }
223         return 0;
224 }
225
226 /*!
227  * \brief Parameter parsing callback for /bridges/{bridgeId}.
228  * \param get_params GET parameters in the HTTP request.
229  * \param path_vars Path variables extracted from the request.
230  * \param headers HTTP headers.
231  * \param[out] response Response to the HTTP request.
232  */
233 static void ast_ari_bridges_create_or_update_with_id_cb(
234         struct ast_tcptls_session_instance *ser,
235         struct ast_variable *get_params, struct ast_variable *path_vars,
236         struct ast_variable *headers, struct ast_ari_response *response)
237 {
238         struct ast_ari_bridges_create_or_update_with_id_args args = {};
239         struct ast_variable *i;
240         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
241 #if defined(AST_DEVMODE)
242         int is_valid;
243         int code;
244 #endif /* AST_DEVMODE */
245
246         for (i = get_params; i; i = i->next) {
247                 if (strcmp(i->name, "type") == 0) {
248                         args.type = (i->value);
249                 } else
250                 if (strcmp(i->name, "name") == 0) {
251                         args.name = (i->value);
252                 } else
253                 {}
254         }
255         for (i = path_vars; i; i = i->next) {
256                 if (strcmp(i->name, "bridgeId") == 0) {
257                         args.bridge_id = (i->value);
258                 } else
259                 {}
260         }
261         /* Look for a JSON request entity */
262         body = ast_http_get_json(ser, headers);
263         if (!body) {
264                 switch (errno) {
265                 case EFBIG:
266                         ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
267                         goto fin;
268                 case ENOMEM:
269                         ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
270                         goto fin;
271                 case EIO:
272                         ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
273                         goto fin;
274                 }
275         }
276         if (ast_ari_bridges_create_or_update_with_id_parse_body(body, &args)) {
277                 ast_ari_response_alloc_failed(response);
278                 goto fin;
279         }
280         ast_ari_bridges_create_or_update_with_id(headers, &args, response);
281 #if defined(AST_DEVMODE)
282         code = response->response_code;
283
284         switch (code) {
285         case 0: /* Implementation is still a stub, or the code wasn't set */
286                 is_valid = response->message == NULL;
287                 break;
288         case 500: /* Internal Server Error */
289         case 501: /* Not Implemented */
290                 is_valid = 1;
291                 break;
292         default:
293                 if (200 <= code && code <= 299) {
294                         is_valid = ast_ari_validate_bridge(
295                                 response->message);
296                 } else {
297                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}\n", code);
298                         is_valid = 0;
299                 }
300         }
301
302         if (!is_valid) {
303                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}\n");
304                 ast_ari_response_error(response, 500,
305                         "Internal Server Error", "Response validation failed");
306         }
307 #endif /* AST_DEVMODE */
308
309 fin: __attribute__((unused))
310         return;
311 }
312 /*!
313  * \brief Parameter parsing callback for /bridges/{bridgeId}.
314  * \param get_params GET parameters in the HTTP request.
315  * \param path_vars Path variables extracted from the request.
316  * \param headers HTTP headers.
317  * \param[out] response Response to the HTTP request.
318  */
319 static void ast_ari_bridges_get_cb(
320         struct ast_tcptls_session_instance *ser,
321         struct ast_variable *get_params, struct ast_variable *path_vars,
322         struct ast_variable *headers, struct ast_ari_response *response)
323 {
324         struct ast_ari_bridges_get_args args = {};
325         struct ast_variable *i;
326         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
327 #if defined(AST_DEVMODE)
328         int is_valid;
329         int code;
330 #endif /* AST_DEVMODE */
331
332         for (i = path_vars; i; i = i->next) {
333                 if (strcmp(i->name, "bridgeId") == 0) {
334                         args.bridge_id = (i->value);
335                 } else
336                 {}
337         }
338         ast_ari_bridges_get(headers, &args, response);
339 #if defined(AST_DEVMODE)
340         code = response->response_code;
341
342         switch (code) {
343         case 0: /* Implementation is still a stub, or the code wasn't set */
344                 is_valid = response->message == NULL;
345                 break;
346         case 500: /* Internal Server Error */
347         case 501: /* Not Implemented */
348         case 404: /* Bridge not found */
349                 is_valid = 1;
350                 break;
351         default:
352                 if (200 <= code && code <= 299) {
353                         is_valid = ast_ari_validate_bridge(
354                                 response->message);
355                 } else {
356                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}\n", code);
357                         is_valid = 0;
358                 }
359         }
360
361         if (!is_valid) {
362                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}\n");
363                 ast_ari_response_error(response, 500,
364                         "Internal Server Error", "Response validation failed");
365         }
366 #endif /* AST_DEVMODE */
367
368 fin: __attribute__((unused))
369         return;
370 }
371 /*!
372  * \brief Parameter parsing callback for /bridges/{bridgeId}.
373  * \param get_params GET parameters in the HTTP request.
374  * \param path_vars Path variables extracted from the request.
375  * \param headers HTTP headers.
376  * \param[out] response Response to the HTTP request.
377  */
378 static void ast_ari_bridges_destroy_cb(
379         struct ast_tcptls_session_instance *ser,
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_ari_bridges_destroy_args args = {};
384         struct ast_variable *i;
385         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
386 #if defined(AST_DEVMODE)
387         int is_valid;
388         int code;
389 #endif /* AST_DEVMODE */
390
391         for (i = path_vars; i; i = i->next) {
392                 if (strcmp(i->name, "bridgeId") == 0) {
393                         args.bridge_id = (i->value);
394                 } else
395                 {}
396         }
397         ast_ari_bridges_destroy(headers, &args, response);
398 #if defined(AST_DEVMODE)
399         code = response->response_code;
400
401         switch (code) {
402         case 0: /* Implementation is still a stub, or the code wasn't set */
403                 is_valid = response->message == NULL;
404                 break;
405         case 500: /* Internal Server Error */
406         case 501: /* Not Implemented */
407         case 404: /* Bridge not found */
408                 is_valid = 1;
409                 break;
410         default:
411                 if (200 <= code && code <= 299) {
412                         is_valid = ast_ari_validate_void(
413                                 response->message);
414                 } else {
415                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}\n", code);
416                         is_valid = 0;
417                 }
418         }
419
420         if (!is_valid) {
421                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}\n");
422                 ast_ari_response_error(response, 500,
423                         "Internal Server Error", "Response validation failed");
424         }
425 #endif /* AST_DEVMODE */
426
427 fin: __attribute__((unused))
428         return;
429 }
430 int ast_ari_bridges_add_channel_parse_body(
431         struct ast_json *body,
432         struct ast_ari_bridges_add_channel_args *args)
433 {
434         struct ast_json *field;
435         /* Parse query parameters out of it */
436         field = ast_json_object_get(body, "channel");
437         if (field) {
438                 /* If they were silly enough to both pass in a query param and a
439                  * JSON body, free up the query value.
440                  */
441                 ast_free(args->channel);
442                 if (ast_json_typeof(field) == AST_JSON_ARRAY) {
443                         /* Multiple param passed as array */
444                         size_t i;
445                         args->channel_count = ast_json_array_size(field);
446                         args->channel = ast_malloc(sizeof(*args->channel) * args->channel_count);
447
448                         if (!args->channel) {
449                                 return -1;
450                         }
451
452                         for (i = 0; i < args->channel_count; ++i) {
453                                 args->channel[i] = ast_json_string_get(ast_json_array_get(field, i));
454                         }
455                 } else {
456                         /* Multiple param passed as single value */
457                         args->channel_count = 1;
458                         args->channel = ast_malloc(sizeof(*args->channel) * args->channel_count);
459                         if (!args->channel) {
460                                 return -1;
461                         }
462                         args->channel[0] = ast_json_string_get(field);
463                 }
464         }
465         field = ast_json_object_get(body, "role");
466         if (field) {
467                 args->role = ast_json_string_get(field);
468         }
469         return 0;
470 }
471
472 /*!
473  * \brief Parameter parsing callback for /bridges/{bridgeId}/addChannel.
474  * \param get_params GET parameters in the HTTP request.
475  * \param path_vars Path variables extracted from the request.
476  * \param headers HTTP headers.
477  * \param[out] response Response to the HTTP request.
478  */
479 static void ast_ari_bridges_add_channel_cb(
480         struct ast_tcptls_session_instance *ser,
481         struct ast_variable *get_params, struct ast_variable *path_vars,
482         struct ast_variable *headers, struct ast_ari_response *response)
483 {
484         struct ast_ari_bridges_add_channel_args args = {};
485         struct ast_variable *i;
486         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
487 #if defined(AST_DEVMODE)
488         int is_valid;
489         int code;
490 #endif /* AST_DEVMODE */
491
492         for (i = get_params; i; i = i->next) {
493                 if (strcmp(i->name, "channel") == 0) {
494                         /* Parse comma separated list */
495                         char *vals[MAX_VALS];
496                         size_t j;
497
498                         args.channel_parse = ast_strdup(i->value);
499                         if (!args.channel_parse) {
500                                 ast_ari_response_alloc_failed(response);
501                                 goto fin;
502                         }
503
504                         if (strlen(args.channel_parse) == 0) {
505                                 /* ast_app_separate_args can't handle "" */
506                                 args.channel_count = 1;
507                                 vals[0] = args.channel_parse;
508                         } else {
509                                 args.channel_count = ast_app_separate_args(
510                                         args.channel_parse, ',', vals,
511                                         ARRAY_LEN(vals));
512                         }
513
514                         if (args.channel_count == 0) {
515                                 ast_ari_response_alloc_failed(response);
516                                 goto fin;
517                         }
518
519                         if (args.channel_count >= MAX_VALS) {
520                                 ast_ari_response_error(response, 400,
521                                         "Bad Request",
522                                         "Too many values for channel");
523                                 goto fin;
524                         }
525
526                         args.channel = ast_malloc(sizeof(*args.channel) * args.channel_count);
527                         if (!args.channel) {
528                                 ast_ari_response_alloc_failed(response);
529                                 goto fin;
530                         }
531
532                         for (j = 0; j < args.channel_count; ++j) {
533                                 args.channel[j] = (vals[j]);
534                         }
535                 } else
536                 if (strcmp(i->name, "role") == 0) {
537                         args.role = (i->value);
538                 } else
539                 {}
540         }
541         for (i = path_vars; i; i = i->next) {
542                 if (strcmp(i->name, "bridgeId") == 0) {
543                         args.bridge_id = (i->value);
544                 } else
545                 {}
546         }
547         /* Look for a JSON request entity */
548         body = ast_http_get_json(ser, headers);
549         if (!body) {
550                 switch (errno) {
551                 case EFBIG:
552                         ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
553                         goto fin;
554                 case ENOMEM:
555                         ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
556                         goto fin;
557                 case EIO:
558                         ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
559                         goto fin;
560                 }
561         }
562         if (ast_ari_bridges_add_channel_parse_body(body, &args)) {
563                 ast_ari_response_alloc_failed(response);
564                 goto fin;
565         }
566         ast_ari_bridges_add_channel(headers, &args, response);
567 #if defined(AST_DEVMODE)
568         code = response->response_code;
569
570         switch (code) {
571         case 0: /* Implementation is still a stub, or the code wasn't set */
572                 is_valid = response->message == NULL;
573                 break;
574         case 500: /* Internal Server Error */
575         case 501: /* Not Implemented */
576         case 400: /* Channel not found */
577         case 404: /* Bridge not found */
578         case 409: /* Bridge not in Stasis application; Channel currently recording */
579         case 422: /* Channel not in Stasis application */
580                 is_valid = 1;
581                 break;
582         default:
583                 if (200 <= code && code <= 299) {
584                         is_valid = ast_ari_validate_void(
585                                 response->message);
586                 } else {
587                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/addChannel\n", code);
588                         is_valid = 0;
589                 }
590         }
591
592         if (!is_valid) {
593                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/addChannel\n");
594                 ast_ari_response_error(response, 500,
595                         "Internal Server Error", "Response validation failed");
596         }
597 #endif /* AST_DEVMODE */
598
599 fin: __attribute__((unused))
600         ast_free(args.channel_parse);
601         ast_free(args.channel);
602         return;
603 }
604 int ast_ari_bridges_remove_channel_parse_body(
605         struct ast_json *body,
606         struct ast_ari_bridges_remove_channel_args *args)
607 {
608         struct ast_json *field;
609         /* Parse query parameters out of it */
610         field = ast_json_object_get(body, "channel");
611         if (field) {
612                 /* If they were silly enough to both pass in a query param and a
613                  * JSON body, free up the query value.
614                  */
615                 ast_free(args->channel);
616                 if (ast_json_typeof(field) == AST_JSON_ARRAY) {
617                         /* Multiple param passed as array */
618                         size_t i;
619                         args->channel_count = ast_json_array_size(field);
620                         args->channel = ast_malloc(sizeof(*args->channel) * args->channel_count);
621
622                         if (!args->channel) {
623                                 return -1;
624                         }
625
626                         for (i = 0; i < args->channel_count; ++i) {
627                                 args->channel[i] = ast_json_string_get(ast_json_array_get(field, i));
628                         }
629                 } else {
630                         /* Multiple param passed as single value */
631                         args->channel_count = 1;
632                         args->channel = ast_malloc(sizeof(*args->channel) * args->channel_count);
633                         if (!args->channel) {
634                                 return -1;
635                         }
636                         args->channel[0] = ast_json_string_get(field);
637                 }
638         }
639         return 0;
640 }
641
642 /*!
643  * \brief Parameter parsing callback for /bridges/{bridgeId}/removeChannel.
644  * \param get_params GET parameters in the HTTP request.
645  * \param path_vars Path variables extracted from the request.
646  * \param headers HTTP headers.
647  * \param[out] response Response to the HTTP request.
648  */
649 static void ast_ari_bridges_remove_channel_cb(
650         struct ast_tcptls_session_instance *ser,
651         struct ast_variable *get_params, struct ast_variable *path_vars,
652         struct ast_variable *headers, struct ast_ari_response *response)
653 {
654         struct ast_ari_bridges_remove_channel_args args = {};
655         struct ast_variable *i;
656         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
657 #if defined(AST_DEVMODE)
658         int is_valid;
659         int code;
660 #endif /* AST_DEVMODE */
661
662         for (i = get_params; i; i = i->next) {
663                 if (strcmp(i->name, "channel") == 0) {
664                         /* Parse comma separated list */
665                         char *vals[MAX_VALS];
666                         size_t j;
667
668                         args.channel_parse = ast_strdup(i->value);
669                         if (!args.channel_parse) {
670                                 ast_ari_response_alloc_failed(response);
671                                 goto fin;
672                         }
673
674                         if (strlen(args.channel_parse) == 0) {
675                                 /* ast_app_separate_args can't handle "" */
676                                 args.channel_count = 1;
677                                 vals[0] = args.channel_parse;
678                         } else {
679                                 args.channel_count = ast_app_separate_args(
680                                         args.channel_parse, ',', vals,
681                                         ARRAY_LEN(vals));
682                         }
683
684                         if (args.channel_count == 0) {
685                                 ast_ari_response_alloc_failed(response);
686                                 goto fin;
687                         }
688
689                         if (args.channel_count >= MAX_VALS) {
690                                 ast_ari_response_error(response, 400,
691                                         "Bad Request",
692                                         "Too many values for channel");
693                                 goto fin;
694                         }
695
696                         args.channel = ast_malloc(sizeof(*args.channel) * args.channel_count);
697                         if (!args.channel) {
698                                 ast_ari_response_alloc_failed(response);
699                                 goto fin;
700                         }
701
702                         for (j = 0; j < args.channel_count; ++j) {
703                                 args.channel[j] = (vals[j]);
704                         }
705                 } else
706                 {}
707         }
708         for (i = path_vars; i; i = i->next) {
709                 if (strcmp(i->name, "bridgeId") == 0) {
710                         args.bridge_id = (i->value);
711                 } else
712                 {}
713         }
714         /* Look for a JSON request entity */
715         body = ast_http_get_json(ser, headers);
716         if (!body) {
717                 switch (errno) {
718                 case EFBIG:
719                         ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
720                         goto fin;
721                 case ENOMEM:
722                         ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
723                         goto fin;
724                 case EIO:
725                         ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
726                         goto fin;
727                 }
728         }
729         if (ast_ari_bridges_remove_channel_parse_body(body, &args)) {
730                 ast_ari_response_alloc_failed(response);
731                 goto fin;
732         }
733         ast_ari_bridges_remove_channel(headers, &args, response);
734 #if defined(AST_DEVMODE)
735         code = response->response_code;
736
737         switch (code) {
738         case 0: /* Implementation is still a stub, or the code wasn't set */
739                 is_valid = response->message == NULL;
740                 break;
741         case 500: /* Internal Server Error */
742         case 501: /* Not Implemented */
743         case 400: /* Channel not found */
744         case 404: /* Bridge not found */
745         case 409: /* Bridge not in Stasis application */
746         case 422: /* Channel not in this bridge */
747                 is_valid = 1;
748                 break;
749         default:
750                 if (200 <= code && code <= 299) {
751                         is_valid = ast_ari_validate_void(
752                                 response->message);
753                 } else {
754                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/removeChannel\n", code);
755                         is_valid = 0;
756                 }
757         }
758
759         if (!is_valid) {
760                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/removeChannel\n");
761                 ast_ari_response_error(response, 500,
762                         "Internal Server Error", "Response validation failed");
763         }
764 #endif /* AST_DEVMODE */
765
766 fin: __attribute__((unused))
767         ast_free(args.channel_parse);
768         ast_free(args.channel);
769         return;
770 }
771 int ast_ari_bridges_start_moh_parse_body(
772         struct ast_json *body,
773         struct ast_ari_bridges_start_moh_args *args)
774 {
775         struct ast_json *field;
776         /* Parse query parameters out of it */
777         field = ast_json_object_get(body, "mohClass");
778         if (field) {
779                 args->moh_class = ast_json_string_get(field);
780         }
781         return 0;
782 }
783
784 /*!
785  * \brief Parameter parsing callback for /bridges/{bridgeId}/moh.
786  * \param get_params GET parameters in the HTTP request.
787  * \param path_vars Path variables extracted from the request.
788  * \param headers HTTP headers.
789  * \param[out] response Response to the HTTP request.
790  */
791 static void ast_ari_bridges_start_moh_cb(
792         struct ast_tcptls_session_instance *ser,
793         struct ast_variable *get_params, struct ast_variable *path_vars,
794         struct ast_variable *headers, struct ast_ari_response *response)
795 {
796         struct ast_ari_bridges_start_moh_args args = {};
797         struct ast_variable *i;
798         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
799 #if defined(AST_DEVMODE)
800         int is_valid;
801         int code;
802 #endif /* AST_DEVMODE */
803
804         for (i = get_params; i; i = i->next) {
805                 if (strcmp(i->name, "mohClass") == 0) {
806                         args.moh_class = (i->value);
807                 } else
808                 {}
809         }
810         for (i = path_vars; i; i = i->next) {
811                 if (strcmp(i->name, "bridgeId") == 0) {
812                         args.bridge_id = (i->value);
813                 } else
814                 {}
815         }
816         /* Look for a JSON request entity */
817         body = ast_http_get_json(ser, headers);
818         if (!body) {
819                 switch (errno) {
820                 case EFBIG:
821                         ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
822                         goto fin;
823                 case ENOMEM:
824                         ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
825                         goto fin;
826                 case EIO:
827                         ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
828                         goto fin;
829                 }
830         }
831         if (ast_ari_bridges_start_moh_parse_body(body, &args)) {
832                 ast_ari_response_alloc_failed(response);
833                 goto fin;
834         }
835         ast_ari_bridges_start_moh(headers, &args, response);
836 #if defined(AST_DEVMODE)
837         code = response->response_code;
838
839         switch (code) {
840         case 0: /* Implementation is still a stub, or the code wasn't set */
841                 is_valid = response->message == NULL;
842                 break;
843         case 500: /* Internal Server Error */
844         case 501: /* Not Implemented */
845         case 404: /* Bridge not found */
846         case 409: /* Bridge not in Stasis application */
847                 is_valid = 1;
848                 break;
849         default:
850                 if (200 <= code && code <= 299) {
851                         is_valid = ast_ari_validate_void(
852                                 response->message);
853                 } else {
854                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/moh\n", code);
855                         is_valid = 0;
856                 }
857         }
858
859         if (!is_valid) {
860                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/moh\n");
861                 ast_ari_response_error(response, 500,
862                         "Internal Server Error", "Response validation failed");
863         }
864 #endif /* AST_DEVMODE */
865
866 fin: __attribute__((unused))
867         return;
868 }
869 /*!
870  * \brief Parameter parsing callback for /bridges/{bridgeId}/moh.
871  * \param get_params GET parameters in the HTTP request.
872  * \param path_vars Path variables extracted from the request.
873  * \param headers HTTP headers.
874  * \param[out] response Response to the HTTP request.
875  */
876 static void ast_ari_bridges_stop_moh_cb(
877         struct ast_tcptls_session_instance *ser,
878         struct ast_variable *get_params, struct ast_variable *path_vars,
879         struct ast_variable *headers, struct ast_ari_response *response)
880 {
881         struct ast_ari_bridges_stop_moh_args args = {};
882         struct ast_variable *i;
883         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
884 #if defined(AST_DEVMODE)
885         int is_valid;
886         int code;
887 #endif /* AST_DEVMODE */
888
889         for (i = path_vars; i; i = i->next) {
890                 if (strcmp(i->name, "bridgeId") == 0) {
891                         args.bridge_id = (i->value);
892                 } else
893                 {}
894         }
895         ast_ari_bridges_stop_moh(headers, &args, response);
896 #if defined(AST_DEVMODE)
897         code = response->response_code;
898
899         switch (code) {
900         case 0: /* Implementation is still a stub, or the code wasn't set */
901                 is_valid = response->message == NULL;
902                 break;
903         case 500: /* Internal Server Error */
904         case 501: /* Not Implemented */
905         case 404: /* Bridge not found */
906         case 409: /* Bridge not in Stasis application */
907                 is_valid = 1;
908                 break;
909         default:
910                 if (200 <= code && code <= 299) {
911                         is_valid = ast_ari_validate_void(
912                                 response->message);
913                 } else {
914                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/moh\n", code);
915                         is_valid = 0;
916                 }
917         }
918
919         if (!is_valid) {
920                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/moh\n");
921                 ast_ari_response_error(response, 500,
922                         "Internal Server Error", "Response validation failed");
923         }
924 #endif /* AST_DEVMODE */
925
926 fin: __attribute__((unused))
927         return;
928 }
929 int ast_ari_bridges_play_parse_body(
930         struct ast_json *body,
931         struct ast_ari_bridges_play_args *args)
932 {
933         struct ast_json *field;
934         /* Parse query parameters out of it */
935         field = ast_json_object_get(body, "media");
936         if (field) {
937                 args->media = ast_json_string_get(field);
938         }
939         field = ast_json_object_get(body, "lang");
940         if (field) {
941                 args->lang = ast_json_string_get(field);
942         }
943         field = ast_json_object_get(body, "offsetms");
944         if (field) {
945                 args->offsetms = ast_json_integer_get(field);
946         }
947         field = ast_json_object_get(body, "skipms");
948         if (field) {
949                 args->skipms = ast_json_integer_get(field);
950         }
951         field = ast_json_object_get(body, "playbackId");
952         if (field) {
953                 args->playback_id = ast_json_string_get(field);
954         }
955         return 0;
956 }
957
958 /*!
959  * \brief Parameter parsing callback for /bridges/{bridgeId}/play.
960  * \param get_params GET parameters in the HTTP request.
961  * \param path_vars Path variables extracted from the request.
962  * \param headers HTTP headers.
963  * \param[out] response Response to the HTTP request.
964  */
965 static void ast_ari_bridges_play_cb(
966         struct ast_tcptls_session_instance *ser,
967         struct ast_variable *get_params, struct ast_variable *path_vars,
968         struct ast_variable *headers, struct ast_ari_response *response)
969 {
970         struct ast_ari_bridges_play_args args = {};
971         struct ast_variable *i;
972         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
973 #if defined(AST_DEVMODE)
974         int is_valid;
975         int code;
976 #endif /* AST_DEVMODE */
977
978         for (i = get_params; i; i = i->next) {
979                 if (strcmp(i->name, "media") == 0) {
980                         args.media = (i->value);
981                 } else
982                 if (strcmp(i->name, "lang") == 0) {
983                         args.lang = (i->value);
984                 } else
985                 if (strcmp(i->name, "offsetms") == 0) {
986                         args.offsetms = atoi(i->value);
987                 } else
988                 if (strcmp(i->name, "skipms") == 0) {
989                         args.skipms = atoi(i->value);
990                 } else
991                 if (strcmp(i->name, "playbackId") == 0) {
992                         args.playback_id = (i->value);
993                 } else
994                 {}
995         }
996         for (i = path_vars; i; i = i->next) {
997                 if (strcmp(i->name, "bridgeId") == 0) {
998                         args.bridge_id = (i->value);
999                 } else
1000                 {}
1001         }
1002         /* Look for a JSON request entity */
1003         body = ast_http_get_json(ser, headers);
1004         if (!body) {
1005                 switch (errno) {
1006                 case EFBIG:
1007                         ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
1008                         goto fin;
1009                 case ENOMEM:
1010                         ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
1011                         goto fin;
1012                 case EIO:
1013                         ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
1014                         goto fin;
1015                 }
1016         }
1017         if (ast_ari_bridges_play_parse_body(body, &args)) {
1018                 ast_ari_response_alloc_failed(response);
1019                 goto fin;
1020         }
1021         ast_ari_bridges_play(headers, &args, response);
1022 #if defined(AST_DEVMODE)
1023         code = response->response_code;
1024
1025         switch (code) {
1026         case 0: /* Implementation is still a stub, or the code wasn't set */
1027                 is_valid = response->message == NULL;
1028                 break;
1029         case 500: /* Internal Server Error */
1030         case 501: /* Not Implemented */
1031         case 404: /* Bridge not found */
1032         case 409: /* Bridge not in a Stasis application */
1033                 is_valid = 1;
1034                 break;
1035         default:
1036                 if (200 <= code && code <= 299) {
1037                         is_valid = ast_ari_validate_playback(
1038                                 response->message);
1039                 } else {
1040                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/play\n", code);
1041                         is_valid = 0;
1042                 }
1043         }
1044
1045         if (!is_valid) {
1046                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/play\n");
1047                 ast_ari_response_error(response, 500,
1048                         "Internal Server Error", "Response validation failed");
1049         }
1050 #endif /* AST_DEVMODE */
1051
1052 fin: __attribute__((unused))
1053         return;
1054 }
1055 int ast_ari_bridges_play_with_id_parse_body(
1056         struct ast_json *body,
1057         struct ast_ari_bridges_play_with_id_args *args)
1058 {
1059         struct ast_json *field;
1060         /* Parse query parameters out of it */
1061         field = ast_json_object_get(body, "media");
1062         if (field) {
1063                 args->media = ast_json_string_get(field);
1064         }
1065         field = ast_json_object_get(body, "lang");
1066         if (field) {
1067                 args->lang = ast_json_string_get(field);
1068         }
1069         field = ast_json_object_get(body, "offsetms");
1070         if (field) {
1071                 args->offsetms = ast_json_integer_get(field);
1072         }
1073         field = ast_json_object_get(body, "skipms");
1074         if (field) {
1075                 args->skipms = ast_json_integer_get(field);
1076         }
1077         return 0;
1078 }
1079
1080 /*!
1081  * \brief Parameter parsing callback for /bridges/{bridgeId}/play/{playbackId}.
1082  * \param get_params GET parameters in the HTTP request.
1083  * \param path_vars Path variables extracted from the request.
1084  * \param headers HTTP headers.
1085  * \param[out] response Response to the HTTP request.
1086  */
1087 static void ast_ari_bridges_play_with_id_cb(
1088         struct ast_tcptls_session_instance *ser,
1089         struct ast_variable *get_params, struct ast_variable *path_vars,
1090         struct ast_variable *headers, struct ast_ari_response *response)
1091 {
1092         struct ast_ari_bridges_play_with_id_args args = {};
1093         struct ast_variable *i;
1094         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
1095 #if defined(AST_DEVMODE)
1096         int is_valid;
1097         int code;
1098 #endif /* AST_DEVMODE */
1099
1100         for (i = get_params; i; i = i->next) {
1101                 if (strcmp(i->name, "media") == 0) {
1102                         args.media = (i->value);
1103                 } else
1104                 if (strcmp(i->name, "lang") == 0) {
1105                         args.lang = (i->value);
1106                 } else
1107                 if (strcmp(i->name, "offsetms") == 0) {
1108                         args.offsetms = atoi(i->value);
1109                 } else
1110                 if (strcmp(i->name, "skipms") == 0) {
1111                         args.skipms = atoi(i->value);
1112                 } else
1113                 {}
1114         }
1115         for (i = path_vars; i; i = i->next) {
1116                 if (strcmp(i->name, "bridgeId") == 0) {
1117                         args.bridge_id = (i->value);
1118                 } else
1119                 if (strcmp(i->name, "playbackId") == 0) {
1120                         args.playback_id = (i->value);
1121                 } else
1122                 {}
1123         }
1124         /* Look for a JSON request entity */
1125         body = ast_http_get_json(ser, headers);
1126         if (!body) {
1127                 switch (errno) {
1128                 case EFBIG:
1129                         ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
1130                         goto fin;
1131                 case ENOMEM:
1132                         ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
1133                         goto fin;
1134                 case EIO:
1135                         ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
1136                         goto fin;
1137                 }
1138         }
1139         if (ast_ari_bridges_play_with_id_parse_body(body, &args)) {
1140                 ast_ari_response_alloc_failed(response);
1141                 goto fin;
1142         }
1143         ast_ari_bridges_play_with_id(headers, &args, response);
1144 #if defined(AST_DEVMODE)
1145         code = response->response_code;
1146
1147         switch (code) {
1148         case 0: /* Implementation is still a stub, or the code wasn't set */
1149                 is_valid = response->message == NULL;
1150                 break;
1151         case 500: /* Internal Server Error */
1152         case 501: /* Not Implemented */
1153         case 404: /* Bridge not found */
1154         case 409: /* Bridge not in a Stasis application */
1155                 is_valid = 1;
1156                 break;
1157         default:
1158                 if (200 <= code && code <= 299) {
1159                         is_valid = ast_ari_validate_playback(
1160                                 response->message);
1161                 } else {
1162                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/play/{playbackId}\n", code);
1163                         is_valid = 0;
1164                 }
1165         }
1166
1167         if (!is_valid) {
1168                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/play/{playbackId}\n");
1169                 ast_ari_response_error(response, 500,
1170                         "Internal Server Error", "Response validation failed");
1171         }
1172 #endif /* AST_DEVMODE */
1173
1174 fin: __attribute__((unused))
1175         return;
1176 }
1177 int ast_ari_bridges_record_parse_body(
1178         struct ast_json *body,
1179         struct ast_ari_bridges_record_args *args)
1180 {
1181         struct ast_json *field;
1182         /* Parse query parameters out of it */
1183         field = ast_json_object_get(body, "name");
1184         if (field) {
1185                 args->name = ast_json_string_get(field);
1186         }
1187         field = ast_json_object_get(body, "format");
1188         if (field) {
1189                 args->format = ast_json_string_get(field);
1190         }
1191         field = ast_json_object_get(body, "maxDurationSeconds");
1192         if (field) {
1193                 args->max_duration_seconds = ast_json_integer_get(field);
1194         }
1195         field = ast_json_object_get(body, "maxSilenceSeconds");
1196         if (field) {
1197                 args->max_silence_seconds = ast_json_integer_get(field);
1198         }
1199         field = ast_json_object_get(body, "ifExists");
1200         if (field) {
1201                 args->if_exists = ast_json_string_get(field);
1202         }
1203         field = ast_json_object_get(body, "beep");
1204         if (field) {
1205                 args->beep = ast_json_is_true(field);
1206         }
1207         field = ast_json_object_get(body, "terminateOn");
1208         if (field) {
1209                 args->terminate_on = ast_json_string_get(field);
1210         }
1211         return 0;
1212 }
1213
1214 /*!
1215  * \brief Parameter parsing callback for /bridges/{bridgeId}/record.
1216  * \param get_params GET parameters in the HTTP request.
1217  * \param path_vars Path variables extracted from the request.
1218  * \param headers HTTP headers.
1219  * \param[out] response Response to the HTTP request.
1220  */
1221 static void ast_ari_bridges_record_cb(
1222         struct ast_tcptls_session_instance *ser,
1223         struct ast_variable *get_params, struct ast_variable *path_vars,
1224         struct ast_variable *headers, struct ast_ari_response *response)
1225 {
1226         struct ast_ari_bridges_record_args args = {};
1227         struct ast_variable *i;
1228         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
1229 #if defined(AST_DEVMODE)
1230         int is_valid;
1231         int code;
1232 #endif /* AST_DEVMODE */
1233
1234         for (i = get_params; i; i = i->next) {
1235                 if (strcmp(i->name, "name") == 0) {
1236                         args.name = (i->value);
1237                 } else
1238                 if (strcmp(i->name, "format") == 0) {
1239                         args.format = (i->value);
1240                 } else
1241                 if (strcmp(i->name, "maxDurationSeconds") == 0) {
1242                         args.max_duration_seconds = atoi(i->value);
1243                 } else
1244                 if (strcmp(i->name, "maxSilenceSeconds") == 0) {
1245                         args.max_silence_seconds = atoi(i->value);
1246                 } else
1247                 if (strcmp(i->name, "ifExists") == 0) {
1248                         args.if_exists = (i->value);
1249                 } else
1250                 if (strcmp(i->name, "beep") == 0) {
1251                         args.beep = ast_true(i->value);
1252                 } else
1253                 if (strcmp(i->name, "terminateOn") == 0) {
1254                         args.terminate_on = (i->value);
1255                 } else
1256                 {}
1257         }
1258         for (i = path_vars; i; i = i->next) {
1259                 if (strcmp(i->name, "bridgeId") == 0) {
1260                         args.bridge_id = (i->value);
1261                 } else
1262                 {}
1263         }
1264         /* Look for a JSON request entity */
1265         body = ast_http_get_json(ser, headers);
1266         if (!body) {
1267                 switch (errno) {
1268                 case EFBIG:
1269                         ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
1270                         goto fin;
1271                 case ENOMEM:
1272                         ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
1273                         goto fin;
1274                 case EIO:
1275                         ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
1276                         goto fin;
1277                 }
1278         }
1279         if (ast_ari_bridges_record_parse_body(body, &args)) {
1280                 ast_ari_response_alloc_failed(response);
1281                 goto fin;
1282         }
1283         ast_ari_bridges_record(headers, &args, response);
1284 #if defined(AST_DEVMODE)
1285         code = response->response_code;
1286
1287         switch (code) {
1288         case 0: /* Implementation is still a stub, or the code wasn't set */
1289                 is_valid = response->message == NULL;
1290                 break;
1291         case 500: /* Internal Server Error */
1292         case 501: /* Not Implemented */
1293         case 400: /* Invalid parameters */
1294         case 404: /* Bridge not found */
1295         case 409: /* Bridge is not in a Stasis application; A recording with the same name already exists on the system and can not be overwritten because it is in progress or ifExists=fail */
1296         case 422: /* The format specified is unknown on this system */
1297                 is_valid = 1;
1298                 break;
1299         default:
1300                 if (200 <= code && code <= 299) {
1301                         is_valid = ast_ari_validate_live_recording(
1302                                 response->message);
1303                 } else {
1304                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/record\n", code);
1305                         is_valid = 0;
1306                 }
1307         }
1308
1309         if (!is_valid) {
1310                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/record\n");
1311                 ast_ari_response_error(response, 500,
1312                         "Internal Server Error", "Response validation failed");
1313         }
1314 #endif /* AST_DEVMODE */
1315
1316 fin: __attribute__((unused))
1317         return;
1318 }
1319
1320 /*! \brief REST handler for /api-docs/bridges.{format} */
1321 static struct stasis_rest_handlers bridges_bridgeId_addChannel = {
1322         .path_segment = "addChannel",
1323         .callbacks = {
1324                 [AST_HTTP_POST] = ast_ari_bridges_add_channel_cb,
1325         },
1326         .num_children = 0,
1327         .children = {  }
1328 };
1329 /*! \brief REST handler for /api-docs/bridges.{format} */
1330 static struct stasis_rest_handlers bridges_bridgeId_removeChannel = {
1331         .path_segment = "removeChannel",
1332         .callbacks = {
1333                 [AST_HTTP_POST] = ast_ari_bridges_remove_channel_cb,
1334         },
1335         .num_children = 0,
1336         .children = {  }
1337 };
1338 /*! \brief REST handler for /api-docs/bridges.{format} */
1339 static struct stasis_rest_handlers bridges_bridgeId_moh = {
1340         .path_segment = "moh",
1341         .callbacks = {
1342                 [AST_HTTP_POST] = ast_ari_bridges_start_moh_cb,
1343                 [AST_HTTP_DELETE] = ast_ari_bridges_stop_moh_cb,
1344         },
1345         .num_children = 0,
1346         .children = {  }
1347 };
1348 /*! \brief REST handler for /api-docs/bridges.{format} */
1349 static struct stasis_rest_handlers bridges_bridgeId_play_playbackId = {
1350         .path_segment = "playbackId",
1351         .is_wildcard = 1,
1352         .callbacks = {
1353                 [AST_HTTP_POST] = ast_ari_bridges_play_with_id_cb,
1354         },
1355         .num_children = 0,
1356         .children = {  }
1357 };
1358 /*! \brief REST handler for /api-docs/bridges.{format} */
1359 static struct stasis_rest_handlers bridges_bridgeId_play = {
1360         .path_segment = "play",
1361         .callbacks = {
1362                 [AST_HTTP_POST] = ast_ari_bridges_play_cb,
1363         },
1364         .num_children = 1,
1365         .children = { &bridges_bridgeId_play_playbackId, }
1366 };
1367 /*! \brief REST handler for /api-docs/bridges.{format} */
1368 static struct stasis_rest_handlers bridges_bridgeId_record = {
1369         .path_segment = "record",
1370         .callbacks = {
1371                 [AST_HTTP_POST] = ast_ari_bridges_record_cb,
1372         },
1373         .num_children = 0,
1374         .children = {  }
1375 };
1376 /*! \brief REST handler for /api-docs/bridges.{format} */
1377 static struct stasis_rest_handlers bridges_bridgeId = {
1378         .path_segment = "bridgeId",
1379         .is_wildcard = 1,
1380         .callbacks = {
1381                 [AST_HTTP_POST] = ast_ari_bridges_create_or_update_with_id_cb,
1382                 [AST_HTTP_GET] = ast_ari_bridges_get_cb,
1383                 [AST_HTTP_DELETE] = ast_ari_bridges_destroy_cb,
1384         },
1385         .num_children = 5,
1386         .children = { &bridges_bridgeId_addChannel,&bridges_bridgeId_removeChannel,&bridges_bridgeId_moh,&bridges_bridgeId_play,&bridges_bridgeId_record, }
1387 };
1388 /*! \brief REST handler for /api-docs/bridges.{format} */
1389 static struct stasis_rest_handlers bridges = {
1390         .path_segment = "bridges",
1391         .callbacks = {
1392                 [AST_HTTP_GET] = ast_ari_bridges_list_cb,
1393                 [AST_HTTP_POST] = ast_ari_bridges_create_cb,
1394         },
1395         .num_children = 1,
1396         .children = { &bridges_bridgeId, }
1397 };
1398
1399 static int load_module(void)
1400 {
1401         int res = 0;
1402         stasis_app_ref();
1403         res |= ast_ari_add_handler(&bridges);
1404         return res;
1405 }
1406
1407 static int unload_module(void)
1408 {
1409         ast_ari_remove_handler(&bridges);
1410         stasis_app_unref();
1411         return 0;
1412 }
1413
1414 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Bridge resources",
1415         .support_level = AST_MODULE_SUPPORT_CORE,
1416         .load = load_module,
1417         .unload = unload_module,
1418         .nonoptreq = "res_ari,res_stasis",
1419         );