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