3d96d60e4cd8d74f17fc3460222bd1f763f7481b
[asterisk/asterisk.git] / res / res_ari_channels.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 Channel 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_answer</depend>
39         <depend type="module">res_stasis_playback</depend>
40         <depend type="module">res_stasis_recording</depend>
41         <depend type="module">res_stasis_snoop</depend>
42         <support_level>core</support_level>
43  ***/
44
45 #include "asterisk.h"
46
47 #include "asterisk/app.h"
48 #include "asterisk/module.h"
49 #include "asterisk/stasis_app.h"
50 #include "ari/resource_channels.h"
51 #if defined(AST_DEVMODE)
52 #include "ari/ari_model_validators.h"
53 #endif
54
55 #define MAX_VALS 128
56
57 /*!
58  * \brief Parameter parsing callback for /channels.
59  * \param get_params GET parameters in the HTTP request.
60  * \param path_vars Path variables extracted from the request.
61  * \param headers HTTP headers.
62  * \param[out] response Response to the HTTP request.
63  */
64 static void ast_ari_channels_list_cb(
65         struct ast_tcptls_session_instance *ser,
66         struct ast_variable *get_params, struct ast_variable *path_vars,
67         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
68 {
69         struct ast_ari_channels_list_args args = {};
70 #if defined(AST_DEVMODE)
71         int is_valid;
72         int code;
73 #endif /* AST_DEVMODE */
74
75         ast_ari_channels_list(headers, &args, response);
76 #if defined(AST_DEVMODE)
77         code = response->response_code;
78
79         switch (code) {
80         case 0: /* Implementation is still a stub, or the code wasn't set */
81                 is_valid = response->message == NULL;
82                 break;
83         case 500: /* Internal Server Error */
84         case 501: /* Not Implemented */
85                 is_valid = 1;
86                 break;
87         default:
88                 if (200 <= code && code <= 299) {
89                         is_valid = ast_ari_validate_list(response->message,
90                                 ast_ari_validate_channel_fn());
91                 } else {
92                         ast_log(LOG_ERROR, "Invalid error response %d for /channels\n", code);
93                         is_valid = 0;
94                 }
95         }
96
97         if (!is_valid) {
98                 ast_log(LOG_ERROR, "Response validation failed for /channels\n");
99                 ast_ari_response_error(response, 500,
100                         "Internal Server Error", "Response validation failed");
101         }
102 #endif /* AST_DEVMODE */
103
104 fin: __attribute__((unused))
105         return;
106 }
107 int ast_ari_channels_originate_parse_body(
108         struct ast_json *body,
109         struct ast_ari_channels_originate_args *args)
110 {
111         struct ast_json *field;
112         /* Parse query parameters out of it */
113         field = ast_json_object_get(body, "endpoint");
114         if (field) {
115                 args->endpoint = ast_json_string_get(field);
116         }
117         field = ast_json_object_get(body, "extension");
118         if (field) {
119                 args->extension = ast_json_string_get(field);
120         }
121         field = ast_json_object_get(body, "context");
122         if (field) {
123                 args->context = ast_json_string_get(field);
124         }
125         field = ast_json_object_get(body, "priority");
126         if (field) {
127                 args->priority = ast_json_integer_get(field);
128         }
129         field = ast_json_object_get(body, "label");
130         if (field) {
131                 args->label = ast_json_string_get(field);
132         }
133         field = ast_json_object_get(body, "app");
134         if (field) {
135                 args->app = ast_json_string_get(field);
136         }
137         field = ast_json_object_get(body, "appArgs");
138         if (field) {
139                 args->app_args = ast_json_string_get(field);
140         }
141         field = ast_json_object_get(body, "callerId");
142         if (field) {
143                 args->caller_id = ast_json_string_get(field);
144         }
145         field = ast_json_object_get(body, "timeout");
146         if (field) {
147                 args->timeout = ast_json_integer_get(field);
148         }
149         field = ast_json_object_get(body, "channelId");
150         if (field) {
151                 args->channel_id = ast_json_string_get(field);
152         }
153         field = ast_json_object_get(body, "otherChannelId");
154         if (field) {
155                 args->other_channel_id = ast_json_string_get(field);
156         }
157         field = ast_json_object_get(body, "originator");
158         if (field) {
159                 args->originator = ast_json_string_get(field);
160         }
161         field = ast_json_object_get(body, "formats");
162         if (field) {
163                 args->formats = ast_json_string_get(field);
164         }
165         return 0;
166 }
167
168 /*!
169  * \brief Parameter parsing callback for /channels.
170  * \param get_params GET parameters in the HTTP request.
171  * \param path_vars Path variables extracted from the request.
172  * \param headers HTTP headers.
173  * \param[out] response Response to the HTTP request.
174  */
175 static void ast_ari_channels_originate_cb(
176         struct ast_tcptls_session_instance *ser,
177         struct ast_variable *get_params, struct ast_variable *path_vars,
178         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
179 {
180         struct ast_ari_channels_originate_args args = {};
181         struct ast_variable *i;
182 #if defined(AST_DEVMODE)
183         int is_valid;
184         int code;
185 #endif /* AST_DEVMODE */
186
187         for (i = get_params; i; i = i->next) {
188                 if (strcmp(i->name, "endpoint") == 0) {
189                         args.endpoint = (i->value);
190                 } else
191                 if (strcmp(i->name, "extension") == 0) {
192                         args.extension = (i->value);
193                 } else
194                 if (strcmp(i->name, "context") == 0) {
195                         args.context = (i->value);
196                 } else
197                 if (strcmp(i->name, "priority") == 0) {
198                         args.priority = atol(i->value);
199                 } else
200                 if (strcmp(i->name, "label") == 0) {
201                         args.label = (i->value);
202                 } else
203                 if (strcmp(i->name, "app") == 0) {
204                         args.app = (i->value);
205                 } else
206                 if (strcmp(i->name, "appArgs") == 0) {
207                         args.app_args = (i->value);
208                 } else
209                 if (strcmp(i->name, "callerId") == 0) {
210                         args.caller_id = (i->value);
211                 } else
212                 if (strcmp(i->name, "timeout") == 0) {
213                         args.timeout = atoi(i->value);
214                 } else
215                 if (strcmp(i->name, "channelId") == 0) {
216                         args.channel_id = (i->value);
217                 } else
218                 if (strcmp(i->name, "otherChannelId") == 0) {
219                         args.other_channel_id = (i->value);
220                 } else
221                 if (strcmp(i->name, "originator") == 0) {
222                         args.originator = (i->value);
223                 } else
224                 if (strcmp(i->name, "formats") == 0) {
225                         args.formats = (i->value);
226                 } else
227                 {}
228         }
229         args.variables = body;
230         ast_ari_channels_originate(headers, &args, response);
231 #if defined(AST_DEVMODE)
232         code = response->response_code;
233
234         switch (code) {
235         case 0: /* Implementation is still a stub, or the code wasn't set */
236                 is_valid = response->message == NULL;
237                 break;
238         case 500: /* Internal Server Error */
239         case 501: /* Not Implemented */
240         case 400: /* Invalid parameters for originating a channel. */
241         case 409: /* Channel with given unique ID already exists. */
242                 is_valid = 1;
243                 break;
244         default:
245                 if (200 <= code && code <= 299) {
246                         is_valid = ast_ari_validate_channel(
247                                 response->message);
248                 } else {
249                         ast_log(LOG_ERROR, "Invalid error response %d for /channels\n", code);
250                         is_valid = 0;
251                 }
252         }
253
254         if (!is_valid) {
255                 ast_log(LOG_ERROR, "Response validation failed for /channels\n");
256                 ast_ari_response_error(response, 500,
257                         "Internal Server Error", "Response validation failed");
258         }
259 #endif /* AST_DEVMODE */
260
261 fin: __attribute__((unused))
262         return;
263 }
264 int ast_ari_channels_create_parse_body(
265         struct ast_json *body,
266         struct ast_ari_channels_create_args *args)
267 {
268         struct ast_json *field;
269         /* Parse query parameters out of it */
270         field = ast_json_object_get(body, "endpoint");
271         if (field) {
272                 args->endpoint = ast_json_string_get(field);
273         }
274         field = ast_json_object_get(body, "app");
275         if (field) {
276                 args->app = ast_json_string_get(field);
277         }
278         field = ast_json_object_get(body, "appArgs");
279         if (field) {
280                 args->app_args = ast_json_string_get(field);
281         }
282         field = ast_json_object_get(body, "channelId");
283         if (field) {
284                 args->channel_id = ast_json_string_get(field);
285         }
286         field = ast_json_object_get(body, "otherChannelId");
287         if (field) {
288                 args->other_channel_id = ast_json_string_get(field);
289         }
290         field = ast_json_object_get(body, "originator");
291         if (field) {
292                 args->originator = ast_json_string_get(field);
293         }
294         field = ast_json_object_get(body, "formats");
295         if (field) {
296                 args->formats = ast_json_string_get(field);
297         }
298         return 0;
299 }
300
301 /*!
302  * \brief Parameter parsing callback for /channels/create.
303  * \param get_params GET parameters in the HTTP request.
304  * \param path_vars Path variables extracted from the request.
305  * \param headers HTTP headers.
306  * \param[out] response Response to the HTTP request.
307  */
308 static void ast_ari_channels_create_cb(
309         struct ast_tcptls_session_instance *ser,
310         struct ast_variable *get_params, struct ast_variable *path_vars,
311         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
312 {
313         struct ast_ari_channels_create_args args = {};
314         struct ast_variable *i;
315 #if defined(AST_DEVMODE)
316         int is_valid;
317         int code;
318 #endif /* AST_DEVMODE */
319
320         for (i = get_params; i; i = i->next) {
321                 if (strcmp(i->name, "endpoint") == 0) {
322                         args.endpoint = (i->value);
323                 } else
324                 if (strcmp(i->name, "app") == 0) {
325                         args.app = (i->value);
326                 } else
327                 if (strcmp(i->name, "appArgs") == 0) {
328                         args.app_args = (i->value);
329                 } else
330                 if (strcmp(i->name, "channelId") == 0) {
331                         args.channel_id = (i->value);
332                 } else
333                 if (strcmp(i->name, "otherChannelId") == 0) {
334                         args.other_channel_id = (i->value);
335                 } else
336                 if (strcmp(i->name, "originator") == 0) {
337                         args.originator = (i->value);
338                 } else
339                 if (strcmp(i->name, "formats") == 0) {
340                         args.formats = (i->value);
341                 } else
342                 {}
343         }
344         if (ast_ari_channels_create_parse_body(body, &args)) {
345                 ast_ari_response_alloc_failed(response);
346                 goto fin;
347         }
348         ast_ari_channels_create(headers, &args, response);
349 #if defined(AST_DEVMODE)
350         code = response->response_code;
351
352         switch (code) {
353         case 0: /* Implementation is still a stub, or the code wasn't set */
354                 is_valid = response->message == NULL;
355                 break;
356         case 500: /* Internal Server Error */
357         case 501: /* Not Implemented */
358         case 409: /* Channel with given unique ID already exists. */
359                 is_valid = 1;
360                 break;
361         default:
362                 if (200 <= code && code <= 299) {
363                         is_valid = ast_ari_validate_channel(
364                                 response->message);
365                 } else {
366                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/create\n", code);
367                         is_valid = 0;
368                 }
369         }
370
371         if (!is_valid) {
372                 ast_log(LOG_ERROR, "Response validation failed for /channels/create\n");
373                 ast_ari_response_error(response, 500,
374                         "Internal Server Error", "Response validation failed");
375         }
376 #endif /* AST_DEVMODE */
377
378 fin: __attribute__((unused))
379         return;
380 }
381 /*!
382  * \brief Parameter parsing callback for /channels/{channelId}.
383  * \param get_params GET parameters in the HTTP request.
384  * \param path_vars Path variables extracted from the request.
385  * \param headers HTTP headers.
386  * \param[out] response Response to the HTTP request.
387  */
388 static void ast_ari_channels_get_cb(
389         struct ast_tcptls_session_instance *ser,
390         struct ast_variable *get_params, struct ast_variable *path_vars,
391         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
392 {
393         struct ast_ari_channels_get_args args = {};
394         struct ast_variable *i;
395 #if defined(AST_DEVMODE)
396         int is_valid;
397         int code;
398 #endif /* AST_DEVMODE */
399
400         for (i = path_vars; i; i = i->next) {
401                 if (strcmp(i->name, "channelId") == 0) {
402                         args.channel_id = (i->value);
403                 } else
404                 {}
405         }
406         ast_ari_channels_get(headers, &args, response);
407 #if defined(AST_DEVMODE)
408         code = response->response_code;
409
410         switch (code) {
411         case 0: /* Implementation is still a stub, or the code wasn't set */
412                 is_valid = response->message == NULL;
413                 break;
414         case 500: /* Internal Server Error */
415         case 501: /* Not Implemented */
416         case 404: /* Channel not found */
417                 is_valid = 1;
418                 break;
419         default:
420                 if (200 <= code && code <= 299) {
421                         is_valid = ast_ari_validate_channel(
422                                 response->message);
423                 } else {
424                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}\n", code);
425                         is_valid = 0;
426                 }
427         }
428
429         if (!is_valid) {
430                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}\n");
431                 ast_ari_response_error(response, 500,
432                         "Internal Server Error", "Response validation failed");
433         }
434 #endif /* AST_DEVMODE */
435
436 fin: __attribute__((unused))
437         return;
438 }
439 int ast_ari_channels_originate_with_id_parse_body(
440         struct ast_json *body,
441         struct ast_ari_channels_originate_with_id_args *args)
442 {
443         struct ast_json *field;
444         /* Parse query parameters out of it */
445         field = ast_json_object_get(body, "endpoint");
446         if (field) {
447                 args->endpoint = ast_json_string_get(field);
448         }
449         field = ast_json_object_get(body, "extension");
450         if (field) {
451                 args->extension = ast_json_string_get(field);
452         }
453         field = ast_json_object_get(body, "context");
454         if (field) {
455                 args->context = ast_json_string_get(field);
456         }
457         field = ast_json_object_get(body, "priority");
458         if (field) {
459                 args->priority = ast_json_integer_get(field);
460         }
461         field = ast_json_object_get(body, "label");
462         if (field) {
463                 args->label = ast_json_string_get(field);
464         }
465         field = ast_json_object_get(body, "app");
466         if (field) {
467                 args->app = ast_json_string_get(field);
468         }
469         field = ast_json_object_get(body, "appArgs");
470         if (field) {
471                 args->app_args = ast_json_string_get(field);
472         }
473         field = ast_json_object_get(body, "callerId");
474         if (field) {
475                 args->caller_id = ast_json_string_get(field);
476         }
477         field = ast_json_object_get(body, "timeout");
478         if (field) {
479                 args->timeout = ast_json_integer_get(field);
480         }
481         field = ast_json_object_get(body, "otherChannelId");
482         if (field) {
483                 args->other_channel_id = ast_json_string_get(field);
484         }
485         field = ast_json_object_get(body, "originator");
486         if (field) {
487                 args->originator = ast_json_string_get(field);
488         }
489         field = ast_json_object_get(body, "formats");
490         if (field) {
491                 args->formats = ast_json_string_get(field);
492         }
493         return 0;
494 }
495
496 /*!
497  * \brief Parameter parsing callback for /channels/{channelId}.
498  * \param get_params GET parameters in the HTTP request.
499  * \param path_vars Path variables extracted from the request.
500  * \param headers HTTP headers.
501  * \param[out] response Response to the HTTP request.
502  */
503 static void ast_ari_channels_originate_with_id_cb(
504         struct ast_tcptls_session_instance *ser,
505         struct ast_variable *get_params, struct ast_variable *path_vars,
506         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
507 {
508         struct ast_ari_channels_originate_with_id_args args = {};
509         struct ast_variable *i;
510 #if defined(AST_DEVMODE)
511         int is_valid;
512         int code;
513 #endif /* AST_DEVMODE */
514
515         for (i = get_params; i; i = i->next) {
516                 if (strcmp(i->name, "endpoint") == 0) {
517                         args.endpoint = (i->value);
518                 } else
519                 if (strcmp(i->name, "extension") == 0) {
520                         args.extension = (i->value);
521                 } else
522                 if (strcmp(i->name, "context") == 0) {
523                         args.context = (i->value);
524                 } else
525                 if (strcmp(i->name, "priority") == 0) {
526                         args.priority = atol(i->value);
527                 } else
528                 if (strcmp(i->name, "label") == 0) {
529                         args.label = (i->value);
530                 } else
531                 if (strcmp(i->name, "app") == 0) {
532                         args.app = (i->value);
533                 } else
534                 if (strcmp(i->name, "appArgs") == 0) {
535                         args.app_args = (i->value);
536                 } else
537                 if (strcmp(i->name, "callerId") == 0) {
538                         args.caller_id = (i->value);
539                 } else
540                 if (strcmp(i->name, "timeout") == 0) {
541                         args.timeout = atoi(i->value);
542                 } else
543                 if (strcmp(i->name, "otherChannelId") == 0) {
544                         args.other_channel_id = (i->value);
545                 } else
546                 if (strcmp(i->name, "originator") == 0) {
547                         args.originator = (i->value);
548                 } else
549                 if (strcmp(i->name, "formats") == 0) {
550                         args.formats = (i->value);
551                 } else
552                 {}
553         }
554         for (i = path_vars; i; i = i->next) {
555                 if (strcmp(i->name, "channelId") == 0) {
556                         args.channel_id = (i->value);
557                 } else
558                 {}
559         }
560         args.variables = body;
561         ast_ari_channels_originate_with_id(headers, &args, response);
562 #if defined(AST_DEVMODE)
563         code = response->response_code;
564
565         switch (code) {
566         case 0: /* Implementation is still a stub, or the code wasn't set */
567                 is_valid = response->message == NULL;
568                 break;
569         case 500: /* Internal Server Error */
570         case 501: /* Not Implemented */
571         case 400: /* Invalid parameters for originating a channel. */
572         case 409: /* Channel with given unique ID already exists. */
573                 is_valid = 1;
574                 break;
575         default:
576                 if (200 <= code && code <= 299) {
577                         is_valid = ast_ari_validate_channel(
578                                 response->message);
579                 } else {
580                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}\n", code);
581                         is_valid = 0;
582                 }
583         }
584
585         if (!is_valid) {
586                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}\n");
587                 ast_ari_response_error(response, 500,
588                         "Internal Server Error", "Response validation failed");
589         }
590 #endif /* AST_DEVMODE */
591
592 fin: __attribute__((unused))
593         return;
594 }
595 int ast_ari_channels_hangup_parse_body(
596         struct ast_json *body,
597         struct ast_ari_channels_hangup_args *args)
598 {
599         struct ast_json *field;
600         /* Parse query parameters out of it */
601         field = ast_json_object_get(body, "reason");
602         if (field) {
603                 args->reason = ast_json_string_get(field);
604         }
605         return 0;
606 }
607
608 /*!
609  * \brief Parameter parsing callback for /channels/{channelId}.
610  * \param get_params GET parameters in the HTTP request.
611  * \param path_vars Path variables extracted from the request.
612  * \param headers HTTP headers.
613  * \param[out] response Response to the HTTP request.
614  */
615 static void ast_ari_channels_hangup_cb(
616         struct ast_tcptls_session_instance *ser,
617         struct ast_variable *get_params, struct ast_variable *path_vars,
618         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
619 {
620         struct ast_ari_channels_hangup_args args = {};
621         struct ast_variable *i;
622 #if defined(AST_DEVMODE)
623         int is_valid;
624         int code;
625 #endif /* AST_DEVMODE */
626
627         for (i = get_params; i; i = i->next) {
628                 if (strcmp(i->name, "reason") == 0) {
629                         args.reason = (i->value);
630                 } else
631                 {}
632         }
633         for (i = path_vars; i; i = i->next) {
634                 if (strcmp(i->name, "channelId") == 0) {
635                         args.channel_id = (i->value);
636                 } else
637                 {}
638         }
639         if (ast_ari_channels_hangup_parse_body(body, &args)) {
640                 ast_ari_response_alloc_failed(response);
641                 goto fin;
642         }
643         ast_ari_channels_hangup(headers, &args, response);
644 #if defined(AST_DEVMODE)
645         code = response->response_code;
646
647         switch (code) {
648         case 0: /* Implementation is still a stub, or the code wasn't set */
649                 is_valid = response->message == NULL;
650                 break;
651         case 500: /* Internal Server Error */
652         case 501: /* Not Implemented */
653         case 400: /* Invalid reason for hangup provided */
654         case 404: /* Channel not found */
655                 is_valid = 1;
656                 break;
657         default:
658                 if (200 <= code && code <= 299) {
659                         is_valid = ast_ari_validate_void(
660                                 response->message);
661                 } else {
662                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}\n", code);
663                         is_valid = 0;
664                 }
665         }
666
667         if (!is_valid) {
668                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}\n");
669                 ast_ari_response_error(response, 500,
670                         "Internal Server Error", "Response validation failed");
671         }
672 #endif /* AST_DEVMODE */
673
674 fin: __attribute__((unused))
675         return;
676 }
677 int ast_ari_channels_continue_in_dialplan_parse_body(
678         struct ast_json *body,
679         struct ast_ari_channels_continue_in_dialplan_args *args)
680 {
681         struct ast_json *field;
682         /* Parse query parameters out of it */
683         field = ast_json_object_get(body, "context");
684         if (field) {
685                 args->context = ast_json_string_get(field);
686         }
687         field = ast_json_object_get(body, "extension");
688         if (field) {
689                 args->extension = ast_json_string_get(field);
690         }
691         field = ast_json_object_get(body, "priority");
692         if (field) {
693                 args->priority = ast_json_integer_get(field);
694         }
695         field = ast_json_object_get(body, "label");
696         if (field) {
697                 args->label = ast_json_string_get(field);
698         }
699         return 0;
700 }
701
702 /*!
703  * \brief Parameter parsing callback for /channels/{channelId}/continue.
704  * \param get_params GET parameters in the HTTP request.
705  * \param path_vars Path variables extracted from the request.
706  * \param headers HTTP headers.
707  * \param[out] response Response to the HTTP request.
708  */
709 static void ast_ari_channels_continue_in_dialplan_cb(
710         struct ast_tcptls_session_instance *ser,
711         struct ast_variable *get_params, struct ast_variable *path_vars,
712         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
713 {
714         struct ast_ari_channels_continue_in_dialplan_args args = {};
715         struct ast_variable *i;
716 #if defined(AST_DEVMODE)
717         int is_valid;
718         int code;
719 #endif /* AST_DEVMODE */
720
721         for (i = get_params; i; i = i->next) {
722                 if (strcmp(i->name, "context") == 0) {
723                         args.context = (i->value);
724                 } else
725                 if (strcmp(i->name, "extension") == 0) {
726                         args.extension = (i->value);
727                 } else
728                 if (strcmp(i->name, "priority") == 0) {
729                         args.priority = atoi(i->value);
730                 } else
731                 if (strcmp(i->name, "label") == 0) {
732                         args.label = (i->value);
733                 } else
734                 {}
735         }
736         for (i = path_vars; i; i = i->next) {
737                 if (strcmp(i->name, "channelId") == 0) {
738                         args.channel_id = (i->value);
739                 } else
740                 {}
741         }
742         if (ast_ari_channels_continue_in_dialplan_parse_body(body, &args)) {
743                 ast_ari_response_alloc_failed(response);
744                 goto fin;
745         }
746         ast_ari_channels_continue_in_dialplan(headers, &args, response);
747 #if defined(AST_DEVMODE)
748         code = response->response_code;
749
750         switch (code) {
751         case 0: /* Implementation is still a stub, or the code wasn't set */
752                 is_valid = response->message == NULL;
753                 break;
754         case 500: /* Internal Server Error */
755         case 501: /* Not Implemented */
756         case 404: /* Channel not found */
757         case 409: /* Channel not in a Stasis application */
758         case 412: /* Channel in invalid state */
759                 is_valid = 1;
760                 break;
761         default:
762                 if (200 <= code && code <= 299) {
763                         is_valid = ast_ari_validate_void(
764                                 response->message);
765                 } else {
766                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/continue\n", code);
767                         is_valid = 0;
768                 }
769         }
770
771         if (!is_valid) {
772                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/continue\n");
773                 ast_ari_response_error(response, 500,
774                         "Internal Server Error", "Response validation failed");
775         }
776 #endif /* AST_DEVMODE */
777
778 fin: __attribute__((unused))
779         return;
780 }
781 int ast_ari_channels_move_parse_body(
782         struct ast_json *body,
783         struct ast_ari_channels_move_args *args)
784 {
785         struct ast_json *field;
786         /* Parse query parameters out of it */
787         field = ast_json_object_get(body, "app");
788         if (field) {
789                 args->app = ast_json_string_get(field);
790         }
791         field = ast_json_object_get(body, "appArgs");
792         if (field) {
793                 args->app_args = ast_json_string_get(field);
794         }
795         return 0;
796 }
797
798 /*!
799  * \brief Parameter parsing callback for /channels/{channelId}/move.
800  * \param get_params GET parameters in the HTTP request.
801  * \param path_vars Path variables extracted from the request.
802  * \param headers HTTP headers.
803  * \param[out] response Response to the HTTP request.
804  */
805 static void ast_ari_channels_move_cb(
806         struct ast_tcptls_session_instance *ser,
807         struct ast_variable *get_params, struct ast_variable *path_vars,
808         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
809 {
810         struct ast_ari_channels_move_args args = {};
811         struct ast_variable *i;
812 #if defined(AST_DEVMODE)
813         int is_valid;
814         int code;
815 #endif /* AST_DEVMODE */
816
817         for (i = get_params; i; i = i->next) {
818                 if (strcmp(i->name, "app") == 0) {
819                         args.app = (i->value);
820                 } else
821                 if (strcmp(i->name, "appArgs") == 0) {
822                         args.app_args = (i->value);
823                 } else
824                 {}
825         }
826         for (i = path_vars; i; i = i->next) {
827                 if (strcmp(i->name, "channelId") == 0) {
828                         args.channel_id = (i->value);
829                 } else
830                 {}
831         }
832         if (ast_ari_channels_move_parse_body(body, &args)) {
833                 ast_ari_response_alloc_failed(response);
834                 goto fin;
835         }
836         ast_ari_channels_move(headers, &args, response);
837 #if defined(AST_DEVMODE)
838         code = response->response_code;
839
840         switch (code) {
841         case 0: /* Implementation is still a stub, or the code wasn't set */
842                 is_valid = response->message == NULL;
843                 break;
844         case 500: /* Internal Server Error */
845         case 501: /* Not Implemented */
846         case 404: /* Channel not found */
847         case 409: /* Channel not in a Stasis application */
848                 is_valid = 1;
849                 break;
850         default:
851                 if (200 <= code && code <= 299) {
852                         is_valid = ast_ari_validate_void(
853                                 response->message);
854                 } else {
855                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/move\n", code);
856                         is_valid = 0;
857                 }
858         }
859
860         if (!is_valid) {
861                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/move\n");
862                 ast_ari_response_error(response, 500,
863                         "Internal Server Error", "Response validation failed");
864         }
865 #endif /* AST_DEVMODE */
866
867 fin: __attribute__((unused))
868         return;
869 }
870 int ast_ari_channels_redirect_parse_body(
871         struct ast_json *body,
872         struct ast_ari_channels_redirect_args *args)
873 {
874         struct ast_json *field;
875         /* Parse query parameters out of it */
876         field = ast_json_object_get(body, "endpoint");
877         if (field) {
878                 args->endpoint = ast_json_string_get(field);
879         }
880         return 0;
881 }
882
883 /*!
884  * \brief Parameter parsing callback for /channels/{channelId}/redirect.
885  * \param get_params GET parameters in the HTTP request.
886  * \param path_vars Path variables extracted from the request.
887  * \param headers HTTP headers.
888  * \param[out] response Response to the HTTP request.
889  */
890 static void ast_ari_channels_redirect_cb(
891         struct ast_tcptls_session_instance *ser,
892         struct ast_variable *get_params, struct ast_variable *path_vars,
893         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
894 {
895         struct ast_ari_channels_redirect_args args = {};
896         struct ast_variable *i;
897 #if defined(AST_DEVMODE)
898         int is_valid;
899         int code;
900 #endif /* AST_DEVMODE */
901
902         for (i = get_params; i; i = i->next) {
903                 if (strcmp(i->name, "endpoint") == 0) {
904                         args.endpoint = (i->value);
905                 } else
906                 {}
907         }
908         for (i = path_vars; i; i = i->next) {
909                 if (strcmp(i->name, "channelId") == 0) {
910                         args.channel_id = (i->value);
911                 } else
912                 {}
913         }
914         if (ast_ari_channels_redirect_parse_body(body, &args)) {
915                 ast_ari_response_alloc_failed(response);
916                 goto fin;
917         }
918         ast_ari_channels_redirect(headers, &args, response);
919 #if defined(AST_DEVMODE)
920         code = response->response_code;
921
922         switch (code) {
923         case 0: /* Implementation is still a stub, or the code wasn't set */
924                 is_valid = response->message == NULL;
925                 break;
926         case 500: /* Internal Server Error */
927         case 501: /* Not Implemented */
928         case 400: /* Endpoint parameter not provided */
929         case 404: /* Channel or endpoint not found */
930         case 409: /* Channel not in a Stasis application */
931         case 422: /* Endpoint is not the same type as the channel */
932         case 412: /* Channel in invalid state */
933                 is_valid = 1;
934                 break;
935         default:
936                 if (200 <= code && code <= 299) {
937                         is_valid = ast_ari_validate_void(
938                                 response->message);
939                 } else {
940                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/redirect\n", code);
941                         is_valid = 0;
942                 }
943         }
944
945         if (!is_valid) {
946                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/redirect\n");
947                 ast_ari_response_error(response, 500,
948                         "Internal Server Error", "Response validation failed");
949         }
950 #endif /* AST_DEVMODE */
951
952 fin: __attribute__((unused))
953         return;
954 }
955 /*!
956  * \brief Parameter parsing callback for /channels/{channelId}/answer.
957  * \param get_params GET parameters in the HTTP request.
958  * \param path_vars Path variables extracted from the request.
959  * \param headers HTTP headers.
960  * \param[out] response Response to the HTTP request.
961  */
962 static void ast_ari_channels_answer_cb(
963         struct ast_tcptls_session_instance *ser,
964         struct ast_variable *get_params, struct ast_variable *path_vars,
965         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
966 {
967         struct ast_ari_channels_answer_args args = {};
968         struct ast_variable *i;
969 #if defined(AST_DEVMODE)
970         int is_valid;
971         int code;
972 #endif /* AST_DEVMODE */
973
974         for (i = path_vars; i; i = i->next) {
975                 if (strcmp(i->name, "channelId") == 0) {
976                         args.channel_id = (i->value);
977                 } else
978                 {}
979         }
980         ast_ari_channels_answer(headers, &args, response);
981 #if defined(AST_DEVMODE)
982         code = response->response_code;
983
984         switch (code) {
985         case 0: /* Implementation is still a stub, or the code wasn't set */
986                 is_valid = response->message == NULL;
987                 break;
988         case 500: /* Internal Server Error */
989         case 501: /* Not Implemented */
990         case 404: /* Channel not found */
991         case 409: /* Channel not in a Stasis application */
992         case 412: /* Channel in invalid state */
993                 is_valid = 1;
994                 break;
995         default:
996                 if (200 <= code && code <= 299) {
997                         is_valid = ast_ari_validate_void(
998                                 response->message);
999                 } else {
1000                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/answer\n", code);
1001                         is_valid = 0;
1002                 }
1003         }
1004
1005         if (!is_valid) {
1006                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/answer\n");
1007                 ast_ari_response_error(response, 500,
1008                         "Internal Server Error", "Response validation failed");
1009         }
1010 #endif /* AST_DEVMODE */
1011
1012 fin: __attribute__((unused))
1013         return;
1014 }
1015 /*!
1016  * \brief Parameter parsing callback for /channels/{channelId}/ring.
1017  * \param get_params GET parameters in the HTTP request.
1018  * \param path_vars Path variables extracted from the request.
1019  * \param headers HTTP headers.
1020  * \param[out] response Response to the HTTP request.
1021  */
1022 static void ast_ari_channels_ring_cb(
1023         struct ast_tcptls_session_instance *ser,
1024         struct ast_variable *get_params, struct ast_variable *path_vars,
1025         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1026 {
1027         struct ast_ari_channels_ring_args args = {};
1028         struct ast_variable *i;
1029 #if defined(AST_DEVMODE)
1030         int is_valid;
1031         int code;
1032 #endif /* AST_DEVMODE */
1033
1034         for (i = path_vars; i; i = i->next) {
1035                 if (strcmp(i->name, "channelId") == 0) {
1036                         args.channel_id = (i->value);
1037                 } else
1038                 {}
1039         }
1040         ast_ari_channels_ring(headers, &args, response);
1041 #if defined(AST_DEVMODE)
1042         code = response->response_code;
1043
1044         switch (code) {
1045         case 0: /* Implementation is still a stub, or the code wasn't set */
1046                 is_valid = response->message == NULL;
1047                 break;
1048         case 500: /* Internal Server Error */
1049         case 501: /* Not Implemented */
1050         case 404: /* Channel not found */
1051         case 409: /* Channel not in a Stasis application */
1052         case 412: /* Channel in invalid state */
1053                 is_valid = 1;
1054                 break;
1055         default:
1056                 if (200 <= code && code <= 299) {
1057                         is_valid = ast_ari_validate_void(
1058                                 response->message);
1059                 } else {
1060                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/ring\n", code);
1061                         is_valid = 0;
1062                 }
1063         }
1064
1065         if (!is_valid) {
1066                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/ring\n");
1067                 ast_ari_response_error(response, 500,
1068                         "Internal Server Error", "Response validation failed");
1069         }
1070 #endif /* AST_DEVMODE */
1071
1072 fin: __attribute__((unused))
1073         return;
1074 }
1075 /*!
1076  * \brief Parameter parsing callback for /channels/{channelId}/ring.
1077  * \param get_params GET parameters in the HTTP request.
1078  * \param path_vars Path variables extracted from the request.
1079  * \param headers HTTP headers.
1080  * \param[out] response Response to the HTTP request.
1081  */
1082 static void ast_ari_channels_ring_stop_cb(
1083         struct ast_tcptls_session_instance *ser,
1084         struct ast_variable *get_params, struct ast_variable *path_vars,
1085         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1086 {
1087         struct ast_ari_channels_ring_stop_args args = {};
1088         struct ast_variable *i;
1089 #if defined(AST_DEVMODE)
1090         int is_valid;
1091         int code;
1092 #endif /* AST_DEVMODE */
1093
1094         for (i = path_vars; i; i = i->next) {
1095                 if (strcmp(i->name, "channelId") == 0) {
1096                         args.channel_id = (i->value);
1097                 } else
1098                 {}
1099         }
1100         ast_ari_channels_ring_stop(headers, &args, response);
1101 #if defined(AST_DEVMODE)
1102         code = response->response_code;
1103
1104         switch (code) {
1105         case 0: /* Implementation is still a stub, or the code wasn't set */
1106                 is_valid = response->message == NULL;
1107                 break;
1108         case 500: /* Internal Server Error */
1109         case 501: /* Not Implemented */
1110         case 404: /* Channel not found */
1111         case 409: /* Channel not in a Stasis application */
1112         case 412: /* Channel in invalid state */
1113                 is_valid = 1;
1114                 break;
1115         default:
1116                 if (200 <= code && code <= 299) {
1117                         is_valid = ast_ari_validate_void(
1118                                 response->message);
1119                 } else {
1120                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/ring\n", code);
1121                         is_valid = 0;
1122                 }
1123         }
1124
1125         if (!is_valid) {
1126                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/ring\n");
1127                 ast_ari_response_error(response, 500,
1128                         "Internal Server Error", "Response validation failed");
1129         }
1130 #endif /* AST_DEVMODE */
1131
1132 fin: __attribute__((unused))
1133         return;
1134 }
1135 int ast_ari_channels_send_dtmf_parse_body(
1136         struct ast_json *body,
1137         struct ast_ari_channels_send_dtmf_args *args)
1138 {
1139         struct ast_json *field;
1140         /* Parse query parameters out of it */
1141         field = ast_json_object_get(body, "dtmf");
1142         if (field) {
1143                 args->dtmf = ast_json_string_get(field);
1144         }
1145         field = ast_json_object_get(body, "before");
1146         if (field) {
1147                 args->before = ast_json_integer_get(field);
1148         }
1149         field = ast_json_object_get(body, "between");
1150         if (field) {
1151                 args->between = ast_json_integer_get(field);
1152         }
1153         field = ast_json_object_get(body, "duration");
1154         if (field) {
1155                 args->duration = ast_json_integer_get(field);
1156         }
1157         field = ast_json_object_get(body, "after");
1158         if (field) {
1159                 args->after = ast_json_integer_get(field);
1160         }
1161         return 0;
1162 }
1163
1164 /*!
1165  * \brief Parameter parsing callback for /channels/{channelId}/dtmf.
1166  * \param get_params GET parameters in the HTTP request.
1167  * \param path_vars Path variables extracted from the request.
1168  * \param headers HTTP headers.
1169  * \param[out] response Response to the HTTP request.
1170  */
1171 static void ast_ari_channels_send_dtmf_cb(
1172         struct ast_tcptls_session_instance *ser,
1173         struct ast_variable *get_params, struct ast_variable *path_vars,
1174         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1175 {
1176         struct ast_ari_channels_send_dtmf_args args = {};
1177         struct ast_variable *i;
1178 #if defined(AST_DEVMODE)
1179         int is_valid;
1180         int code;
1181 #endif /* AST_DEVMODE */
1182
1183         for (i = get_params; i; i = i->next) {
1184                 if (strcmp(i->name, "dtmf") == 0) {
1185                         args.dtmf = (i->value);
1186                 } else
1187                 if (strcmp(i->name, "before") == 0) {
1188                         args.before = atoi(i->value);
1189                 } else
1190                 if (strcmp(i->name, "between") == 0) {
1191                         args.between = atoi(i->value);
1192                 } else
1193                 if (strcmp(i->name, "duration") == 0) {
1194                         args.duration = atoi(i->value);
1195                 } else
1196                 if (strcmp(i->name, "after") == 0) {
1197                         args.after = atoi(i->value);
1198                 } else
1199                 {}
1200         }
1201         for (i = path_vars; i; i = i->next) {
1202                 if (strcmp(i->name, "channelId") == 0) {
1203                         args.channel_id = (i->value);
1204                 } else
1205                 {}
1206         }
1207         if (ast_ari_channels_send_dtmf_parse_body(body, &args)) {
1208                 ast_ari_response_alloc_failed(response);
1209                 goto fin;
1210         }
1211         ast_ari_channels_send_dtmf(headers, &args, response);
1212 #if defined(AST_DEVMODE)
1213         code = response->response_code;
1214
1215         switch (code) {
1216         case 0: /* Implementation is still a stub, or the code wasn't set */
1217                 is_valid = response->message == NULL;
1218                 break;
1219         case 500: /* Internal Server Error */
1220         case 501: /* Not Implemented */
1221         case 400: /* DTMF is required */
1222         case 404: /* Channel not found */
1223         case 409: /* Channel not in a Stasis application */
1224         case 412: /* Channel in invalid state */
1225                 is_valid = 1;
1226                 break;
1227         default:
1228                 if (200 <= code && code <= 299) {
1229                         is_valid = ast_ari_validate_void(
1230                                 response->message);
1231                 } else {
1232                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/dtmf\n", code);
1233                         is_valid = 0;
1234                 }
1235         }
1236
1237         if (!is_valid) {
1238                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/dtmf\n");
1239                 ast_ari_response_error(response, 500,
1240                         "Internal Server Error", "Response validation failed");
1241         }
1242 #endif /* AST_DEVMODE */
1243
1244 fin: __attribute__((unused))
1245         return;
1246 }
1247 int ast_ari_channels_mute_parse_body(
1248         struct ast_json *body,
1249         struct ast_ari_channels_mute_args *args)
1250 {
1251         struct ast_json *field;
1252         /* Parse query parameters out of it */
1253         field = ast_json_object_get(body, "direction");
1254         if (field) {
1255                 args->direction = ast_json_string_get(field);
1256         }
1257         return 0;
1258 }
1259
1260 /*!
1261  * \brief Parameter parsing callback for /channels/{channelId}/mute.
1262  * \param get_params GET parameters in the HTTP request.
1263  * \param path_vars Path variables extracted from the request.
1264  * \param headers HTTP headers.
1265  * \param[out] response Response to the HTTP request.
1266  */
1267 static void ast_ari_channels_mute_cb(
1268         struct ast_tcptls_session_instance *ser,
1269         struct ast_variable *get_params, struct ast_variable *path_vars,
1270         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1271 {
1272         struct ast_ari_channels_mute_args args = {};
1273         struct ast_variable *i;
1274 #if defined(AST_DEVMODE)
1275         int is_valid;
1276         int code;
1277 #endif /* AST_DEVMODE */
1278
1279         for (i = get_params; i; i = i->next) {
1280                 if (strcmp(i->name, "direction") == 0) {
1281                         args.direction = (i->value);
1282                 } else
1283                 {}
1284         }
1285         for (i = path_vars; i; i = i->next) {
1286                 if (strcmp(i->name, "channelId") == 0) {
1287                         args.channel_id = (i->value);
1288                 } else
1289                 {}
1290         }
1291         if (ast_ari_channels_mute_parse_body(body, &args)) {
1292                 ast_ari_response_alloc_failed(response);
1293                 goto fin;
1294         }
1295         ast_ari_channels_mute(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: /* Channel not found */
1306         case 409: /* Channel not in a Stasis application */
1307         case 412: /* Channel in invalid state */
1308                 is_valid = 1;
1309                 break;
1310         default:
1311                 if (200 <= code && code <= 299) {
1312                         is_valid = ast_ari_validate_void(
1313                                 response->message);
1314                 } else {
1315                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/mute\n", code);
1316                         is_valid = 0;
1317                 }
1318         }
1319
1320         if (!is_valid) {
1321                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/mute\n");
1322                 ast_ari_response_error(response, 500,
1323                         "Internal Server Error", "Response validation failed");
1324         }
1325 #endif /* AST_DEVMODE */
1326
1327 fin: __attribute__((unused))
1328         return;
1329 }
1330 int ast_ari_channels_unmute_parse_body(
1331         struct ast_json *body,
1332         struct ast_ari_channels_unmute_args *args)
1333 {
1334         struct ast_json *field;
1335         /* Parse query parameters out of it */
1336         field = ast_json_object_get(body, "direction");
1337         if (field) {
1338                 args->direction = ast_json_string_get(field);
1339         }
1340         return 0;
1341 }
1342
1343 /*!
1344  * \brief Parameter parsing callback for /channels/{channelId}/mute.
1345  * \param get_params GET parameters in the HTTP request.
1346  * \param path_vars Path variables extracted from the request.
1347  * \param headers HTTP headers.
1348  * \param[out] response Response to the HTTP request.
1349  */
1350 static void ast_ari_channels_unmute_cb(
1351         struct ast_tcptls_session_instance *ser,
1352         struct ast_variable *get_params, struct ast_variable *path_vars,
1353         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1354 {
1355         struct ast_ari_channels_unmute_args args = {};
1356         struct ast_variable *i;
1357 #if defined(AST_DEVMODE)
1358         int is_valid;
1359         int code;
1360 #endif /* AST_DEVMODE */
1361
1362         for (i = get_params; i; i = i->next) {
1363                 if (strcmp(i->name, "direction") == 0) {
1364                         args.direction = (i->value);
1365                 } else
1366                 {}
1367         }
1368         for (i = path_vars; i; i = i->next) {
1369                 if (strcmp(i->name, "channelId") == 0) {
1370                         args.channel_id = (i->value);
1371                 } else
1372                 {}
1373         }
1374         if (ast_ari_channels_unmute_parse_body(body, &args)) {
1375                 ast_ari_response_alloc_failed(response);
1376                 goto fin;
1377         }
1378         ast_ari_channels_unmute(headers, &args, response);
1379 #if defined(AST_DEVMODE)
1380         code = response->response_code;
1381
1382         switch (code) {
1383         case 0: /* Implementation is still a stub, or the code wasn't set */
1384                 is_valid = response->message == NULL;
1385                 break;
1386         case 500: /* Internal Server Error */
1387         case 501: /* Not Implemented */
1388         case 404: /* Channel not found */
1389         case 409: /* Channel not in a Stasis application */
1390         case 412: /* Channel in invalid state */
1391                 is_valid = 1;
1392                 break;
1393         default:
1394                 if (200 <= code && code <= 299) {
1395                         is_valid = ast_ari_validate_void(
1396                                 response->message);
1397                 } else {
1398                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/mute\n", code);
1399                         is_valid = 0;
1400                 }
1401         }
1402
1403         if (!is_valid) {
1404                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/mute\n");
1405                 ast_ari_response_error(response, 500,
1406                         "Internal Server Error", "Response validation failed");
1407         }
1408 #endif /* AST_DEVMODE */
1409
1410 fin: __attribute__((unused))
1411         return;
1412 }
1413 /*!
1414  * \brief Parameter parsing callback for /channels/{channelId}/hold.
1415  * \param get_params GET parameters in the HTTP request.
1416  * \param path_vars Path variables extracted from the request.
1417  * \param headers HTTP headers.
1418  * \param[out] response Response to the HTTP request.
1419  */
1420 static void ast_ari_channels_hold_cb(
1421         struct ast_tcptls_session_instance *ser,
1422         struct ast_variable *get_params, struct ast_variable *path_vars,
1423         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1424 {
1425         struct ast_ari_channels_hold_args args = {};
1426         struct ast_variable *i;
1427 #if defined(AST_DEVMODE)
1428         int is_valid;
1429         int code;
1430 #endif /* AST_DEVMODE */
1431
1432         for (i = path_vars; i; i = i->next) {
1433                 if (strcmp(i->name, "channelId") == 0) {
1434                         args.channel_id = (i->value);
1435                 } else
1436                 {}
1437         }
1438         ast_ari_channels_hold(headers, &args, response);
1439 #if defined(AST_DEVMODE)
1440         code = response->response_code;
1441
1442         switch (code) {
1443         case 0: /* Implementation is still a stub, or the code wasn't set */
1444                 is_valid = response->message == NULL;
1445                 break;
1446         case 500: /* Internal Server Error */
1447         case 501: /* Not Implemented */
1448         case 404: /* Channel not found */
1449         case 409: /* Channel not in a Stasis application */
1450         case 412: /* Channel in invalid state */
1451                 is_valid = 1;
1452                 break;
1453         default:
1454                 if (200 <= code && code <= 299) {
1455                         is_valid = ast_ari_validate_void(
1456                                 response->message);
1457                 } else {
1458                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/hold\n", code);
1459                         is_valid = 0;
1460                 }
1461         }
1462
1463         if (!is_valid) {
1464                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/hold\n");
1465                 ast_ari_response_error(response, 500,
1466                         "Internal Server Error", "Response validation failed");
1467         }
1468 #endif /* AST_DEVMODE */
1469
1470 fin: __attribute__((unused))
1471         return;
1472 }
1473 /*!
1474  * \brief Parameter parsing callback for /channels/{channelId}/hold.
1475  * \param get_params GET parameters in the HTTP request.
1476  * \param path_vars Path variables extracted from the request.
1477  * \param headers HTTP headers.
1478  * \param[out] response Response to the HTTP request.
1479  */
1480 static void ast_ari_channels_unhold_cb(
1481         struct ast_tcptls_session_instance *ser,
1482         struct ast_variable *get_params, struct ast_variable *path_vars,
1483         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1484 {
1485         struct ast_ari_channels_unhold_args args = {};
1486         struct ast_variable *i;
1487 #if defined(AST_DEVMODE)
1488         int is_valid;
1489         int code;
1490 #endif /* AST_DEVMODE */
1491
1492         for (i = path_vars; i; i = i->next) {
1493                 if (strcmp(i->name, "channelId") == 0) {
1494                         args.channel_id = (i->value);
1495                 } else
1496                 {}
1497         }
1498         ast_ari_channels_unhold(headers, &args, response);
1499 #if defined(AST_DEVMODE)
1500         code = response->response_code;
1501
1502         switch (code) {
1503         case 0: /* Implementation is still a stub, or the code wasn't set */
1504                 is_valid = response->message == NULL;
1505                 break;
1506         case 500: /* Internal Server Error */
1507         case 501: /* Not Implemented */
1508         case 404: /* Channel not found */
1509         case 409: /* Channel not in a Stasis application */
1510         case 412: /* Channel in invalid state */
1511                 is_valid = 1;
1512                 break;
1513         default:
1514                 if (200 <= code && code <= 299) {
1515                         is_valid = ast_ari_validate_void(
1516                                 response->message);
1517                 } else {
1518                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/hold\n", code);
1519                         is_valid = 0;
1520                 }
1521         }
1522
1523         if (!is_valid) {
1524                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/hold\n");
1525                 ast_ari_response_error(response, 500,
1526                         "Internal Server Error", "Response validation failed");
1527         }
1528 #endif /* AST_DEVMODE */
1529
1530 fin: __attribute__((unused))
1531         return;
1532 }
1533 int ast_ari_channels_start_moh_parse_body(
1534         struct ast_json *body,
1535         struct ast_ari_channels_start_moh_args *args)
1536 {
1537         struct ast_json *field;
1538         /* Parse query parameters out of it */
1539         field = ast_json_object_get(body, "mohClass");
1540         if (field) {
1541                 args->moh_class = ast_json_string_get(field);
1542         }
1543         return 0;
1544 }
1545
1546 /*!
1547  * \brief Parameter parsing callback for /channels/{channelId}/moh.
1548  * \param get_params GET parameters in the HTTP request.
1549  * \param path_vars Path variables extracted from the request.
1550  * \param headers HTTP headers.
1551  * \param[out] response Response to the HTTP request.
1552  */
1553 static void ast_ari_channels_start_moh_cb(
1554         struct ast_tcptls_session_instance *ser,
1555         struct ast_variable *get_params, struct ast_variable *path_vars,
1556         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1557 {
1558         struct ast_ari_channels_start_moh_args args = {};
1559         struct ast_variable *i;
1560 #if defined(AST_DEVMODE)
1561         int is_valid;
1562         int code;
1563 #endif /* AST_DEVMODE */
1564
1565         for (i = get_params; i; i = i->next) {
1566                 if (strcmp(i->name, "mohClass") == 0) {
1567                         args.moh_class = (i->value);
1568                 } else
1569                 {}
1570         }
1571         for (i = path_vars; i; i = i->next) {
1572                 if (strcmp(i->name, "channelId") == 0) {
1573                         args.channel_id = (i->value);
1574                 } else
1575                 {}
1576         }
1577         if (ast_ari_channels_start_moh_parse_body(body, &args)) {
1578                 ast_ari_response_alloc_failed(response);
1579                 goto fin;
1580         }
1581         ast_ari_channels_start_moh(headers, &args, response);
1582 #if defined(AST_DEVMODE)
1583         code = response->response_code;
1584
1585         switch (code) {
1586         case 0: /* Implementation is still a stub, or the code wasn't set */
1587                 is_valid = response->message == NULL;
1588                 break;
1589         case 500: /* Internal Server Error */
1590         case 501: /* Not Implemented */
1591         case 404: /* Channel not found */
1592         case 409: /* Channel not in a Stasis application */
1593         case 412: /* Channel in invalid state */
1594                 is_valid = 1;
1595                 break;
1596         default:
1597                 if (200 <= code && code <= 299) {
1598                         is_valid = ast_ari_validate_void(
1599                                 response->message);
1600                 } else {
1601                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/moh\n", code);
1602                         is_valid = 0;
1603                 }
1604         }
1605
1606         if (!is_valid) {
1607                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/moh\n");
1608                 ast_ari_response_error(response, 500,
1609                         "Internal Server Error", "Response validation failed");
1610         }
1611 #endif /* AST_DEVMODE */
1612
1613 fin: __attribute__((unused))
1614         return;
1615 }
1616 /*!
1617  * \brief Parameter parsing callback for /channels/{channelId}/moh.
1618  * \param get_params GET parameters in the HTTP request.
1619  * \param path_vars Path variables extracted from the request.
1620  * \param headers HTTP headers.
1621  * \param[out] response Response to the HTTP request.
1622  */
1623 static void ast_ari_channels_stop_moh_cb(
1624         struct ast_tcptls_session_instance *ser,
1625         struct ast_variable *get_params, struct ast_variable *path_vars,
1626         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1627 {
1628         struct ast_ari_channels_stop_moh_args args = {};
1629         struct ast_variable *i;
1630 #if defined(AST_DEVMODE)
1631         int is_valid;
1632         int code;
1633 #endif /* AST_DEVMODE */
1634
1635         for (i = path_vars; i; i = i->next) {
1636                 if (strcmp(i->name, "channelId") == 0) {
1637                         args.channel_id = (i->value);
1638                 } else
1639                 {}
1640         }
1641         ast_ari_channels_stop_moh(headers, &args, response);
1642 #if defined(AST_DEVMODE)
1643         code = response->response_code;
1644
1645         switch (code) {
1646         case 0: /* Implementation is still a stub, or the code wasn't set */
1647                 is_valid = response->message == NULL;
1648                 break;
1649         case 500: /* Internal Server Error */
1650         case 501: /* Not Implemented */
1651         case 404: /* Channel not found */
1652         case 409: /* Channel not in a Stasis application */
1653         case 412: /* Channel in invalid state */
1654                 is_valid = 1;
1655                 break;
1656         default:
1657                 if (200 <= code && code <= 299) {
1658                         is_valid = ast_ari_validate_void(
1659                                 response->message);
1660                 } else {
1661                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/moh\n", code);
1662                         is_valid = 0;
1663                 }
1664         }
1665
1666         if (!is_valid) {
1667                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/moh\n");
1668                 ast_ari_response_error(response, 500,
1669                         "Internal Server Error", "Response validation failed");
1670         }
1671 #endif /* AST_DEVMODE */
1672
1673 fin: __attribute__((unused))
1674         return;
1675 }
1676 /*!
1677  * \brief Parameter parsing callback for /channels/{channelId}/silence.
1678  * \param get_params GET parameters in the HTTP request.
1679  * \param path_vars Path variables extracted from the request.
1680  * \param headers HTTP headers.
1681  * \param[out] response Response to the HTTP request.
1682  */
1683 static void ast_ari_channels_start_silence_cb(
1684         struct ast_tcptls_session_instance *ser,
1685         struct ast_variable *get_params, struct ast_variable *path_vars,
1686         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1687 {
1688         struct ast_ari_channels_start_silence_args args = {};
1689         struct ast_variable *i;
1690 #if defined(AST_DEVMODE)
1691         int is_valid;
1692         int code;
1693 #endif /* AST_DEVMODE */
1694
1695         for (i = path_vars; i; i = i->next) {
1696                 if (strcmp(i->name, "channelId") == 0) {
1697                         args.channel_id = (i->value);
1698                 } else
1699                 {}
1700         }
1701         ast_ari_channels_start_silence(headers, &args, response);
1702 #if defined(AST_DEVMODE)
1703         code = response->response_code;
1704
1705         switch (code) {
1706         case 0: /* Implementation is still a stub, or the code wasn't set */
1707                 is_valid = response->message == NULL;
1708                 break;
1709         case 500: /* Internal Server Error */
1710         case 501: /* Not Implemented */
1711         case 404: /* Channel not found */
1712         case 409: /* Channel not in a Stasis application */
1713         case 412: /* Channel in invalid state */
1714                 is_valid = 1;
1715                 break;
1716         default:
1717                 if (200 <= code && code <= 299) {
1718                         is_valid = ast_ari_validate_void(
1719                                 response->message);
1720                 } else {
1721                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/silence\n", code);
1722                         is_valid = 0;
1723                 }
1724         }
1725
1726         if (!is_valid) {
1727                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/silence\n");
1728                 ast_ari_response_error(response, 500,
1729                         "Internal Server Error", "Response validation failed");
1730         }
1731 #endif /* AST_DEVMODE */
1732
1733 fin: __attribute__((unused))
1734         return;
1735 }
1736 /*!
1737  * \brief Parameter parsing callback for /channels/{channelId}/silence.
1738  * \param get_params GET parameters in the HTTP request.
1739  * \param path_vars Path variables extracted from the request.
1740  * \param headers HTTP headers.
1741  * \param[out] response Response to the HTTP request.
1742  */
1743 static void ast_ari_channels_stop_silence_cb(
1744         struct ast_tcptls_session_instance *ser,
1745         struct ast_variable *get_params, struct ast_variable *path_vars,
1746         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1747 {
1748         struct ast_ari_channels_stop_silence_args args = {};
1749         struct ast_variable *i;
1750 #if defined(AST_DEVMODE)
1751         int is_valid;
1752         int code;
1753 #endif /* AST_DEVMODE */
1754
1755         for (i = path_vars; i; i = i->next) {
1756                 if (strcmp(i->name, "channelId") == 0) {
1757                         args.channel_id = (i->value);
1758                 } else
1759                 {}
1760         }
1761         ast_ari_channels_stop_silence(headers, &args, response);
1762 #if defined(AST_DEVMODE)
1763         code = response->response_code;
1764
1765         switch (code) {
1766         case 0: /* Implementation is still a stub, or the code wasn't set */
1767                 is_valid = response->message == NULL;
1768                 break;
1769         case 500: /* Internal Server Error */
1770         case 501: /* Not Implemented */
1771         case 404: /* Channel not found */
1772         case 409: /* Channel not in a Stasis application */
1773         case 412: /* Channel in invalid state */
1774                 is_valid = 1;
1775                 break;
1776         default:
1777                 if (200 <= code && code <= 299) {
1778                         is_valid = ast_ari_validate_void(
1779                                 response->message);
1780                 } else {
1781                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/silence\n", code);
1782                         is_valid = 0;
1783                 }
1784         }
1785
1786         if (!is_valid) {
1787                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/silence\n");
1788                 ast_ari_response_error(response, 500,
1789                         "Internal Server Error", "Response validation failed");
1790         }
1791 #endif /* AST_DEVMODE */
1792
1793 fin: __attribute__((unused))
1794         return;
1795 }
1796 int ast_ari_channels_play_parse_body(
1797         struct ast_json *body,
1798         struct ast_ari_channels_play_args *args)
1799 {
1800         struct ast_json *field;
1801         /* Parse query parameters out of it */
1802         field = ast_json_object_get(body, "media");
1803         if (field) {
1804                 /* If they were silly enough to both pass in a query param and a
1805                  * JSON body, free up the query value.
1806                  */
1807                 ast_free(args->media);
1808                 if (ast_json_typeof(field) == AST_JSON_ARRAY) {
1809                         /* Multiple param passed as array */
1810                         size_t i;
1811                         args->media_count = ast_json_array_size(field);
1812                         args->media = ast_malloc(sizeof(*args->media) * args->media_count);
1813
1814                         if (!args->media) {
1815                                 return -1;
1816                         }
1817
1818                         for (i = 0; i < args->media_count; ++i) {
1819                                 args->media[i] = ast_json_string_get(ast_json_array_get(field, i));
1820                         }
1821                 } else {
1822                         /* Multiple param passed as single value */
1823                         args->media_count = 1;
1824                         args->media = ast_malloc(sizeof(*args->media) * args->media_count);
1825                         if (!args->media) {
1826                                 return -1;
1827                         }
1828                         args->media[0] = ast_json_string_get(field);
1829                 }
1830         }
1831         field = ast_json_object_get(body, "lang");
1832         if (field) {
1833                 args->lang = ast_json_string_get(field);
1834         }
1835         field = ast_json_object_get(body, "offsetms");
1836         if (field) {
1837                 args->offsetms = ast_json_integer_get(field);
1838         }
1839         field = ast_json_object_get(body, "skipms");
1840         if (field) {
1841                 args->skipms = ast_json_integer_get(field);
1842         }
1843         field = ast_json_object_get(body, "playbackId");
1844         if (field) {
1845                 args->playback_id = ast_json_string_get(field);
1846         }
1847         return 0;
1848 }
1849
1850 /*!
1851  * \brief Parameter parsing callback for /channels/{channelId}/play.
1852  * \param get_params GET parameters in the HTTP request.
1853  * \param path_vars Path variables extracted from the request.
1854  * \param headers HTTP headers.
1855  * \param[out] response Response to the HTTP request.
1856  */
1857 static void ast_ari_channels_play_cb(
1858         struct ast_tcptls_session_instance *ser,
1859         struct ast_variable *get_params, struct ast_variable *path_vars,
1860         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1861 {
1862         struct ast_ari_channels_play_args args = {};
1863         struct ast_variable *i;
1864 #if defined(AST_DEVMODE)
1865         int is_valid;
1866         int code;
1867 #endif /* AST_DEVMODE */
1868
1869         for (i = get_params; i; i = i->next) {
1870                 if (strcmp(i->name, "media") == 0) {
1871                         /* Parse comma separated list */
1872                         char *vals[MAX_VALS];
1873                         size_t j;
1874
1875                         args.media_parse = ast_strdup(i->value);
1876                         if (!args.media_parse) {
1877                                 ast_ari_response_alloc_failed(response);
1878                                 goto fin;
1879                         }
1880
1881                         if (strlen(args.media_parse) == 0) {
1882                                 /* ast_app_separate_args can't handle "" */
1883                                 args.media_count = 1;
1884                                 vals[0] = args.media_parse;
1885                         } else {
1886                                 args.media_count = ast_app_separate_args(
1887                                         args.media_parse, ',', vals,
1888                                         ARRAY_LEN(vals));
1889                         }
1890
1891                         if (args.media_count == 0) {
1892                                 ast_ari_response_alloc_failed(response);
1893                                 goto fin;
1894                         }
1895
1896                         if (args.media_count >= MAX_VALS) {
1897                                 ast_ari_response_error(response, 400,
1898                                         "Bad Request",
1899                                         "Too many values for media");
1900                                 goto fin;
1901                         }
1902
1903                         args.media = ast_malloc(sizeof(*args.media) * args.media_count);
1904                         if (!args.media) {
1905                                 ast_ari_response_alloc_failed(response);
1906                                 goto fin;
1907                         }
1908
1909                         for (j = 0; j < args.media_count; ++j) {
1910                                 args.media[j] = (vals[j]);
1911                         }
1912                 } else
1913                 if (strcmp(i->name, "lang") == 0) {
1914                         args.lang = (i->value);
1915                 } else
1916                 if (strcmp(i->name, "offsetms") == 0) {
1917                         args.offsetms = atoi(i->value);
1918                 } else
1919                 if (strcmp(i->name, "skipms") == 0) {
1920                         args.skipms = atoi(i->value);
1921                 } else
1922                 if (strcmp(i->name, "playbackId") == 0) {
1923                         args.playback_id = (i->value);
1924                 } else
1925                 {}
1926         }
1927         for (i = path_vars; i; i = i->next) {
1928                 if (strcmp(i->name, "channelId") == 0) {
1929                         args.channel_id = (i->value);
1930                 } else
1931                 {}
1932         }
1933         if (ast_ari_channels_play_parse_body(body, &args)) {
1934                 ast_ari_response_alloc_failed(response);
1935                 goto fin;
1936         }
1937         ast_ari_channels_play(headers, &args, response);
1938 #if defined(AST_DEVMODE)
1939         code = response->response_code;
1940
1941         switch (code) {
1942         case 0: /* Implementation is still a stub, or the code wasn't set */
1943                 is_valid = response->message == NULL;
1944                 break;
1945         case 500: /* Internal Server Error */
1946         case 501: /* Not Implemented */
1947         case 404: /* Channel not found */
1948         case 409: /* Channel not in a Stasis application */
1949         case 412: /* Channel in invalid state */
1950                 is_valid = 1;
1951                 break;
1952         default:
1953                 if (200 <= code && code <= 299) {
1954                         is_valid = ast_ari_validate_playback(
1955                                 response->message);
1956                 } else {
1957                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/play\n", code);
1958                         is_valid = 0;
1959                 }
1960         }
1961
1962         if (!is_valid) {
1963                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/play\n");
1964                 ast_ari_response_error(response, 500,
1965                         "Internal Server Error", "Response validation failed");
1966         }
1967 #endif /* AST_DEVMODE */
1968
1969 fin: __attribute__((unused))
1970         ast_free(args.media_parse);
1971         ast_free(args.media);
1972         return;
1973 }
1974 int ast_ari_channels_play_with_id_parse_body(
1975         struct ast_json *body,
1976         struct ast_ari_channels_play_with_id_args *args)
1977 {
1978         struct ast_json *field;
1979         /* Parse query parameters out of it */
1980         field = ast_json_object_get(body, "media");
1981         if (field) {
1982                 /* If they were silly enough to both pass in a query param and a
1983                  * JSON body, free up the query value.
1984                  */
1985                 ast_free(args->media);
1986                 if (ast_json_typeof(field) == AST_JSON_ARRAY) {
1987                         /* Multiple param passed as array */
1988                         size_t i;
1989                         args->media_count = ast_json_array_size(field);
1990                         args->media = ast_malloc(sizeof(*args->media) * args->media_count);
1991
1992                         if (!args->media) {
1993                                 return -1;
1994                         }
1995
1996                         for (i = 0; i < args->media_count; ++i) {
1997                                 args->media[i] = ast_json_string_get(ast_json_array_get(field, i));
1998                         }
1999                 } else {
2000                         /* Multiple param passed as single value */
2001                         args->media_count = 1;
2002                         args->media = ast_malloc(sizeof(*args->media) * args->media_count);
2003                         if (!args->media) {
2004                                 return -1;
2005                         }
2006                         args->media[0] = ast_json_string_get(field);
2007                 }
2008         }
2009         field = ast_json_object_get(body, "lang");
2010         if (field) {
2011                 args->lang = ast_json_string_get(field);
2012         }
2013         field = ast_json_object_get(body, "offsetms");
2014         if (field) {
2015                 args->offsetms = ast_json_integer_get(field);
2016         }
2017         field = ast_json_object_get(body, "skipms");
2018         if (field) {
2019                 args->skipms = ast_json_integer_get(field);
2020         }
2021         return 0;
2022 }
2023
2024 /*!
2025  * \brief Parameter parsing callback for /channels/{channelId}/play/{playbackId}.
2026  * \param get_params GET parameters in the HTTP request.
2027  * \param path_vars Path variables extracted from the request.
2028  * \param headers HTTP headers.
2029  * \param[out] response Response to the HTTP request.
2030  */
2031 static void ast_ari_channels_play_with_id_cb(
2032         struct ast_tcptls_session_instance *ser,
2033         struct ast_variable *get_params, struct ast_variable *path_vars,
2034         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
2035 {
2036         struct ast_ari_channels_play_with_id_args args = {};
2037         struct ast_variable *i;
2038 #if defined(AST_DEVMODE)
2039         int is_valid;
2040         int code;
2041 #endif /* AST_DEVMODE */
2042
2043         for (i = get_params; i; i = i->next) {
2044                 if (strcmp(i->name, "media") == 0) {
2045                         /* Parse comma separated list */
2046                         char *vals[MAX_VALS];
2047                         size_t j;
2048
2049                         args.media_parse = ast_strdup(i->value);
2050                         if (!args.media_parse) {
2051                                 ast_ari_response_alloc_failed(response);
2052                                 goto fin;
2053                         }
2054
2055                         if (strlen(args.media_parse) == 0) {
2056                                 /* ast_app_separate_args can't handle "" */
2057                                 args.media_count = 1;
2058                                 vals[0] = args.media_parse;
2059                         } else {
2060                                 args.media_count = ast_app_separate_args(
2061                                         args.media_parse, ',', vals,
2062                                         ARRAY_LEN(vals));
2063                         }
2064
2065                         if (args.media_count == 0) {
2066                                 ast_ari_response_alloc_failed(response);
2067                                 goto fin;
2068                         }
2069
2070                         if (args.media_count >= MAX_VALS) {
2071                                 ast_ari_response_error(response, 400,
2072                                         "Bad Request",
2073                                         "Too many values for media");
2074                                 goto fin;
2075                         }
2076
2077                         args.media = ast_malloc(sizeof(*args.media) * args.media_count);
2078                         if (!args.media) {
2079                                 ast_ari_response_alloc_failed(response);
2080                                 goto fin;
2081                         }
2082
2083                         for (j = 0; j < args.media_count; ++j) {
2084                                 args.media[j] = (vals[j]);
2085                         }
2086                 } else
2087                 if (strcmp(i->name, "lang") == 0) {
2088                         args.lang = (i->value);
2089                 } else
2090                 if (strcmp(i->name, "offsetms") == 0) {
2091                         args.offsetms = atoi(i->value);
2092                 } else
2093                 if (strcmp(i->name, "skipms") == 0) {
2094                         args.skipms = atoi(i->value);
2095                 } else
2096                 {}
2097         }
2098         for (i = path_vars; i; i = i->next) {
2099                 if (strcmp(i->name, "channelId") == 0) {
2100                         args.channel_id = (i->value);
2101                 } else
2102                 if (strcmp(i->name, "playbackId") == 0) {
2103                         args.playback_id = (i->value);
2104                 } else
2105                 {}
2106         }
2107         if (ast_ari_channels_play_with_id_parse_body(body, &args)) {
2108                 ast_ari_response_alloc_failed(response);
2109                 goto fin;
2110         }
2111         ast_ari_channels_play_with_id(headers, &args, response);
2112 #if defined(AST_DEVMODE)
2113         code = response->response_code;
2114
2115         switch (code) {
2116         case 0: /* Implementation is still a stub, or the code wasn't set */
2117                 is_valid = response->message == NULL;
2118                 break;
2119         case 500: /* Internal Server Error */
2120         case 501: /* Not Implemented */
2121         case 404: /* Channel not found */
2122         case 409: /* Channel not in a Stasis application */
2123         case 412: /* Channel in invalid state */
2124                 is_valid = 1;
2125                 break;
2126         default:
2127                 if (200 <= code && code <= 299) {
2128                         is_valid = ast_ari_validate_playback(
2129                                 response->message);
2130                 } else {
2131                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/play/{playbackId}\n", code);
2132                         is_valid = 0;
2133                 }
2134         }
2135
2136         if (!is_valid) {
2137                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/play/{playbackId}\n");
2138                 ast_ari_response_error(response, 500,
2139                         "Internal Server Error", "Response validation failed");
2140         }
2141 #endif /* AST_DEVMODE */
2142
2143 fin: __attribute__((unused))
2144         ast_free(args.media_parse);
2145         ast_free(args.media);
2146         return;
2147 }
2148 int ast_ari_channels_record_parse_body(
2149         struct ast_json *body,
2150         struct ast_ari_channels_record_args *args)
2151 {
2152         struct ast_json *field;
2153         /* Parse query parameters out of it */
2154         field = ast_json_object_get(body, "name");
2155         if (field) {
2156                 args->name = ast_json_string_get(field);
2157         }
2158         field = ast_json_object_get(body, "format");
2159         if (field) {
2160                 args->format = ast_json_string_get(field);
2161         }
2162         field = ast_json_object_get(body, "maxDurationSeconds");
2163         if (field) {
2164                 args->max_duration_seconds = ast_json_integer_get(field);
2165         }
2166         field = ast_json_object_get(body, "maxSilenceSeconds");
2167         if (field) {
2168                 args->max_silence_seconds = ast_json_integer_get(field);
2169         }
2170         field = ast_json_object_get(body, "ifExists");
2171         if (field) {
2172                 args->if_exists = ast_json_string_get(field);
2173         }
2174         field = ast_json_object_get(body, "beep");
2175         if (field) {
2176                 args->beep = ast_json_is_true(field);
2177         }
2178         field = ast_json_object_get(body, "terminateOn");
2179         if (field) {
2180                 args->terminate_on = ast_json_string_get(field);
2181         }
2182         return 0;
2183 }
2184
2185 /*!
2186  * \brief Parameter parsing callback for /channels/{channelId}/record.
2187  * \param get_params GET parameters in the HTTP request.
2188  * \param path_vars Path variables extracted from the request.
2189  * \param headers HTTP headers.
2190  * \param[out] response Response to the HTTP request.
2191  */
2192 static void ast_ari_channels_record_cb(
2193         struct ast_tcptls_session_instance *ser,
2194         struct ast_variable *get_params, struct ast_variable *path_vars,
2195         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
2196 {
2197         struct ast_ari_channels_record_args args = {};
2198         struct ast_variable *i;
2199 #if defined(AST_DEVMODE)
2200         int is_valid;
2201         int code;
2202 #endif /* AST_DEVMODE */
2203
2204         for (i = get_params; i; i = i->next) {
2205                 if (strcmp(i->name, "name") == 0) {
2206                         args.name = (i->value);
2207                 } else
2208                 if (strcmp(i->name, "format") == 0) {
2209                         args.format = (i->value);
2210                 } else
2211                 if (strcmp(i->name, "maxDurationSeconds") == 0) {
2212                         args.max_duration_seconds = atoi(i->value);
2213                 } else
2214                 if (strcmp(i->name, "maxSilenceSeconds") == 0) {
2215                         args.max_silence_seconds = atoi(i->value);
2216                 } else
2217                 if (strcmp(i->name, "ifExists") == 0) {
2218                         args.if_exists = (i->value);
2219                 } else
2220                 if (strcmp(i->name, "beep") == 0) {
2221                         args.beep = ast_true(i->value);
2222                 } else
2223                 if (strcmp(i->name, "terminateOn") == 0) {
2224                         args.terminate_on = (i->value);
2225                 } else
2226                 {}
2227         }
2228         for (i = path_vars; i; i = i->next) {
2229                 if (strcmp(i->name, "channelId") == 0) {
2230                         args.channel_id = (i->value);
2231                 } else
2232                 {}
2233         }
2234         if (ast_ari_channels_record_parse_body(body, &args)) {
2235                 ast_ari_response_alloc_failed(response);
2236                 goto fin;
2237         }
2238         ast_ari_channels_record(headers, &args, response);
2239 #if defined(AST_DEVMODE)
2240         code = response->response_code;
2241
2242         switch (code) {
2243         case 0: /* Implementation is still a stub, or the code wasn't set */
2244                 is_valid = response->message == NULL;
2245                 break;
2246         case 500: /* Internal Server Error */
2247         case 501: /* Not Implemented */
2248         case 400: /* Invalid parameters */
2249         case 404: /* Channel not found */
2250         case 409: /* Channel is not in a Stasis application; the channel is currently bridged with other hcannels; A recording with the same name already exists on the system and can not be overwritten because it is in progress or ifExists=fail */
2251         case 422: /* The format specified is unknown on this system */
2252                 is_valid = 1;
2253                 break;
2254         default:
2255                 if (200 <= code && code <= 299) {
2256                         is_valid = ast_ari_validate_live_recording(
2257                                 response->message);
2258                 } else {
2259                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/record\n", code);
2260                         is_valid = 0;
2261                 }
2262         }
2263
2264         if (!is_valid) {
2265                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/record\n");
2266                 ast_ari_response_error(response, 500,
2267                         "Internal Server Error", "Response validation failed");
2268         }
2269 #endif /* AST_DEVMODE */
2270
2271 fin: __attribute__((unused))
2272         return;
2273 }
2274 int ast_ari_channels_get_channel_var_parse_body(
2275         struct ast_json *body,
2276         struct ast_ari_channels_get_channel_var_args *args)
2277 {
2278         struct ast_json *field;
2279         /* Parse query parameters out of it */
2280         field = ast_json_object_get(body, "variable");
2281         if (field) {
2282                 args->variable = ast_json_string_get(field);
2283         }
2284         return 0;
2285 }
2286
2287 /*!
2288  * \brief Parameter parsing callback for /channels/{channelId}/variable.
2289  * \param get_params GET parameters in the HTTP request.
2290  * \param path_vars Path variables extracted from the request.
2291  * \param headers HTTP headers.
2292  * \param[out] response Response to the HTTP request.
2293  */
2294 static void ast_ari_channels_get_channel_var_cb(
2295         struct ast_tcptls_session_instance *ser,
2296         struct ast_variable *get_params, struct ast_variable *path_vars,
2297         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
2298 {
2299         struct ast_ari_channels_get_channel_var_args args = {};
2300         struct ast_variable *i;
2301 #if defined(AST_DEVMODE)
2302         int is_valid;
2303         int code;
2304 #endif /* AST_DEVMODE */
2305
2306         for (i = get_params; i; i = i->next) {
2307                 if (strcmp(i->name, "variable") == 0) {
2308                         args.variable = (i->value);
2309                 } else
2310                 {}
2311         }
2312         for (i = path_vars; i; i = i->next) {
2313                 if (strcmp(i->name, "channelId") == 0) {
2314                         args.channel_id = (i->value);
2315                 } else
2316                 {}
2317         }
2318         if (ast_ari_channels_get_channel_var_parse_body(body, &args)) {
2319                 ast_ari_response_alloc_failed(response);
2320                 goto fin;
2321         }
2322         ast_ari_channels_get_channel_var(headers, &args, response);
2323 #if defined(AST_DEVMODE)
2324         code = response->response_code;
2325
2326         switch (code) {
2327         case 0: /* Implementation is still a stub, or the code wasn't set */
2328                 is_valid = response->message == NULL;
2329                 break;
2330         case 500: /* Internal Server Error */
2331         case 501: /* Not Implemented */
2332         case 400: /* Missing variable parameter. */
2333         case 404: /* Channel or variable not found */
2334         case 409: /* Channel not in a Stasis application */
2335                 is_valid = 1;
2336                 break;
2337         default:
2338                 if (200 <= code && code <= 299) {
2339                         is_valid = ast_ari_validate_variable(
2340                                 response->message);
2341                 } else {
2342                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/variable\n", code);
2343                         is_valid = 0;
2344                 }
2345         }
2346
2347         if (!is_valid) {
2348                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/variable\n");
2349                 ast_ari_response_error(response, 500,
2350                         "Internal Server Error", "Response validation failed");
2351         }
2352 #endif /* AST_DEVMODE */
2353
2354 fin: __attribute__((unused))
2355         return;
2356 }
2357 int ast_ari_channels_set_channel_var_parse_body(
2358         struct ast_json *body,
2359         struct ast_ari_channels_set_channel_var_args *args)
2360 {
2361         struct ast_json *field;
2362         /* Parse query parameters out of it */
2363         field = ast_json_object_get(body, "variable");
2364         if (field) {
2365                 args->variable = ast_json_string_get(field);
2366         }
2367         field = ast_json_object_get(body, "value");
2368         if (field) {
2369                 args->value = ast_json_string_get(field);
2370         }
2371         return 0;
2372 }
2373
2374 /*!
2375  * \brief Parameter parsing callback for /channels/{channelId}/variable.
2376  * \param get_params GET parameters in the HTTP request.
2377  * \param path_vars Path variables extracted from the request.
2378  * \param headers HTTP headers.
2379  * \param[out] response Response to the HTTP request.
2380  */
2381 static void ast_ari_channels_set_channel_var_cb(
2382         struct ast_tcptls_session_instance *ser,
2383         struct ast_variable *get_params, struct ast_variable *path_vars,
2384         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
2385 {
2386         struct ast_ari_channels_set_channel_var_args args = {};
2387         struct ast_variable *i;
2388 #if defined(AST_DEVMODE)
2389         int is_valid;
2390         int code;
2391 #endif /* AST_DEVMODE */
2392
2393         for (i = get_params; i; i = i->next) {
2394                 if (strcmp(i->name, "variable") == 0) {
2395                         args.variable = (i->value);
2396                 } else
2397                 if (strcmp(i->name, "value") == 0) {
2398                         args.value = (i->value);
2399                 } else
2400                 {}
2401         }
2402         for (i = path_vars; i; i = i->next) {
2403                 if (strcmp(i->name, "channelId") == 0) {
2404                         args.channel_id = (i->value);
2405                 } else
2406                 {}
2407         }
2408         if (ast_ari_channels_set_channel_var_parse_body(body, &args)) {
2409                 ast_ari_response_alloc_failed(response);
2410                 goto fin;
2411         }
2412         ast_ari_channels_set_channel_var(headers, &args, response);
2413 #if defined(AST_DEVMODE)
2414         code = response->response_code;
2415
2416         switch (code) {
2417         case 0: /* Implementation is still a stub, or the code wasn't set */
2418                 is_valid = response->message == NULL;
2419                 break;
2420         case 500: /* Internal Server Error */
2421         case 501: /* Not Implemented */
2422         case 400: /* Missing variable parameter. */
2423         case 404: /* Channel not found */
2424         case 409: /* Channel not in a Stasis application */
2425                 is_valid = 1;
2426                 break;
2427         default:
2428                 if (200 <= code && code <= 299) {
2429                         is_valid = ast_ari_validate_void(
2430                                 response->message);
2431                 } else {
2432                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/variable\n", code);
2433                         is_valid = 0;
2434                 }
2435         }
2436
2437         if (!is_valid) {
2438                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/variable\n");
2439                 ast_ari_response_error(response, 500,
2440                         "Internal Server Error", "Response validation failed");
2441         }
2442 #endif /* AST_DEVMODE */
2443
2444 fin: __attribute__((unused))
2445         return;
2446 }
2447 int ast_ari_channels_snoop_channel_parse_body(
2448         struct ast_json *body,
2449         struct ast_ari_channels_snoop_channel_args *args)
2450 {
2451         struct ast_json *field;
2452         /* Parse query parameters out of it */
2453         field = ast_json_object_get(body, "spy");
2454         if (field) {
2455                 args->spy = ast_json_string_get(field);
2456         }
2457         field = ast_json_object_get(body, "whisper");
2458         if (field) {
2459                 args->whisper = ast_json_string_get(field);
2460         }
2461         field = ast_json_object_get(body, "app");
2462         if (field) {
2463                 args->app = ast_json_string_get(field);
2464         }
2465         field = ast_json_object_get(body, "appArgs");
2466         if (field) {
2467                 args->app_args = ast_json_string_get(field);
2468         }
2469         field = ast_json_object_get(body, "snoopId");
2470         if (field) {
2471                 args->snoop_id = ast_json_string_get(field);
2472         }
2473         return 0;
2474 }
2475
2476 /*!
2477  * \brief Parameter parsing callback for /channels/{channelId}/snoop.
2478  * \param get_params GET parameters in the HTTP request.
2479  * \param path_vars Path variables extracted from the request.
2480  * \param headers HTTP headers.
2481  * \param[out] response Response to the HTTP request.
2482  */
2483 static void ast_ari_channels_snoop_channel_cb(
2484         struct ast_tcptls_session_instance *ser,
2485         struct ast_variable *get_params, struct ast_variable *path_vars,
2486         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
2487 {
2488         struct ast_ari_channels_snoop_channel_args args = {};
2489         struct ast_variable *i;
2490 #if defined(AST_DEVMODE)
2491         int is_valid;
2492         int code;
2493 #endif /* AST_DEVMODE */
2494
2495         for (i = get_params; i; i = i->next) {
2496                 if (strcmp(i->name, "spy") == 0) {
2497                         args.spy = (i->value);
2498                 } else
2499                 if (strcmp(i->name, "whisper") == 0) {
2500                         args.whisper = (i->value);
2501                 } else
2502                 if (strcmp(i->name, "app") == 0) {
2503                         args.app = (i->value);
2504                 } else
2505                 if (strcmp(i->name, "appArgs") == 0) {
2506                         args.app_args = (i->value);
2507                 } else
2508                 if (strcmp(i->name, "snoopId") == 0) {
2509                         args.snoop_id = (i->value);
2510                 } else
2511                 {}
2512         }
2513         for (i = path_vars; i; i = i->next) {
2514                 if (strcmp(i->name, "channelId") == 0) {
2515                         args.channel_id = (i->value);
2516                 } else
2517                 {}
2518         }
2519         if (ast_ari_channels_snoop_channel_parse_body(body, &args)) {
2520                 ast_ari_response_alloc_failed(response);
2521                 goto fin;
2522         }
2523         ast_ari_channels_snoop_channel(headers, &args, response);
2524 #if defined(AST_DEVMODE)
2525         code = response->response_code;
2526
2527         switch (code) {
2528         case 0: /* Implementation is still a stub, or the code wasn't set */
2529                 is_valid = response->message == NULL;
2530                 break;
2531         case 500: /* Internal Server Error */
2532         case 501: /* Not Implemented */
2533         case 400: /* Invalid parameters */
2534         case 404: /* Channel not found */
2535                 is_valid = 1;
2536                 break;
2537         default:
2538                 if (200 <= code && code <= 299) {
2539                         is_valid = ast_ari_validate_channel(
2540                                 response->message);
2541                 } else {
2542                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/snoop\n", code);
2543                         is_valid = 0;
2544                 }
2545         }
2546
2547         if (!is_valid) {
2548                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/snoop\n");
2549                 ast_ari_response_error(response, 500,
2550                         "Internal Server Error", "Response validation failed");
2551         }
2552 #endif /* AST_DEVMODE */
2553
2554 fin: __attribute__((unused))
2555         return;
2556 }
2557 int ast_ari_channels_snoop_channel_with_id_parse_body(
2558         struct ast_json *body,
2559         struct ast_ari_channels_snoop_channel_with_id_args *args)
2560 {
2561         struct ast_json *field;
2562         /* Parse query parameters out of it */
2563         field = ast_json_object_get(body, "spy");
2564         if (field) {
2565                 args->spy = ast_json_string_get(field);
2566         }
2567         field = ast_json_object_get(body, "whisper");
2568         if (field) {
2569                 args->whisper = ast_json_string_get(field);
2570         }
2571         field = ast_json_object_get(body, "app");
2572         if (field) {
2573                 args->app = ast_json_string_get(field);
2574         }
2575         field = ast_json_object_get(body, "appArgs");
2576         if (field) {
2577                 args->app_args = ast_json_string_get(field);
2578         }
2579         return 0;
2580 }
2581
2582 /*!
2583  * \brief Parameter parsing callback for /channels/{channelId}/snoop/{snoopId}.
2584  * \param get_params GET parameters in the HTTP request.
2585  * \param path_vars Path variables extracted from the request.
2586  * \param headers HTTP headers.
2587  * \param[out] response Response to the HTTP request.
2588  */
2589 static void ast_ari_channels_snoop_channel_with_id_cb(
2590         struct ast_tcptls_session_instance *ser,
2591         struct ast_variable *get_params, struct ast_variable *path_vars,
2592         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
2593 {
2594         struct ast_ari_channels_snoop_channel_with_id_args args = {};
2595         struct ast_variable *i;
2596 #if defined(AST_DEVMODE)
2597         int is_valid;
2598         int code;
2599 #endif /* AST_DEVMODE */
2600
2601         for (i = get_params; i; i = i->next) {
2602                 if (strcmp(i->name, "spy") == 0) {
2603                         args.spy = (i->value);
2604                 } else
2605                 if (strcmp(i->name, "whisper") == 0) {
2606                         args.whisper = (i->value);
2607                 } else
2608                 if (strcmp(i->name, "app") == 0) {
2609                         args.app = (i->value);
2610                 } else
2611                 if (strcmp(i->name, "appArgs") == 0) {
2612                         args.app_args = (i->value);
2613                 } else
2614                 {}
2615         }
2616         for (i = path_vars; i; i = i->next) {
2617                 if (strcmp(i->name, "channelId") == 0) {
2618                         args.channel_id = (i->value);
2619                 } else
2620                 if (strcmp(i->name, "snoopId") == 0) {
2621                         args.snoop_id = (i->value);
2622                 } else
2623                 {}
2624         }
2625         if (ast_ari_channels_snoop_channel_with_id_parse_body(body, &args)) {
2626                 ast_ari_response_alloc_failed(response);
2627                 goto fin;
2628         }
2629         ast_ari_channels_snoop_channel_with_id(headers, &args, response);
2630 #if defined(AST_DEVMODE)
2631         code = response->response_code;
2632
2633         switch (code) {
2634         case 0: /* Implementation is still a stub, or the code wasn't set */
2635                 is_valid = response->message == NULL;
2636                 break;
2637         case 500: /* Internal Server Error */
2638         case 501: /* Not Implemented */
2639         case 400: /* Invalid parameters */
2640         case 404: /* Channel not found */
2641                 is_valid = 1;
2642                 break;
2643         default:
2644                 if (200 <= code && code <= 299) {
2645                         is_valid = ast_ari_validate_channel(
2646                                 response->message);
2647                 } else {
2648                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/snoop/{snoopId}\n", code);
2649                         is_valid = 0;
2650                 }
2651         }
2652
2653         if (!is_valid) {
2654                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/snoop/{snoopId}\n");
2655                 ast_ari_response_error(response, 500,
2656                         "Internal Server Error", "Response validation failed");
2657         }
2658 #endif /* AST_DEVMODE */
2659
2660 fin: __attribute__((unused))
2661         return;
2662 }
2663 int ast_ari_channels_dial_parse_body(
2664         struct ast_json *body,
2665         struct ast_ari_channels_dial_args *args)
2666 {
2667         struct ast_json *field;
2668         /* Parse query parameters out of it */
2669         field = ast_json_object_get(body, "caller");
2670         if (field) {
2671                 args->caller = ast_json_string_get(field);
2672         }
2673         field = ast_json_object_get(body, "timeout");
2674         if (field) {
2675                 args->timeout = ast_json_integer_get(field);
2676         }
2677         return 0;
2678 }
2679
2680 /*!
2681  * \brief Parameter parsing callback for /channels/{channelId}/dial.
2682  * \param get_params GET parameters in the HTTP request.
2683  * \param path_vars Path variables extracted from the request.
2684  * \param headers HTTP headers.
2685  * \param[out] response Response to the HTTP request.
2686  */
2687 static void ast_ari_channels_dial_cb(
2688         struct ast_tcptls_session_instance *ser,
2689         struct ast_variable *get_params, struct ast_variable *path_vars,
2690         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
2691 {
2692         struct ast_ari_channels_dial_args args = {};
2693         struct ast_variable *i;
2694 #if defined(AST_DEVMODE)
2695         int is_valid;
2696         int code;
2697 #endif /* AST_DEVMODE */
2698
2699         for (i = get_params; i; i = i->next) {
2700                 if (strcmp(i->name, "caller") == 0) {
2701                         args.caller = (i->value);
2702                 } else
2703                 if (strcmp(i->name, "timeout") == 0) {
2704                         args.timeout = atoi(i->value);
2705                 } else
2706                 {}
2707         }
2708         for (i = path_vars; i; i = i->next) {
2709                 if (strcmp(i->name, "channelId") == 0) {
2710                         args.channel_id = (i->value);
2711                 } else
2712                 {}
2713         }
2714         if (ast_ari_channels_dial_parse_body(body, &args)) {
2715                 ast_ari_response_alloc_failed(response);
2716                 goto fin;
2717         }
2718         ast_ari_channels_dial(headers, &args, response);
2719 #if defined(AST_DEVMODE)
2720         code = response->response_code;
2721
2722         switch (code) {
2723         case 0: /* Implementation is still a stub, or the code wasn't set */
2724                 is_valid = response->message == NULL;
2725                 break;
2726         case 500: /* Internal Server Error */
2727         case 501: /* Not Implemented */
2728         case 404: /* Channel cannot be found. */
2729         case 409: /* Channel cannot be dialed. */
2730                 is_valid = 1;
2731                 break;
2732         default:
2733                 if (200 <= code && code <= 299) {
2734                         is_valid = ast_ari_validate_void(
2735                                 response->message);
2736                 } else {
2737                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/dial\n", code);
2738                         is_valid = 0;
2739                 }
2740         }
2741
2742         if (!is_valid) {
2743                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/dial\n");
2744                 ast_ari_response_error(response, 500,
2745                         "Internal Server Error", "Response validation failed");
2746         }
2747 #endif /* AST_DEVMODE */
2748
2749 fin: __attribute__((unused))
2750         return;
2751 }
2752
2753 /*! \brief REST handler for /api-docs/channels.json */
2754 static struct stasis_rest_handlers channels_create = {
2755         .path_segment = "create",
2756         .callbacks = {
2757                 [AST_HTTP_POST] = ast_ari_channels_create_cb,
2758         },
2759         .num_children = 0,
2760         .children = {  }
2761 };
2762 /*! \brief REST handler for /api-docs/channels.json */
2763 static struct stasis_rest_handlers channels_channelId_continue = {
2764         .path_segment = "continue",
2765         .callbacks = {
2766                 [AST_HTTP_POST] = ast_ari_channels_continue_in_dialplan_cb,
2767         },
2768         .num_children = 0,
2769         .children = {  }
2770 };
2771 /*! \brief REST handler for /api-docs/channels.json */
2772 static struct stasis_rest_handlers channels_channelId_move = {
2773         .path_segment = "move",
2774         .callbacks = {
2775                 [AST_HTTP_POST] = ast_ari_channels_move_cb,
2776         },
2777         .num_children = 0,
2778         .children = {  }
2779 };
2780 /*! \brief REST handler for /api-docs/channels.json */
2781 static struct stasis_rest_handlers channels_channelId_redirect = {
2782         .path_segment = "redirect",
2783         .callbacks = {
2784                 [AST_HTTP_POST] = ast_ari_channels_redirect_cb,
2785         },
2786         .num_children = 0,
2787         .children = {  }
2788 };
2789 /*! \brief REST handler for /api-docs/channels.json */
2790 static struct stasis_rest_handlers channels_channelId_answer = {
2791         .path_segment = "answer",
2792         .callbacks = {
2793                 [AST_HTTP_POST] = ast_ari_channels_answer_cb,
2794         },
2795         .num_children = 0,
2796         .children = {  }
2797 };
2798 /*! \brief REST handler for /api-docs/channels.json */
2799 static struct stasis_rest_handlers channels_channelId_ring = {
2800         .path_segment = "ring",
2801         .callbacks = {
2802                 [AST_HTTP_POST] = ast_ari_channels_ring_cb,
2803                 [AST_HTTP_DELETE] = ast_ari_channels_ring_stop_cb,
2804         },
2805         .num_children = 0,
2806         .children = {  }
2807 };
2808 /*! \brief REST handler for /api-docs/channels.json */
2809 static struct stasis_rest_handlers channels_channelId_dtmf = {
2810         .path_segment = "dtmf",
2811         .callbacks = {
2812                 [AST_HTTP_POST] = ast_ari_channels_send_dtmf_cb,
2813         },
2814         .num_children = 0,
2815         .children = {  }
2816 };
2817 /*! \brief REST handler for /api-docs/channels.json */
2818 static struct stasis_rest_handlers channels_channelId_mute = {
2819         .path_segment = "mute",
2820         .callbacks = {
2821                 [AST_HTTP_POST] = ast_ari_channels_mute_cb,
2822                 [AST_HTTP_DELETE] = ast_ari_channels_unmute_cb,
2823         },
2824         .num_children = 0,
2825         .children = {  }
2826 };
2827 /*! \brief REST handler for /api-docs/channels.json */
2828 static struct stasis_rest_handlers channels_channelId_hold = {
2829         .path_segment = "hold",
2830         .callbacks = {
2831                 [AST_HTTP_POST] = ast_ari_channels_hold_cb,
2832                 [AST_HTTP_DELETE] = ast_ari_channels_unhold_cb,
2833         },
2834         .num_children = 0,
2835         .children = {  }
2836 };
2837 /*! \brief REST handler for /api-docs/channels.json */
2838 static struct stasis_rest_handlers channels_channelId_moh = {
2839         .path_segment = "moh",
2840         .callbacks = {
2841                 [AST_HTTP_POST] = ast_ari_channels_start_moh_cb,
2842                 [AST_HTTP_DELETE] = ast_ari_channels_stop_moh_cb,
2843         },
2844         .num_children = 0,
2845         .children = {  }
2846 };
2847 /*! \brief REST handler for /api-docs/channels.json */
2848 static struct stasis_rest_handlers channels_channelId_silence = {
2849         .path_segment = "silence",
2850         .callbacks = {
2851                 [AST_HTTP_POST] = ast_ari_channels_start_silence_cb,
2852                 [AST_HTTP_DELETE] = ast_ari_channels_stop_silence_cb,
2853         },
2854         .num_children = 0,
2855         .children = {  }
2856 };
2857 /*! \brief REST handler for /api-docs/channels.json */
2858 static struct stasis_rest_handlers channels_channelId_play_playbackId = {
2859         .path_segment = "playbackId",
2860         .is_wildcard = 1,
2861         .callbacks = {
2862                 [AST_HTTP_POST] = ast_ari_channels_play_with_id_cb,
2863         },
2864         .num_children = 0,
2865         .children = {  }
2866 };
2867 /*! \brief REST handler for /api-docs/channels.json */
2868 static struct stasis_rest_handlers channels_channelId_play = {
2869         .path_segment = "play",
2870         .callbacks = {
2871                 [AST_HTTP_POST] = ast_ari_channels_play_cb,
2872         },
2873         .num_children = 1,
2874         .children = { &channels_channelId_play_playbackId, }
2875 };
2876 /*! \brief REST handler for /api-docs/channels.json */
2877 static struct stasis_rest_handlers channels_channelId_record = {
2878         .path_segment = "record",
2879         .callbacks = {
2880                 [AST_HTTP_POST] = ast_ari_channels_record_cb,
2881         },
2882         .num_children = 0,
2883         .children = {  }
2884 };
2885 /*! \brief REST handler for /api-docs/channels.json */
2886 static struct stasis_rest_handlers channels_channelId_variable = {
2887         .path_segment = "variable",
2888         .callbacks = {
2889                 [AST_HTTP_GET] = ast_ari_channels_get_channel_var_cb,
2890                 [AST_HTTP_POST] = ast_ari_channels_set_channel_var_cb,
2891         },
2892         .num_children = 0,
2893         .children = {  }
2894 };
2895 /*! \brief REST handler for /api-docs/channels.json */
2896 static struct stasis_rest_handlers channels_channelId_snoop_snoopId = {
2897         .path_segment = "snoopId",
2898         .is_wildcard = 1,
2899         .callbacks = {
2900                 [AST_HTTP_POST] = ast_ari_channels_snoop_channel_with_id_cb,
2901         },
2902         .num_children = 0,
2903         .children = {  }
2904 };
2905 /*! \brief REST handler for /api-docs/channels.json */
2906 static struct stasis_rest_handlers channels_channelId_snoop = {
2907         .path_segment = "snoop",
2908         .callbacks = {
2909                 [AST_HTTP_POST] = ast_ari_channels_snoop_channel_cb,
2910         },
2911         .num_children = 1,
2912         .children = { &channels_channelId_snoop_snoopId, }
2913 };
2914 /*! \brief REST handler for /api-docs/channels.json */
2915 static struct stasis_rest_handlers channels_channelId_dial = {
2916         .path_segment = "dial",
2917         .callbacks = {
2918                 [AST_HTTP_POST] = ast_ari_channels_dial_cb,
2919         },
2920         .num_children = 0,
2921         .children = {  }
2922 };
2923 /*! \brief REST handler for /api-docs/channels.json */
2924 static struct stasis_rest_handlers channels_channelId = {
2925         .path_segment = "channelId",
2926         .is_wildcard = 1,
2927         .callbacks = {
2928                 [AST_HTTP_GET] = ast_ari_channels_get_cb,
2929                 [AST_HTTP_POST] = ast_ari_channels_originate_with_id_cb,
2930                 [AST_HTTP_DELETE] = ast_ari_channels_hangup_cb,
2931         },
2932         .num_children = 15,
2933         .children = { &channels_channelId_continue,&channels_channelId_move,&channels_channelId_redirect,&channels_channelId_answer,&channels_channelId_ring,&channels_channelId_dtmf,&channels_channelId_mute,&channels_channelId_hold,&channels_channelId_moh,&channels_channelId_silence,&channels_channelId_play,&channels_channelId_record,&channels_channelId_variable,&channels_channelId_snoop,&channels_channelId_dial, }
2934 };
2935 /*! \brief REST handler for /api-docs/channels.json */
2936 static struct stasis_rest_handlers channels = {
2937         .path_segment = "channels",
2938         .callbacks = {
2939                 [AST_HTTP_GET] = ast_ari_channels_list_cb,
2940                 [AST_HTTP_POST] = ast_ari_channels_originate_cb,
2941         },
2942         .num_children = 2,
2943         .children = { &channels_create,&channels_channelId, }
2944 };
2945
2946 static int unload_module(void)
2947 {
2948         ast_ari_remove_handler(&channels);
2949         return 0;
2950 }
2951
2952 static int load_module(void)
2953 {
2954         int res = 0;
2955
2956
2957         res |= ast_ari_add_handler(&channels);
2958         if (res) {
2959                 unload_module();
2960                 return AST_MODULE_LOAD_DECLINE;
2961         }
2962
2963         return AST_MODULE_LOAD_SUCCESS;
2964 }
2965
2966 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Channel resources",
2967         .support_level = AST_MODULE_SUPPORT_CORE,
2968         .load = load_module,
2969         .unload = unload_module,
2970         .requires = "res_ari,res_ari_model,res_stasis,res_stasis_answer,res_stasis_playback,res_stasis_recording,res_stasis_snoop",
2971 );