ari:Add application/json parameter 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_stasis</depend>
37         <support_level>core</support_level>
38  ***/
39
40 #include "asterisk.h"
41
42 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
43
44 #include "asterisk/app.h"
45 #include "asterisk/module.h"
46 #include "asterisk/stasis_app.h"
47 #include "ari/resource_channels.h"
48 #if defined(AST_DEVMODE)
49 #include "ari/ari_model_validators.h"
50 #endif
51
52 #define MAX_VALS 128
53
54 /*!
55  * \brief Parameter parsing callback for /channels.
56  * \param get_params GET parameters in the HTTP request.
57  * \param path_vars Path variables extracted from the request.
58  * \param headers HTTP headers.
59  * \param[out] response Response to the HTTP request.
60  */
61 static void ast_ari_channels_list_cb(
62         struct ast_tcptls_session_instance *ser,
63         struct ast_variable *get_params, struct ast_variable *path_vars,
64         struct ast_variable *headers, struct ast_ari_response *response)
65 {
66         struct ast_ari_channels_list_args args = {};
67         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
68 #if defined(AST_DEVMODE)
69         int is_valid;
70         int code;
71 #endif /* AST_DEVMODE */
72
73         ast_ari_channels_list(headers, &args, response);
74 #if defined(AST_DEVMODE)
75         code = response->response_code;
76
77         switch (code) {
78         case 0: /* Implementation is still a stub, or the code wasn't set */
79                 is_valid = response->message == NULL;
80                 break;
81         case 500: /* Internal Server Error */
82         case 501: /* Not Implemented */
83                 is_valid = 1;
84                 break;
85         default:
86                 if (200 <= code && code <= 299) {
87                         is_valid = ast_ari_validate_list(response->message,
88                                 ast_ari_validate_channel_fn());
89                 } else {
90                         ast_log(LOG_ERROR, "Invalid error response %d for /channels\n", code);
91                         is_valid = 0;
92                 }
93         }
94
95         if (!is_valid) {
96                 ast_log(LOG_ERROR, "Response validation failed for /channels\n");
97                 ast_ari_response_error(response, 500,
98                         "Internal Server Error", "Response validation failed");
99         }
100 #endif /* AST_DEVMODE */
101
102 fin: __attribute__((unused))
103         return;
104 }
105 /*!
106  * \brief Parameter parsing callback for /channels.
107  * \param get_params GET parameters in the HTTP request.
108  * \param path_vars Path variables extracted from the request.
109  * \param headers HTTP headers.
110  * \param[out] response Response to the HTTP request.
111  */
112 static void ast_ari_channels_originate_cb(
113         struct ast_tcptls_session_instance *ser,
114         struct ast_variable *get_params, struct ast_variable *path_vars,
115         struct ast_variable *headers, struct ast_ari_response *response)
116 {
117         struct ast_ari_channels_originate_args args = {};
118         struct ast_variable *i;
119         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
120         struct ast_json *field;
121 #if defined(AST_DEVMODE)
122         int is_valid;
123         int code;
124 #endif /* AST_DEVMODE */
125
126         for (i = get_params; i; i = i->next) {
127                 if (strcmp(i->name, "endpoint") == 0) {
128                         args.endpoint = (i->value);
129                 } else
130                 if (strcmp(i->name, "extension") == 0) {
131                         args.extension = (i->value);
132                 } else
133                 if (strcmp(i->name, "context") == 0) {
134                         args.context = (i->value);
135                 } else
136                 if (strcmp(i->name, "priority") == 0) {
137                         args.priority = atol(i->value);
138                 } else
139                 if (strcmp(i->name, "app") == 0) {
140                         args.app = (i->value);
141                 } else
142                 if (strcmp(i->name, "appArgs") == 0) {
143                         args.app_args = (i->value);
144                 } else
145                 if (strcmp(i->name, "callerId") == 0) {
146                         args.caller_id = (i->value);
147                 } else
148                 if (strcmp(i->name, "timeout") == 0) {
149                         args.timeout = atoi(i->value);
150                 } else
151                 {}
152         }
153         /* Look for a JSON request entity */
154         body = ast_http_get_json(ser, headers);
155         if (!body) {
156                 switch (errno) {
157                 case EFBIG:
158                         ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
159                         goto fin;
160                 case ENOMEM:
161                         ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
162                         goto fin;
163                 case EIO:
164                         ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
165                         goto fin;
166                 }
167         }
168         /* Parse query parameters out of it */
169         field = ast_json_object_get(body, "endpoint");
170         if (field) {
171                 args.endpoint = ast_json_string_get(field);
172         }
173         field = ast_json_object_get(body, "extension");
174         if (field) {
175                 args.extension = ast_json_string_get(field);
176         }
177         field = ast_json_object_get(body, "context");
178         if (field) {
179                 args.context = ast_json_string_get(field);
180         }
181         field = ast_json_object_get(body, "priority");
182         if (field) {
183                 args.priority = ast_json_integer_get(field);
184         }
185         field = ast_json_object_get(body, "app");
186         if (field) {
187                 args.app = ast_json_string_get(field);
188         }
189         field = ast_json_object_get(body, "appArgs");
190         if (field) {
191                 args.app_args = ast_json_string_get(field);
192         }
193         field = ast_json_object_get(body, "callerId");
194         if (field) {
195                 args.caller_id = ast_json_string_get(field);
196         }
197         field = ast_json_object_get(body, "timeout");
198         if (field) {
199                 args.timeout = ast_json_integer_get(field);
200         }
201         ast_ari_channels_originate(headers, &args, response);
202 #if defined(AST_DEVMODE)
203         code = response->response_code;
204
205         switch (code) {
206         case 0: /* Implementation is still a stub, or the code wasn't set */
207                 is_valid = response->message == NULL;
208                 break;
209         case 500: /* Internal Server Error */
210         case 501: /* Not Implemented */
211         case 400: /* Invalid parameters for originating a channel. */
212                 is_valid = 1;
213                 break;
214         default:
215                 if (200 <= code && code <= 299) {
216                         is_valid = ast_ari_validate_channel(
217                                 response->message);
218                 } else {
219                         ast_log(LOG_ERROR, "Invalid error response %d for /channels\n", code);
220                         is_valid = 0;
221                 }
222         }
223
224         if (!is_valid) {
225                 ast_log(LOG_ERROR, "Response validation failed for /channels\n");
226                 ast_ari_response_error(response, 500,
227                         "Internal Server Error", "Response validation failed");
228         }
229 #endif /* AST_DEVMODE */
230
231 fin: __attribute__((unused))
232         return;
233 }
234 /*!
235  * \brief Parameter parsing callback for /channels/{channelId}.
236  * \param get_params GET parameters in the HTTP request.
237  * \param path_vars Path variables extracted from the request.
238  * \param headers HTTP headers.
239  * \param[out] response Response to the HTTP request.
240  */
241 static void ast_ari_channels_get_cb(
242         struct ast_tcptls_session_instance *ser,
243         struct ast_variable *get_params, struct ast_variable *path_vars,
244         struct ast_variable *headers, struct ast_ari_response *response)
245 {
246         struct ast_ari_channels_get_args args = {};
247         struct ast_variable *i;
248         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
249 #if defined(AST_DEVMODE)
250         int is_valid;
251         int code;
252 #endif /* AST_DEVMODE */
253
254         for (i = path_vars; i; i = i->next) {
255                 if (strcmp(i->name, "channelId") == 0) {
256                         args.channel_id = (i->value);
257                 } else
258                 {}
259         }
260         ast_ari_channels_get(headers, &args, response);
261 #if defined(AST_DEVMODE)
262         code = response->response_code;
263
264         switch (code) {
265         case 0: /* Implementation is still a stub, or the code wasn't set */
266                 is_valid = response->message == NULL;
267                 break;
268         case 500: /* Internal Server Error */
269         case 501: /* Not Implemented */
270         case 404: /* Channel not found */
271                 is_valid = 1;
272                 break;
273         default:
274                 if (200 <= code && code <= 299) {
275                         is_valid = ast_ari_validate_channel(
276                                 response->message);
277                 } else {
278                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}\n", code);
279                         is_valid = 0;
280                 }
281         }
282
283         if (!is_valid) {
284                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}\n");
285                 ast_ari_response_error(response, 500,
286                         "Internal Server Error", "Response validation failed");
287         }
288 #endif /* AST_DEVMODE */
289
290 fin: __attribute__((unused))
291         return;
292 }
293 /*!
294  * \brief Parameter parsing callback for /channels/{channelId}.
295  * \param get_params GET parameters in the HTTP request.
296  * \param path_vars Path variables extracted from the request.
297  * \param headers HTTP headers.
298  * \param[out] response Response to the HTTP request.
299  */
300 static void ast_ari_channels_hangup_cb(
301         struct ast_tcptls_session_instance *ser,
302         struct ast_variable *get_params, struct ast_variable *path_vars,
303         struct ast_variable *headers, struct ast_ari_response *response)
304 {
305         struct ast_ari_channels_hangup_args args = {};
306         struct ast_variable *i;
307         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
308         struct ast_json *field;
309 #if defined(AST_DEVMODE)
310         int is_valid;
311         int code;
312 #endif /* AST_DEVMODE */
313
314         for (i = get_params; i; i = i->next) {
315                 if (strcmp(i->name, "reason") == 0) {
316                         args.reason = (i->value);
317                 } else
318                 {}
319         }
320         for (i = path_vars; i; i = i->next) {
321                 if (strcmp(i->name, "channelId") == 0) {
322                         args.channel_id = (i->value);
323                 } else
324                 {}
325         }
326         /* Look for a JSON request entity */
327         body = ast_http_get_json(ser, headers);
328         if (!body) {
329                 switch (errno) {
330                 case EFBIG:
331                         ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
332                         goto fin;
333                 case ENOMEM:
334                         ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
335                         goto fin;
336                 case EIO:
337                         ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
338                         goto fin;
339                 }
340         }
341         /* Parse query parameters out of it */
342         field = ast_json_object_get(body, "reason");
343         if (field) {
344                 args.reason = ast_json_string_get(field);
345         }
346         ast_ari_channels_hangup(headers, &args, response);
347 #if defined(AST_DEVMODE)
348         code = response->response_code;
349
350         switch (code) {
351         case 0: /* Implementation is still a stub, or the code wasn't set */
352                 is_valid = response->message == NULL;
353                 break;
354         case 500: /* Internal Server Error */
355         case 501: /* Not Implemented */
356         case 400: /* Invalid reason for hangup provided */
357         case 404: /* Channel not found */
358                 is_valid = 1;
359                 break;
360         default:
361                 if (200 <= code && code <= 299) {
362                         is_valid = ast_ari_validate_void(
363                                 response->message);
364                 } else {
365                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}\n", code);
366                         is_valid = 0;
367                 }
368         }
369
370         if (!is_valid) {
371                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}\n");
372                 ast_ari_response_error(response, 500,
373                         "Internal Server Error", "Response validation failed");
374         }
375 #endif /* AST_DEVMODE */
376
377 fin: __attribute__((unused))
378         return;
379 }
380 /*!
381  * \brief Parameter parsing callback for /channels/{channelId}/continue.
382  * \param get_params GET parameters in the HTTP request.
383  * \param path_vars Path variables extracted from the request.
384  * \param headers HTTP headers.
385  * \param[out] response Response to the HTTP request.
386  */
387 static void ast_ari_channels_continue_in_dialplan_cb(
388         struct ast_tcptls_session_instance *ser,
389         struct ast_variable *get_params, struct ast_variable *path_vars,
390         struct ast_variable *headers, struct ast_ari_response *response)
391 {
392         struct ast_ari_channels_continue_in_dialplan_args args = {};
393         struct ast_variable *i;
394         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
395         struct ast_json *field;
396 #if defined(AST_DEVMODE)
397         int is_valid;
398         int code;
399 #endif /* AST_DEVMODE */
400
401         for (i = get_params; i; i = i->next) {
402                 if (strcmp(i->name, "context") == 0) {
403                         args.context = (i->value);
404                 } else
405                 if (strcmp(i->name, "extension") == 0) {
406                         args.extension = (i->value);
407                 } else
408                 if (strcmp(i->name, "priority") == 0) {
409                         args.priority = atoi(i->value);
410                 } else
411                 {}
412         }
413         for (i = path_vars; i; i = i->next) {
414                 if (strcmp(i->name, "channelId") == 0) {
415                         args.channel_id = (i->value);
416                 } else
417                 {}
418         }
419         /* Look for a JSON request entity */
420         body = ast_http_get_json(ser, headers);
421         if (!body) {
422                 switch (errno) {
423                 case EFBIG:
424                         ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
425                         goto fin;
426                 case ENOMEM:
427                         ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
428                         goto fin;
429                 case EIO:
430                         ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
431                         goto fin;
432                 }
433         }
434         /* Parse query parameters out of it */
435         field = ast_json_object_get(body, "context");
436         if (field) {
437                 args.context = ast_json_string_get(field);
438         }
439         field = ast_json_object_get(body, "extension");
440         if (field) {
441                 args.extension = ast_json_string_get(field);
442         }
443         field = ast_json_object_get(body, "priority");
444         if (field) {
445                 args.priority = ast_json_integer_get(field);
446         }
447         ast_ari_channels_continue_in_dialplan(headers, &args, response);
448 #if defined(AST_DEVMODE)
449         code = response->response_code;
450
451         switch (code) {
452         case 0: /* Implementation is still a stub, or the code wasn't set */
453                 is_valid = response->message == NULL;
454                 break;
455         case 500: /* Internal Server Error */
456         case 501: /* Not Implemented */
457         case 404: /* Channel not found */
458         case 409: /* Channel not in a Stasis application */
459                 is_valid = 1;
460                 break;
461         default:
462                 if (200 <= code && code <= 299) {
463                         is_valid = ast_ari_validate_void(
464                                 response->message);
465                 } else {
466                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/continue\n", code);
467                         is_valid = 0;
468                 }
469         }
470
471         if (!is_valid) {
472                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/continue\n");
473                 ast_ari_response_error(response, 500,
474                         "Internal Server Error", "Response validation failed");
475         }
476 #endif /* AST_DEVMODE */
477
478 fin: __attribute__((unused))
479         return;
480 }
481 /*!
482  * \brief Parameter parsing callback for /channels/{channelId}/answer.
483  * \param get_params GET parameters in the HTTP request.
484  * \param path_vars Path variables extracted from the request.
485  * \param headers HTTP headers.
486  * \param[out] response Response to the HTTP request.
487  */
488 static void ast_ari_channels_answer_cb(
489         struct ast_tcptls_session_instance *ser,
490         struct ast_variable *get_params, struct ast_variable *path_vars,
491         struct ast_variable *headers, struct ast_ari_response *response)
492 {
493         struct ast_ari_channels_answer_args args = {};
494         struct ast_variable *i;
495         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
496 #if defined(AST_DEVMODE)
497         int is_valid;
498         int code;
499 #endif /* AST_DEVMODE */
500
501         for (i = path_vars; i; i = i->next) {
502                 if (strcmp(i->name, "channelId") == 0) {
503                         args.channel_id = (i->value);
504                 } else
505                 {}
506         }
507         ast_ari_channels_answer(headers, &args, response);
508 #if defined(AST_DEVMODE)
509         code = response->response_code;
510
511         switch (code) {
512         case 0: /* Implementation is still a stub, or the code wasn't set */
513                 is_valid = response->message == NULL;
514                 break;
515         case 500: /* Internal Server Error */
516         case 501: /* Not Implemented */
517         case 404: /* Channel not found */
518         case 409: /* Channel not in a Stasis application */
519                 is_valid = 1;
520                 break;
521         default:
522                 if (200 <= code && code <= 299) {
523                         is_valid = ast_ari_validate_void(
524                                 response->message);
525                 } else {
526                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/answer\n", code);
527                         is_valid = 0;
528                 }
529         }
530
531         if (!is_valid) {
532                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/answer\n");
533                 ast_ari_response_error(response, 500,
534                         "Internal Server Error", "Response validation failed");
535         }
536 #endif /* AST_DEVMODE */
537
538 fin: __attribute__((unused))
539         return;
540 }
541 /*!
542  * \brief Parameter parsing callback for /channels/{channelId}/ring.
543  * \param get_params GET parameters in the HTTP request.
544  * \param path_vars Path variables extracted from the request.
545  * \param headers HTTP headers.
546  * \param[out] response Response to the HTTP request.
547  */
548 static void ast_ari_channels_ring_cb(
549         struct ast_tcptls_session_instance *ser,
550         struct ast_variable *get_params, struct ast_variable *path_vars,
551         struct ast_variable *headers, struct ast_ari_response *response)
552 {
553         struct ast_ari_channels_ring_args args = {};
554         struct ast_variable *i;
555         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
556 #if defined(AST_DEVMODE)
557         int is_valid;
558         int code;
559 #endif /* AST_DEVMODE */
560
561         for (i = path_vars; i; i = i->next) {
562                 if (strcmp(i->name, "channelId") == 0) {
563                         args.channel_id = (i->value);
564                 } else
565                 {}
566         }
567         ast_ari_channels_ring(headers, &args, response);
568 #if defined(AST_DEVMODE)
569         code = response->response_code;
570
571         switch (code) {
572         case 0: /* Implementation is still a stub, or the code wasn't set */
573                 is_valid = response->message == NULL;
574                 break;
575         case 500: /* Internal Server Error */
576         case 501: /* Not Implemented */
577         case 404: /* Channel not found */
578         case 409: /* Channel not in a Stasis application */
579                 is_valid = 1;
580                 break;
581         default:
582                 if (200 <= code && code <= 299) {
583                         is_valid = ast_ari_validate_void(
584                                 response->message);
585                 } else {
586                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/ring\n", code);
587                         is_valid = 0;
588                 }
589         }
590
591         if (!is_valid) {
592                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/ring\n");
593                 ast_ari_response_error(response, 500,
594                         "Internal Server Error", "Response validation failed");
595         }
596 #endif /* AST_DEVMODE */
597
598 fin: __attribute__((unused))
599         return;
600 }
601 /*!
602  * \brief Parameter parsing callback for /channels/{channelId}/ring.
603  * \param get_params GET parameters in the HTTP request.
604  * \param path_vars Path variables extracted from the request.
605  * \param headers HTTP headers.
606  * \param[out] response Response to the HTTP request.
607  */
608 static void ast_ari_channels_ring_stop_cb(
609         struct ast_tcptls_session_instance *ser,
610         struct ast_variable *get_params, struct ast_variable *path_vars,
611         struct ast_variable *headers, struct ast_ari_response *response)
612 {
613         struct ast_ari_channels_ring_stop_args args = {};
614         struct ast_variable *i;
615         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
616 #if defined(AST_DEVMODE)
617         int is_valid;
618         int code;
619 #endif /* AST_DEVMODE */
620
621         for (i = path_vars; i; i = i->next) {
622                 if (strcmp(i->name, "channelId") == 0) {
623                         args.channel_id = (i->value);
624                 } else
625                 {}
626         }
627         ast_ari_channels_ring_stop(headers, &args, response);
628 #if defined(AST_DEVMODE)
629         code = response->response_code;
630
631         switch (code) {
632         case 0: /* Implementation is still a stub, or the code wasn't set */
633                 is_valid = response->message == NULL;
634                 break;
635         case 500: /* Internal Server Error */
636         case 501: /* Not Implemented */
637         case 404: /* Channel not found */
638         case 409: /* Channel not in a Stasis application */
639                 is_valid = 1;
640                 break;
641         default:
642                 if (200 <= code && code <= 299) {
643                         is_valid = ast_ari_validate_void(
644                                 response->message);
645                 } else {
646                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/ring\n", code);
647                         is_valid = 0;
648                 }
649         }
650
651         if (!is_valid) {
652                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/ring\n");
653                 ast_ari_response_error(response, 500,
654                         "Internal Server Error", "Response validation failed");
655         }
656 #endif /* AST_DEVMODE */
657
658 fin: __attribute__((unused))
659         return;
660 }
661 /*!
662  * \brief Parameter parsing callback for /channels/{channelId}/dtmf.
663  * \param get_params GET parameters in the HTTP request.
664  * \param path_vars Path variables extracted from the request.
665  * \param headers HTTP headers.
666  * \param[out] response Response to the HTTP request.
667  */
668 static void ast_ari_channels_send_dtmf_cb(
669         struct ast_tcptls_session_instance *ser,
670         struct ast_variable *get_params, struct ast_variable *path_vars,
671         struct ast_variable *headers, struct ast_ari_response *response)
672 {
673         struct ast_ari_channels_send_dtmf_args args = {};
674         struct ast_variable *i;
675         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
676         struct ast_json *field;
677 #if defined(AST_DEVMODE)
678         int is_valid;
679         int code;
680 #endif /* AST_DEVMODE */
681
682         for (i = get_params; i; i = i->next) {
683                 if (strcmp(i->name, "dtmf") == 0) {
684                         args.dtmf = (i->value);
685                 } else
686                 if (strcmp(i->name, "before") == 0) {
687                         args.before = atoi(i->value);
688                 } else
689                 if (strcmp(i->name, "between") == 0) {
690                         args.between = atoi(i->value);
691                 } else
692                 if (strcmp(i->name, "duration") == 0) {
693                         args.duration = atoi(i->value);
694                 } else
695                 if (strcmp(i->name, "after") == 0) {
696                         args.after = atoi(i->value);
697                 } else
698                 {}
699         }
700         for (i = path_vars; i; i = i->next) {
701                 if (strcmp(i->name, "channelId") == 0) {
702                         args.channel_id = (i->value);
703                 } else
704                 {}
705         }
706         /* Look for a JSON request entity */
707         body = ast_http_get_json(ser, headers);
708         if (!body) {
709                 switch (errno) {
710                 case EFBIG:
711                         ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
712                         goto fin;
713                 case ENOMEM:
714                         ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
715                         goto fin;
716                 case EIO:
717                         ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
718                         goto fin;
719                 }
720         }
721         /* Parse query parameters out of it */
722         field = ast_json_object_get(body, "dtmf");
723         if (field) {
724                 args.dtmf = ast_json_string_get(field);
725         }
726         field = ast_json_object_get(body, "before");
727         if (field) {
728                 args.before = ast_json_integer_get(field);
729         }
730         field = ast_json_object_get(body, "between");
731         if (field) {
732                 args.between = ast_json_integer_get(field);
733         }
734         field = ast_json_object_get(body, "duration");
735         if (field) {
736                 args.duration = ast_json_integer_get(field);
737         }
738         field = ast_json_object_get(body, "after");
739         if (field) {
740                 args.after = ast_json_integer_get(field);
741         }
742         ast_ari_channels_send_dtmf(headers, &args, response);
743 #if defined(AST_DEVMODE)
744         code = response->response_code;
745
746         switch (code) {
747         case 0: /* Implementation is still a stub, or the code wasn't set */
748                 is_valid = response->message == NULL;
749                 break;
750         case 500: /* Internal Server Error */
751         case 501: /* Not Implemented */
752         case 400: /* DTMF is required */
753         case 404: /* Channel not found */
754         case 409: /* Channel not in a Stasis application */
755                 is_valid = 1;
756                 break;
757         default:
758                 if (200 <= code && code <= 299) {
759                         is_valid = ast_ari_validate_void(
760                                 response->message);
761                 } else {
762                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/dtmf\n", code);
763                         is_valid = 0;
764                 }
765         }
766
767         if (!is_valid) {
768                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/dtmf\n");
769                 ast_ari_response_error(response, 500,
770                         "Internal Server Error", "Response validation failed");
771         }
772 #endif /* AST_DEVMODE */
773
774 fin: __attribute__((unused))
775         return;
776 }
777 /*!
778  * \brief Parameter parsing callback for /channels/{channelId}/mute.
779  * \param get_params GET parameters in the HTTP request.
780  * \param path_vars Path variables extracted from the request.
781  * \param headers HTTP headers.
782  * \param[out] response Response to the HTTP request.
783  */
784 static void ast_ari_channels_mute_cb(
785         struct ast_tcptls_session_instance *ser,
786         struct ast_variable *get_params, struct ast_variable *path_vars,
787         struct ast_variable *headers, struct ast_ari_response *response)
788 {
789         struct ast_ari_channels_mute_args args = {};
790         struct ast_variable *i;
791         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
792         struct ast_json *field;
793 #if defined(AST_DEVMODE)
794         int is_valid;
795         int code;
796 #endif /* AST_DEVMODE */
797
798         for (i = get_params; i; i = i->next) {
799                 if (strcmp(i->name, "direction") == 0) {
800                         args.direction = (i->value);
801                 } else
802                 {}
803         }
804         for (i = path_vars; i; i = i->next) {
805                 if (strcmp(i->name, "channelId") == 0) {
806                         args.channel_id = (i->value);
807                 } else
808                 {}
809         }
810         /* Look for a JSON request entity */
811         body = ast_http_get_json(ser, headers);
812         if (!body) {
813                 switch (errno) {
814                 case EFBIG:
815                         ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
816                         goto fin;
817                 case ENOMEM:
818                         ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
819                         goto fin;
820                 case EIO:
821                         ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
822                         goto fin;
823                 }
824         }
825         /* Parse query parameters out of it */
826         field = ast_json_object_get(body, "direction");
827         if (field) {
828                 args.direction = ast_json_string_get(field);
829         }
830         ast_ari_channels_mute(headers, &args, response);
831 #if defined(AST_DEVMODE)
832         code = response->response_code;
833
834         switch (code) {
835         case 0: /* Implementation is still a stub, or the code wasn't set */
836                 is_valid = response->message == NULL;
837                 break;
838         case 500: /* Internal Server Error */
839         case 501: /* Not Implemented */
840         case 404: /* Channel not found */
841         case 409: /* Channel not in a Stasis application */
842                 is_valid = 1;
843                 break;
844         default:
845                 if (200 <= code && code <= 299) {
846                         is_valid = ast_ari_validate_void(
847                                 response->message);
848                 } else {
849                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/mute\n", code);
850                         is_valid = 0;
851                 }
852         }
853
854         if (!is_valid) {
855                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/mute\n");
856                 ast_ari_response_error(response, 500,
857                         "Internal Server Error", "Response validation failed");
858         }
859 #endif /* AST_DEVMODE */
860
861 fin: __attribute__((unused))
862         return;
863 }
864 /*!
865  * \brief Parameter parsing callback for /channels/{channelId}/mute.
866  * \param get_params GET parameters in the HTTP request.
867  * \param path_vars Path variables extracted from the request.
868  * \param headers HTTP headers.
869  * \param[out] response Response to the HTTP request.
870  */
871 static void ast_ari_channels_unmute_cb(
872         struct ast_tcptls_session_instance *ser,
873         struct ast_variable *get_params, struct ast_variable *path_vars,
874         struct ast_variable *headers, struct ast_ari_response *response)
875 {
876         struct ast_ari_channels_unmute_args args = {};
877         struct ast_variable *i;
878         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
879         struct ast_json *field;
880 #if defined(AST_DEVMODE)
881         int is_valid;
882         int code;
883 #endif /* AST_DEVMODE */
884
885         for (i = get_params; i; i = i->next) {
886                 if (strcmp(i->name, "direction") == 0) {
887                         args.direction = (i->value);
888                 } else
889                 {}
890         }
891         for (i = path_vars; i; i = i->next) {
892                 if (strcmp(i->name, "channelId") == 0) {
893                         args.channel_id = (i->value);
894                 } else
895                 {}
896         }
897         /* Look for a JSON request entity */
898         body = ast_http_get_json(ser, headers);
899         if (!body) {
900                 switch (errno) {
901                 case EFBIG:
902                         ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
903                         goto fin;
904                 case ENOMEM:
905                         ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
906                         goto fin;
907                 case EIO:
908                         ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
909                         goto fin;
910                 }
911         }
912         /* Parse query parameters out of it */
913         field = ast_json_object_get(body, "direction");
914         if (field) {
915                 args.direction = ast_json_string_get(field);
916         }
917         ast_ari_channels_unmute(headers, &args, response);
918 #if defined(AST_DEVMODE)
919         code = response->response_code;
920
921         switch (code) {
922         case 0: /* Implementation is still a stub, or the code wasn't set */
923                 is_valid = response->message == NULL;
924                 break;
925         case 500: /* Internal Server Error */
926         case 501: /* Not Implemented */
927         case 404: /* Channel not found */
928         case 409: /* Channel not in a Stasis application */
929                 is_valid = 1;
930                 break;
931         default:
932                 if (200 <= code && code <= 299) {
933                         is_valid = ast_ari_validate_void(
934                                 response->message);
935                 } else {
936                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/mute\n", code);
937                         is_valid = 0;
938                 }
939         }
940
941         if (!is_valid) {
942                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/mute\n");
943                 ast_ari_response_error(response, 500,
944                         "Internal Server Error", "Response validation failed");
945         }
946 #endif /* AST_DEVMODE */
947
948 fin: __attribute__((unused))
949         return;
950 }
951 /*!
952  * \brief Parameter parsing callback for /channels/{channelId}/hold.
953  * \param get_params GET parameters in the HTTP request.
954  * \param path_vars Path variables extracted from the request.
955  * \param headers HTTP headers.
956  * \param[out] response Response to the HTTP request.
957  */
958 static void ast_ari_channels_hold_cb(
959         struct ast_tcptls_session_instance *ser,
960         struct ast_variable *get_params, struct ast_variable *path_vars,
961         struct ast_variable *headers, struct ast_ari_response *response)
962 {
963         struct ast_ari_channels_hold_args args = {};
964         struct ast_variable *i;
965         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
966 #if defined(AST_DEVMODE)
967         int is_valid;
968         int code;
969 #endif /* AST_DEVMODE */
970
971         for (i = path_vars; i; i = i->next) {
972                 if (strcmp(i->name, "channelId") == 0) {
973                         args.channel_id = (i->value);
974                 } else
975                 {}
976         }
977         ast_ari_channels_hold(headers, &args, response);
978 #if defined(AST_DEVMODE)
979         code = response->response_code;
980
981         switch (code) {
982         case 0: /* Implementation is still a stub, or the code wasn't set */
983                 is_valid = response->message == NULL;
984                 break;
985         case 500: /* Internal Server Error */
986         case 501: /* Not Implemented */
987         case 404: /* Channel not found */
988         case 409: /* Channel not in a Stasis application */
989                 is_valid = 1;
990                 break;
991         default:
992                 if (200 <= code && code <= 299) {
993                         is_valid = ast_ari_validate_void(
994                                 response->message);
995                 } else {
996                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/hold\n", code);
997                         is_valid = 0;
998                 }
999         }
1000
1001         if (!is_valid) {
1002                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/hold\n");
1003                 ast_ari_response_error(response, 500,
1004                         "Internal Server Error", "Response validation failed");
1005         }
1006 #endif /* AST_DEVMODE */
1007
1008 fin: __attribute__((unused))
1009         return;
1010 }
1011 /*!
1012  * \brief Parameter parsing callback for /channels/{channelId}/hold.
1013  * \param get_params GET parameters in the HTTP request.
1014  * \param path_vars Path variables extracted from the request.
1015  * \param headers HTTP headers.
1016  * \param[out] response Response to the HTTP request.
1017  */
1018 static void ast_ari_channels_unhold_cb(
1019         struct ast_tcptls_session_instance *ser,
1020         struct ast_variable *get_params, struct ast_variable *path_vars,
1021         struct ast_variable *headers, struct ast_ari_response *response)
1022 {
1023         struct ast_ari_channels_unhold_args args = {};
1024         struct ast_variable *i;
1025         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
1026 #if defined(AST_DEVMODE)
1027         int is_valid;
1028         int code;
1029 #endif /* AST_DEVMODE */
1030
1031         for (i = path_vars; i; i = i->next) {
1032                 if (strcmp(i->name, "channelId") == 0) {
1033                         args.channel_id = (i->value);
1034                 } else
1035                 {}
1036         }
1037         ast_ari_channels_unhold(headers, &args, response);
1038 #if defined(AST_DEVMODE)
1039         code = response->response_code;
1040
1041         switch (code) {
1042         case 0: /* Implementation is still a stub, or the code wasn't set */
1043                 is_valid = response->message == NULL;
1044                 break;
1045         case 500: /* Internal Server Error */
1046         case 501: /* Not Implemented */
1047         case 404: /* Channel not found */
1048         case 409: /* Channel not in a Stasis application */
1049                 is_valid = 1;
1050                 break;
1051         default:
1052                 if (200 <= code && code <= 299) {
1053                         is_valid = ast_ari_validate_void(
1054                                 response->message);
1055                 } else {
1056                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/hold\n", code);
1057                         is_valid = 0;
1058                 }
1059         }
1060
1061         if (!is_valid) {
1062                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/hold\n");
1063                 ast_ari_response_error(response, 500,
1064                         "Internal Server Error", "Response validation failed");
1065         }
1066 #endif /* AST_DEVMODE */
1067
1068 fin: __attribute__((unused))
1069         return;
1070 }
1071 /*!
1072  * \brief Parameter parsing callback for /channels/{channelId}/moh.
1073  * \param get_params GET parameters in the HTTP request.
1074  * \param path_vars Path variables extracted from the request.
1075  * \param headers HTTP headers.
1076  * \param[out] response Response to the HTTP request.
1077  */
1078 static void ast_ari_channels_start_moh_cb(
1079         struct ast_tcptls_session_instance *ser,
1080         struct ast_variable *get_params, struct ast_variable *path_vars,
1081         struct ast_variable *headers, struct ast_ari_response *response)
1082 {
1083         struct ast_ari_channels_start_moh_args args = {};
1084         struct ast_variable *i;
1085         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
1086         struct ast_json *field;
1087 #if defined(AST_DEVMODE)
1088         int is_valid;
1089         int code;
1090 #endif /* AST_DEVMODE */
1091
1092         for (i = get_params; i; i = i->next) {
1093                 if (strcmp(i->name, "mohClass") == 0) {
1094                         args.moh_class = (i->value);
1095                 } else
1096                 {}
1097         }
1098         for (i = path_vars; i; i = i->next) {
1099                 if (strcmp(i->name, "channelId") == 0) {
1100                         args.channel_id = (i->value);
1101                 } else
1102                 {}
1103         }
1104         /* Look for a JSON request entity */
1105         body = ast_http_get_json(ser, headers);
1106         if (!body) {
1107                 switch (errno) {
1108                 case EFBIG:
1109                         ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
1110                         goto fin;
1111                 case ENOMEM:
1112                         ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
1113                         goto fin;
1114                 case EIO:
1115                         ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
1116                         goto fin;
1117                 }
1118         }
1119         /* Parse query parameters out of it */
1120         field = ast_json_object_get(body, "mohClass");
1121         if (field) {
1122                 args.moh_class = ast_json_string_get(field);
1123         }
1124         ast_ari_channels_start_moh(headers, &args, response);
1125 #if defined(AST_DEVMODE)
1126         code = response->response_code;
1127
1128         switch (code) {
1129         case 0: /* Implementation is still a stub, or the code wasn't set */
1130                 is_valid = response->message == NULL;
1131                 break;
1132         case 500: /* Internal Server Error */
1133         case 501: /* Not Implemented */
1134         case 404: /* Channel not found */
1135         case 409: /* Channel not in a Stasis application */
1136                 is_valid = 1;
1137                 break;
1138         default:
1139                 if (200 <= code && code <= 299) {
1140                         is_valid = ast_ari_validate_void(
1141                                 response->message);
1142                 } else {
1143                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/moh\n", code);
1144                         is_valid = 0;
1145                 }
1146         }
1147
1148         if (!is_valid) {
1149                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/moh\n");
1150                 ast_ari_response_error(response, 500,
1151                         "Internal Server Error", "Response validation failed");
1152         }
1153 #endif /* AST_DEVMODE */
1154
1155 fin: __attribute__((unused))
1156         return;
1157 }
1158 /*!
1159  * \brief Parameter parsing callback for /channels/{channelId}/moh.
1160  * \param get_params GET parameters in the HTTP request.
1161  * \param path_vars Path variables extracted from the request.
1162  * \param headers HTTP headers.
1163  * \param[out] response Response to the HTTP request.
1164  */
1165 static void ast_ari_channels_stop_moh_cb(
1166         struct ast_tcptls_session_instance *ser,
1167         struct ast_variable *get_params, struct ast_variable *path_vars,
1168         struct ast_variable *headers, struct ast_ari_response *response)
1169 {
1170         struct ast_ari_channels_stop_moh_args args = {};
1171         struct ast_variable *i;
1172         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
1173 #if defined(AST_DEVMODE)
1174         int is_valid;
1175         int code;
1176 #endif /* AST_DEVMODE */
1177
1178         for (i = path_vars; i; i = i->next) {
1179                 if (strcmp(i->name, "channelId") == 0) {
1180                         args.channel_id = (i->value);
1181                 } else
1182                 {}
1183         }
1184         ast_ari_channels_stop_moh(headers, &args, response);
1185 #if defined(AST_DEVMODE)
1186         code = response->response_code;
1187
1188         switch (code) {
1189         case 0: /* Implementation is still a stub, or the code wasn't set */
1190                 is_valid = response->message == NULL;
1191                 break;
1192         case 500: /* Internal Server Error */
1193         case 501: /* Not Implemented */
1194         case 404: /* Channel not found */
1195         case 409: /* Channel not in a Stasis application */
1196                 is_valid = 1;
1197                 break;
1198         default:
1199                 if (200 <= code && code <= 299) {
1200                         is_valid = ast_ari_validate_void(
1201                                 response->message);
1202                 } else {
1203                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/moh\n", code);
1204                         is_valid = 0;
1205                 }
1206         }
1207
1208         if (!is_valid) {
1209                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/moh\n");
1210                 ast_ari_response_error(response, 500,
1211                         "Internal Server Error", "Response validation failed");
1212         }
1213 #endif /* AST_DEVMODE */
1214
1215 fin: __attribute__((unused))
1216         return;
1217 }
1218 /*!
1219  * \brief Parameter parsing callback for /channels/{channelId}/silence.
1220  * \param get_params GET parameters in the HTTP request.
1221  * \param path_vars Path variables extracted from the request.
1222  * \param headers HTTP headers.
1223  * \param[out] response Response to the HTTP request.
1224  */
1225 static void ast_ari_channels_start_silence_cb(
1226         struct ast_tcptls_session_instance *ser,
1227         struct ast_variable *get_params, struct ast_variable *path_vars,
1228         struct ast_variable *headers, struct ast_ari_response *response)
1229 {
1230         struct ast_ari_channels_start_silence_args args = {};
1231         struct ast_variable *i;
1232         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
1233 #if defined(AST_DEVMODE)
1234         int is_valid;
1235         int code;
1236 #endif /* AST_DEVMODE */
1237
1238         for (i = path_vars; i; i = i->next) {
1239                 if (strcmp(i->name, "channelId") == 0) {
1240                         args.channel_id = (i->value);
1241                 } else
1242                 {}
1243         }
1244         ast_ari_channels_start_silence(headers, &args, response);
1245 #if defined(AST_DEVMODE)
1246         code = response->response_code;
1247
1248         switch (code) {
1249         case 0: /* Implementation is still a stub, or the code wasn't set */
1250                 is_valid = response->message == NULL;
1251                 break;
1252         case 500: /* Internal Server Error */
1253         case 501: /* Not Implemented */
1254         case 404: /* Channel not found */
1255         case 409: /* Channel not in a Stasis application */
1256                 is_valid = 1;
1257                 break;
1258         default:
1259                 if (200 <= code && code <= 299) {
1260                         is_valid = ast_ari_validate_void(
1261                                 response->message);
1262                 } else {
1263                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/silence\n", code);
1264                         is_valid = 0;
1265                 }
1266         }
1267
1268         if (!is_valid) {
1269                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/silence\n");
1270                 ast_ari_response_error(response, 500,
1271                         "Internal Server Error", "Response validation failed");
1272         }
1273 #endif /* AST_DEVMODE */
1274
1275 fin: __attribute__((unused))
1276         return;
1277 }
1278 /*!
1279  * \brief Parameter parsing callback for /channels/{channelId}/silence.
1280  * \param get_params GET parameters in the HTTP request.
1281  * \param path_vars Path variables extracted from the request.
1282  * \param headers HTTP headers.
1283  * \param[out] response Response to the HTTP request.
1284  */
1285 static void ast_ari_channels_stop_silence_cb(
1286         struct ast_tcptls_session_instance *ser,
1287         struct ast_variable *get_params, struct ast_variable *path_vars,
1288         struct ast_variable *headers, struct ast_ari_response *response)
1289 {
1290         struct ast_ari_channels_stop_silence_args args = {};
1291         struct ast_variable *i;
1292         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
1293 #if defined(AST_DEVMODE)
1294         int is_valid;
1295         int code;
1296 #endif /* AST_DEVMODE */
1297
1298         for (i = path_vars; i; i = i->next) {
1299                 if (strcmp(i->name, "channelId") == 0) {
1300                         args.channel_id = (i->value);
1301                 } else
1302                 {}
1303         }
1304         ast_ari_channels_stop_silence(headers, &args, response);
1305 #if defined(AST_DEVMODE)
1306         code = response->response_code;
1307
1308         switch (code) {
1309         case 0: /* Implementation is still a stub, or the code wasn't set */
1310                 is_valid = response->message == NULL;
1311                 break;
1312         case 500: /* Internal Server Error */
1313         case 501: /* Not Implemented */
1314         case 404: /* Channel not found */
1315         case 409: /* Channel not in a Stasis application */
1316                 is_valid = 1;
1317                 break;
1318         default:
1319                 if (200 <= code && code <= 299) {
1320                         is_valid = ast_ari_validate_void(
1321                                 response->message);
1322                 } else {
1323                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/silence\n", code);
1324                         is_valid = 0;
1325                 }
1326         }
1327
1328         if (!is_valid) {
1329                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/silence\n");
1330                 ast_ari_response_error(response, 500,
1331                         "Internal Server Error", "Response validation failed");
1332         }
1333 #endif /* AST_DEVMODE */
1334
1335 fin: __attribute__((unused))
1336         return;
1337 }
1338 /*!
1339  * \brief Parameter parsing callback for /channels/{channelId}/play.
1340  * \param get_params GET parameters in the HTTP request.
1341  * \param path_vars Path variables extracted from the request.
1342  * \param headers HTTP headers.
1343  * \param[out] response Response to the HTTP request.
1344  */
1345 static void ast_ari_channels_play_cb(
1346         struct ast_tcptls_session_instance *ser,
1347         struct ast_variable *get_params, struct ast_variable *path_vars,
1348         struct ast_variable *headers, struct ast_ari_response *response)
1349 {
1350         struct ast_ari_channels_play_args args = {};
1351         struct ast_variable *i;
1352         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
1353         struct ast_json *field;
1354 #if defined(AST_DEVMODE)
1355         int is_valid;
1356         int code;
1357 #endif /* AST_DEVMODE */
1358
1359         for (i = get_params; i; i = i->next) {
1360                 if (strcmp(i->name, "media") == 0) {
1361                         args.media = (i->value);
1362                 } else
1363                 if (strcmp(i->name, "lang") == 0) {
1364                         args.lang = (i->value);
1365                 } else
1366                 if (strcmp(i->name, "offsetms") == 0) {
1367                         args.offsetms = atoi(i->value);
1368                 } else
1369                 if (strcmp(i->name, "skipms") == 0) {
1370                         args.skipms = atoi(i->value);
1371                 } else
1372                 {}
1373         }
1374         for (i = path_vars; i; i = i->next) {
1375                 if (strcmp(i->name, "channelId") == 0) {
1376                         args.channel_id = (i->value);
1377                 } else
1378                 {}
1379         }
1380         /* Look for a JSON request entity */
1381         body = ast_http_get_json(ser, headers);
1382         if (!body) {
1383                 switch (errno) {
1384                 case EFBIG:
1385                         ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
1386                         goto fin;
1387                 case ENOMEM:
1388                         ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
1389                         goto fin;
1390                 case EIO:
1391                         ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
1392                         goto fin;
1393                 }
1394         }
1395         /* Parse query parameters out of it */
1396         field = ast_json_object_get(body, "media");
1397         if (field) {
1398                 args.media = ast_json_string_get(field);
1399         }
1400         field = ast_json_object_get(body, "lang");
1401         if (field) {
1402                 args.lang = ast_json_string_get(field);
1403         }
1404         field = ast_json_object_get(body, "offsetms");
1405         if (field) {
1406                 args.offsetms = ast_json_integer_get(field);
1407         }
1408         field = ast_json_object_get(body, "skipms");
1409         if (field) {
1410                 args.skipms = ast_json_integer_get(field);
1411         }
1412         ast_ari_channels_play(headers, &args, response);
1413 #if defined(AST_DEVMODE)
1414         code = response->response_code;
1415
1416         switch (code) {
1417         case 0: /* Implementation is still a stub, or the code wasn't set */
1418                 is_valid = response->message == NULL;
1419                 break;
1420         case 500: /* Internal Server Error */
1421         case 501: /* Not Implemented */
1422         case 404: /* Channel not found */
1423         case 409: /* Channel not in a Stasis application */
1424                 is_valid = 1;
1425                 break;
1426         default:
1427                 if (200 <= code && code <= 299) {
1428                         is_valid = ast_ari_validate_playback(
1429                                 response->message);
1430                 } else {
1431                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/play\n", code);
1432                         is_valid = 0;
1433                 }
1434         }
1435
1436         if (!is_valid) {
1437                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/play\n");
1438                 ast_ari_response_error(response, 500,
1439                         "Internal Server Error", "Response validation failed");
1440         }
1441 #endif /* AST_DEVMODE */
1442
1443 fin: __attribute__((unused))
1444         return;
1445 }
1446 /*!
1447  * \brief Parameter parsing callback for /channels/{channelId}/record.
1448  * \param get_params GET parameters in the HTTP request.
1449  * \param path_vars Path variables extracted from the request.
1450  * \param headers HTTP headers.
1451  * \param[out] response Response to the HTTP request.
1452  */
1453 static void ast_ari_channels_record_cb(
1454         struct ast_tcptls_session_instance *ser,
1455         struct ast_variable *get_params, struct ast_variable *path_vars,
1456         struct ast_variable *headers, struct ast_ari_response *response)
1457 {
1458         struct ast_ari_channels_record_args args = {};
1459         struct ast_variable *i;
1460         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
1461         struct ast_json *field;
1462 #if defined(AST_DEVMODE)
1463         int is_valid;
1464         int code;
1465 #endif /* AST_DEVMODE */
1466
1467         for (i = get_params; i; i = i->next) {
1468                 if (strcmp(i->name, "name") == 0) {
1469                         args.name = (i->value);
1470                 } else
1471                 if (strcmp(i->name, "format") == 0) {
1472                         args.format = (i->value);
1473                 } else
1474                 if (strcmp(i->name, "maxDurationSeconds") == 0) {
1475                         args.max_duration_seconds = atoi(i->value);
1476                 } else
1477                 if (strcmp(i->name, "maxSilenceSeconds") == 0) {
1478                         args.max_silence_seconds = atoi(i->value);
1479                 } else
1480                 if (strcmp(i->name, "ifExists") == 0) {
1481                         args.if_exists = (i->value);
1482                 } else
1483                 if (strcmp(i->name, "beep") == 0) {
1484                         args.beep = ast_true(i->value);
1485                 } else
1486                 if (strcmp(i->name, "terminateOn") == 0) {
1487                         args.terminate_on = (i->value);
1488                 } else
1489                 {}
1490         }
1491         for (i = path_vars; i; i = i->next) {
1492                 if (strcmp(i->name, "channelId") == 0) {
1493                         args.channel_id = (i->value);
1494                 } else
1495                 {}
1496         }
1497         /* Look for a JSON request entity */
1498         body = ast_http_get_json(ser, headers);
1499         if (!body) {
1500                 switch (errno) {
1501                 case EFBIG:
1502                         ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
1503                         goto fin;
1504                 case ENOMEM:
1505                         ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
1506                         goto fin;
1507                 case EIO:
1508                         ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
1509                         goto fin;
1510                 }
1511         }
1512         /* Parse query parameters out of it */
1513         field = ast_json_object_get(body, "name");
1514         if (field) {
1515                 args.name = ast_json_string_get(field);
1516         }
1517         field = ast_json_object_get(body, "format");
1518         if (field) {
1519                 args.format = ast_json_string_get(field);
1520         }
1521         field = ast_json_object_get(body, "maxDurationSeconds");
1522         if (field) {
1523                 args.max_duration_seconds = ast_json_integer_get(field);
1524         }
1525         field = ast_json_object_get(body, "maxSilenceSeconds");
1526         if (field) {
1527                 args.max_silence_seconds = ast_json_integer_get(field);
1528         }
1529         field = ast_json_object_get(body, "ifExists");
1530         if (field) {
1531                 args.if_exists = ast_json_string_get(field);
1532         }
1533         field = ast_json_object_get(body, "beep");
1534         if (field) {
1535                 args.beep = ast_json_is_true(field);
1536         }
1537         field = ast_json_object_get(body, "terminateOn");
1538         if (field) {
1539                 args.terminate_on = ast_json_string_get(field);
1540         }
1541         ast_ari_channels_record(headers, &args, response);
1542 #if defined(AST_DEVMODE)
1543         code = response->response_code;
1544
1545         switch (code) {
1546         case 0: /* Implementation is still a stub, or the code wasn't set */
1547                 is_valid = response->message == NULL;
1548                 break;
1549         case 500: /* Internal Server Error */
1550         case 501: /* Not Implemented */
1551         case 400: /* Invalid parameters */
1552         case 404: /* Channel not found */
1553         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 */
1554         case 422: /* The format specified is unknown on this system */
1555                 is_valid = 1;
1556                 break;
1557         default:
1558                 if (200 <= code && code <= 299) {
1559                         is_valid = ast_ari_validate_live_recording(
1560                                 response->message);
1561                 } else {
1562                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/record\n", code);
1563                         is_valid = 0;
1564                 }
1565         }
1566
1567         if (!is_valid) {
1568                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/record\n");
1569                 ast_ari_response_error(response, 500,
1570                         "Internal Server Error", "Response validation failed");
1571         }
1572 #endif /* AST_DEVMODE */
1573
1574 fin: __attribute__((unused))
1575         return;
1576 }
1577 /*!
1578  * \brief Parameter parsing callback for /channels/{channelId}/variable.
1579  * \param get_params GET parameters in the HTTP request.
1580  * \param path_vars Path variables extracted from the request.
1581  * \param headers HTTP headers.
1582  * \param[out] response Response to the HTTP request.
1583  */
1584 static void ast_ari_channels_get_channel_var_cb(
1585         struct ast_tcptls_session_instance *ser,
1586         struct ast_variable *get_params, struct ast_variable *path_vars,
1587         struct ast_variable *headers, struct ast_ari_response *response)
1588 {
1589         struct ast_ari_channels_get_channel_var_args args = {};
1590         struct ast_variable *i;
1591         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
1592         struct ast_json *field;
1593 #if defined(AST_DEVMODE)
1594         int is_valid;
1595         int code;
1596 #endif /* AST_DEVMODE */
1597
1598         for (i = get_params; i; i = i->next) {
1599                 if (strcmp(i->name, "variable") == 0) {
1600                         args.variable = (i->value);
1601                 } else
1602                 {}
1603         }
1604         for (i = path_vars; i; i = i->next) {
1605                 if (strcmp(i->name, "channelId") == 0) {
1606                         args.channel_id = (i->value);
1607                 } else
1608                 {}
1609         }
1610         /* Look for a JSON request entity */
1611         body = ast_http_get_json(ser, headers);
1612         if (!body) {
1613                 switch (errno) {
1614                 case EFBIG:
1615                         ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
1616                         goto fin;
1617                 case ENOMEM:
1618                         ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
1619                         goto fin;
1620                 case EIO:
1621                         ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
1622                         goto fin;
1623                 }
1624         }
1625         /* Parse query parameters out of it */
1626         field = ast_json_object_get(body, "variable");
1627         if (field) {
1628                 args.variable = ast_json_string_get(field);
1629         }
1630         ast_ari_channels_get_channel_var(headers, &args, response);
1631 #if defined(AST_DEVMODE)
1632         code = response->response_code;
1633
1634         switch (code) {
1635         case 0: /* Implementation is still a stub, or the code wasn't set */
1636                 is_valid = response->message == NULL;
1637                 break;
1638         case 500: /* Internal Server Error */
1639         case 501: /* Not Implemented */
1640         case 400: /* Missing variable parameter. */
1641         case 404: /* Channel not found */
1642         case 409: /* Channel not in a Stasis application */
1643                 is_valid = 1;
1644                 break;
1645         default:
1646                 if (200 <= code && code <= 299) {
1647                         is_valid = ast_ari_validate_variable(
1648                                 response->message);
1649                 } else {
1650                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/variable\n", code);
1651                         is_valid = 0;
1652                 }
1653         }
1654
1655         if (!is_valid) {
1656                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/variable\n");
1657                 ast_ari_response_error(response, 500,
1658                         "Internal Server Error", "Response validation failed");
1659         }
1660 #endif /* AST_DEVMODE */
1661
1662 fin: __attribute__((unused))
1663         return;
1664 }
1665 /*!
1666  * \brief Parameter parsing callback for /channels/{channelId}/variable.
1667  * \param get_params GET parameters in the HTTP request.
1668  * \param path_vars Path variables extracted from the request.
1669  * \param headers HTTP headers.
1670  * \param[out] response Response to the HTTP request.
1671  */
1672 static void ast_ari_channels_set_channel_var_cb(
1673         struct ast_tcptls_session_instance *ser,
1674         struct ast_variable *get_params, struct ast_variable *path_vars,
1675         struct ast_variable *headers, struct ast_ari_response *response)
1676 {
1677         struct ast_ari_channels_set_channel_var_args args = {};
1678         struct ast_variable *i;
1679         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
1680         struct ast_json *field;
1681 #if defined(AST_DEVMODE)
1682         int is_valid;
1683         int code;
1684 #endif /* AST_DEVMODE */
1685
1686         for (i = get_params; i; i = i->next) {
1687                 if (strcmp(i->name, "variable") == 0) {
1688                         args.variable = (i->value);
1689                 } else
1690                 if (strcmp(i->name, "value") == 0) {
1691                         args.value = (i->value);
1692                 } else
1693                 {}
1694         }
1695         for (i = path_vars; i; i = i->next) {
1696                 if (strcmp(i->name, "channelId") == 0) {
1697                         args.channel_id = (i->value);
1698                 } else
1699                 {}
1700         }
1701         /* Look for a JSON request entity */
1702         body = ast_http_get_json(ser, headers);
1703         if (!body) {
1704                 switch (errno) {
1705                 case EFBIG:
1706                         ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
1707                         goto fin;
1708                 case ENOMEM:
1709                         ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
1710                         goto fin;
1711                 case EIO:
1712                         ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
1713                         goto fin;
1714                 }
1715         }
1716         /* Parse query parameters out of it */
1717         field = ast_json_object_get(body, "variable");
1718         if (field) {
1719                 args.variable = ast_json_string_get(field);
1720         }
1721         field = ast_json_object_get(body, "value");
1722         if (field) {
1723                 args.value = ast_json_string_get(field);
1724         }
1725         ast_ari_channels_set_channel_var(headers, &args, response);
1726 #if defined(AST_DEVMODE)
1727         code = response->response_code;
1728
1729         switch (code) {
1730         case 0: /* Implementation is still a stub, or the code wasn't set */
1731                 is_valid = response->message == NULL;
1732                 break;
1733         case 500: /* Internal Server Error */
1734         case 501: /* Not Implemented */
1735         case 400: /* Missing variable parameter. */
1736         case 404: /* Channel not found */
1737         case 409: /* Channel not in a Stasis application */
1738                 is_valid = 1;
1739                 break;
1740         default:
1741                 if (200 <= code && code <= 299) {
1742                         is_valid = ast_ari_validate_void(
1743                                 response->message);
1744                 } else {
1745                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/variable\n", code);
1746                         is_valid = 0;
1747                 }
1748         }
1749
1750         if (!is_valid) {
1751                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/variable\n");
1752                 ast_ari_response_error(response, 500,
1753                         "Internal Server Error", "Response validation failed");
1754         }
1755 #endif /* AST_DEVMODE */
1756
1757 fin: __attribute__((unused))
1758         return;
1759 }
1760 /*!
1761  * \brief Parameter parsing callback for /channels/{channelId}/snoop.
1762  * \param get_params GET parameters in the HTTP request.
1763  * \param path_vars Path variables extracted from the request.
1764  * \param headers HTTP headers.
1765  * \param[out] response Response to the HTTP request.
1766  */
1767 static void ast_ari_channels_snoop_channel_cb(
1768         struct ast_tcptls_session_instance *ser,
1769         struct ast_variable *get_params, struct ast_variable *path_vars,
1770         struct ast_variable *headers, struct ast_ari_response *response)
1771 {
1772         struct ast_ari_channels_snoop_channel_args args = {};
1773         struct ast_variable *i;
1774         RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
1775         struct ast_json *field;
1776 #if defined(AST_DEVMODE)
1777         int is_valid;
1778         int code;
1779 #endif /* AST_DEVMODE */
1780
1781         for (i = get_params; i; i = i->next) {
1782                 if (strcmp(i->name, "spy") == 0) {
1783                         args.spy = (i->value);
1784                 } else
1785                 if (strcmp(i->name, "whisper") == 0) {
1786                         args.whisper = (i->value);
1787                 } else
1788                 if (strcmp(i->name, "app") == 0) {
1789                         args.app = (i->value);
1790                 } else
1791                 if (strcmp(i->name, "appArgs") == 0) {
1792                         args.app_args = (i->value);
1793                 } else
1794                 {}
1795         }
1796         for (i = path_vars; i; i = i->next) {
1797                 if (strcmp(i->name, "channelId") == 0) {
1798                         args.channel_id = (i->value);
1799                 } else
1800                 {}
1801         }
1802         /* Look for a JSON request entity */
1803         body = ast_http_get_json(ser, headers);
1804         if (!body) {
1805                 switch (errno) {
1806                 case EFBIG:
1807                         ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
1808                         goto fin;
1809                 case ENOMEM:
1810                         ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
1811                         goto fin;
1812                 case EIO:
1813                         ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
1814                         goto fin;
1815                 }
1816         }
1817         /* Parse query parameters out of it */
1818         field = ast_json_object_get(body, "spy");
1819         if (field) {
1820                 args.spy = ast_json_string_get(field);
1821         }
1822         field = ast_json_object_get(body, "whisper");
1823         if (field) {
1824                 args.whisper = ast_json_string_get(field);
1825         }
1826         field = ast_json_object_get(body, "app");
1827         if (field) {
1828                 args.app = ast_json_string_get(field);
1829         }
1830         field = ast_json_object_get(body, "appArgs");
1831         if (field) {
1832                 args.app_args = ast_json_string_get(field);
1833         }
1834         ast_ari_channels_snoop_channel(headers, &args, response);
1835 #if defined(AST_DEVMODE)
1836         code = response->response_code;
1837
1838         switch (code) {
1839         case 0: /* Implementation is still a stub, or the code wasn't set */
1840                 is_valid = response->message == NULL;
1841                 break;
1842         case 500: /* Internal Server Error */
1843         case 501: /* Not Implemented */
1844         case 400: /* Invalid parameters */
1845         case 404: /* Channel not found */
1846                 is_valid = 1;
1847                 break;
1848         default:
1849                 if (200 <= code && code <= 299) {
1850                         is_valid = ast_ari_validate_channel(
1851                                 response->message);
1852                 } else {
1853                         ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/snoop\n", code);
1854                         is_valid = 0;
1855                 }
1856         }
1857
1858         if (!is_valid) {
1859                 ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/snoop\n");
1860                 ast_ari_response_error(response, 500,
1861                         "Internal Server Error", "Response validation failed");
1862         }
1863 #endif /* AST_DEVMODE */
1864
1865 fin: __attribute__((unused))
1866         return;
1867 }
1868
1869 /*! \brief REST handler for /api-docs/channels.{format} */
1870 static struct stasis_rest_handlers channels_channelId_continue = {
1871         .path_segment = "continue",
1872         .callbacks = {
1873                 [AST_HTTP_POST] = ast_ari_channels_continue_in_dialplan_cb,
1874         },
1875         .num_children = 0,
1876         .children = {  }
1877 };
1878 /*! \brief REST handler for /api-docs/channels.{format} */
1879 static struct stasis_rest_handlers channels_channelId_answer = {
1880         .path_segment = "answer",
1881         .callbacks = {
1882                 [AST_HTTP_POST] = ast_ari_channels_answer_cb,
1883         },
1884         .num_children = 0,
1885         .children = {  }
1886 };
1887 /*! \brief REST handler for /api-docs/channels.{format} */
1888 static struct stasis_rest_handlers channels_channelId_ring = {
1889         .path_segment = "ring",
1890         .callbacks = {
1891                 [AST_HTTP_POST] = ast_ari_channels_ring_cb,
1892                 [AST_HTTP_DELETE] = ast_ari_channels_ring_stop_cb,
1893         },
1894         .num_children = 0,
1895         .children = {  }
1896 };
1897 /*! \brief REST handler for /api-docs/channels.{format} */
1898 static struct stasis_rest_handlers channels_channelId_dtmf = {
1899         .path_segment = "dtmf",
1900         .callbacks = {
1901                 [AST_HTTP_POST] = ast_ari_channels_send_dtmf_cb,
1902         },
1903         .num_children = 0,
1904         .children = {  }
1905 };
1906 /*! \brief REST handler for /api-docs/channels.{format} */
1907 static struct stasis_rest_handlers channels_channelId_mute = {
1908         .path_segment = "mute",
1909         .callbacks = {
1910                 [AST_HTTP_POST] = ast_ari_channels_mute_cb,
1911                 [AST_HTTP_DELETE] = ast_ari_channels_unmute_cb,
1912         },
1913         .num_children = 0,
1914         .children = {  }
1915 };
1916 /*! \brief REST handler for /api-docs/channels.{format} */
1917 static struct stasis_rest_handlers channels_channelId_hold = {
1918         .path_segment = "hold",
1919         .callbacks = {
1920                 [AST_HTTP_POST] = ast_ari_channels_hold_cb,
1921                 [AST_HTTP_DELETE] = ast_ari_channels_unhold_cb,
1922         },
1923         .num_children = 0,
1924         .children = {  }
1925 };
1926 /*! \brief REST handler for /api-docs/channels.{format} */
1927 static struct stasis_rest_handlers channels_channelId_moh = {
1928         .path_segment = "moh",
1929         .callbacks = {
1930                 [AST_HTTP_POST] = ast_ari_channels_start_moh_cb,
1931                 [AST_HTTP_DELETE] = ast_ari_channels_stop_moh_cb,
1932         },
1933         .num_children = 0,
1934         .children = {  }
1935 };
1936 /*! \brief REST handler for /api-docs/channels.{format} */
1937 static struct stasis_rest_handlers channels_channelId_silence = {
1938         .path_segment = "silence",
1939         .callbacks = {
1940                 [AST_HTTP_POST] = ast_ari_channels_start_silence_cb,
1941                 [AST_HTTP_DELETE] = ast_ari_channels_stop_silence_cb,
1942         },
1943         .num_children = 0,
1944         .children = {  }
1945 };
1946 /*! \brief REST handler for /api-docs/channels.{format} */
1947 static struct stasis_rest_handlers channels_channelId_play = {
1948         .path_segment = "play",
1949         .callbacks = {
1950                 [AST_HTTP_POST] = ast_ari_channels_play_cb,
1951         },
1952         .num_children = 0,
1953         .children = {  }
1954 };
1955 /*! \brief REST handler for /api-docs/channels.{format} */
1956 static struct stasis_rest_handlers channels_channelId_record = {
1957         .path_segment = "record",
1958         .callbacks = {
1959                 [AST_HTTP_POST] = ast_ari_channels_record_cb,
1960         },
1961         .num_children = 0,
1962         .children = {  }
1963 };
1964 /*! \brief REST handler for /api-docs/channels.{format} */
1965 static struct stasis_rest_handlers channels_channelId_variable = {
1966         .path_segment = "variable",
1967         .callbacks = {
1968                 [AST_HTTP_GET] = ast_ari_channels_get_channel_var_cb,
1969                 [AST_HTTP_POST] = ast_ari_channels_set_channel_var_cb,
1970         },
1971         .num_children = 0,
1972         .children = {  }
1973 };
1974 /*! \brief REST handler for /api-docs/channels.{format} */
1975 static struct stasis_rest_handlers channels_channelId_snoop = {
1976         .path_segment = "snoop",
1977         .callbacks = {
1978                 [AST_HTTP_POST] = ast_ari_channels_snoop_channel_cb,
1979         },
1980         .num_children = 0,
1981         .children = {  }
1982 };
1983 /*! \brief REST handler for /api-docs/channels.{format} */
1984 static struct stasis_rest_handlers channels_channelId = {
1985         .path_segment = "channelId",
1986         .is_wildcard = 1,
1987         .callbacks = {
1988                 [AST_HTTP_GET] = ast_ari_channels_get_cb,
1989                 [AST_HTTP_DELETE] = ast_ari_channels_hangup_cb,
1990         },
1991         .num_children = 12,
1992         .children = { &channels_channelId_continue,&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, }
1993 };
1994 /*! \brief REST handler for /api-docs/channels.{format} */
1995 static struct stasis_rest_handlers channels = {
1996         .path_segment = "channels",
1997         .callbacks = {
1998                 [AST_HTTP_GET] = ast_ari_channels_list_cb,
1999                 [AST_HTTP_POST] = ast_ari_channels_originate_cb,
2000         },
2001         .num_children = 1,
2002         .children = { &channels_channelId, }
2003 };
2004
2005 static int load_module(void)
2006 {
2007         int res = 0;
2008         stasis_app_ref();
2009         res |= ast_ari_add_handler(&channels);
2010         return res;
2011 }
2012
2013 static int unload_module(void)
2014 {
2015         ast_ari_remove_handler(&channels);
2016         stasis_app_unref();
2017         return 0;
2018 }
2019
2020 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Channel resources",
2021         .load = load_module,
2022         .unload = unload_module,
2023         .nonoptreq = "res_ari,res_stasis",
2024         );