feat: AudioSocket channel, application, and ARI support.
[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_code");
602         if (field) {
603                 args->reason_code = ast_json_string_get(field);
604         }
605         field = ast_json_object_get(body, "reason");
606         if (field) {
607                 args->reason = ast_json_string_get(field);
608         }
609         return 0;
610 }
611
612 /*!
613  * \brief Parameter parsing callback for /channels/{channelId}.
614  * \param get_params GET parameters in the HTTP request.
615  * \param path_vars Path variables extracted from the request.
616  * \param headers HTTP headers.
617  * \param[out] response Response to the HTTP request.
618  */
619 static void ast_ari_channels_hangup_cb(
620         struct ast_tcptls_session_instance *ser,
621         struct ast_variable *get_params, struct ast_variable *path_vars,
622         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
623 {
624         struct ast_ari_channels_hangup_args args = {};
625         struct ast_variable *i;
626 #if defined(AST_DEVMODE)
627         int is_valid;
628         int code;
629 #endif /* AST_DEVMODE */
630
631         for (i = get_params; i; i = i->next) {
632                 if (strcmp(i->name, "reason_code") == 0) {
633                         args.reason_code = (i->value);
634                 } else
635                 if (strcmp(i->name, "reason") == 0) {
636                         args.reason = (i->value);
637                 } else
638                 {}
639         }
640         for (i = path_vars; i; i = i->next) {
641                 if (strcmp(i->name, "channelId") == 0) {
642                         args.channel_id = (i->value);
643                 } else
644                 {}
645         }
646         if (ast_ari_channels_hangup_parse_body(body, &args)) {
647                 ast_ari_response_alloc_failed(response);
648                 goto fin;
649         }
650         ast_ari_channels_hangup(headers, &args, response);
651 #if defined(AST_DEVMODE)
652         code = response->response_code;
653
654         switch (code) {
655         case 0: /* Implementation is still a stub, or the code wasn't set */
656                 is_valid = response->message == NULL;
657                 break;
658         case 500: /* Internal Server Error */
659         case 501: /* Not Implemented */
660         case 400: /* Invalid reason for hangup provided */
661         case 404: /* Channel not found */
662                 is_valid = 1;
663                 break;
664         default:
665                 if (200 <= code && code <= 299) {
666                         is_valid = ast_ari_validate_void(
667                                 response->message);
668                 } else {
669                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}\n", code);
670                         is_valid = 0;
671                 }
672         }
673
674         if (!is_valid) {
675                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}\n");
676                 ast_ari_response_error(response, 500,
677                         "Internal Server Error", "Response validation failed");
678         }
679 #endif /* AST_DEVMODE */
680
681 fin: __attribute__((unused))
682         return;
683 }
684 int ast_ari_channels_continue_in_dialplan_parse_body(
685         struct ast_json *body,
686         struct ast_ari_channels_continue_in_dialplan_args *args)
687 {
688         struct ast_json *field;
689         /* Parse query parameters out of it */
690         field = ast_json_object_get(body, "context");
691         if (field) {
692                 args->context = ast_json_string_get(field);
693         }
694         field = ast_json_object_get(body, "extension");
695         if (field) {
696                 args->extension = ast_json_string_get(field);
697         }
698         field = ast_json_object_get(body, "priority");
699         if (field) {
700                 args->priority = ast_json_integer_get(field);
701         }
702         field = ast_json_object_get(body, "label");
703         if (field) {
704                 args->label = ast_json_string_get(field);
705         }
706         return 0;
707 }
708
709 /*!
710  * \brief Parameter parsing callback for /channels/{channelId}/continue.
711  * \param get_params GET parameters in the HTTP request.
712  * \param path_vars Path variables extracted from the request.
713  * \param headers HTTP headers.
714  * \param[out] response Response to the HTTP request.
715  */
716 static void ast_ari_channels_continue_in_dialplan_cb(
717         struct ast_tcptls_session_instance *ser,
718         struct ast_variable *get_params, struct ast_variable *path_vars,
719         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
720 {
721         struct ast_ari_channels_continue_in_dialplan_args args = {};
722         struct ast_variable *i;
723 #if defined(AST_DEVMODE)
724         int is_valid;
725         int code;
726 #endif /* AST_DEVMODE */
727
728         for (i = get_params; i; i = i->next) {
729                 if (strcmp(i->name, "context") == 0) {
730                         args.context = (i->value);
731                 } else
732                 if (strcmp(i->name, "extension") == 0) {
733                         args.extension = (i->value);
734                 } else
735                 if (strcmp(i->name, "priority") == 0) {
736                         args.priority = atoi(i->value);
737                 } else
738                 if (strcmp(i->name, "label") == 0) {
739                         args.label = (i->value);
740                 } else
741                 {}
742         }
743         for (i = path_vars; i; i = i->next) {
744                 if (strcmp(i->name, "channelId") == 0) {
745                         args.channel_id = (i->value);
746                 } else
747                 {}
748         }
749         if (ast_ari_channels_continue_in_dialplan_parse_body(body, &args)) {
750                 ast_ari_response_alloc_failed(response);
751                 goto fin;
752         }
753         ast_ari_channels_continue_in_dialplan(headers, &args, response);
754 #if defined(AST_DEVMODE)
755         code = response->response_code;
756
757         switch (code) {
758         case 0: /* Implementation is still a stub, or the code wasn't set */
759                 is_valid = response->message == NULL;
760                 break;
761         case 500: /* Internal Server Error */
762         case 501: /* Not Implemented */
763         case 404: /* Channel not found */
764         case 409: /* Channel not in a Stasis application */
765         case 412: /* Channel in invalid state */
766                 is_valid = 1;
767                 break;
768         default:
769                 if (200 <= code && code <= 299) {
770                         is_valid = ast_ari_validate_void(
771                                 response->message);
772                 } else {
773                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/continue\n", code);
774                         is_valid = 0;
775                 }
776         }
777
778         if (!is_valid) {
779                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/continue\n");
780                 ast_ari_response_error(response, 500,
781                         "Internal Server Error", "Response validation failed");
782         }
783 #endif /* AST_DEVMODE */
784
785 fin: __attribute__((unused))
786         return;
787 }
788 int ast_ari_channels_move_parse_body(
789         struct ast_json *body,
790         struct ast_ari_channels_move_args *args)
791 {
792         struct ast_json *field;
793         /* Parse query parameters out of it */
794         field = ast_json_object_get(body, "app");
795         if (field) {
796                 args->app = ast_json_string_get(field);
797         }
798         field = ast_json_object_get(body, "appArgs");
799         if (field) {
800                 args->app_args = ast_json_string_get(field);
801         }
802         return 0;
803 }
804
805 /*!
806  * \brief Parameter parsing callback for /channels/{channelId}/move.
807  * \param get_params GET parameters in the HTTP request.
808  * \param path_vars Path variables extracted from the request.
809  * \param headers HTTP headers.
810  * \param[out] response Response to the HTTP request.
811  */
812 static void ast_ari_channels_move_cb(
813         struct ast_tcptls_session_instance *ser,
814         struct ast_variable *get_params, struct ast_variable *path_vars,
815         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
816 {
817         struct ast_ari_channels_move_args args = {};
818         struct ast_variable *i;
819 #if defined(AST_DEVMODE)
820         int is_valid;
821         int code;
822 #endif /* AST_DEVMODE */
823
824         for (i = get_params; i; i = i->next) {
825                 if (strcmp(i->name, "app") == 0) {
826                         args.app = (i->value);
827                 } else
828                 if (strcmp(i->name, "appArgs") == 0) {
829                         args.app_args = (i->value);
830                 } else
831                 {}
832         }
833         for (i = path_vars; i; i = i->next) {
834                 if (strcmp(i->name, "channelId") == 0) {
835                         args.channel_id = (i->value);
836                 } else
837                 {}
838         }
839         if (ast_ari_channels_move_parse_body(body, &args)) {
840                 ast_ari_response_alloc_failed(response);
841                 goto fin;
842         }
843         ast_ari_channels_move(headers, &args, response);
844 #if defined(AST_DEVMODE)
845         code = response->response_code;
846
847         switch (code) {
848         case 0: /* Implementation is still a stub, or the code wasn't set */
849                 is_valid = response->message == NULL;
850                 break;
851         case 500: /* Internal Server Error */
852         case 501: /* Not Implemented */
853         case 404: /* Channel not found */
854         case 409: /* Channel not in a Stasis application */
855                 is_valid = 1;
856                 break;
857         default:
858                 if (200 <= code && code <= 299) {
859                         is_valid = ast_ari_validate_void(
860                                 response->message);
861                 } else {
862                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/move\n", code);
863                         is_valid = 0;
864                 }
865         }
866
867         if (!is_valid) {
868                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/move\n");
869                 ast_ari_response_error(response, 500,
870                         "Internal Server Error", "Response validation failed");
871         }
872 #endif /* AST_DEVMODE */
873
874 fin: __attribute__((unused))
875         return;
876 }
877 int ast_ari_channels_redirect_parse_body(
878         struct ast_json *body,
879         struct ast_ari_channels_redirect_args *args)
880 {
881         struct ast_json *field;
882         /* Parse query parameters out of it */
883         field = ast_json_object_get(body, "endpoint");
884         if (field) {
885                 args->endpoint = ast_json_string_get(field);
886         }
887         return 0;
888 }
889
890 /*!
891  * \brief Parameter parsing callback for /channels/{channelId}/redirect.
892  * \param get_params GET parameters in the HTTP request.
893  * \param path_vars Path variables extracted from the request.
894  * \param headers HTTP headers.
895  * \param[out] response Response to the HTTP request.
896  */
897 static void ast_ari_channels_redirect_cb(
898         struct ast_tcptls_session_instance *ser,
899         struct ast_variable *get_params, struct ast_variable *path_vars,
900         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
901 {
902         struct ast_ari_channels_redirect_args args = {};
903         struct ast_variable *i;
904 #if defined(AST_DEVMODE)
905         int is_valid;
906         int code;
907 #endif /* AST_DEVMODE */
908
909         for (i = get_params; i; i = i->next) {
910                 if (strcmp(i->name, "endpoint") == 0) {
911                         args.endpoint = (i->value);
912                 } else
913                 {}
914         }
915         for (i = path_vars; i; i = i->next) {
916                 if (strcmp(i->name, "channelId") == 0) {
917                         args.channel_id = (i->value);
918                 } else
919                 {}
920         }
921         if (ast_ari_channels_redirect_parse_body(body, &args)) {
922                 ast_ari_response_alloc_failed(response);
923                 goto fin;
924         }
925         ast_ari_channels_redirect(headers, &args, response);
926 #if defined(AST_DEVMODE)
927         code = response->response_code;
928
929         switch (code) {
930         case 0: /* Implementation is still a stub, or the code wasn't set */
931                 is_valid = response->message == NULL;
932                 break;
933         case 500: /* Internal Server Error */
934         case 501: /* Not Implemented */
935         case 400: /* Endpoint parameter not provided */
936         case 404: /* Channel or endpoint not found */
937         case 409: /* Channel not in a Stasis application */
938         case 422: /* Endpoint is not the same type as the channel */
939         case 412: /* Channel in invalid state */
940                 is_valid = 1;
941                 break;
942         default:
943                 if (200 <= code && code <= 299) {
944                         is_valid = ast_ari_validate_void(
945                                 response->message);
946                 } else {
947                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/redirect\n", code);
948                         is_valid = 0;
949                 }
950         }
951
952         if (!is_valid) {
953                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/redirect\n");
954                 ast_ari_response_error(response, 500,
955                         "Internal Server Error", "Response validation failed");
956         }
957 #endif /* AST_DEVMODE */
958
959 fin: __attribute__((unused))
960         return;
961 }
962 /*!
963  * \brief Parameter parsing callback for /channels/{channelId}/answer.
964  * \param get_params GET parameters in the HTTP request.
965  * \param path_vars Path variables extracted from the request.
966  * \param headers HTTP headers.
967  * \param[out] response Response to the HTTP request.
968  */
969 static void ast_ari_channels_answer_cb(
970         struct ast_tcptls_session_instance *ser,
971         struct ast_variable *get_params, struct ast_variable *path_vars,
972         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
973 {
974         struct ast_ari_channels_answer_args args = {};
975         struct ast_variable *i;
976 #if defined(AST_DEVMODE)
977         int is_valid;
978         int code;
979 #endif /* AST_DEVMODE */
980
981         for (i = path_vars; i; i = i->next) {
982                 if (strcmp(i->name, "channelId") == 0) {
983                         args.channel_id = (i->value);
984                 } else
985                 {}
986         }
987         ast_ari_channels_answer(headers, &args, response);
988 #if defined(AST_DEVMODE)
989         code = response->response_code;
990
991         switch (code) {
992         case 0: /* Implementation is still a stub, or the code wasn't set */
993                 is_valid = response->message == NULL;
994                 break;
995         case 500: /* Internal Server Error */
996         case 501: /* Not Implemented */
997         case 404: /* Channel not found */
998         case 409: /* Channel not in a Stasis application */
999         case 412: /* Channel in invalid state */
1000                 is_valid = 1;
1001                 break;
1002         default:
1003                 if (200 <= code && code <= 299) {
1004                         is_valid = ast_ari_validate_void(
1005                                 response->message);
1006                 } else {
1007                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/answer\n", code);
1008                         is_valid = 0;
1009                 }
1010         }
1011
1012         if (!is_valid) {
1013                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/answer\n");
1014                 ast_ari_response_error(response, 500,
1015                         "Internal Server Error", "Response validation failed");
1016         }
1017 #endif /* AST_DEVMODE */
1018
1019 fin: __attribute__((unused))
1020         return;
1021 }
1022 /*!
1023  * \brief Parameter parsing callback for /channels/{channelId}/ring.
1024  * \param get_params GET parameters in the HTTP request.
1025  * \param path_vars Path variables extracted from the request.
1026  * \param headers HTTP headers.
1027  * \param[out] response Response to the HTTP request.
1028  */
1029 static void ast_ari_channels_ring_cb(
1030         struct ast_tcptls_session_instance *ser,
1031         struct ast_variable *get_params, struct ast_variable *path_vars,
1032         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1033 {
1034         struct ast_ari_channels_ring_args args = {};
1035         struct ast_variable *i;
1036 #if defined(AST_DEVMODE)
1037         int is_valid;
1038         int code;
1039 #endif /* AST_DEVMODE */
1040
1041         for (i = path_vars; i; i = i->next) {
1042                 if (strcmp(i->name, "channelId") == 0) {
1043                         args.channel_id = (i->value);
1044                 } else
1045                 {}
1046         }
1047         ast_ari_channels_ring(headers, &args, response);
1048 #if defined(AST_DEVMODE)
1049         code = response->response_code;
1050
1051         switch (code) {
1052         case 0: /* Implementation is still a stub, or the code wasn't set */
1053                 is_valid = response->message == NULL;
1054                 break;
1055         case 500: /* Internal Server Error */
1056         case 501: /* Not Implemented */
1057         case 404: /* Channel not found */
1058         case 409: /* Channel not in a Stasis application */
1059         case 412: /* Channel in invalid state */
1060                 is_valid = 1;
1061                 break;
1062         default:
1063                 if (200 <= code && code <= 299) {
1064                         is_valid = ast_ari_validate_void(
1065                                 response->message);
1066                 } else {
1067                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/ring\n", code);
1068                         is_valid = 0;
1069                 }
1070         }
1071
1072         if (!is_valid) {
1073                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/ring\n");
1074                 ast_ari_response_error(response, 500,
1075                         "Internal Server Error", "Response validation failed");
1076         }
1077 #endif /* AST_DEVMODE */
1078
1079 fin: __attribute__((unused))
1080         return;
1081 }
1082 /*!
1083  * \brief Parameter parsing callback for /channels/{channelId}/ring.
1084  * \param get_params GET parameters in the HTTP request.
1085  * \param path_vars Path variables extracted from the request.
1086  * \param headers HTTP headers.
1087  * \param[out] response Response to the HTTP request.
1088  */
1089 static void ast_ari_channels_ring_stop_cb(
1090         struct ast_tcptls_session_instance *ser,
1091         struct ast_variable *get_params, struct ast_variable *path_vars,
1092         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1093 {
1094         struct ast_ari_channels_ring_stop_args args = {};
1095         struct ast_variable *i;
1096 #if defined(AST_DEVMODE)
1097         int is_valid;
1098         int code;
1099 #endif /* AST_DEVMODE */
1100
1101         for (i = path_vars; i; i = i->next) {
1102                 if (strcmp(i->name, "channelId") == 0) {
1103                         args.channel_id = (i->value);
1104                 } else
1105                 {}
1106         }
1107         ast_ari_channels_ring_stop(headers, &args, response);
1108 #if defined(AST_DEVMODE)
1109         code = response->response_code;
1110
1111         switch (code) {
1112         case 0: /* Implementation is still a stub, or the code wasn't set */
1113                 is_valid = response->message == NULL;
1114                 break;
1115         case 500: /* Internal Server Error */
1116         case 501: /* Not Implemented */
1117         case 404: /* Channel not found */
1118         case 409: /* Channel not in a Stasis application */
1119         case 412: /* Channel in invalid state */
1120                 is_valid = 1;
1121                 break;
1122         default:
1123                 if (200 <= code && code <= 299) {
1124                         is_valid = ast_ari_validate_void(
1125                                 response->message);
1126                 } else {
1127                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/ring\n", code);
1128                         is_valid = 0;
1129                 }
1130         }
1131
1132         if (!is_valid) {
1133                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/ring\n");
1134                 ast_ari_response_error(response, 500,
1135                         "Internal Server Error", "Response validation failed");
1136         }
1137 #endif /* AST_DEVMODE */
1138
1139 fin: __attribute__((unused))
1140         return;
1141 }
1142 int ast_ari_channels_send_dtmf_parse_body(
1143         struct ast_json *body,
1144         struct ast_ari_channels_send_dtmf_args *args)
1145 {
1146         struct ast_json *field;
1147         /* Parse query parameters out of it */
1148         field = ast_json_object_get(body, "dtmf");
1149         if (field) {
1150                 args->dtmf = ast_json_string_get(field);
1151         }
1152         field = ast_json_object_get(body, "before");
1153         if (field) {
1154                 args->before = ast_json_integer_get(field);
1155         }
1156         field = ast_json_object_get(body, "between");
1157         if (field) {
1158                 args->between = ast_json_integer_get(field);
1159         }
1160         field = ast_json_object_get(body, "duration");
1161         if (field) {
1162                 args->duration = ast_json_integer_get(field);
1163         }
1164         field = ast_json_object_get(body, "after");
1165         if (field) {
1166                 args->after = ast_json_integer_get(field);
1167         }
1168         return 0;
1169 }
1170
1171 /*!
1172  * \brief Parameter parsing callback for /channels/{channelId}/dtmf.
1173  * \param get_params GET parameters in the HTTP request.
1174  * \param path_vars Path variables extracted from the request.
1175  * \param headers HTTP headers.
1176  * \param[out] response Response to the HTTP request.
1177  */
1178 static void ast_ari_channels_send_dtmf_cb(
1179         struct ast_tcptls_session_instance *ser,
1180         struct ast_variable *get_params, struct ast_variable *path_vars,
1181         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1182 {
1183         struct ast_ari_channels_send_dtmf_args args = {};
1184         struct ast_variable *i;
1185 #if defined(AST_DEVMODE)
1186         int is_valid;
1187         int code;
1188 #endif /* AST_DEVMODE */
1189
1190         for (i = get_params; i; i = i->next) {
1191                 if (strcmp(i->name, "dtmf") == 0) {
1192                         args.dtmf = (i->value);
1193                 } else
1194                 if (strcmp(i->name, "before") == 0) {
1195                         args.before = atoi(i->value);
1196                 } else
1197                 if (strcmp(i->name, "between") == 0) {
1198                         args.between = atoi(i->value);
1199                 } else
1200                 if (strcmp(i->name, "duration") == 0) {
1201                         args.duration = atoi(i->value);
1202                 } else
1203                 if (strcmp(i->name, "after") == 0) {
1204                         args.after = atoi(i->value);
1205                 } else
1206                 {}
1207         }
1208         for (i = path_vars; i; i = i->next) {
1209                 if (strcmp(i->name, "channelId") == 0) {
1210                         args.channel_id = (i->value);
1211                 } else
1212                 {}
1213         }
1214         if (ast_ari_channels_send_dtmf_parse_body(body, &args)) {
1215                 ast_ari_response_alloc_failed(response);
1216                 goto fin;
1217         }
1218         ast_ari_channels_send_dtmf(headers, &args, response);
1219 #if defined(AST_DEVMODE)
1220         code = response->response_code;
1221
1222         switch (code) {
1223         case 0: /* Implementation is still a stub, or the code wasn't set */
1224                 is_valid = response->message == NULL;
1225                 break;
1226         case 500: /* Internal Server Error */
1227         case 501: /* Not Implemented */
1228         case 400: /* DTMF is required */
1229         case 404: /* Channel not found */
1230         case 409: /* Channel not in a Stasis application */
1231         case 412: /* Channel in invalid state */
1232                 is_valid = 1;
1233                 break;
1234         default:
1235                 if (200 <= code && code <= 299) {
1236                         is_valid = ast_ari_validate_void(
1237                                 response->message);
1238                 } else {
1239                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/dtmf\n", code);
1240                         is_valid = 0;
1241                 }
1242         }
1243
1244         if (!is_valid) {
1245                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/dtmf\n");
1246                 ast_ari_response_error(response, 500,
1247                         "Internal Server Error", "Response validation failed");
1248         }
1249 #endif /* AST_DEVMODE */
1250
1251 fin: __attribute__((unused))
1252         return;
1253 }
1254 int ast_ari_channels_mute_parse_body(
1255         struct ast_json *body,
1256         struct ast_ari_channels_mute_args *args)
1257 {
1258         struct ast_json *field;
1259         /* Parse query parameters out of it */
1260         field = ast_json_object_get(body, "direction");
1261         if (field) {
1262                 args->direction = ast_json_string_get(field);
1263         }
1264         return 0;
1265 }
1266
1267 /*!
1268  * \brief Parameter parsing callback for /channels/{channelId}/mute.
1269  * \param get_params GET parameters in the HTTP request.
1270  * \param path_vars Path variables extracted from the request.
1271  * \param headers HTTP headers.
1272  * \param[out] response Response to the HTTP request.
1273  */
1274 static void ast_ari_channels_mute_cb(
1275         struct ast_tcptls_session_instance *ser,
1276         struct ast_variable *get_params, struct ast_variable *path_vars,
1277         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1278 {
1279         struct ast_ari_channels_mute_args args = {};
1280         struct ast_variable *i;
1281 #if defined(AST_DEVMODE)
1282         int is_valid;
1283         int code;
1284 #endif /* AST_DEVMODE */
1285
1286         for (i = get_params; i; i = i->next) {
1287                 if (strcmp(i->name, "direction") == 0) {
1288                         args.direction = (i->value);
1289                 } else
1290                 {}
1291         }
1292         for (i = path_vars; i; i = i->next) {
1293                 if (strcmp(i->name, "channelId") == 0) {
1294                         args.channel_id = (i->value);
1295                 } else
1296                 {}
1297         }
1298         if (ast_ari_channels_mute_parse_body(body, &args)) {
1299                 ast_ari_response_alloc_failed(response);
1300                 goto fin;
1301         }
1302         ast_ari_channels_mute(headers, &args, response);
1303 #if defined(AST_DEVMODE)
1304         code = response->response_code;
1305
1306         switch (code) {
1307         case 0: /* Implementation is still a stub, or the code wasn't set */
1308                 is_valid = response->message == NULL;
1309                 break;
1310         case 500: /* Internal Server Error */
1311         case 501: /* Not Implemented */
1312         case 404: /* Channel not found */
1313         case 409: /* Channel not in a Stasis application */
1314         case 412: /* Channel in invalid state */
1315                 is_valid = 1;
1316                 break;
1317         default:
1318                 if (200 <= code && code <= 299) {
1319                         is_valid = ast_ari_validate_void(
1320                                 response->message);
1321                 } else {
1322                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/mute\n", code);
1323                         is_valid = 0;
1324                 }
1325         }
1326
1327         if (!is_valid) {
1328                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/mute\n");
1329                 ast_ari_response_error(response, 500,
1330                         "Internal Server Error", "Response validation failed");
1331         }
1332 #endif /* AST_DEVMODE */
1333
1334 fin: __attribute__((unused))
1335         return;
1336 }
1337 int ast_ari_channels_unmute_parse_body(
1338         struct ast_json *body,
1339         struct ast_ari_channels_unmute_args *args)
1340 {
1341         struct ast_json *field;
1342         /* Parse query parameters out of it */
1343         field = ast_json_object_get(body, "direction");
1344         if (field) {
1345                 args->direction = ast_json_string_get(field);
1346         }
1347         return 0;
1348 }
1349
1350 /*!
1351  * \brief Parameter parsing callback for /channels/{channelId}/mute.
1352  * \param get_params GET parameters in the HTTP request.
1353  * \param path_vars Path variables extracted from the request.
1354  * \param headers HTTP headers.
1355  * \param[out] response Response to the HTTP request.
1356  */
1357 static void ast_ari_channels_unmute_cb(
1358         struct ast_tcptls_session_instance *ser,
1359         struct ast_variable *get_params, struct ast_variable *path_vars,
1360         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1361 {
1362         struct ast_ari_channels_unmute_args args = {};
1363         struct ast_variable *i;
1364 #if defined(AST_DEVMODE)
1365         int is_valid;
1366         int code;
1367 #endif /* AST_DEVMODE */
1368
1369         for (i = get_params; i; i = i->next) {
1370                 if (strcmp(i->name, "direction") == 0) {
1371                         args.direction = (i->value);
1372                 } else
1373                 {}
1374         }
1375         for (i = path_vars; i; i = i->next) {
1376                 if (strcmp(i->name, "channelId") == 0) {
1377                         args.channel_id = (i->value);
1378                 } else
1379                 {}
1380         }
1381         if (ast_ari_channels_unmute_parse_body(body, &args)) {
1382                 ast_ari_response_alloc_failed(response);
1383                 goto fin;
1384         }
1385         ast_ari_channels_unmute(headers, &args, response);
1386 #if defined(AST_DEVMODE)
1387         code = response->response_code;
1388
1389         switch (code) {
1390         case 0: /* Implementation is still a stub, or the code wasn't set */
1391                 is_valid = response->message == NULL;
1392                 break;
1393         case 500: /* Internal Server Error */
1394         case 501: /* Not Implemented */
1395         case 404: /* Channel not found */
1396         case 409: /* Channel not in a Stasis application */
1397         case 412: /* Channel in invalid state */
1398                 is_valid = 1;
1399                 break;
1400         default:
1401                 if (200 <= code && code <= 299) {
1402                         is_valid = ast_ari_validate_void(
1403                                 response->message);
1404                 } else {
1405                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/mute\n", code);
1406                         is_valid = 0;
1407                 }
1408         }
1409
1410         if (!is_valid) {
1411                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/mute\n");
1412                 ast_ari_response_error(response, 500,
1413                         "Internal Server Error", "Response validation failed");
1414         }
1415 #endif /* AST_DEVMODE */
1416
1417 fin: __attribute__((unused))
1418         return;
1419 }
1420 /*!
1421  * \brief Parameter parsing callback for /channels/{channelId}/hold.
1422  * \param get_params GET parameters in the HTTP request.
1423  * \param path_vars Path variables extracted from the request.
1424  * \param headers HTTP headers.
1425  * \param[out] response Response to the HTTP request.
1426  */
1427 static void ast_ari_channels_hold_cb(
1428         struct ast_tcptls_session_instance *ser,
1429         struct ast_variable *get_params, struct ast_variable *path_vars,
1430         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1431 {
1432         struct ast_ari_channels_hold_args args = {};
1433         struct ast_variable *i;
1434 #if defined(AST_DEVMODE)
1435         int is_valid;
1436         int code;
1437 #endif /* AST_DEVMODE */
1438
1439         for (i = path_vars; i; i = i->next) {
1440                 if (strcmp(i->name, "channelId") == 0) {
1441                         args.channel_id = (i->value);
1442                 } else
1443                 {}
1444         }
1445         ast_ari_channels_hold(headers, &args, response);
1446 #if defined(AST_DEVMODE)
1447         code = response->response_code;
1448
1449         switch (code) {
1450         case 0: /* Implementation is still a stub, or the code wasn't set */
1451                 is_valid = response->message == NULL;
1452                 break;
1453         case 500: /* Internal Server Error */
1454         case 501: /* Not Implemented */
1455         case 404: /* Channel not found */
1456         case 409: /* Channel not in a Stasis application */
1457         case 412: /* Channel in invalid state */
1458                 is_valid = 1;
1459                 break;
1460         default:
1461                 if (200 <= code && code <= 299) {
1462                         is_valid = ast_ari_validate_void(
1463                                 response->message);
1464                 } else {
1465                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/hold\n", code);
1466                         is_valid = 0;
1467                 }
1468         }
1469
1470         if (!is_valid) {
1471                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/hold\n");
1472                 ast_ari_response_error(response, 500,
1473                         "Internal Server Error", "Response validation failed");
1474         }
1475 #endif /* AST_DEVMODE */
1476
1477 fin: __attribute__((unused))
1478         return;
1479 }
1480 /*!
1481  * \brief Parameter parsing callback for /channels/{channelId}/hold.
1482  * \param get_params GET parameters in the HTTP request.
1483  * \param path_vars Path variables extracted from the request.
1484  * \param headers HTTP headers.
1485  * \param[out] response Response to the HTTP request.
1486  */
1487 static void ast_ari_channels_unhold_cb(
1488         struct ast_tcptls_session_instance *ser,
1489         struct ast_variable *get_params, struct ast_variable *path_vars,
1490         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1491 {
1492         struct ast_ari_channels_unhold_args args = {};
1493         struct ast_variable *i;
1494 #if defined(AST_DEVMODE)
1495         int is_valid;
1496         int code;
1497 #endif /* AST_DEVMODE */
1498
1499         for (i = path_vars; i; i = i->next) {
1500                 if (strcmp(i->name, "channelId") == 0) {
1501                         args.channel_id = (i->value);
1502                 } else
1503                 {}
1504         }
1505         ast_ari_channels_unhold(headers, &args, response);
1506 #if defined(AST_DEVMODE)
1507         code = response->response_code;
1508
1509         switch (code) {
1510         case 0: /* Implementation is still a stub, or the code wasn't set */
1511                 is_valid = response->message == NULL;
1512                 break;
1513         case 500: /* Internal Server Error */
1514         case 501: /* Not Implemented */
1515         case 404: /* Channel not found */
1516         case 409: /* Channel not in a Stasis application */
1517         case 412: /* Channel in invalid state */
1518                 is_valid = 1;
1519                 break;
1520         default:
1521                 if (200 <= code && code <= 299) {
1522                         is_valid = ast_ari_validate_void(
1523                                 response->message);
1524                 } else {
1525                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/hold\n", code);
1526                         is_valid = 0;
1527                 }
1528         }
1529
1530         if (!is_valid) {
1531                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/hold\n");
1532                 ast_ari_response_error(response, 500,
1533                         "Internal Server Error", "Response validation failed");
1534         }
1535 #endif /* AST_DEVMODE */
1536
1537 fin: __attribute__((unused))
1538         return;
1539 }
1540 int ast_ari_channels_start_moh_parse_body(
1541         struct ast_json *body,
1542         struct ast_ari_channels_start_moh_args *args)
1543 {
1544         struct ast_json *field;
1545         /* Parse query parameters out of it */
1546         field = ast_json_object_get(body, "mohClass");
1547         if (field) {
1548                 args->moh_class = ast_json_string_get(field);
1549         }
1550         return 0;
1551 }
1552
1553 /*!
1554  * \brief Parameter parsing callback for /channels/{channelId}/moh.
1555  * \param get_params GET parameters in the HTTP request.
1556  * \param path_vars Path variables extracted from the request.
1557  * \param headers HTTP headers.
1558  * \param[out] response Response to the HTTP request.
1559  */
1560 static void ast_ari_channels_start_moh_cb(
1561         struct ast_tcptls_session_instance *ser,
1562         struct ast_variable *get_params, struct ast_variable *path_vars,
1563         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1564 {
1565         struct ast_ari_channels_start_moh_args args = {};
1566         struct ast_variable *i;
1567 #if defined(AST_DEVMODE)
1568         int is_valid;
1569         int code;
1570 #endif /* AST_DEVMODE */
1571
1572         for (i = get_params; i; i = i->next) {
1573                 if (strcmp(i->name, "mohClass") == 0) {
1574                         args.moh_class = (i->value);
1575                 } else
1576                 {}
1577         }
1578         for (i = path_vars; i; i = i->next) {
1579                 if (strcmp(i->name, "channelId") == 0) {
1580                         args.channel_id = (i->value);
1581                 } else
1582                 {}
1583         }
1584         if (ast_ari_channels_start_moh_parse_body(body, &args)) {
1585                 ast_ari_response_alloc_failed(response);
1586                 goto fin;
1587         }
1588         ast_ari_channels_start_moh(headers, &args, response);
1589 #if defined(AST_DEVMODE)
1590         code = response->response_code;
1591
1592         switch (code) {
1593         case 0: /* Implementation is still a stub, or the code wasn't set */
1594                 is_valid = response->message == NULL;
1595                 break;
1596         case 500: /* Internal Server Error */
1597         case 501: /* Not Implemented */
1598         case 404: /* Channel not found */
1599         case 409: /* Channel not in a Stasis application */
1600         case 412: /* Channel in invalid state */
1601                 is_valid = 1;
1602                 break;
1603         default:
1604                 if (200 <= code && code <= 299) {
1605                         is_valid = ast_ari_validate_void(
1606                                 response->message);
1607                 } else {
1608                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/moh\n", code);
1609                         is_valid = 0;
1610                 }
1611         }
1612
1613         if (!is_valid) {
1614                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/moh\n");
1615                 ast_ari_response_error(response, 500,
1616                         "Internal Server Error", "Response validation failed");
1617         }
1618 #endif /* AST_DEVMODE */
1619
1620 fin: __attribute__((unused))
1621         return;
1622 }
1623 /*!
1624  * \brief Parameter parsing callback for /channels/{channelId}/moh.
1625  * \param get_params GET parameters in the HTTP request.
1626  * \param path_vars Path variables extracted from the request.
1627  * \param headers HTTP headers.
1628  * \param[out] response Response to the HTTP request.
1629  */
1630 static void ast_ari_channels_stop_moh_cb(
1631         struct ast_tcptls_session_instance *ser,
1632         struct ast_variable *get_params, struct ast_variable *path_vars,
1633         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1634 {
1635         struct ast_ari_channels_stop_moh_args args = {};
1636         struct ast_variable *i;
1637 #if defined(AST_DEVMODE)
1638         int is_valid;
1639         int code;
1640 #endif /* AST_DEVMODE */
1641
1642         for (i = path_vars; i; i = i->next) {
1643                 if (strcmp(i->name, "channelId") == 0) {
1644                         args.channel_id = (i->value);
1645                 } else
1646                 {}
1647         }
1648         ast_ari_channels_stop_moh(headers, &args, response);
1649 #if defined(AST_DEVMODE)
1650         code = response->response_code;
1651
1652         switch (code) {
1653         case 0: /* Implementation is still a stub, or the code wasn't set */
1654                 is_valid = response->message == NULL;
1655                 break;
1656         case 500: /* Internal Server Error */
1657         case 501: /* Not Implemented */
1658         case 404: /* Channel not found */
1659         case 409: /* Channel not in a Stasis application */
1660         case 412: /* Channel in invalid state */
1661                 is_valid = 1;
1662                 break;
1663         default:
1664                 if (200 <= code && code <= 299) {
1665                         is_valid = ast_ari_validate_void(
1666                                 response->message);
1667                 } else {
1668                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/moh\n", code);
1669                         is_valid = 0;
1670                 }
1671         }
1672
1673         if (!is_valid) {
1674                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/moh\n");
1675                 ast_ari_response_error(response, 500,
1676                         "Internal Server Error", "Response validation failed");
1677         }
1678 #endif /* AST_DEVMODE */
1679
1680 fin: __attribute__((unused))
1681         return;
1682 }
1683 /*!
1684  * \brief Parameter parsing callback for /channels/{channelId}/silence.
1685  * \param get_params GET parameters in the HTTP request.
1686  * \param path_vars Path variables extracted from the request.
1687  * \param headers HTTP headers.
1688  * \param[out] response Response to the HTTP request.
1689  */
1690 static void ast_ari_channels_start_silence_cb(
1691         struct ast_tcptls_session_instance *ser,
1692         struct ast_variable *get_params, struct ast_variable *path_vars,
1693         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1694 {
1695         struct ast_ari_channels_start_silence_args args = {};
1696         struct ast_variable *i;
1697 #if defined(AST_DEVMODE)
1698         int is_valid;
1699         int code;
1700 #endif /* AST_DEVMODE */
1701
1702         for (i = path_vars; i; i = i->next) {
1703                 if (strcmp(i->name, "channelId") == 0) {
1704                         args.channel_id = (i->value);
1705                 } else
1706                 {}
1707         }
1708         ast_ari_channels_start_silence(headers, &args, response);
1709 #if defined(AST_DEVMODE)
1710         code = response->response_code;
1711
1712         switch (code) {
1713         case 0: /* Implementation is still a stub, or the code wasn't set */
1714                 is_valid = response->message == NULL;
1715                 break;
1716         case 500: /* Internal Server Error */
1717         case 501: /* Not Implemented */
1718         case 404: /* Channel not found */
1719         case 409: /* Channel not in a Stasis application */
1720         case 412: /* Channel in invalid state */
1721                 is_valid = 1;
1722                 break;
1723         default:
1724                 if (200 <= code && code <= 299) {
1725                         is_valid = ast_ari_validate_void(
1726                                 response->message);
1727                 } else {
1728                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/silence\n", code);
1729                         is_valid = 0;
1730                 }
1731         }
1732
1733         if (!is_valid) {
1734                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/silence\n");
1735                 ast_ari_response_error(response, 500,
1736                         "Internal Server Error", "Response validation failed");
1737         }
1738 #endif /* AST_DEVMODE */
1739
1740 fin: __attribute__((unused))
1741         return;
1742 }
1743 /*!
1744  * \brief Parameter parsing callback for /channels/{channelId}/silence.
1745  * \param get_params GET parameters in the HTTP request.
1746  * \param path_vars Path variables extracted from the request.
1747  * \param headers HTTP headers.
1748  * \param[out] response Response to the HTTP request.
1749  */
1750 static void ast_ari_channels_stop_silence_cb(
1751         struct ast_tcptls_session_instance *ser,
1752         struct ast_variable *get_params, struct ast_variable *path_vars,
1753         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1754 {
1755         struct ast_ari_channels_stop_silence_args args = {};
1756         struct ast_variable *i;
1757 #if defined(AST_DEVMODE)
1758         int is_valid;
1759         int code;
1760 #endif /* AST_DEVMODE */
1761
1762         for (i = path_vars; i; i = i->next) {
1763                 if (strcmp(i->name, "channelId") == 0) {
1764                         args.channel_id = (i->value);
1765                 } else
1766                 {}
1767         }
1768         ast_ari_channels_stop_silence(headers, &args, response);
1769 #if defined(AST_DEVMODE)
1770         code = response->response_code;
1771
1772         switch (code) {
1773         case 0: /* Implementation is still a stub, or the code wasn't set */
1774                 is_valid = response->message == NULL;
1775                 break;
1776         case 500: /* Internal Server Error */
1777         case 501: /* Not Implemented */
1778         case 404: /* Channel not found */
1779         case 409: /* Channel not in a Stasis application */
1780         case 412: /* Channel in invalid state */
1781                 is_valid = 1;
1782                 break;
1783         default:
1784                 if (200 <= code && code <= 299) {
1785                         is_valid = ast_ari_validate_void(
1786                                 response->message);
1787                 } else {
1788                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/silence\n", code);
1789                         is_valid = 0;
1790                 }
1791         }
1792
1793         if (!is_valid) {
1794                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/silence\n");
1795                 ast_ari_response_error(response, 500,
1796                         "Internal Server Error", "Response validation failed");
1797         }
1798 #endif /* AST_DEVMODE */
1799
1800 fin: __attribute__((unused))
1801         return;
1802 }
1803 int ast_ari_channels_play_parse_body(
1804         struct ast_json *body,
1805         struct ast_ari_channels_play_args *args)
1806 {
1807         struct ast_json *field;
1808         /* Parse query parameters out of it */
1809         field = ast_json_object_get(body, "media");
1810         if (field) {
1811                 /* If they were silly enough to both pass in a query param and a
1812                  * JSON body, free up the query value.
1813                  */
1814                 ast_free(args->media);
1815                 if (ast_json_typeof(field) == AST_JSON_ARRAY) {
1816                         /* Multiple param passed as array */
1817                         size_t i;
1818                         args->media_count = ast_json_array_size(field);
1819                         args->media = ast_malloc(sizeof(*args->media) * args->media_count);
1820
1821                         if (!args->media) {
1822                                 return -1;
1823                         }
1824
1825                         for (i = 0; i < args->media_count; ++i) {
1826                                 args->media[i] = ast_json_string_get(ast_json_array_get(field, i));
1827                         }
1828                 } else {
1829                         /* Multiple param passed as single value */
1830                         args->media_count = 1;
1831                         args->media = ast_malloc(sizeof(*args->media) * args->media_count);
1832                         if (!args->media) {
1833                                 return -1;
1834                         }
1835                         args->media[0] = ast_json_string_get(field);
1836                 }
1837         }
1838         field = ast_json_object_get(body, "lang");
1839         if (field) {
1840                 args->lang = ast_json_string_get(field);
1841         }
1842         field = ast_json_object_get(body, "offsetms");
1843         if (field) {
1844                 args->offsetms = ast_json_integer_get(field);
1845         }
1846         field = ast_json_object_get(body, "skipms");
1847         if (field) {
1848                 args->skipms = ast_json_integer_get(field);
1849         }
1850         field = ast_json_object_get(body, "playbackId");
1851         if (field) {
1852                 args->playback_id = ast_json_string_get(field);
1853         }
1854         return 0;
1855 }
1856
1857 /*!
1858  * \brief Parameter parsing callback for /channels/{channelId}/play.
1859  * \param get_params GET parameters in the HTTP request.
1860  * \param path_vars Path variables extracted from the request.
1861  * \param headers HTTP headers.
1862  * \param[out] response Response to the HTTP request.
1863  */
1864 static void ast_ari_channels_play_cb(
1865         struct ast_tcptls_session_instance *ser,
1866         struct ast_variable *get_params, struct ast_variable *path_vars,
1867         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
1868 {
1869         struct ast_ari_channels_play_args args = {};
1870         struct ast_variable *i;
1871 #if defined(AST_DEVMODE)
1872         int is_valid;
1873         int code;
1874 #endif /* AST_DEVMODE */
1875
1876         for (i = get_params; i; i = i->next) {
1877                 if (strcmp(i->name, "media") == 0) {
1878                         /* Parse comma separated list */
1879                         char *vals[MAX_VALS];
1880                         size_t j;
1881
1882                         args.media_parse = ast_strdup(i->value);
1883                         if (!args.media_parse) {
1884                                 ast_ari_response_alloc_failed(response);
1885                                 goto fin;
1886                         }
1887
1888                         if (strlen(args.media_parse) == 0) {
1889                                 /* ast_app_separate_args can't handle "" */
1890                                 args.media_count = 1;
1891                                 vals[0] = args.media_parse;
1892                         } else {
1893                                 args.media_count = ast_app_separate_args(
1894                                         args.media_parse, ',', vals,
1895                                         ARRAY_LEN(vals));
1896                         }
1897
1898                         if (args.media_count == 0) {
1899                                 ast_ari_response_alloc_failed(response);
1900                                 goto fin;
1901                         }
1902
1903                         if (args.media_count >= MAX_VALS) {
1904                                 ast_ari_response_error(response, 400,
1905                                         "Bad Request",
1906                                         "Too many values for media");
1907                                 goto fin;
1908                         }
1909
1910                         args.media = ast_malloc(sizeof(*args.media) * args.media_count);
1911                         if (!args.media) {
1912                                 ast_ari_response_alloc_failed(response);
1913                                 goto fin;
1914                         }
1915
1916                         for (j = 0; j < args.media_count; ++j) {
1917                                 args.media[j] = (vals[j]);
1918                         }
1919                 } else
1920                 if (strcmp(i->name, "lang") == 0) {
1921                         args.lang = (i->value);
1922                 } else
1923                 if (strcmp(i->name, "offsetms") == 0) {
1924                         args.offsetms = atoi(i->value);
1925                 } else
1926                 if (strcmp(i->name, "skipms") == 0) {
1927                         args.skipms = atoi(i->value);
1928                 } else
1929                 if (strcmp(i->name, "playbackId") == 0) {
1930                         args.playback_id = (i->value);
1931                 } else
1932                 {}
1933         }
1934         for (i = path_vars; i; i = i->next) {
1935                 if (strcmp(i->name, "channelId") == 0) {
1936                         args.channel_id = (i->value);
1937                 } else
1938                 {}
1939         }
1940         if (ast_ari_channels_play_parse_body(body, &args)) {
1941                 ast_ari_response_alloc_failed(response);
1942                 goto fin;
1943         }
1944         ast_ari_channels_play(headers, &args, response);
1945 #if defined(AST_DEVMODE)
1946         code = response->response_code;
1947
1948         switch (code) {
1949         case 0: /* Implementation is still a stub, or the code wasn't set */
1950                 is_valid = response->message == NULL;
1951                 break;
1952         case 500: /* Internal Server Error */
1953         case 501: /* Not Implemented */
1954         case 404: /* Channel not found */
1955         case 409: /* Channel not in a Stasis application */
1956         case 412: /* Channel in invalid state */
1957                 is_valid = 1;
1958                 break;
1959         default:
1960                 if (200 <= code && code <= 299) {
1961                         is_valid = ast_ari_validate_playback(
1962                                 response->message);
1963                 } else {
1964                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/play\n", code);
1965                         is_valid = 0;
1966                 }
1967         }
1968
1969         if (!is_valid) {
1970                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/play\n");
1971                 ast_ari_response_error(response, 500,
1972                         "Internal Server Error", "Response validation failed");
1973         }
1974 #endif /* AST_DEVMODE */
1975
1976 fin: __attribute__((unused))
1977         ast_free(args.media_parse);
1978         ast_free(args.media);
1979         return;
1980 }
1981 int ast_ari_channels_play_with_id_parse_body(
1982         struct ast_json *body,
1983         struct ast_ari_channels_play_with_id_args *args)
1984 {
1985         struct ast_json *field;
1986         /* Parse query parameters out of it */
1987         field = ast_json_object_get(body, "media");
1988         if (field) {
1989                 /* If they were silly enough to both pass in a query param and a
1990                  * JSON body, free up the query value.
1991                  */
1992                 ast_free(args->media);
1993                 if (ast_json_typeof(field) == AST_JSON_ARRAY) {
1994                         /* Multiple param passed as array */
1995                         size_t i;
1996                         args->media_count = ast_json_array_size(field);
1997                         args->media = ast_malloc(sizeof(*args->media) * args->media_count);
1998
1999                         if (!args->media) {
2000                                 return -1;
2001                         }
2002
2003                         for (i = 0; i < args->media_count; ++i) {
2004                                 args->media[i] = ast_json_string_get(ast_json_array_get(field, i));
2005                         }
2006                 } else {
2007                         /* Multiple param passed as single value */
2008                         args->media_count = 1;
2009                         args->media = ast_malloc(sizeof(*args->media) * args->media_count);
2010                         if (!args->media) {
2011                                 return -1;
2012                         }
2013                         args->media[0] = ast_json_string_get(field);
2014                 }
2015         }
2016         field = ast_json_object_get(body, "lang");
2017         if (field) {
2018                 args->lang = ast_json_string_get(field);
2019         }
2020         field = ast_json_object_get(body, "offsetms");
2021         if (field) {
2022                 args->offsetms = ast_json_integer_get(field);
2023         }
2024         field = ast_json_object_get(body, "skipms");
2025         if (field) {
2026                 args->skipms = ast_json_integer_get(field);
2027         }
2028         return 0;
2029 }
2030
2031 /*!
2032  * \brief Parameter parsing callback for /channels/{channelId}/play/{playbackId}.
2033  * \param get_params GET parameters in the HTTP request.
2034  * \param path_vars Path variables extracted from the request.
2035  * \param headers HTTP headers.
2036  * \param[out] response Response to the HTTP request.
2037  */
2038 static void ast_ari_channels_play_with_id_cb(
2039         struct ast_tcptls_session_instance *ser,
2040         struct ast_variable *get_params, struct ast_variable *path_vars,
2041         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
2042 {
2043         struct ast_ari_channels_play_with_id_args args = {};
2044         struct ast_variable *i;
2045 #if defined(AST_DEVMODE)
2046         int is_valid;
2047         int code;
2048 #endif /* AST_DEVMODE */
2049
2050         for (i = get_params; i; i = i->next) {
2051                 if (strcmp(i->name, "media") == 0) {
2052                         /* Parse comma separated list */
2053                         char *vals[MAX_VALS];
2054                         size_t j;
2055
2056                         args.media_parse = ast_strdup(i->value);
2057                         if (!args.media_parse) {
2058                                 ast_ari_response_alloc_failed(response);
2059                                 goto fin;
2060                         }
2061
2062                         if (strlen(args.media_parse) == 0) {
2063                                 /* ast_app_separate_args can't handle "" */
2064                                 args.media_count = 1;
2065                                 vals[0] = args.media_parse;
2066                         } else {
2067                                 args.media_count = ast_app_separate_args(
2068                                         args.media_parse, ',', vals,
2069                                         ARRAY_LEN(vals));
2070                         }
2071
2072                         if (args.media_count == 0) {
2073                                 ast_ari_response_alloc_failed(response);
2074                                 goto fin;
2075                         }
2076
2077                         if (args.media_count >= MAX_VALS) {
2078                                 ast_ari_response_error(response, 400,
2079                                         "Bad Request",
2080                                         "Too many values for media");
2081                                 goto fin;
2082                         }
2083
2084                         args.media = ast_malloc(sizeof(*args.media) * args.media_count);
2085                         if (!args.media) {
2086                                 ast_ari_response_alloc_failed(response);
2087                                 goto fin;
2088                         }
2089
2090                         for (j = 0; j < args.media_count; ++j) {
2091                                 args.media[j] = (vals[j]);
2092                         }
2093                 } else
2094                 if (strcmp(i->name, "lang") == 0) {
2095                         args.lang = (i->value);
2096                 } else
2097                 if (strcmp(i->name, "offsetms") == 0) {
2098                         args.offsetms = atoi(i->value);
2099                 } else
2100                 if (strcmp(i->name, "skipms") == 0) {
2101                         args.skipms = atoi(i->value);
2102                 } else
2103                 {}
2104         }
2105         for (i = path_vars; i; i = i->next) {
2106                 if (strcmp(i->name, "channelId") == 0) {
2107                         args.channel_id = (i->value);
2108                 } else
2109                 if (strcmp(i->name, "playbackId") == 0) {
2110                         args.playback_id = (i->value);
2111                 } else
2112                 {}
2113         }
2114         if (ast_ari_channels_play_with_id_parse_body(body, &args)) {
2115                 ast_ari_response_alloc_failed(response);
2116                 goto fin;
2117         }
2118         ast_ari_channels_play_with_id(headers, &args, response);
2119 #if defined(AST_DEVMODE)
2120         code = response->response_code;
2121
2122         switch (code) {
2123         case 0: /* Implementation is still a stub, or the code wasn't set */
2124                 is_valid = response->message == NULL;
2125                 break;
2126         case 500: /* Internal Server Error */
2127         case 501: /* Not Implemented */
2128         case 404: /* Channel not found */
2129         case 409: /* Channel not in a Stasis application */
2130         case 412: /* Channel in invalid state */
2131                 is_valid = 1;
2132                 break;
2133         default:
2134                 if (200 <= code && code <= 299) {
2135                         is_valid = ast_ari_validate_playback(
2136                                 response->message);
2137                 } else {
2138                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/play/{playbackId}\n", code);
2139                         is_valid = 0;
2140                 }
2141         }
2142
2143         if (!is_valid) {
2144                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/play/{playbackId}\n");
2145                 ast_ari_response_error(response, 500,
2146                         "Internal Server Error", "Response validation failed");
2147         }
2148 #endif /* AST_DEVMODE */
2149
2150 fin: __attribute__((unused))
2151         ast_free(args.media_parse);
2152         ast_free(args.media);
2153         return;
2154 }
2155 int ast_ari_channels_record_parse_body(
2156         struct ast_json *body,
2157         struct ast_ari_channels_record_args *args)
2158 {
2159         struct ast_json *field;
2160         /* Parse query parameters out of it */
2161         field = ast_json_object_get(body, "name");
2162         if (field) {
2163                 args->name = ast_json_string_get(field);
2164         }
2165         field = ast_json_object_get(body, "format");
2166         if (field) {
2167                 args->format = ast_json_string_get(field);
2168         }
2169         field = ast_json_object_get(body, "maxDurationSeconds");
2170         if (field) {
2171                 args->max_duration_seconds = ast_json_integer_get(field);
2172         }
2173         field = ast_json_object_get(body, "maxSilenceSeconds");
2174         if (field) {
2175                 args->max_silence_seconds = ast_json_integer_get(field);
2176         }
2177         field = ast_json_object_get(body, "ifExists");
2178         if (field) {
2179                 args->if_exists = ast_json_string_get(field);
2180         }
2181         field = ast_json_object_get(body, "beep");
2182         if (field) {
2183                 args->beep = ast_json_is_true(field);
2184         }
2185         field = ast_json_object_get(body, "terminateOn");
2186         if (field) {
2187                 args->terminate_on = ast_json_string_get(field);
2188         }
2189         return 0;
2190 }
2191
2192 /*!
2193  * \brief Parameter parsing callback for /channels/{channelId}/record.
2194  * \param get_params GET parameters in the HTTP request.
2195  * \param path_vars Path variables extracted from the request.
2196  * \param headers HTTP headers.
2197  * \param[out] response Response to the HTTP request.
2198  */
2199 static void ast_ari_channels_record_cb(
2200         struct ast_tcptls_session_instance *ser,
2201         struct ast_variable *get_params, struct ast_variable *path_vars,
2202         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
2203 {
2204         struct ast_ari_channels_record_args args = {};
2205         struct ast_variable *i;
2206 #if defined(AST_DEVMODE)
2207         int is_valid;
2208         int code;
2209 #endif /* AST_DEVMODE */
2210
2211         for (i = get_params; i; i = i->next) {
2212                 if (strcmp(i->name, "name") == 0) {
2213                         args.name = (i->value);
2214                 } else
2215                 if (strcmp(i->name, "format") == 0) {
2216                         args.format = (i->value);
2217                 } else
2218                 if (strcmp(i->name, "maxDurationSeconds") == 0) {
2219                         args.max_duration_seconds = atoi(i->value);
2220                 } else
2221                 if (strcmp(i->name, "maxSilenceSeconds") == 0) {
2222                         args.max_silence_seconds = atoi(i->value);
2223                 } else
2224                 if (strcmp(i->name, "ifExists") == 0) {
2225                         args.if_exists = (i->value);
2226                 } else
2227                 if (strcmp(i->name, "beep") == 0) {
2228                         args.beep = ast_true(i->value);
2229                 } else
2230                 if (strcmp(i->name, "terminateOn") == 0) {
2231                         args.terminate_on = (i->value);
2232                 } else
2233                 {}
2234         }
2235         for (i = path_vars; i; i = i->next) {
2236                 if (strcmp(i->name, "channelId") == 0) {
2237                         args.channel_id = (i->value);
2238                 } else
2239                 {}
2240         }
2241         if (ast_ari_channels_record_parse_body(body, &args)) {
2242                 ast_ari_response_alloc_failed(response);
2243                 goto fin;
2244         }
2245         ast_ari_channels_record(headers, &args, response);
2246 #if defined(AST_DEVMODE)
2247         code = response->response_code;
2248
2249         switch (code) {
2250         case 0: /* Implementation is still a stub, or the code wasn't set */
2251                 is_valid = response->message == NULL;
2252                 break;
2253         case 500: /* Internal Server Error */
2254         case 501: /* Not Implemented */
2255         case 400: /* Invalid parameters */
2256         case 404: /* Channel not found */
2257         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 */
2258         case 422: /* The format specified is unknown on this system */
2259                 is_valid = 1;
2260                 break;
2261         default:
2262                 if (200 <= code && code <= 299) {
2263                         is_valid = ast_ari_validate_live_recording(
2264                                 response->message);
2265                 } else {
2266                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/record\n", code);
2267                         is_valid = 0;
2268                 }
2269         }
2270
2271         if (!is_valid) {
2272                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/record\n");
2273                 ast_ari_response_error(response, 500,
2274                         "Internal Server Error", "Response validation failed");
2275         }
2276 #endif /* AST_DEVMODE */
2277
2278 fin: __attribute__((unused))
2279         return;
2280 }
2281 int ast_ari_channels_get_channel_var_parse_body(
2282         struct ast_json *body,
2283         struct ast_ari_channels_get_channel_var_args *args)
2284 {
2285         struct ast_json *field;
2286         /* Parse query parameters out of it */
2287         field = ast_json_object_get(body, "variable");
2288         if (field) {
2289                 args->variable = ast_json_string_get(field);
2290         }
2291         return 0;
2292 }
2293
2294 /*!
2295  * \brief Parameter parsing callback for /channels/{channelId}/variable.
2296  * \param get_params GET parameters in the HTTP request.
2297  * \param path_vars Path variables extracted from the request.
2298  * \param headers HTTP headers.
2299  * \param[out] response Response to the HTTP request.
2300  */
2301 static void ast_ari_channels_get_channel_var_cb(
2302         struct ast_tcptls_session_instance *ser,
2303         struct ast_variable *get_params, struct ast_variable *path_vars,
2304         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
2305 {
2306         struct ast_ari_channels_get_channel_var_args args = {};
2307         struct ast_variable *i;
2308 #if defined(AST_DEVMODE)
2309         int is_valid;
2310         int code;
2311 #endif /* AST_DEVMODE */
2312
2313         for (i = get_params; i; i = i->next) {
2314                 if (strcmp(i->name, "variable") == 0) {
2315                         args.variable = (i->value);
2316                 } else
2317                 {}
2318         }
2319         for (i = path_vars; i; i = i->next) {
2320                 if (strcmp(i->name, "channelId") == 0) {
2321                         args.channel_id = (i->value);
2322                 } else
2323                 {}
2324         }
2325         if (ast_ari_channels_get_channel_var_parse_body(body, &args)) {
2326                 ast_ari_response_alloc_failed(response);
2327                 goto fin;
2328         }
2329         ast_ari_channels_get_channel_var(headers, &args, response);
2330 #if defined(AST_DEVMODE)
2331         code = response->response_code;
2332
2333         switch (code) {
2334         case 0: /* Implementation is still a stub, or the code wasn't set */
2335                 is_valid = response->message == NULL;
2336                 break;
2337         case 500: /* Internal Server Error */
2338         case 501: /* Not Implemented */
2339         case 400: /* Missing variable parameter. */
2340         case 404: /* Channel or variable not found */
2341         case 409: /* Channel not in a Stasis application */
2342                 is_valid = 1;
2343                 break;
2344         default:
2345                 if (200 <= code && code <= 299) {
2346                         is_valid = ast_ari_validate_variable(
2347                                 response->message);
2348                 } else {
2349                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/variable\n", code);
2350                         is_valid = 0;
2351                 }
2352         }
2353
2354         if (!is_valid) {
2355                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/variable\n");
2356                 ast_ari_response_error(response, 500,
2357                         "Internal Server Error", "Response validation failed");
2358         }
2359 #endif /* AST_DEVMODE */
2360
2361 fin: __attribute__((unused))
2362         return;
2363 }
2364 int ast_ari_channels_set_channel_var_parse_body(
2365         struct ast_json *body,
2366         struct ast_ari_channels_set_channel_var_args *args)
2367 {
2368         struct ast_json *field;
2369         /* Parse query parameters out of it */
2370         field = ast_json_object_get(body, "variable");
2371         if (field) {
2372                 args->variable = ast_json_string_get(field);
2373         }
2374         field = ast_json_object_get(body, "value");
2375         if (field) {
2376                 args->value = ast_json_string_get(field);
2377         }
2378         return 0;
2379 }
2380
2381 /*!
2382  * \brief Parameter parsing callback for /channels/{channelId}/variable.
2383  * \param get_params GET parameters in the HTTP request.
2384  * \param path_vars Path variables extracted from the request.
2385  * \param headers HTTP headers.
2386  * \param[out] response Response to the HTTP request.
2387  */
2388 static void ast_ari_channels_set_channel_var_cb(
2389         struct ast_tcptls_session_instance *ser,
2390         struct ast_variable *get_params, struct ast_variable *path_vars,
2391         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
2392 {
2393         struct ast_ari_channels_set_channel_var_args args = {};
2394         struct ast_variable *i;
2395 #if defined(AST_DEVMODE)
2396         int is_valid;
2397         int code;
2398 #endif /* AST_DEVMODE */
2399
2400         for (i = get_params; i; i = i->next) {
2401                 if (strcmp(i->name, "variable") == 0) {
2402                         args.variable = (i->value);
2403                 } else
2404                 if (strcmp(i->name, "value") == 0) {
2405                         args.value = (i->value);
2406                 } else
2407                 {}
2408         }
2409         for (i = path_vars; i; i = i->next) {
2410                 if (strcmp(i->name, "channelId") == 0) {
2411                         args.channel_id = (i->value);
2412                 } else
2413                 {}
2414         }
2415         if (ast_ari_channels_set_channel_var_parse_body(body, &args)) {
2416                 ast_ari_response_alloc_failed(response);
2417                 goto fin;
2418         }
2419         ast_ari_channels_set_channel_var(headers, &args, response);
2420 #if defined(AST_DEVMODE)
2421         code = response->response_code;
2422
2423         switch (code) {
2424         case 0: /* Implementation is still a stub, or the code wasn't set */
2425                 is_valid = response->message == NULL;
2426                 break;
2427         case 500: /* Internal Server Error */
2428         case 501: /* Not Implemented */
2429         case 400: /* Missing variable parameter. */
2430         case 404: /* Channel not found */
2431         case 409: /* Channel not in a Stasis application */
2432                 is_valid = 1;
2433                 break;
2434         default:
2435                 if (200 <= code && code <= 299) {
2436                         is_valid = ast_ari_validate_void(
2437                                 response->message);
2438                 } else {
2439                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/variable\n", code);
2440                         is_valid = 0;
2441                 }
2442         }
2443
2444         if (!is_valid) {
2445                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/variable\n");
2446                 ast_ari_response_error(response, 500,
2447                         "Internal Server Error", "Response validation failed");
2448         }
2449 #endif /* AST_DEVMODE */
2450
2451 fin: __attribute__((unused))
2452         return;
2453 }
2454 int ast_ari_channels_snoop_channel_parse_body(
2455         struct ast_json *body,
2456         struct ast_ari_channels_snoop_channel_args *args)
2457 {
2458         struct ast_json *field;
2459         /* Parse query parameters out of it */
2460         field = ast_json_object_get(body, "spy");
2461         if (field) {
2462                 args->spy = ast_json_string_get(field);
2463         }
2464         field = ast_json_object_get(body, "whisper");
2465         if (field) {
2466                 args->whisper = ast_json_string_get(field);
2467         }
2468         field = ast_json_object_get(body, "app");
2469         if (field) {
2470                 args->app = ast_json_string_get(field);
2471         }
2472         field = ast_json_object_get(body, "appArgs");
2473         if (field) {
2474                 args->app_args = ast_json_string_get(field);
2475         }
2476         field = ast_json_object_get(body, "snoopId");
2477         if (field) {
2478                 args->snoop_id = ast_json_string_get(field);
2479         }
2480         return 0;
2481 }
2482
2483 /*!
2484  * \brief Parameter parsing callback for /channels/{channelId}/snoop.
2485  * \param get_params GET parameters in the HTTP request.
2486  * \param path_vars Path variables extracted from the request.
2487  * \param headers HTTP headers.
2488  * \param[out] response Response to the HTTP request.
2489  */
2490 static void ast_ari_channels_snoop_channel_cb(
2491         struct ast_tcptls_session_instance *ser,
2492         struct ast_variable *get_params, struct ast_variable *path_vars,
2493         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
2494 {
2495         struct ast_ari_channels_snoop_channel_args args = {};
2496         struct ast_variable *i;
2497 #if defined(AST_DEVMODE)
2498         int is_valid;
2499         int code;
2500 #endif /* AST_DEVMODE */
2501
2502         for (i = get_params; i; i = i->next) {
2503                 if (strcmp(i->name, "spy") == 0) {
2504                         args.spy = (i->value);
2505                 } else
2506                 if (strcmp(i->name, "whisper") == 0) {
2507                         args.whisper = (i->value);
2508                 } else
2509                 if (strcmp(i->name, "app") == 0) {
2510                         args.app = (i->value);
2511                 } else
2512                 if (strcmp(i->name, "appArgs") == 0) {
2513                         args.app_args = (i->value);
2514                 } else
2515                 if (strcmp(i->name, "snoopId") == 0) {
2516                         args.snoop_id = (i->value);
2517                 } else
2518                 {}
2519         }
2520         for (i = path_vars; i; i = i->next) {
2521                 if (strcmp(i->name, "channelId") == 0) {
2522                         args.channel_id = (i->value);
2523                 } else
2524                 {}
2525         }
2526         if (ast_ari_channels_snoop_channel_parse_body(body, &args)) {
2527                 ast_ari_response_alloc_failed(response);
2528                 goto fin;
2529         }
2530         ast_ari_channels_snoop_channel(headers, &args, response);
2531 #if defined(AST_DEVMODE)
2532         code = response->response_code;
2533
2534         switch (code) {
2535         case 0: /* Implementation is still a stub, or the code wasn't set */
2536                 is_valid = response->message == NULL;
2537                 break;
2538         case 500: /* Internal Server Error */
2539         case 501: /* Not Implemented */
2540         case 400: /* Invalid parameters */
2541         case 404: /* Channel not found */
2542                 is_valid = 1;
2543                 break;
2544         default:
2545                 if (200 <= code && code <= 299) {
2546                         is_valid = ast_ari_validate_channel(
2547                                 response->message);
2548                 } else {
2549                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/snoop\n", code);
2550                         is_valid = 0;
2551                 }
2552         }
2553
2554         if (!is_valid) {
2555                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/snoop\n");
2556                 ast_ari_response_error(response, 500,
2557                         "Internal Server Error", "Response validation failed");
2558         }
2559 #endif /* AST_DEVMODE */
2560
2561 fin: __attribute__((unused))
2562         return;
2563 }
2564 int ast_ari_channels_snoop_channel_with_id_parse_body(
2565         struct ast_json *body,
2566         struct ast_ari_channels_snoop_channel_with_id_args *args)
2567 {
2568         struct ast_json *field;
2569         /* Parse query parameters out of it */
2570         field = ast_json_object_get(body, "spy");
2571         if (field) {
2572                 args->spy = ast_json_string_get(field);
2573         }
2574         field = ast_json_object_get(body, "whisper");
2575         if (field) {
2576                 args->whisper = ast_json_string_get(field);
2577         }
2578         field = ast_json_object_get(body, "app");
2579         if (field) {
2580                 args->app = ast_json_string_get(field);
2581         }
2582         field = ast_json_object_get(body, "appArgs");
2583         if (field) {
2584                 args->app_args = ast_json_string_get(field);
2585         }
2586         return 0;
2587 }
2588
2589 /*!
2590  * \brief Parameter parsing callback for /channels/{channelId}/snoop/{snoopId}.
2591  * \param get_params GET parameters in the HTTP request.
2592  * \param path_vars Path variables extracted from the request.
2593  * \param headers HTTP headers.
2594  * \param[out] response Response to the HTTP request.
2595  */
2596 static void ast_ari_channels_snoop_channel_with_id_cb(
2597         struct ast_tcptls_session_instance *ser,
2598         struct ast_variable *get_params, struct ast_variable *path_vars,
2599         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
2600 {
2601         struct ast_ari_channels_snoop_channel_with_id_args args = {};
2602         struct ast_variable *i;
2603 #if defined(AST_DEVMODE)
2604         int is_valid;
2605         int code;
2606 #endif /* AST_DEVMODE */
2607
2608         for (i = get_params; i; i = i->next) {
2609                 if (strcmp(i->name, "spy") == 0) {
2610                         args.spy = (i->value);
2611                 } else
2612                 if (strcmp(i->name, "whisper") == 0) {
2613                         args.whisper = (i->value);
2614                 } else
2615                 if (strcmp(i->name, "app") == 0) {
2616                         args.app = (i->value);
2617                 } else
2618                 if (strcmp(i->name, "appArgs") == 0) {
2619                         args.app_args = (i->value);
2620                 } else
2621                 {}
2622         }
2623         for (i = path_vars; i; i = i->next) {
2624                 if (strcmp(i->name, "channelId") == 0) {
2625                         args.channel_id = (i->value);
2626                 } else
2627                 if (strcmp(i->name, "snoopId") == 0) {
2628                         args.snoop_id = (i->value);
2629                 } else
2630                 {}
2631         }
2632         if (ast_ari_channels_snoop_channel_with_id_parse_body(body, &args)) {
2633                 ast_ari_response_alloc_failed(response);
2634                 goto fin;
2635         }
2636         ast_ari_channels_snoop_channel_with_id(headers, &args, response);
2637 #if defined(AST_DEVMODE)
2638         code = response->response_code;
2639
2640         switch (code) {
2641         case 0: /* Implementation is still a stub, or the code wasn't set */
2642                 is_valid = response->message == NULL;
2643                 break;
2644         case 500: /* Internal Server Error */
2645         case 501: /* Not Implemented */
2646         case 400: /* Invalid parameters */
2647         case 404: /* Channel not found */
2648                 is_valid = 1;
2649                 break;
2650         default:
2651                 if (200 <= code && code <= 299) {
2652                         is_valid = ast_ari_validate_channel(
2653                                 response->message);
2654                 } else {
2655                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/snoop/{snoopId}\n", code);
2656                         is_valid = 0;
2657                 }
2658         }
2659
2660         if (!is_valid) {
2661                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/snoop/{snoopId}\n");
2662                 ast_ari_response_error(response, 500,
2663                         "Internal Server Error", "Response validation failed");
2664         }
2665 #endif /* AST_DEVMODE */
2666
2667 fin: __attribute__((unused))
2668         return;
2669 }
2670 int ast_ari_channels_dial_parse_body(
2671         struct ast_json *body,
2672         struct ast_ari_channels_dial_args *args)
2673 {
2674         struct ast_json *field;
2675         /* Parse query parameters out of it */
2676         field = ast_json_object_get(body, "caller");
2677         if (field) {
2678                 args->caller = ast_json_string_get(field);
2679         }
2680         field = ast_json_object_get(body, "timeout");
2681         if (field) {
2682                 args->timeout = ast_json_integer_get(field);
2683         }
2684         return 0;
2685 }
2686
2687 /*!
2688  * \brief Parameter parsing callback for /channels/{channelId}/dial.
2689  * \param get_params GET parameters in the HTTP request.
2690  * \param path_vars Path variables extracted from the request.
2691  * \param headers HTTP headers.
2692  * \param[out] response Response to the HTTP request.
2693  */
2694 static void ast_ari_channels_dial_cb(
2695         struct ast_tcptls_session_instance *ser,
2696         struct ast_variable *get_params, struct ast_variable *path_vars,
2697         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
2698 {
2699         struct ast_ari_channels_dial_args args = {};
2700         struct ast_variable *i;
2701 #if defined(AST_DEVMODE)
2702         int is_valid;
2703         int code;
2704 #endif /* AST_DEVMODE */
2705
2706         for (i = get_params; i; i = i->next) {
2707                 if (strcmp(i->name, "caller") == 0) {
2708                         args.caller = (i->value);
2709                 } else
2710                 if (strcmp(i->name, "timeout") == 0) {
2711                         args.timeout = atoi(i->value);
2712                 } else
2713                 {}
2714         }
2715         for (i = path_vars; i; i = i->next) {
2716                 if (strcmp(i->name, "channelId") == 0) {
2717                         args.channel_id = (i->value);
2718                 } else
2719                 {}
2720         }
2721         if (ast_ari_channels_dial_parse_body(body, &args)) {
2722                 ast_ari_response_alloc_failed(response);
2723                 goto fin;
2724         }
2725         ast_ari_channels_dial(headers, &args, response);
2726 #if defined(AST_DEVMODE)
2727         code = response->response_code;
2728
2729         switch (code) {
2730         case 0: /* Implementation is still a stub, or the code wasn't set */
2731                 is_valid = response->message == NULL;
2732                 break;
2733         case 500: /* Internal Server Error */
2734         case 501: /* Not Implemented */
2735         case 404: /* Channel cannot be found. */
2736         case 409: /* Channel cannot be dialed. */
2737                 is_valid = 1;
2738                 break;
2739         default:
2740                 if (200 <= code && code <= 299) {
2741                         is_valid = ast_ari_validate_void(
2742                                 response->message);
2743                 } else {
2744                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/dial\n", code);
2745                         is_valid = 0;
2746                 }
2747         }
2748
2749         if (!is_valid) {
2750                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/dial\n");
2751                 ast_ari_response_error(response, 500,
2752                         "Internal Server Error", "Response validation failed");
2753         }
2754 #endif /* AST_DEVMODE */
2755
2756 fin: __attribute__((unused))
2757         return;
2758 }
2759 /*!
2760  * \brief Parameter parsing callback for /channels/{channelId}/rtp_statistics.
2761  * \param get_params GET parameters in the HTTP request.
2762  * \param path_vars Path variables extracted from the request.
2763  * \param headers HTTP headers.
2764  * \param[out] response Response to the HTTP request.
2765  */
2766 static void ast_ari_channels_rtpstatistics_cb(
2767         struct ast_tcptls_session_instance *ser,
2768         struct ast_variable *get_params, struct ast_variable *path_vars,
2769         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
2770 {
2771         struct ast_ari_channels_rtpstatistics_args args = {};
2772         struct ast_variable *i;
2773 #if defined(AST_DEVMODE)
2774         int is_valid;
2775         int code;
2776 #endif /* AST_DEVMODE */
2777
2778         for (i = path_vars; i; i = i->next) {
2779                 if (strcmp(i->name, "channelId") == 0) {
2780                         args.channel_id = (i->value);
2781                 } else
2782                 {}
2783         }
2784         ast_ari_channels_rtpstatistics(headers, &args, response);
2785 #if defined(AST_DEVMODE)
2786         code = response->response_code;
2787
2788         switch (code) {
2789         case 0: /* Implementation is still a stub, or the code wasn't set */
2790                 is_valid = response->message == NULL;
2791                 break;
2792         case 500: /* Internal Server Error */
2793         case 501: /* Not Implemented */
2794         case 404: /* Channel cannot be found. */
2795                 is_valid = 1;
2796                 break;
2797         default:
2798                 if (200 <= code && code <= 299) {
2799                         is_valid = ast_ari_validate_rtpstat(
2800                                 response->message);
2801                 } else {
2802                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/rtp_statistics\n", code);
2803                         is_valid = 0;
2804                 }
2805         }
2806
2807         if (!is_valid) {
2808                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/rtp_statistics\n");
2809                 ast_ari_response_error(response, 500,
2810                         "Internal Server Error", "Response validation failed");
2811         }
2812 #endif /* AST_DEVMODE */
2813
2814 fin: __attribute__((unused))
2815         return;
2816 }
2817 int ast_ari_channels_external_media_parse_body(
2818         struct ast_json *body,
2819         struct ast_ari_channels_external_media_args *args)
2820 {
2821         struct ast_json *field;
2822         /* Parse query parameters out of it */
2823         field = ast_json_object_get(body, "channelId");
2824         if (field) {
2825                 args->channel_id = ast_json_string_get(field);
2826         }
2827         field = ast_json_object_get(body, "app");
2828         if (field) {
2829                 args->app = ast_json_string_get(field);
2830         }
2831         field = ast_json_object_get(body, "external_host");
2832         if (field) {
2833                 args->external_host = ast_json_string_get(field);
2834         }
2835         field = ast_json_object_get(body, "encapsulation");
2836         if (field) {
2837                 args->encapsulation = ast_json_string_get(field);
2838         }
2839         field = ast_json_object_get(body, "transport");
2840         if (field) {
2841                 args->transport = ast_json_string_get(field);
2842         }
2843         field = ast_json_object_get(body, "connection_type");
2844         if (field) {
2845                 args->connection_type = ast_json_string_get(field);
2846         }
2847         field = ast_json_object_get(body, "format");
2848         if (field) {
2849                 args->format = ast_json_string_get(field);
2850         }
2851         field = ast_json_object_get(body, "direction");
2852         if (field) {
2853                 args->direction = ast_json_string_get(field);
2854         }
2855         field = ast_json_object_get(body, "data");
2856         if (field) {
2857                 args->data = ast_json_string_get(field);
2858         }
2859         return 0;
2860 }
2861
2862 /*!
2863  * \brief Parameter parsing callback for /channels/externalMedia.
2864  * \param get_params GET parameters in the HTTP request.
2865  * \param path_vars Path variables extracted from the request.
2866  * \param headers HTTP headers.
2867  * \param[out] response Response to the HTTP request.
2868  */
2869 static void ast_ari_channels_external_media_cb(
2870         struct ast_tcptls_session_instance *ser,
2871         struct ast_variable *get_params, struct ast_variable *path_vars,
2872         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
2873 {
2874         struct ast_ari_channels_external_media_args args = {};
2875         struct ast_variable *i;
2876 #if defined(AST_DEVMODE)
2877         int is_valid;
2878         int code;
2879 #endif /* AST_DEVMODE */
2880
2881         for (i = get_params; i; i = i->next) {
2882                 if (strcmp(i->name, "channelId") == 0) {
2883                         args.channel_id = (i->value);
2884                 } else
2885                 if (strcmp(i->name, "app") == 0) {
2886                         args.app = (i->value);
2887                 } else
2888                 if (strcmp(i->name, "external_host") == 0) {
2889                         args.external_host = (i->value);
2890                 } else
2891                 if (strcmp(i->name, "encapsulation") == 0) {
2892                         args.encapsulation = (i->value);
2893                 } else
2894                 if (strcmp(i->name, "transport") == 0) {
2895                         args.transport = (i->value);
2896                 } else
2897                 if (strcmp(i->name, "connection_type") == 0) {
2898                         args.connection_type = (i->value);
2899                 } else
2900                 if (strcmp(i->name, "format") == 0) {
2901                         args.format = (i->value);
2902                 } else
2903                 if (strcmp(i->name, "direction") == 0) {
2904                         args.direction = (i->value);
2905                 } else
2906                 if (strcmp(i->name, "data") == 0) {
2907                         args.data = (i->value);
2908                 } else
2909                 {}
2910         }
2911         args.variables = body;
2912         ast_ari_channels_external_media(headers, &args, response);
2913 #if defined(AST_DEVMODE)
2914         code = response->response_code;
2915
2916         switch (code) {
2917         case 0: /* Implementation is still a stub, or the code wasn't set */
2918                 is_valid = response->message == NULL;
2919                 break;
2920         case 500: /* Internal Server Error */
2921         case 501: /* Not Implemented */
2922         case 400: /* Invalid parameters */
2923         case 409: /* Channel is not in a Stasis application; Channel is already bridged */
2924                 is_valid = 1;
2925                 break;
2926         default:
2927                 if (200 <= code && code <= 299) {
2928                         is_valid = ast_ari_validate_channel(
2929                                 response->message);
2930                 } else {
2931                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/externalMedia\n", code);
2932                         is_valid = 0;
2933                 }
2934         }
2935
2936         if (!is_valid) {
2937                 ast_log(LOG_ERROR, "Response validation failed for /channels/externalMedia\n");
2938                 ast_ari_response_error(response, 500,
2939                         "Internal Server Error", "Response validation failed");
2940         }
2941 #endif /* AST_DEVMODE */
2942
2943 fin: __attribute__((unused))
2944         return;
2945 }
2946
2947 /*! \brief REST handler for /api-docs/channels.json */
2948 static struct stasis_rest_handlers channels_create = {
2949         .path_segment = "create",
2950         .callbacks = {
2951                 [AST_HTTP_POST] = ast_ari_channels_create_cb,
2952         },
2953         .num_children = 0,
2954         .children = {  }
2955 };
2956 /*! \brief REST handler for /api-docs/channels.json */
2957 static struct stasis_rest_handlers channels_channelId_continue = {
2958         .path_segment = "continue",
2959         .callbacks = {
2960                 [AST_HTTP_POST] = ast_ari_channels_continue_in_dialplan_cb,
2961         },
2962         .num_children = 0,
2963         .children = {  }
2964 };
2965 /*! \brief REST handler for /api-docs/channels.json */
2966 static struct stasis_rest_handlers channels_channelId_move = {
2967         .path_segment = "move",
2968         .callbacks = {
2969                 [AST_HTTP_POST] = ast_ari_channels_move_cb,
2970         },
2971         .num_children = 0,
2972         .children = {  }
2973 };
2974 /*! \brief REST handler for /api-docs/channels.json */
2975 static struct stasis_rest_handlers channels_channelId_redirect = {
2976         .path_segment = "redirect",
2977         .callbacks = {
2978                 [AST_HTTP_POST] = ast_ari_channels_redirect_cb,
2979         },
2980         .num_children = 0,
2981         .children = {  }
2982 };
2983 /*! \brief REST handler for /api-docs/channels.json */
2984 static struct stasis_rest_handlers channels_channelId_answer = {
2985         .path_segment = "answer",
2986         .callbacks = {
2987                 [AST_HTTP_POST] = ast_ari_channels_answer_cb,
2988         },
2989         .num_children = 0,
2990         .children = {  }
2991 };
2992 /*! \brief REST handler for /api-docs/channels.json */
2993 static struct stasis_rest_handlers channels_channelId_ring = {
2994         .path_segment = "ring",
2995         .callbacks = {
2996                 [AST_HTTP_POST] = ast_ari_channels_ring_cb,
2997                 [AST_HTTP_DELETE] = ast_ari_channels_ring_stop_cb,
2998         },
2999         .num_children = 0,
3000         .children = {  }
3001 };
3002 /*! \brief REST handler for /api-docs/channels.json */
3003 static struct stasis_rest_handlers channels_channelId_dtmf = {
3004         .path_segment = "dtmf",
3005         .callbacks = {
3006                 [AST_HTTP_POST] = ast_ari_channels_send_dtmf_cb,
3007         },
3008         .num_children = 0,
3009         .children = {  }
3010 };
3011 /*! \brief REST handler for /api-docs/channels.json */
3012 static struct stasis_rest_handlers channels_channelId_mute = {
3013         .path_segment = "mute",
3014         .callbacks = {
3015                 [AST_HTTP_POST] = ast_ari_channels_mute_cb,
3016                 [AST_HTTP_DELETE] = ast_ari_channels_unmute_cb,
3017         },
3018         .num_children = 0,
3019         .children = {  }
3020 };
3021 /*! \brief REST handler for /api-docs/channels.json */
3022 static struct stasis_rest_handlers channels_channelId_hold = {
3023         .path_segment = "hold",
3024         .callbacks = {
3025                 [AST_HTTP_POST] = ast_ari_channels_hold_cb,
3026                 [AST_HTTP_DELETE] = ast_ari_channels_unhold_cb,
3027         },
3028         .num_children = 0,
3029         .children = {  }
3030 };
3031 /*! \brief REST handler for /api-docs/channels.json */
3032 static struct stasis_rest_handlers channels_channelId_moh = {
3033         .path_segment = "moh",
3034         .callbacks = {
3035                 [AST_HTTP_POST] = ast_ari_channels_start_moh_cb,
3036                 [AST_HTTP_DELETE] = ast_ari_channels_stop_moh_cb,
3037         },
3038         .num_children = 0,
3039         .children = {  }
3040 };
3041 /*! \brief REST handler for /api-docs/channels.json */
3042 static struct stasis_rest_handlers channels_channelId_silence = {
3043         .path_segment = "silence",
3044         .callbacks = {
3045                 [AST_HTTP_POST] = ast_ari_channels_start_silence_cb,
3046                 [AST_HTTP_DELETE] = ast_ari_channels_stop_silence_cb,
3047         },
3048         .num_children = 0,
3049         .children = {  }
3050 };
3051 /*! \brief REST handler for /api-docs/channels.json */
3052 static struct stasis_rest_handlers channels_channelId_play_playbackId = {
3053         .path_segment = "playbackId",
3054         .is_wildcard = 1,
3055         .callbacks = {
3056                 [AST_HTTP_POST] = ast_ari_channels_play_with_id_cb,
3057         },
3058         .num_children = 0,
3059         .children = {  }
3060 };
3061 /*! \brief REST handler for /api-docs/channels.json */
3062 static struct stasis_rest_handlers channels_channelId_play = {
3063         .path_segment = "play",
3064         .callbacks = {
3065                 [AST_HTTP_POST] = ast_ari_channels_play_cb,
3066         },
3067         .num_children = 1,
3068         .children = { &channels_channelId_play_playbackId, }
3069 };
3070 /*! \brief REST handler for /api-docs/channels.json */
3071 static struct stasis_rest_handlers channels_channelId_record = {
3072         .path_segment = "record",
3073         .callbacks = {
3074                 [AST_HTTP_POST] = ast_ari_channels_record_cb,
3075         },
3076         .num_children = 0,
3077         .children = {  }
3078 };
3079 /*! \brief REST handler for /api-docs/channels.json */
3080 static struct stasis_rest_handlers channels_channelId_variable = {
3081         .path_segment = "variable",
3082         .callbacks = {
3083                 [AST_HTTP_GET] = ast_ari_channels_get_channel_var_cb,
3084                 [AST_HTTP_POST] = ast_ari_channels_set_channel_var_cb,
3085         },
3086         .num_children = 0,
3087         .children = {  }
3088 };
3089 /*! \brief REST handler for /api-docs/channels.json */
3090 static struct stasis_rest_handlers channels_channelId_snoop_snoopId = {
3091         .path_segment = "snoopId",
3092         .is_wildcard = 1,
3093         .callbacks = {
3094                 [AST_HTTP_POST] = ast_ari_channels_snoop_channel_with_id_cb,
3095         },
3096         .num_children = 0,
3097         .children = {  }
3098 };
3099 /*! \brief REST handler for /api-docs/channels.json */
3100 static struct stasis_rest_handlers channels_channelId_snoop = {
3101         .path_segment = "snoop",
3102         .callbacks = {
3103                 [AST_HTTP_POST] = ast_ari_channels_snoop_channel_cb,
3104         },
3105         .num_children = 1,
3106         .children = { &channels_channelId_snoop_snoopId, }
3107 };
3108 /*! \brief REST handler for /api-docs/channels.json */
3109 static struct stasis_rest_handlers channels_channelId_dial = {
3110         .path_segment = "dial",
3111         .callbacks = {
3112                 [AST_HTTP_POST] = ast_ari_channels_dial_cb,
3113         },
3114         .num_children = 0,
3115         .children = {  }
3116 };
3117 /*! \brief REST handler for /api-docs/channels.json */
3118 static struct stasis_rest_handlers channels_channelId_rtp_statistics = {
3119         .path_segment = "rtp_statistics",
3120         .callbacks = {
3121                 [AST_HTTP_GET] = ast_ari_channels_rtpstatistics_cb,
3122         },
3123         .num_children = 0,
3124         .children = {  }
3125 };
3126 /*! \brief REST handler for /api-docs/channels.json */
3127 static struct stasis_rest_handlers channels_channelId = {
3128         .path_segment = "channelId",
3129         .is_wildcard = 1,
3130         .callbacks = {
3131                 [AST_HTTP_GET] = ast_ari_channels_get_cb,
3132                 [AST_HTTP_POST] = ast_ari_channels_originate_with_id_cb,
3133                 [AST_HTTP_DELETE] = ast_ari_channels_hangup_cb,
3134         },
3135         .num_children = 16,
3136         .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,&channels_channelId_rtp_statistics, }
3137 };
3138 /*! \brief REST handler for /api-docs/channels.json */
3139 static struct stasis_rest_handlers channels_externalMedia = {
3140         .path_segment = "externalMedia",
3141         .callbacks = {
3142                 [AST_HTTP_POST] = ast_ari_channels_external_media_cb,
3143         },
3144         .num_children = 0,
3145         .children = {  }
3146 };
3147 /*! \brief REST handler for /api-docs/channels.json */
3148 static struct stasis_rest_handlers channels = {
3149         .path_segment = "channels",
3150         .callbacks = {
3151                 [AST_HTTP_GET] = ast_ari_channels_list_cb,
3152                 [AST_HTTP_POST] = ast_ari_channels_originate_cb,
3153         },
3154         .num_children = 3,
3155         .children = { &channels_create,&channels_channelId,&channels_externalMedia, }
3156 };
3157
3158 static int unload_module(void)
3159 {
3160         ast_ari_remove_handler(&channels);
3161         return 0;
3162 }
3163
3164 static int load_module(void)
3165 {
3166         int res = 0;
3167
3168
3169         res |= ast_ari_add_handler(&channels);
3170         if (res) {
3171                 unload_module();
3172                 return AST_MODULE_LOAD_DECLINE;
3173         }
3174
3175         return AST_MODULE_LOAD_SUCCESS;
3176 }
3177
3178 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Channel resources",
3179         .support_level = AST_MODULE_SUPPORT_CORE,
3180         .load = load_module,
3181         .unload = unload_module,
3182         .requires = "res_ari,res_ari_model,res_stasis,res_stasis_answer,res_stasis_playback,res_stasis_recording,res_stasis_snoop",
3183 );