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