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