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