Merge "res_pjsip/res_pjsip_callerid: NULL check on caller id name string"
[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         return 0;
434 }
435
436 /*!
437  * \brief Parameter parsing callback for /bridges/{bridgeId}/addChannel.
438  * \param get_params GET parameters in the HTTP request.
439  * \param path_vars Path variables extracted from the request.
440  * \param headers HTTP headers.
441  * \param[out] response Response to the HTTP request.
442  */
443 static void ast_ari_bridges_add_channel_cb(
444         struct ast_tcptls_session_instance *ser,
445         struct ast_variable *get_params, struct ast_variable *path_vars,
446         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
447 {
448         struct ast_ari_bridges_add_channel_args args = {};
449         struct ast_variable *i;
450 #if defined(AST_DEVMODE)
451         int is_valid;
452         int code;
453 #endif /* AST_DEVMODE */
454
455         for (i = get_params; i; i = i->next) {
456                 if (strcmp(i->name, "channel") == 0) {
457                         /* Parse comma separated list */
458                         char *vals[MAX_VALS];
459                         size_t j;
460
461                         args.channel_parse = ast_strdup(i->value);
462                         if (!args.channel_parse) {
463                                 ast_ari_response_alloc_failed(response);
464                                 goto fin;
465                         }
466
467                         if (strlen(args.channel_parse) == 0) {
468                                 /* ast_app_separate_args can't handle "" */
469                                 args.channel_count = 1;
470                                 vals[0] = args.channel_parse;
471                         } else {
472                                 args.channel_count = ast_app_separate_args(
473                                         args.channel_parse, ',', vals,
474                                         ARRAY_LEN(vals));
475                         }
476
477                         if (args.channel_count == 0) {
478                                 ast_ari_response_alloc_failed(response);
479                                 goto fin;
480                         }
481
482                         if (args.channel_count >= MAX_VALS) {
483                                 ast_ari_response_error(response, 400,
484                                         "Bad Request",
485                                         "Too many values for channel");
486                                 goto fin;
487                         }
488
489                         args.channel = ast_malloc(sizeof(*args.channel) * args.channel_count);
490                         if (!args.channel) {
491                                 ast_ari_response_alloc_failed(response);
492                                 goto fin;
493                         }
494
495                         for (j = 0; j < args.channel_count; ++j) {
496                                 args.channel[j] = (vals[j]);
497                         }
498                 } else
499                 if (strcmp(i->name, "role") == 0) {
500                         args.role = (i->value);
501                 } else
502                 {}
503         }
504         for (i = path_vars; i; i = i->next) {
505                 if (strcmp(i->name, "bridgeId") == 0) {
506                         args.bridge_id = (i->value);
507                 } else
508                 {}
509         }
510         if (ast_ari_bridges_add_channel_parse_body(body, &args)) {
511                 ast_ari_response_alloc_failed(response);
512                 goto fin;
513         }
514         ast_ari_bridges_add_channel(headers, &args, response);
515 #if defined(AST_DEVMODE)
516         code = response->response_code;
517
518         switch (code) {
519         case 0: /* Implementation is still a stub, or the code wasn't set */
520                 is_valid = response->message == NULL;
521                 break;
522         case 500: /* Internal Server Error */
523         case 501: /* Not Implemented */
524         case 400: /* Channel not found */
525         case 404: /* Bridge not found */
526         case 409: /* Bridge not in Stasis application; Channel currently recording */
527         case 422: /* Channel not in Stasis application */
528                 is_valid = 1;
529                 break;
530         default:
531                 if (200 <= code && code <= 299) {
532                         is_valid = ast_ari_validate_void(
533                                 response->message);
534                 } else {
535                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/addChannel\n", code);
536                         is_valid = 0;
537                 }
538         }
539
540         if (!is_valid) {
541                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/addChannel\n");
542                 ast_ari_response_error(response, 500,
543                         "Internal Server Error", "Response validation failed");
544         }
545 #endif /* AST_DEVMODE */
546
547 fin: __attribute__((unused))
548         ast_free(args.channel_parse);
549         ast_free(args.channel);
550         return;
551 }
552 int ast_ari_bridges_remove_channel_parse_body(
553         struct ast_json *body,
554         struct ast_ari_bridges_remove_channel_args *args)
555 {
556         struct ast_json *field;
557         /* Parse query parameters out of it */
558         field = ast_json_object_get(body, "channel");
559         if (field) {
560                 /* If they were silly enough to both pass in a query param and a
561                  * JSON body, free up the query value.
562                  */
563                 ast_free(args->channel);
564                 if (ast_json_typeof(field) == AST_JSON_ARRAY) {
565                         /* Multiple param passed as array */
566                         size_t i;
567                         args->channel_count = ast_json_array_size(field);
568                         args->channel = ast_malloc(sizeof(*args->channel) * args->channel_count);
569
570                         if (!args->channel) {
571                                 return -1;
572                         }
573
574                         for (i = 0; i < args->channel_count; ++i) {
575                                 args->channel[i] = ast_json_string_get(ast_json_array_get(field, i));
576                         }
577                 } else {
578                         /* Multiple param passed as single value */
579                         args->channel_count = 1;
580                         args->channel = ast_malloc(sizeof(*args->channel) * args->channel_count);
581                         if (!args->channel) {
582                                 return -1;
583                         }
584                         args->channel[0] = ast_json_string_get(field);
585                 }
586         }
587         return 0;
588 }
589
590 /*!
591  * \brief Parameter parsing callback for /bridges/{bridgeId}/removeChannel.
592  * \param get_params GET parameters in the HTTP request.
593  * \param path_vars Path variables extracted from the request.
594  * \param headers HTTP headers.
595  * \param[out] response Response to the HTTP request.
596  */
597 static void ast_ari_bridges_remove_channel_cb(
598         struct ast_tcptls_session_instance *ser,
599         struct ast_variable *get_params, struct ast_variable *path_vars,
600         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
601 {
602         struct ast_ari_bridges_remove_channel_args args = {};
603         struct ast_variable *i;
604 #if defined(AST_DEVMODE)
605         int is_valid;
606         int code;
607 #endif /* AST_DEVMODE */
608
609         for (i = get_params; i; i = i->next) {
610                 if (strcmp(i->name, "channel") == 0) {
611                         /* Parse comma separated list */
612                         char *vals[MAX_VALS];
613                         size_t j;
614
615                         args.channel_parse = ast_strdup(i->value);
616                         if (!args.channel_parse) {
617                                 ast_ari_response_alloc_failed(response);
618                                 goto fin;
619                         }
620
621                         if (strlen(args.channel_parse) == 0) {
622                                 /* ast_app_separate_args can't handle "" */
623                                 args.channel_count = 1;
624                                 vals[0] = args.channel_parse;
625                         } else {
626                                 args.channel_count = ast_app_separate_args(
627                                         args.channel_parse, ',', vals,
628                                         ARRAY_LEN(vals));
629                         }
630
631                         if (args.channel_count == 0) {
632                                 ast_ari_response_alloc_failed(response);
633                                 goto fin;
634                         }
635
636                         if (args.channel_count >= MAX_VALS) {
637                                 ast_ari_response_error(response, 400,
638                                         "Bad Request",
639                                         "Too many values for channel");
640                                 goto fin;
641                         }
642
643                         args.channel = ast_malloc(sizeof(*args.channel) * args.channel_count);
644                         if (!args.channel) {
645                                 ast_ari_response_alloc_failed(response);
646                                 goto fin;
647                         }
648
649                         for (j = 0; j < args.channel_count; ++j) {
650                                 args.channel[j] = (vals[j]);
651                         }
652                 } else
653                 {}
654         }
655         for (i = path_vars; i; i = i->next) {
656                 if (strcmp(i->name, "bridgeId") == 0) {
657                         args.bridge_id = (i->value);
658                 } else
659                 {}
660         }
661         if (ast_ari_bridges_remove_channel_parse_body(body, &args)) {
662                 ast_ari_response_alloc_failed(response);
663                 goto fin;
664         }
665         ast_ari_bridges_remove_channel(headers, &args, response);
666 #if defined(AST_DEVMODE)
667         code = response->response_code;
668
669         switch (code) {
670         case 0: /* Implementation is still a stub, or the code wasn't set */
671                 is_valid = response->message == NULL;
672                 break;
673         case 500: /* Internal Server Error */
674         case 501: /* Not Implemented */
675         case 400: /* Channel not found */
676         case 404: /* Bridge not found */
677         case 409: /* Bridge not in Stasis application */
678         case 422: /* Channel not in this bridge */
679                 is_valid = 1;
680                 break;
681         default:
682                 if (200 <= code && code <= 299) {
683                         is_valid = ast_ari_validate_void(
684                                 response->message);
685                 } else {
686                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/removeChannel\n", code);
687                         is_valid = 0;
688                 }
689         }
690
691         if (!is_valid) {
692                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/removeChannel\n");
693                 ast_ari_response_error(response, 500,
694                         "Internal Server Error", "Response validation failed");
695         }
696 #endif /* AST_DEVMODE */
697
698 fin: __attribute__((unused))
699         ast_free(args.channel_parse);
700         ast_free(args.channel);
701         return;
702 }
703 /*!
704  * \brief Parameter parsing callback for /bridges/{bridgeId}/videoSource/{channelId}.
705  * \param get_params GET parameters in the HTTP request.
706  * \param path_vars Path variables extracted from the request.
707  * \param headers HTTP headers.
708  * \param[out] response Response to the HTTP request.
709  */
710 static void ast_ari_bridges_set_video_source_cb(
711         struct ast_tcptls_session_instance *ser,
712         struct ast_variable *get_params, struct ast_variable *path_vars,
713         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
714 {
715         struct ast_ari_bridges_set_video_source_args args = {};
716         struct ast_variable *i;
717 #if defined(AST_DEVMODE)
718         int is_valid;
719         int code;
720 #endif /* AST_DEVMODE */
721
722         for (i = path_vars; i; i = i->next) {
723                 if (strcmp(i->name, "bridgeId") == 0) {
724                         args.bridge_id = (i->value);
725                 } else
726                 if (strcmp(i->name, "channelId") == 0) {
727                         args.channel_id = (i->value);
728                 } else
729                 {}
730         }
731         ast_ari_bridges_set_video_source(headers, &args, response);
732 #if defined(AST_DEVMODE)
733         code = response->response_code;
734
735         switch (code) {
736         case 0: /* Implementation is still a stub, or the code wasn't set */
737                 is_valid = response->message == NULL;
738                 break;
739         case 500: /* Internal Server Error */
740         case 501: /* Not Implemented */
741         case 404: /* Bridge or Channel not found */
742         case 409: /* Channel not in Stasis application */
743         case 422: /* Channel not in this Bridge */
744                 is_valid = 1;
745                 break;
746         default:
747                 if (200 <= code && code <= 299) {
748                         is_valid = ast_ari_validate_void(
749                                 response->message);
750                 } else {
751                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/videoSource/{channelId}\n", code);
752                         is_valid = 0;
753                 }
754         }
755
756         if (!is_valid) {
757                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/videoSource/{channelId}\n");
758                 ast_ari_response_error(response, 500,
759                         "Internal Server Error", "Response validation failed");
760         }
761 #endif /* AST_DEVMODE */
762
763 fin: __attribute__((unused))
764         return;
765 }
766 /*!
767  * \brief Parameter parsing callback for /bridges/{bridgeId}/videoSource.
768  * \param get_params GET parameters in the HTTP request.
769  * \param path_vars Path variables extracted from the request.
770  * \param headers HTTP headers.
771  * \param[out] response Response to the HTTP request.
772  */
773 static void ast_ari_bridges_clear_video_source_cb(
774         struct ast_tcptls_session_instance *ser,
775         struct ast_variable *get_params, struct ast_variable *path_vars,
776         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
777 {
778         struct ast_ari_bridges_clear_video_source_args args = {};
779         struct ast_variable *i;
780 #if defined(AST_DEVMODE)
781         int is_valid;
782         int code;
783 #endif /* AST_DEVMODE */
784
785         for (i = path_vars; i; i = i->next) {
786                 if (strcmp(i->name, "bridgeId") == 0) {
787                         args.bridge_id = (i->value);
788                 } else
789                 {}
790         }
791         ast_ari_bridges_clear_video_source(headers, &args, response);
792 #if defined(AST_DEVMODE)
793         code = response->response_code;
794
795         switch (code) {
796         case 0: /* Implementation is still a stub, or the code wasn't set */
797                 is_valid = response->message == NULL;
798                 break;
799         case 500: /* Internal Server Error */
800         case 501: /* Not Implemented */
801         case 404: /* Bridge not found */
802                 is_valid = 1;
803                 break;
804         default:
805                 if (200 <= code && code <= 299) {
806                         is_valid = ast_ari_validate_void(
807                                 response->message);
808                 } else {
809                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/videoSource\n", code);
810                         is_valid = 0;
811                 }
812         }
813
814         if (!is_valid) {
815                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/videoSource\n");
816                 ast_ari_response_error(response, 500,
817                         "Internal Server Error", "Response validation failed");
818         }
819 #endif /* AST_DEVMODE */
820
821 fin: __attribute__((unused))
822         return;
823 }
824 int ast_ari_bridges_start_moh_parse_body(
825         struct ast_json *body,
826         struct ast_ari_bridges_start_moh_args *args)
827 {
828         struct ast_json *field;
829         /* Parse query parameters out of it */
830         field = ast_json_object_get(body, "mohClass");
831         if (field) {
832                 args->moh_class = ast_json_string_get(field);
833         }
834         return 0;
835 }
836
837 /*!
838  * \brief Parameter parsing callback for /bridges/{bridgeId}/moh.
839  * \param get_params GET parameters in the HTTP request.
840  * \param path_vars Path variables extracted from the request.
841  * \param headers HTTP headers.
842  * \param[out] response Response to the HTTP request.
843  */
844 static void ast_ari_bridges_start_moh_cb(
845         struct ast_tcptls_session_instance *ser,
846         struct ast_variable *get_params, struct ast_variable *path_vars,
847         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
848 {
849         struct ast_ari_bridges_start_moh_args args = {};
850         struct ast_variable *i;
851 #if defined(AST_DEVMODE)
852         int is_valid;
853         int code;
854 #endif /* AST_DEVMODE */
855
856         for (i = get_params; i; i = i->next) {
857                 if (strcmp(i->name, "mohClass") == 0) {
858                         args.moh_class = (i->value);
859                 } else
860                 {}
861         }
862         for (i = path_vars; i; i = i->next) {
863                 if (strcmp(i->name, "bridgeId") == 0) {
864                         args.bridge_id = (i->value);
865                 } else
866                 {}
867         }
868         if (ast_ari_bridges_start_moh_parse_body(body, &args)) {
869                 ast_ari_response_alloc_failed(response);
870                 goto fin;
871         }
872         ast_ari_bridges_start_moh(headers, &args, response);
873 #if defined(AST_DEVMODE)
874         code = response->response_code;
875
876         switch (code) {
877         case 0: /* Implementation is still a stub, or the code wasn't set */
878                 is_valid = response->message == NULL;
879                 break;
880         case 500: /* Internal Server Error */
881         case 501: /* Not Implemented */
882         case 404: /* Bridge not found */
883         case 409: /* Bridge not in Stasis application */
884                 is_valid = 1;
885                 break;
886         default:
887                 if (200 <= code && code <= 299) {
888                         is_valid = ast_ari_validate_void(
889                                 response->message);
890                 } else {
891                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/moh\n", code);
892                         is_valid = 0;
893                 }
894         }
895
896         if (!is_valid) {
897                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/moh\n");
898                 ast_ari_response_error(response, 500,
899                         "Internal Server Error", "Response validation failed");
900         }
901 #endif /* AST_DEVMODE */
902
903 fin: __attribute__((unused))
904         return;
905 }
906 /*!
907  * \brief Parameter parsing callback for /bridges/{bridgeId}/moh.
908  * \param get_params GET parameters in the HTTP request.
909  * \param path_vars Path variables extracted from the request.
910  * \param headers HTTP headers.
911  * \param[out] response Response to the HTTP request.
912  */
913 static void ast_ari_bridges_stop_moh_cb(
914         struct ast_tcptls_session_instance *ser,
915         struct ast_variable *get_params, struct ast_variable *path_vars,
916         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
917 {
918         struct ast_ari_bridges_stop_moh_args args = {};
919         struct ast_variable *i;
920 #if defined(AST_DEVMODE)
921         int is_valid;
922         int code;
923 #endif /* AST_DEVMODE */
924
925         for (i = path_vars; i; i = i->next) {
926                 if (strcmp(i->name, "bridgeId") == 0) {
927                         args.bridge_id = (i->value);
928                 } else
929                 {}
930         }
931         ast_ari_bridges_stop_moh(headers, &args, response);
932 #if defined(AST_DEVMODE)
933         code = response->response_code;
934
935         switch (code) {
936         case 0: /* Implementation is still a stub, or the code wasn't set */
937                 is_valid = response->message == NULL;
938                 break;
939         case 500: /* Internal Server Error */
940         case 501: /* Not Implemented */
941         case 404: /* Bridge not found */
942         case 409: /* Bridge not in Stasis application */
943                 is_valid = 1;
944                 break;
945         default:
946                 if (200 <= code && code <= 299) {
947                         is_valid = ast_ari_validate_void(
948                                 response->message);
949                 } else {
950                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/moh\n", code);
951                         is_valid = 0;
952                 }
953         }
954
955         if (!is_valid) {
956                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/moh\n");
957                 ast_ari_response_error(response, 500,
958                         "Internal Server Error", "Response validation failed");
959         }
960 #endif /* AST_DEVMODE */
961
962 fin: __attribute__((unused))
963         return;
964 }
965 int ast_ari_bridges_play_parse_body(
966         struct ast_json *body,
967         struct ast_ari_bridges_play_args *args)
968 {
969         struct ast_json *field;
970         /* Parse query parameters out of it */
971         field = ast_json_object_get(body, "media");
972         if (field) {
973                 /* If they were silly enough to both pass in a query param and a
974                  * JSON body, free up the query value.
975                  */
976                 ast_free(args->media);
977                 if (ast_json_typeof(field) == AST_JSON_ARRAY) {
978                         /* Multiple param passed as array */
979                         size_t i;
980                         args->media_count = ast_json_array_size(field);
981                         args->media = ast_malloc(sizeof(*args->media) * args->media_count);
982
983                         if (!args->media) {
984                                 return -1;
985                         }
986
987                         for (i = 0; i < args->media_count; ++i) {
988                                 args->media[i] = ast_json_string_get(ast_json_array_get(field, i));
989                         }
990                 } else {
991                         /* Multiple param passed as single value */
992                         args->media_count = 1;
993                         args->media = ast_malloc(sizeof(*args->media) * args->media_count);
994                         if (!args->media) {
995                                 return -1;
996                         }
997                         args->media[0] = ast_json_string_get(field);
998                 }
999         }
1000         field = ast_json_object_get(body, "lang");
1001         if (field) {
1002                 args->lang = ast_json_string_get(field);
1003         }
1004         field = ast_json_object_get(body, "offsetms");
1005         if (field) {
1006                 args->offsetms = ast_json_integer_get(field);
1007         }
1008         field = ast_json_object_get(body, "skipms");
1009         if (field) {
1010                 args->skipms = ast_json_integer_get(field);
1011         }
1012         field = ast_json_object_get(body, "playbackId");
1013         if (field) {
1014                 args->playback_id = ast_json_string_get(field);
1015         }
1016         return 0;
1017 }
1018
1019 /*!
1020  * \brief Parameter parsing callback for /bridges/{bridgeId}/play.
1021  * \param get_params GET parameters in the HTTP request.
1022  * \param path_vars Path variables extracted from the request.
1023  * \param headers HTTP headers.
1024  * \param[out] response Response to the HTTP request.
1025  */
1026 static void ast_ari_bridges_play_cb(
1027         struct ast_tcptls_session_instance *ser,
1028         struct ast_variable *get_params, struct ast_variable *path_vars,
1029         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1030 {
1031         struct ast_ari_bridges_play_args args = {};
1032         struct ast_variable *i;
1033 #if defined(AST_DEVMODE)
1034         int is_valid;
1035         int code;
1036 #endif /* AST_DEVMODE */
1037
1038         for (i = get_params; i; i = i->next) {
1039                 if (strcmp(i->name, "media") == 0) {
1040                         /* Parse comma separated list */
1041                         char *vals[MAX_VALS];
1042                         size_t j;
1043
1044                         args.media_parse = ast_strdup(i->value);
1045                         if (!args.media_parse) {
1046                                 ast_ari_response_alloc_failed(response);
1047                                 goto fin;
1048                         }
1049
1050                         if (strlen(args.media_parse) == 0) {
1051                                 /* ast_app_separate_args can't handle "" */
1052                                 args.media_count = 1;
1053                                 vals[0] = args.media_parse;
1054                         } else {
1055                                 args.media_count = ast_app_separate_args(
1056                                         args.media_parse, ',', vals,
1057                                         ARRAY_LEN(vals));
1058                         }
1059
1060                         if (args.media_count == 0) {
1061                                 ast_ari_response_alloc_failed(response);
1062                                 goto fin;
1063                         }
1064
1065                         if (args.media_count >= MAX_VALS) {
1066                                 ast_ari_response_error(response, 400,
1067                                         "Bad Request",
1068                                         "Too many values for media");
1069                                 goto fin;
1070                         }
1071
1072                         args.media = ast_malloc(sizeof(*args.media) * args.media_count);
1073                         if (!args.media) {
1074                                 ast_ari_response_alloc_failed(response);
1075                                 goto fin;
1076                         }
1077
1078                         for (j = 0; j < args.media_count; ++j) {
1079                                 args.media[j] = (vals[j]);
1080                         }
1081                 } else
1082                 if (strcmp(i->name, "lang") == 0) {
1083                         args.lang = (i->value);
1084                 } else
1085                 if (strcmp(i->name, "offsetms") == 0) {
1086                         args.offsetms = atoi(i->value);
1087                 } else
1088                 if (strcmp(i->name, "skipms") == 0) {
1089                         args.skipms = atoi(i->value);
1090                 } else
1091                 if (strcmp(i->name, "playbackId") == 0) {
1092                         args.playback_id = (i->value);
1093                 } else
1094                 {}
1095         }
1096         for (i = path_vars; i; i = i->next) {
1097                 if (strcmp(i->name, "bridgeId") == 0) {
1098                         args.bridge_id = (i->value);
1099                 } else
1100                 {}
1101         }
1102         if (ast_ari_bridges_play_parse_body(body, &args)) {
1103                 ast_ari_response_alloc_failed(response);
1104                 goto fin;
1105         }
1106         ast_ari_bridges_play(headers, &args, response);
1107 #if defined(AST_DEVMODE)
1108         code = response->response_code;
1109
1110         switch (code) {
1111         case 0: /* Implementation is still a stub, or the code wasn't set */
1112                 is_valid = response->message == NULL;
1113                 break;
1114         case 500: /* Internal Server Error */
1115         case 501: /* Not Implemented */
1116         case 404: /* Bridge not found */
1117         case 409: /* Bridge not in a Stasis application */
1118                 is_valid = 1;
1119                 break;
1120         default:
1121                 if (200 <= code && code <= 299) {
1122                         is_valid = ast_ari_validate_playback(
1123                                 response->message);
1124                 } else {
1125                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/play\n", code);
1126                         is_valid = 0;
1127                 }
1128         }
1129
1130         if (!is_valid) {
1131                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/play\n");
1132                 ast_ari_response_error(response, 500,
1133                         "Internal Server Error", "Response validation failed");
1134         }
1135 #endif /* AST_DEVMODE */
1136
1137 fin: __attribute__((unused))
1138         ast_free(args.media_parse);
1139         ast_free(args.media);
1140         return;
1141 }
1142 int ast_ari_bridges_play_with_id_parse_body(
1143         struct ast_json *body,
1144         struct ast_ari_bridges_play_with_id_args *args)
1145 {
1146         struct ast_json *field;
1147         /* Parse query parameters out of it */
1148         field = ast_json_object_get(body, "media");
1149         if (field) {
1150                 /* If they were silly enough to both pass in a query param and a
1151                  * JSON body, free up the query value.
1152                  */
1153                 ast_free(args->media);
1154                 if (ast_json_typeof(field) == AST_JSON_ARRAY) {
1155                         /* Multiple param passed as array */
1156                         size_t i;
1157                         args->media_count = ast_json_array_size(field);
1158                         args->media = ast_malloc(sizeof(*args->media) * args->media_count);
1159
1160                         if (!args->media) {
1161                                 return -1;
1162                         }
1163
1164                         for (i = 0; i < args->media_count; ++i) {
1165                                 args->media[i] = ast_json_string_get(ast_json_array_get(field, i));
1166                         }
1167                 } else {
1168                         /* Multiple param passed as single value */
1169                         args->media_count = 1;
1170                         args->media = ast_malloc(sizeof(*args->media) * args->media_count);
1171                         if (!args->media) {
1172                                 return -1;
1173                         }
1174                         args->media[0] = ast_json_string_get(field);
1175                 }
1176         }
1177         field = ast_json_object_get(body, "lang");
1178         if (field) {
1179                 args->lang = ast_json_string_get(field);
1180         }
1181         field = ast_json_object_get(body, "offsetms");
1182         if (field) {
1183                 args->offsetms = ast_json_integer_get(field);
1184         }
1185         field = ast_json_object_get(body, "skipms");
1186         if (field) {
1187                 args->skipms = ast_json_integer_get(field);
1188         }
1189         return 0;
1190 }
1191
1192 /*!
1193  * \brief Parameter parsing callback for /bridges/{bridgeId}/play/{playbackId}.
1194  * \param get_params GET parameters in the HTTP request.
1195  * \param path_vars Path variables extracted from the request.
1196  * \param headers HTTP headers.
1197  * \param[out] response Response to the HTTP request.
1198  */
1199 static void ast_ari_bridges_play_with_id_cb(
1200         struct ast_tcptls_session_instance *ser,
1201         struct ast_variable *get_params, struct ast_variable *path_vars,
1202         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1203 {
1204         struct ast_ari_bridges_play_with_id_args args = {};
1205         struct ast_variable *i;
1206 #if defined(AST_DEVMODE)
1207         int is_valid;
1208         int code;
1209 #endif /* AST_DEVMODE */
1210
1211         for (i = get_params; i; i = i->next) {
1212                 if (strcmp(i->name, "media") == 0) {
1213                         /* Parse comma separated list */
1214                         char *vals[MAX_VALS];
1215                         size_t j;
1216
1217                         args.media_parse = ast_strdup(i->value);
1218                         if (!args.media_parse) {
1219                                 ast_ari_response_alloc_failed(response);
1220                                 goto fin;
1221                         }
1222
1223                         if (strlen(args.media_parse) == 0) {
1224                                 /* ast_app_separate_args can't handle "" */
1225                                 args.media_count = 1;
1226                                 vals[0] = args.media_parse;
1227                         } else {
1228                                 args.media_count = ast_app_separate_args(
1229                                         args.media_parse, ',', vals,
1230                                         ARRAY_LEN(vals));
1231                         }
1232
1233                         if (args.media_count == 0) {
1234                                 ast_ari_response_alloc_failed(response);
1235                                 goto fin;
1236                         }
1237
1238                         if (args.media_count >= MAX_VALS) {
1239                                 ast_ari_response_error(response, 400,
1240                                         "Bad Request",
1241                                         "Too many values for media");
1242                                 goto fin;
1243                         }
1244
1245                         args.media = ast_malloc(sizeof(*args.media) * args.media_count);
1246                         if (!args.media) {
1247                                 ast_ari_response_alloc_failed(response);
1248                                 goto fin;
1249                         }
1250
1251                         for (j = 0; j < args.media_count; ++j) {
1252                                 args.media[j] = (vals[j]);
1253                         }
1254                 } else
1255                 if (strcmp(i->name, "lang") == 0) {
1256                         args.lang = (i->value);
1257                 } else
1258                 if (strcmp(i->name, "offsetms") == 0) {
1259                         args.offsetms = atoi(i->value);
1260                 } else
1261                 if (strcmp(i->name, "skipms") == 0) {
1262                         args.skipms = atoi(i->value);
1263                 } else
1264                 {}
1265         }
1266         for (i = path_vars; i; i = i->next) {
1267                 if (strcmp(i->name, "bridgeId") == 0) {
1268                         args.bridge_id = (i->value);
1269                 } else
1270                 if (strcmp(i->name, "playbackId") == 0) {
1271                         args.playback_id = (i->value);
1272                 } else
1273                 {}
1274         }
1275         if (ast_ari_bridges_play_with_id_parse_body(body, &args)) {
1276                 ast_ari_response_alloc_failed(response);
1277                 goto fin;
1278         }
1279         ast_ari_bridges_play_with_id(headers, &args, response);
1280 #if defined(AST_DEVMODE)
1281         code = response->response_code;
1282
1283         switch (code) {
1284         case 0: /* Implementation is still a stub, or the code wasn't set */
1285                 is_valid = response->message == NULL;
1286                 break;
1287         case 500: /* Internal Server Error */
1288         case 501: /* Not Implemented */
1289         case 404: /* Bridge not found */
1290         case 409: /* Bridge not in a Stasis application */
1291                 is_valid = 1;
1292                 break;
1293         default:
1294                 if (200 <= code && code <= 299) {
1295                         is_valid = ast_ari_validate_playback(
1296                                 response->message);
1297                 } else {
1298                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/play/{playbackId}\n", code);
1299                         is_valid = 0;
1300                 }
1301         }
1302
1303         if (!is_valid) {
1304                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/play/{playbackId}\n");
1305                 ast_ari_response_error(response, 500,
1306                         "Internal Server Error", "Response validation failed");
1307         }
1308 #endif /* AST_DEVMODE */
1309
1310 fin: __attribute__((unused))
1311         ast_free(args.media_parse);
1312         ast_free(args.media);
1313         return;
1314 }
1315 int ast_ari_bridges_record_parse_body(
1316         struct ast_json *body,
1317         struct ast_ari_bridges_record_args *args)
1318 {
1319         struct ast_json *field;
1320         /* Parse query parameters out of it */
1321         field = ast_json_object_get(body, "name");
1322         if (field) {
1323                 args->name = ast_json_string_get(field);
1324         }
1325         field = ast_json_object_get(body, "format");
1326         if (field) {
1327                 args->format = ast_json_string_get(field);
1328         }
1329         field = ast_json_object_get(body, "maxDurationSeconds");
1330         if (field) {
1331                 args->max_duration_seconds = ast_json_integer_get(field);
1332         }
1333         field = ast_json_object_get(body, "maxSilenceSeconds");
1334         if (field) {
1335                 args->max_silence_seconds = ast_json_integer_get(field);
1336         }
1337         field = ast_json_object_get(body, "ifExists");
1338         if (field) {
1339                 args->if_exists = ast_json_string_get(field);
1340         }
1341         field = ast_json_object_get(body, "beep");
1342         if (field) {
1343                 args->beep = ast_json_is_true(field);
1344         }
1345         field = ast_json_object_get(body, "terminateOn");
1346         if (field) {
1347                 args->terminate_on = ast_json_string_get(field);
1348         }
1349         return 0;
1350 }
1351
1352 /*!
1353  * \brief Parameter parsing callback for /bridges/{bridgeId}/record.
1354  * \param get_params GET parameters in the HTTP request.
1355  * \param path_vars Path variables extracted from the request.
1356  * \param headers HTTP headers.
1357  * \param[out] response Response to the HTTP request.
1358  */
1359 static void ast_ari_bridges_record_cb(
1360         struct ast_tcptls_session_instance *ser,
1361         struct ast_variable *get_params, struct ast_variable *path_vars,
1362         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1363 {
1364         struct ast_ari_bridges_record_args args = {};
1365         struct ast_variable *i;
1366 #if defined(AST_DEVMODE)
1367         int is_valid;
1368         int code;
1369 #endif /* AST_DEVMODE */
1370
1371         for (i = get_params; i; i = i->next) {
1372                 if (strcmp(i->name, "name") == 0) {
1373                         args.name = (i->value);
1374                 } else
1375                 if (strcmp(i->name, "format") == 0) {
1376                         args.format = (i->value);
1377                 } else
1378                 if (strcmp(i->name, "maxDurationSeconds") == 0) {
1379                         args.max_duration_seconds = atoi(i->value);
1380                 } else
1381                 if (strcmp(i->name, "maxSilenceSeconds") == 0) {
1382                         args.max_silence_seconds = atoi(i->value);
1383                 } else
1384                 if (strcmp(i->name, "ifExists") == 0) {
1385                         args.if_exists = (i->value);
1386                 } else
1387                 if (strcmp(i->name, "beep") == 0) {
1388                         args.beep = ast_true(i->value);
1389                 } else
1390                 if (strcmp(i->name, "terminateOn") == 0) {
1391                         args.terminate_on = (i->value);
1392                 } else
1393                 {}
1394         }
1395         for (i = path_vars; i; i = i->next) {
1396                 if (strcmp(i->name, "bridgeId") == 0) {
1397                         args.bridge_id = (i->value);
1398                 } else
1399                 {}
1400         }
1401         if (ast_ari_bridges_record_parse_body(body, &args)) {
1402                 ast_ari_response_alloc_failed(response);
1403                 goto fin;
1404         }
1405         ast_ari_bridges_record(headers, &args, response);
1406 #if defined(AST_DEVMODE)
1407         code = response->response_code;
1408
1409         switch (code) {
1410         case 0: /* Implementation is still a stub, or the code wasn't set */
1411                 is_valid = response->message == NULL;
1412                 break;
1413         case 500: /* Internal Server Error */
1414         case 501: /* Not Implemented */
1415         case 400: /* Invalid parameters */
1416         case 404: /* Bridge not found */
1417         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 */
1418         case 422: /* The format specified is unknown on this system */
1419                 is_valid = 1;
1420                 break;
1421         default:
1422                 if (200 <= code && code <= 299) {
1423                         is_valid = ast_ari_validate_live_recording(
1424                                 response->message);
1425                 } else {
1426                         ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/record\n", code);
1427                         is_valid = 0;
1428                 }
1429         }
1430
1431         if (!is_valid) {
1432                 ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/record\n");
1433                 ast_ari_response_error(response, 500,
1434                         "Internal Server Error", "Response validation failed");
1435         }
1436 #endif /* AST_DEVMODE */
1437
1438 fin: __attribute__((unused))
1439         return;
1440 }
1441
1442 /*! \brief REST handler for /api-docs/bridges.json */
1443 static struct stasis_rest_handlers bridges_bridgeId_addChannel = {
1444         .path_segment = "addChannel",
1445         .callbacks = {
1446                 [AST_HTTP_POST] = ast_ari_bridges_add_channel_cb,
1447         },
1448         .num_children = 0,
1449         .children = {  }
1450 };
1451 /*! \brief REST handler for /api-docs/bridges.json */
1452 static struct stasis_rest_handlers bridges_bridgeId_removeChannel = {
1453         .path_segment = "removeChannel",
1454         .callbacks = {
1455                 [AST_HTTP_POST] = ast_ari_bridges_remove_channel_cb,
1456         },
1457         .num_children = 0,
1458         .children = {  }
1459 };
1460 /*! \brief REST handler for /api-docs/bridges.json */
1461 static struct stasis_rest_handlers bridges_bridgeId_videoSource_channelId = {
1462         .path_segment = "channelId",
1463         .is_wildcard = 1,
1464         .callbacks = {
1465                 [AST_HTTP_POST] = ast_ari_bridges_set_video_source_cb,
1466         },
1467         .num_children = 0,
1468         .children = {  }
1469 };
1470 /*! \brief REST handler for /api-docs/bridges.json */
1471 static struct stasis_rest_handlers bridges_bridgeId_videoSource = {
1472         .path_segment = "videoSource",
1473         .callbacks = {
1474                 [AST_HTTP_DELETE] = ast_ari_bridges_clear_video_source_cb,
1475         },
1476         .num_children = 1,
1477         .children = { &bridges_bridgeId_videoSource_channelId, }
1478 };
1479 /*! \brief REST handler for /api-docs/bridges.json */
1480 static struct stasis_rest_handlers bridges_bridgeId_moh = {
1481         .path_segment = "moh",
1482         .callbacks = {
1483                 [AST_HTTP_POST] = ast_ari_bridges_start_moh_cb,
1484                 [AST_HTTP_DELETE] = ast_ari_bridges_stop_moh_cb,
1485         },
1486         .num_children = 0,
1487         .children = {  }
1488 };
1489 /*! \brief REST handler for /api-docs/bridges.json */
1490 static struct stasis_rest_handlers bridges_bridgeId_play_playbackId = {
1491         .path_segment = "playbackId",
1492         .is_wildcard = 1,
1493         .callbacks = {
1494                 [AST_HTTP_POST] = ast_ari_bridges_play_with_id_cb,
1495         },
1496         .num_children = 0,
1497         .children = {  }
1498 };
1499 /*! \brief REST handler for /api-docs/bridges.json */
1500 static struct stasis_rest_handlers bridges_bridgeId_play = {
1501         .path_segment = "play",
1502         .callbacks = {
1503                 [AST_HTTP_POST] = ast_ari_bridges_play_cb,
1504         },
1505         .num_children = 1,
1506         .children = { &bridges_bridgeId_play_playbackId, }
1507 };
1508 /*! \brief REST handler for /api-docs/bridges.json */
1509 static struct stasis_rest_handlers bridges_bridgeId_record = {
1510         .path_segment = "record",
1511         .callbacks = {
1512                 [AST_HTTP_POST] = ast_ari_bridges_record_cb,
1513         },
1514         .num_children = 0,
1515         .children = {  }
1516 };
1517 /*! \brief REST handler for /api-docs/bridges.json */
1518 static struct stasis_rest_handlers bridges_bridgeId = {
1519         .path_segment = "bridgeId",
1520         .is_wildcard = 1,
1521         .callbacks = {
1522                 [AST_HTTP_POST] = ast_ari_bridges_create_with_id_cb,
1523                 [AST_HTTP_GET] = ast_ari_bridges_get_cb,
1524                 [AST_HTTP_DELETE] = ast_ari_bridges_destroy_cb,
1525         },
1526         .num_children = 6,
1527         .children = { &bridges_bridgeId_addChannel,&bridges_bridgeId_removeChannel,&bridges_bridgeId_videoSource,&bridges_bridgeId_moh,&bridges_bridgeId_play,&bridges_bridgeId_record, }
1528 };
1529 /*! \brief REST handler for /api-docs/bridges.json */
1530 static struct stasis_rest_handlers bridges = {
1531         .path_segment = "bridges",
1532         .callbacks = {
1533                 [AST_HTTP_GET] = ast_ari_bridges_list_cb,
1534                 [AST_HTTP_POST] = ast_ari_bridges_create_cb,
1535         },
1536         .num_children = 1,
1537         .children = { &bridges_bridgeId, }
1538 };
1539
1540 static int unload_module(void)
1541 {
1542         ast_ari_remove_handler(&bridges);
1543         stasis_app_unref();
1544         return 0;
1545 }
1546
1547 static int load_module(void)
1548 {
1549         int res = 0;
1550         stasis_app_ref();
1551         res |= ast_ari_add_handler(&bridges);
1552         if (res) {
1553                 unload_module();
1554                 return AST_MODULE_LOAD_DECLINE;
1555         }
1556
1557         return AST_MODULE_LOAD_SUCCESS;
1558 }
1559
1560 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Bridge resources",
1561         .support_level = AST_MODULE_SUPPORT_CORE,
1562         .load = load_module,
1563         .unload = unload_module,
1564         .nonoptreq = "res_ari,res_stasis",
1565 );