This adds a new ARI method that allows for you to dial a channel that you previously created in ARI. By combining this with the create method for channels, it allows for a workflow where a channel can be created, manipulated, and then dialed. The channel is under control of the ARI application during all stages of the Dial and can even be manipulated based on channel state changes observed within an ARI application. The overarching goal for this is to eventually be able to add a dialed channel to a Stasis bridge earlier than the "Up" state. However, at the moment more work is needed in the Dial and Bridge APIs in order to facilitate that. ASTERISK-25889 #close Change-Id: Ic6c399c791e66c4aa52454222fe4f8b02483a205
2991 lines
85 KiB
C
2991 lines
85 KiB
C
/*
|
|
* Asterisk -- An open source telephony toolkit.
|
|
*
|
|
* Copyright (C) 2012 - 2013, Digium, Inc.
|
|
*
|
|
* David M. Lee, II <dlee@digium.com>
|
|
*
|
|
* See http://www.asterisk.org for more information about
|
|
* the Asterisk project. Please do not directly contact
|
|
* any of the maintainers of this project for assistance;
|
|
* the project provides a web site, mailing lists and IRC
|
|
* channels for your use.
|
|
*
|
|
* This program is free software, distributed under the terms of
|
|
* the GNU General Public License Version 2. See the LICENSE file
|
|
* at the top of the source tree.
|
|
*/
|
|
|
|
/*
|
|
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
* !!!!! DO NOT EDIT !!!!!
|
|
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
* This file is generated by a mustache template. Please see the original
|
|
* template in rest-api-templates/res_ari_resource.c.mustache
|
|
*/
|
|
|
|
/*! \file
|
|
*
|
|
* \brief Channel resources
|
|
*
|
|
* \author David M. Lee, II <dlee@digium.com>
|
|
*/
|
|
|
|
/*** MODULEINFO
|
|
<depend type="module">res_ari</depend>
|
|
<depend type="module">res_ari_model</depend>
|
|
<depend type="module">res_stasis</depend>
|
|
<support_level>core</support_level>
|
|
***/
|
|
|
|
#include "asterisk.h"
|
|
|
|
ASTERISK_REGISTER_FILE()
|
|
|
|
#include "asterisk/app.h"
|
|
#include "asterisk/module.h"
|
|
#include "asterisk/stasis_app.h"
|
|
#include "ari/resource_channels.h"
|
|
#if defined(AST_DEVMODE)
|
|
#include "ari/ari_model_validators.h"
|
|
#endif
|
|
|
|
#define MAX_VALS 128
|
|
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_list_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_list_args args = {};
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
ast_ari_channels_list(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_list(response->message,
|
|
ast_ari_validate_channel_fn());
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
int ast_ari_channels_originate_parse_body(
|
|
struct ast_json *body,
|
|
struct ast_ari_channels_originate_args *args)
|
|
{
|
|
struct ast_json *field;
|
|
/* Parse query parameters out of it */
|
|
field = ast_json_object_get(body, "endpoint");
|
|
if (field) {
|
|
args->endpoint = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "extension");
|
|
if (field) {
|
|
args->extension = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "context");
|
|
if (field) {
|
|
args->context = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "priority");
|
|
if (field) {
|
|
args->priority = ast_json_integer_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "label");
|
|
if (field) {
|
|
args->label = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "app");
|
|
if (field) {
|
|
args->app = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "appArgs");
|
|
if (field) {
|
|
args->app_args = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "callerId");
|
|
if (field) {
|
|
args->caller_id = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "timeout");
|
|
if (field) {
|
|
args->timeout = ast_json_integer_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "channelId");
|
|
if (field) {
|
|
args->channel_id = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "otherChannelId");
|
|
if (field) {
|
|
args->other_channel_id = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "originator");
|
|
if (field) {
|
|
args->originator = ast_json_string_get(field);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_originate_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_originate_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = get_params; i; i = i->next) {
|
|
if (strcmp(i->name, "endpoint") == 0) {
|
|
args.endpoint = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "extension") == 0) {
|
|
args.extension = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "context") == 0) {
|
|
args.context = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "priority") == 0) {
|
|
args.priority = atol(i->value);
|
|
} else
|
|
if (strcmp(i->name, "label") == 0) {
|
|
args.label = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "app") == 0) {
|
|
args.app = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "appArgs") == 0) {
|
|
args.app_args = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "callerId") == 0) {
|
|
args.caller_id = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "timeout") == 0) {
|
|
args.timeout = atoi(i->value);
|
|
} else
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "otherChannelId") == 0) {
|
|
args.other_channel_id = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "originator") == 0) {
|
|
args.originator = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
/* Look for a JSON request entity */
|
|
body = ast_http_get_json(ser, headers);
|
|
if (!body) {
|
|
switch (errno) {
|
|
case EFBIG:
|
|
ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
|
|
goto fin;
|
|
case ENOMEM:
|
|
ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
|
|
goto fin;
|
|
case EIO:
|
|
ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
|
|
goto fin;
|
|
}
|
|
}
|
|
args.variables = body;
|
|
ast_ari_channels_originate(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 400: /* Invalid parameters for originating a channel. */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_channel(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
int ast_ari_channels_create_parse_body(
|
|
struct ast_json *body,
|
|
struct ast_ari_channels_create_args *args)
|
|
{
|
|
struct ast_json *field;
|
|
/* Parse query parameters out of it */
|
|
field = ast_json_object_get(body, "endpoint");
|
|
if (field) {
|
|
args->endpoint = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "app");
|
|
if (field) {
|
|
args->app = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "appArgs");
|
|
if (field) {
|
|
args->app_args = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "channelId");
|
|
if (field) {
|
|
args->channel_id = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "otherChannelId");
|
|
if (field) {
|
|
args->other_channel_id = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "originator");
|
|
if (field) {
|
|
args->originator = ast_json_string_get(field);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/create.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_create_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_create_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = get_params; i; i = i->next) {
|
|
if (strcmp(i->name, "endpoint") == 0) {
|
|
args.endpoint = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "app") == 0) {
|
|
args.app = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "appArgs") == 0) {
|
|
args.app_args = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "otherChannelId") == 0) {
|
|
args.other_channel_id = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "originator") == 0) {
|
|
args.originator = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
/* Look for a JSON request entity */
|
|
body = ast_http_get_json(ser, headers);
|
|
if (!body) {
|
|
switch (errno) {
|
|
case EFBIG:
|
|
ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
|
|
goto fin;
|
|
case ENOMEM:
|
|
ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
|
|
goto fin;
|
|
case EIO:
|
|
ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
|
|
goto fin;
|
|
}
|
|
}
|
|
if (ast_ari_channels_create_parse_body(body, &args)) {
|
|
ast_ari_response_alloc_failed(response);
|
|
goto fin;
|
|
}
|
|
ast_ari_channels_create(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_channel(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/create\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/create\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_get_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_get_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
ast_ari_channels_get(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 404: /* Channel not found */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_channel(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
int ast_ari_channels_originate_with_id_parse_body(
|
|
struct ast_json *body,
|
|
struct ast_ari_channels_originate_with_id_args *args)
|
|
{
|
|
struct ast_json *field;
|
|
/* Parse query parameters out of it */
|
|
field = ast_json_object_get(body, "endpoint");
|
|
if (field) {
|
|
args->endpoint = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "extension");
|
|
if (field) {
|
|
args->extension = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "context");
|
|
if (field) {
|
|
args->context = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "priority");
|
|
if (field) {
|
|
args->priority = ast_json_integer_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "label");
|
|
if (field) {
|
|
args->label = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "app");
|
|
if (field) {
|
|
args->app = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "appArgs");
|
|
if (field) {
|
|
args->app_args = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "callerId");
|
|
if (field) {
|
|
args->caller_id = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "timeout");
|
|
if (field) {
|
|
args->timeout = ast_json_integer_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "otherChannelId");
|
|
if (field) {
|
|
args->other_channel_id = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "originator");
|
|
if (field) {
|
|
args->originator = ast_json_string_get(field);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_originate_with_id_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_originate_with_id_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = get_params; i; i = i->next) {
|
|
if (strcmp(i->name, "endpoint") == 0) {
|
|
args.endpoint = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "extension") == 0) {
|
|
args.extension = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "context") == 0) {
|
|
args.context = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "priority") == 0) {
|
|
args.priority = atol(i->value);
|
|
} else
|
|
if (strcmp(i->name, "label") == 0) {
|
|
args.label = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "app") == 0) {
|
|
args.app = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "appArgs") == 0) {
|
|
args.app_args = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "callerId") == 0) {
|
|
args.caller_id = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "timeout") == 0) {
|
|
args.timeout = atoi(i->value);
|
|
} else
|
|
if (strcmp(i->name, "otherChannelId") == 0) {
|
|
args.other_channel_id = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "originator") == 0) {
|
|
args.originator = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
/* Look for a JSON request entity */
|
|
body = ast_http_get_json(ser, headers);
|
|
if (!body) {
|
|
switch (errno) {
|
|
case EFBIG:
|
|
ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
|
|
goto fin;
|
|
case ENOMEM:
|
|
ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
|
|
goto fin;
|
|
case EIO:
|
|
ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
|
|
goto fin;
|
|
}
|
|
}
|
|
args.variables = body;
|
|
ast_ari_channels_originate_with_id(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 400: /* Invalid parameters for originating a channel. */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_channel(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
int ast_ari_channels_hangup_parse_body(
|
|
struct ast_json *body,
|
|
struct ast_ari_channels_hangup_args *args)
|
|
{
|
|
struct ast_json *field;
|
|
/* Parse query parameters out of it */
|
|
field = ast_json_object_get(body, "reason");
|
|
if (field) {
|
|
args->reason = ast_json_string_get(field);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_hangup_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_hangup_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = get_params; i; i = i->next) {
|
|
if (strcmp(i->name, "reason") == 0) {
|
|
args.reason = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
/* Look for a JSON request entity */
|
|
body = ast_http_get_json(ser, headers);
|
|
if (!body) {
|
|
switch (errno) {
|
|
case EFBIG:
|
|
ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
|
|
goto fin;
|
|
case ENOMEM:
|
|
ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
|
|
goto fin;
|
|
case EIO:
|
|
ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
|
|
goto fin;
|
|
}
|
|
}
|
|
if (ast_ari_channels_hangup_parse_body(body, &args)) {
|
|
ast_ari_response_alloc_failed(response);
|
|
goto fin;
|
|
}
|
|
ast_ari_channels_hangup(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 400: /* Invalid reason for hangup provided */
|
|
case 404: /* Channel not found */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_void(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
int ast_ari_channels_continue_in_dialplan_parse_body(
|
|
struct ast_json *body,
|
|
struct ast_ari_channels_continue_in_dialplan_args *args)
|
|
{
|
|
struct ast_json *field;
|
|
/* Parse query parameters out of it */
|
|
field = ast_json_object_get(body, "context");
|
|
if (field) {
|
|
args->context = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "extension");
|
|
if (field) {
|
|
args->extension = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "priority");
|
|
if (field) {
|
|
args->priority = ast_json_integer_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "label");
|
|
if (field) {
|
|
args->label = ast_json_string_get(field);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}/continue.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_continue_in_dialplan_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_continue_in_dialplan_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = get_params; i; i = i->next) {
|
|
if (strcmp(i->name, "context") == 0) {
|
|
args.context = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "extension") == 0) {
|
|
args.extension = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "priority") == 0) {
|
|
args.priority = atoi(i->value);
|
|
} else
|
|
if (strcmp(i->name, "label") == 0) {
|
|
args.label = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
/* Look for a JSON request entity */
|
|
body = ast_http_get_json(ser, headers);
|
|
if (!body) {
|
|
switch (errno) {
|
|
case EFBIG:
|
|
ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
|
|
goto fin;
|
|
case ENOMEM:
|
|
ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
|
|
goto fin;
|
|
case EIO:
|
|
ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
|
|
goto fin;
|
|
}
|
|
}
|
|
if (ast_ari_channels_continue_in_dialplan_parse_body(body, &args)) {
|
|
ast_ari_response_alloc_failed(response);
|
|
goto fin;
|
|
}
|
|
ast_ari_channels_continue_in_dialplan(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 404: /* Channel not found */
|
|
case 409: /* Channel not in a Stasis application */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_void(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/continue\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/continue\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
int ast_ari_channels_redirect_parse_body(
|
|
struct ast_json *body,
|
|
struct ast_ari_channels_redirect_args *args)
|
|
{
|
|
struct ast_json *field;
|
|
/* Parse query parameters out of it */
|
|
field = ast_json_object_get(body, "endpoint");
|
|
if (field) {
|
|
args->endpoint = ast_json_string_get(field);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}/redirect.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_redirect_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_redirect_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = get_params; i; i = i->next) {
|
|
if (strcmp(i->name, "endpoint") == 0) {
|
|
args.endpoint = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
/* Look for a JSON request entity */
|
|
body = ast_http_get_json(ser, headers);
|
|
if (!body) {
|
|
switch (errno) {
|
|
case EFBIG:
|
|
ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
|
|
goto fin;
|
|
case ENOMEM:
|
|
ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
|
|
goto fin;
|
|
case EIO:
|
|
ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
|
|
goto fin;
|
|
}
|
|
}
|
|
if (ast_ari_channels_redirect_parse_body(body, &args)) {
|
|
ast_ari_response_alloc_failed(response);
|
|
goto fin;
|
|
}
|
|
ast_ari_channels_redirect(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 400: /* Endpoint parameter not provided */
|
|
case 404: /* Channel or endpoint not found */
|
|
case 409: /* Channel not in a Stasis application */
|
|
case 422: /* Endpoint is not the same type as the channel */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_void(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/redirect\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/redirect\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}/answer.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_answer_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_answer_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
ast_ari_channels_answer(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 404: /* Channel not found */
|
|
case 409: /* Channel not in a Stasis application */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_void(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/answer\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/answer\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}/ring.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_ring_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_ring_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
ast_ari_channels_ring(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 404: /* Channel not found */
|
|
case 409: /* Channel not in a Stasis application */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_void(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/ring\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/ring\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}/ring.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_ring_stop_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_ring_stop_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
ast_ari_channels_ring_stop(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 404: /* Channel not found */
|
|
case 409: /* Channel not in a Stasis application */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_void(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/ring\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/ring\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
int ast_ari_channels_send_dtmf_parse_body(
|
|
struct ast_json *body,
|
|
struct ast_ari_channels_send_dtmf_args *args)
|
|
{
|
|
struct ast_json *field;
|
|
/* Parse query parameters out of it */
|
|
field = ast_json_object_get(body, "dtmf");
|
|
if (field) {
|
|
args->dtmf = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "before");
|
|
if (field) {
|
|
args->before = ast_json_integer_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "between");
|
|
if (field) {
|
|
args->between = ast_json_integer_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "duration");
|
|
if (field) {
|
|
args->duration = ast_json_integer_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "after");
|
|
if (field) {
|
|
args->after = ast_json_integer_get(field);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}/dtmf.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_send_dtmf_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_send_dtmf_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = get_params; i; i = i->next) {
|
|
if (strcmp(i->name, "dtmf") == 0) {
|
|
args.dtmf = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "before") == 0) {
|
|
args.before = atoi(i->value);
|
|
} else
|
|
if (strcmp(i->name, "between") == 0) {
|
|
args.between = atoi(i->value);
|
|
} else
|
|
if (strcmp(i->name, "duration") == 0) {
|
|
args.duration = atoi(i->value);
|
|
} else
|
|
if (strcmp(i->name, "after") == 0) {
|
|
args.after = atoi(i->value);
|
|
} else
|
|
{}
|
|
}
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
/* Look for a JSON request entity */
|
|
body = ast_http_get_json(ser, headers);
|
|
if (!body) {
|
|
switch (errno) {
|
|
case EFBIG:
|
|
ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
|
|
goto fin;
|
|
case ENOMEM:
|
|
ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
|
|
goto fin;
|
|
case EIO:
|
|
ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
|
|
goto fin;
|
|
}
|
|
}
|
|
if (ast_ari_channels_send_dtmf_parse_body(body, &args)) {
|
|
ast_ari_response_alloc_failed(response);
|
|
goto fin;
|
|
}
|
|
ast_ari_channels_send_dtmf(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 400: /* DTMF is required */
|
|
case 404: /* Channel not found */
|
|
case 409: /* Channel not in a Stasis application */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_void(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/dtmf\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/dtmf\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
int ast_ari_channels_mute_parse_body(
|
|
struct ast_json *body,
|
|
struct ast_ari_channels_mute_args *args)
|
|
{
|
|
struct ast_json *field;
|
|
/* Parse query parameters out of it */
|
|
field = ast_json_object_get(body, "direction");
|
|
if (field) {
|
|
args->direction = ast_json_string_get(field);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}/mute.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_mute_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_mute_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = get_params; i; i = i->next) {
|
|
if (strcmp(i->name, "direction") == 0) {
|
|
args.direction = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
/* Look for a JSON request entity */
|
|
body = ast_http_get_json(ser, headers);
|
|
if (!body) {
|
|
switch (errno) {
|
|
case EFBIG:
|
|
ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
|
|
goto fin;
|
|
case ENOMEM:
|
|
ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
|
|
goto fin;
|
|
case EIO:
|
|
ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
|
|
goto fin;
|
|
}
|
|
}
|
|
if (ast_ari_channels_mute_parse_body(body, &args)) {
|
|
ast_ari_response_alloc_failed(response);
|
|
goto fin;
|
|
}
|
|
ast_ari_channels_mute(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 404: /* Channel not found */
|
|
case 409: /* Channel not in a Stasis application */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_void(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/mute\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/mute\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
int ast_ari_channels_unmute_parse_body(
|
|
struct ast_json *body,
|
|
struct ast_ari_channels_unmute_args *args)
|
|
{
|
|
struct ast_json *field;
|
|
/* Parse query parameters out of it */
|
|
field = ast_json_object_get(body, "direction");
|
|
if (field) {
|
|
args->direction = ast_json_string_get(field);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}/mute.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_unmute_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_unmute_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = get_params; i; i = i->next) {
|
|
if (strcmp(i->name, "direction") == 0) {
|
|
args.direction = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
/* Look for a JSON request entity */
|
|
body = ast_http_get_json(ser, headers);
|
|
if (!body) {
|
|
switch (errno) {
|
|
case EFBIG:
|
|
ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
|
|
goto fin;
|
|
case ENOMEM:
|
|
ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
|
|
goto fin;
|
|
case EIO:
|
|
ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
|
|
goto fin;
|
|
}
|
|
}
|
|
if (ast_ari_channels_unmute_parse_body(body, &args)) {
|
|
ast_ari_response_alloc_failed(response);
|
|
goto fin;
|
|
}
|
|
ast_ari_channels_unmute(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 404: /* Channel not found */
|
|
case 409: /* Channel not in a Stasis application */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_void(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/mute\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/mute\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}/hold.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_hold_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_hold_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
ast_ari_channels_hold(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 404: /* Channel not found */
|
|
case 409: /* Channel not in a Stasis application */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_void(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/hold\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/hold\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}/hold.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_unhold_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_unhold_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
ast_ari_channels_unhold(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 404: /* Channel not found */
|
|
case 409: /* Channel not in a Stasis application */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_void(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/hold\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/hold\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
int ast_ari_channels_start_moh_parse_body(
|
|
struct ast_json *body,
|
|
struct ast_ari_channels_start_moh_args *args)
|
|
{
|
|
struct ast_json *field;
|
|
/* Parse query parameters out of it */
|
|
field = ast_json_object_get(body, "mohClass");
|
|
if (field) {
|
|
args->moh_class = ast_json_string_get(field);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}/moh.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_start_moh_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_start_moh_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = get_params; i; i = i->next) {
|
|
if (strcmp(i->name, "mohClass") == 0) {
|
|
args.moh_class = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
/* Look for a JSON request entity */
|
|
body = ast_http_get_json(ser, headers);
|
|
if (!body) {
|
|
switch (errno) {
|
|
case EFBIG:
|
|
ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
|
|
goto fin;
|
|
case ENOMEM:
|
|
ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
|
|
goto fin;
|
|
case EIO:
|
|
ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
|
|
goto fin;
|
|
}
|
|
}
|
|
if (ast_ari_channels_start_moh_parse_body(body, &args)) {
|
|
ast_ari_response_alloc_failed(response);
|
|
goto fin;
|
|
}
|
|
ast_ari_channels_start_moh(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 404: /* Channel not found */
|
|
case 409: /* Channel not in a Stasis application */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_void(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/moh\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/moh\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}/moh.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_stop_moh_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_stop_moh_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
ast_ari_channels_stop_moh(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 404: /* Channel not found */
|
|
case 409: /* Channel not in a Stasis application */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_void(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/moh\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/moh\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}/silence.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_start_silence_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_start_silence_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
ast_ari_channels_start_silence(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 404: /* Channel not found */
|
|
case 409: /* Channel not in a Stasis application */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_void(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/silence\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/silence\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}/silence.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_stop_silence_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_stop_silence_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
ast_ari_channels_stop_silence(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 404: /* Channel not found */
|
|
case 409: /* Channel not in a Stasis application */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_void(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/silence\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/silence\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
int ast_ari_channels_play_parse_body(
|
|
struct ast_json *body,
|
|
struct ast_ari_channels_play_args *args)
|
|
{
|
|
struct ast_json *field;
|
|
/* Parse query parameters out of it */
|
|
field = ast_json_object_get(body, "media");
|
|
if (field) {
|
|
args->media = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "lang");
|
|
if (field) {
|
|
args->lang = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "offsetms");
|
|
if (field) {
|
|
args->offsetms = ast_json_integer_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "skipms");
|
|
if (field) {
|
|
args->skipms = ast_json_integer_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "playbackId");
|
|
if (field) {
|
|
args->playback_id = ast_json_string_get(field);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}/play.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_play_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_play_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = get_params; i; i = i->next) {
|
|
if (strcmp(i->name, "media") == 0) {
|
|
args.media = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "lang") == 0) {
|
|
args.lang = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "offsetms") == 0) {
|
|
args.offsetms = atoi(i->value);
|
|
} else
|
|
if (strcmp(i->name, "skipms") == 0) {
|
|
args.skipms = atoi(i->value);
|
|
} else
|
|
if (strcmp(i->name, "playbackId") == 0) {
|
|
args.playback_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
/* Look for a JSON request entity */
|
|
body = ast_http_get_json(ser, headers);
|
|
if (!body) {
|
|
switch (errno) {
|
|
case EFBIG:
|
|
ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
|
|
goto fin;
|
|
case ENOMEM:
|
|
ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
|
|
goto fin;
|
|
case EIO:
|
|
ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
|
|
goto fin;
|
|
}
|
|
}
|
|
if (ast_ari_channels_play_parse_body(body, &args)) {
|
|
ast_ari_response_alloc_failed(response);
|
|
goto fin;
|
|
}
|
|
ast_ari_channels_play(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 404: /* Channel not found */
|
|
case 409: /* Channel not in a Stasis application */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_playback(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/play\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/play\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
int ast_ari_channels_play_with_id_parse_body(
|
|
struct ast_json *body,
|
|
struct ast_ari_channels_play_with_id_args *args)
|
|
{
|
|
struct ast_json *field;
|
|
/* Parse query parameters out of it */
|
|
field = ast_json_object_get(body, "media");
|
|
if (field) {
|
|
args->media = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "lang");
|
|
if (field) {
|
|
args->lang = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "offsetms");
|
|
if (field) {
|
|
args->offsetms = ast_json_integer_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "skipms");
|
|
if (field) {
|
|
args->skipms = ast_json_integer_get(field);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}/play/{playbackId}.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_play_with_id_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_play_with_id_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = get_params; i; i = i->next) {
|
|
if (strcmp(i->name, "media") == 0) {
|
|
args.media = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "lang") == 0) {
|
|
args.lang = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "offsetms") == 0) {
|
|
args.offsetms = atoi(i->value);
|
|
} else
|
|
if (strcmp(i->name, "skipms") == 0) {
|
|
args.skipms = atoi(i->value);
|
|
} else
|
|
{}
|
|
}
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "playbackId") == 0) {
|
|
args.playback_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
/* Look for a JSON request entity */
|
|
body = ast_http_get_json(ser, headers);
|
|
if (!body) {
|
|
switch (errno) {
|
|
case EFBIG:
|
|
ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
|
|
goto fin;
|
|
case ENOMEM:
|
|
ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
|
|
goto fin;
|
|
case EIO:
|
|
ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
|
|
goto fin;
|
|
}
|
|
}
|
|
if (ast_ari_channels_play_with_id_parse_body(body, &args)) {
|
|
ast_ari_response_alloc_failed(response);
|
|
goto fin;
|
|
}
|
|
ast_ari_channels_play_with_id(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 404: /* Channel not found */
|
|
case 409: /* Channel not in a Stasis application */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_playback(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/play/{playbackId}\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/play/{playbackId}\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
int ast_ari_channels_record_parse_body(
|
|
struct ast_json *body,
|
|
struct ast_ari_channels_record_args *args)
|
|
{
|
|
struct ast_json *field;
|
|
/* Parse query parameters out of it */
|
|
field = ast_json_object_get(body, "name");
|
|
if (field) {
|
|
args->name = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "format");
|
|
if (field) {
|
|
args->format = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "maxDurationSeconds");
|
|
if (field) {
|
|
args->max_duration_seconds = ast_json_integer_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "maxSilenceSeconds");
|
|
if (field) {
|
|
args->max_silence_seconds = ast_json_integer_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "ifExists");
|
|
if (field) {
|
|
args->if_exists = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "beep");
|
|
if (field) {
|
|
args->beep = ast_json_is_true(field);
|
|
}
|
|
field = ast_json_object_get(body, "terminateOn");
|
|
if (field) {
|
|
args->terminate_on = ast_json_string_get(field);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}/record.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_record_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_record_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = get_params; i; i = i->next) {
|
|
if (strcmp(i->name, "name") == 0) {
|
|
args.name = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "format") == 0) {
|
|
args.format = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "maxDurationSeconds") == 0) {
|
|
args.max_duration_seconds = atoi(i->value);
|
|
} else
|
|
if (strcmp(i->name, "maxSilenceSeconds") == 0) {
|
|
args.max_silence_seconds = atoi(i->value);
|
|
} else
|
|
if (strcmp(i->name, "ifExists") == 0) {
|
|
args.if_exists = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "beep") == 0) {
|
|
args.beep = ast_true(i->value);
|
|
} else
|
|
if (strcmp(i->name, "terminateOn") == 0) {
|
|
args.terminate_on = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
/* Look for a JSON request entity */
|
|
body = ast_http_get_json(ser, headers);
|
|
if (!body) {
|
|
switch (errno) {
|
|
case EFBIG:
|
|
ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
|
|
goto fin;
|
|
case ENOMEM:
|
|
ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
|
|
goto fin;
|
|
case EIO:
|
|
ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
|
|
goto fin;
|
|
}
|
|
}
|
|
if (ast_ari_channels_record_parse_body(body, &args)) {
|
|
ast_ari_response_alloc_failed(response);
|
|
goto fin;
|
|
}
|
|
ast_ari_channels_record(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 400: /* Invalid parameters */
|
|
case 404: /* Channel not found */
|
|
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 */
|
|
case 422: /* The format specified is unknown on this system */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_live_recording(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/record\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/record\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
int ast_ari_channels_get_channel_var_parse_body(
|
|
struct ast_json *body,
|
|
struct ast_ari_channels_get_channel_var_args *args)
|
|
{
|
|
struct ast_json *field;
|
|
/* Parse query parameters out of it */
|
|
field = ast_json_object_get(body, "variable");
|
|
if (field) {
|
|
args->variable = ast_json_string_get(field);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}/variable.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_get_channel_var_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_get_channel_var_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = get_params; i; i = i->next) {
|
|
if (strcmp(i->name, "variable") == 0) {
|
|
args.variable = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
/* Look for a JSON request entity */
|
|
body = ast_http_get_json(ser, headers);
|
|
if (!body) {
|
|
switch (errno) {
|
|
case EFBIG:
|
|
ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
|
|
goto fin;
|
|
case ENOMEM:
|
|
ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
|
|
goto fin;
|
|
case EIO:
|
|
ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
|
|
goto fin;
|
|
}
|
|
}
|
|
if (ast_ari_channels_get_channel_var_parse_body(body, &args)) {
|
|
ast_ari_response_alloc_failed(response);
|
|
goto fin;
|
|
}
|
|
ast_ari_channels_get_channel_var(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 400: /* Missing variable parameter. */
|
|
case 404: /* Channel or variable not found */
|
|
case 409: /* Channel not in a Stasis application */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_variable(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/variable\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/variable\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
int ast_ari_channels_set_channel_var_parse_body(
|
|
struct ast_json *body,
|
|
struct ast_ari_channels_set_channel_var_args *args)
|
|
{
|
|
struct ast_json *field;
|
|
/* Parse query parameters out of it */
|
|
field = ast_json_object_get(body, "variable");
|
|
if (field) {
|
|
args->variable = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "value");
|
|
if (field) {
|
|
args->value = ast_json_string_get(field);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}/variable.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_set_channel_var_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_set_channel_var_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = get_params; i; i = i->next) {
|
|
if (strcmp(i->name, "variable") == 0) {
|
|
args.variable = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "value") == 0) {
|
|
args.value = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
/* Look for a JSON request entity */
|
|
body = ast_http_get_json(ser, headers);
|
|
if (!body) {
|
|
switch (errno) {
|
|
case EFBIG:
|
|
ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
|
|
goto fin;
|
|
case ENOMEM:
|
|
ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
|
|
goto fin;
|
|
case EIO:
|
|
ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
|
|
goto fin;
|
|
}
|
|
}
|
|
if (ast_ari_channels_set_channel_var_parse_body(body, &args)) {
|
|
ast_ari_response_alloc_failed(response);
|
|
goto fin;
|
|
}
|
|
ast_ari_channels_set_channel_var(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 400: /* Missing variable parameter. */
|
|
case 404: /* Channel not found */
|
|
case 409: /* Channel not in a Stasis application */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_void(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/variable\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/variable\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
int ast_ari_channels_snoop_channel_parse_body(
|
|
struct ast_json *body,
|
|
struct ast_ari_channels_snoop_channel_args *args)
|
|
{
|
|
struct ast_json *field;
|
|
/* Parse query parameters out of it */
|
|
field = ast_json_object_get(body, "spy");
|
|
if (field) {
|
|
args->spy = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "whisper");
|
|
if (field) {
|
|
args->whisper = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "app");
|
|
if (field) {
|
|
args->app = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "appArgs");
|
|
if (field) {
|
|
args->app_args = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "snoopId");
|
|
if (field) {
|
|
args->snoop_id = ast_json_string_get(field);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}/snoop.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_snoop_channel_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_snoop_channel_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = get_params; i; i = i->next) {
|
|
if (strcmp(i->name, "spy") == 0) {
|
|
args.spy = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "whisper") == 0) {
|
|
args.whisper = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "app") == 0) {
|
|
args.app = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "appArgs") == 0) {
|
|
args.app_args = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "snoopId") == 0) {
|
|
args.snoop_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
/* Look for a JSON request entity */
|
|
body = ast_http_get_json(ser, headers);
|
|
if (!body) {
|
|
switch (errno) {
|
|
case EFBIG:
|
|
ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
|
|
goto fin;
|
|
case ENOMEM:
|
|
ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
|
|
goto fin;
|
|
case EIO:
|
|
ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
|
|
goto fin;
|
|
}
|
|
}
|
|
if (ast_ari_channels_snoop_channel_parse_body(body, &args)) {
|
|
ast_ari_response_alloc_failed(response);
|
|
goto fin;
|
|
}
|
|
ast_ari_channels_snoop_channel(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 400: /* Invalid parameters */
|
|
case 404: /* Channel not found */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_channel(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/snoop\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/snoop\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
int ast_ari_channels_snoop_channel_with_id_parse_body(
|
|
struct ast_json *body,
|
|
struct ast_ari_channels_snoop_channel_with_id_args *args)
|
|
{
|
|
struct ast_json *field;
|
|
/* Parse query parameters out of it */
|
|
field = ast_json_object_get(body, "spy");
|
|
if (field) {
|
|
args->spy = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "whisper");
|
|
if (field) {
|
|
args->whisper = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "app");
|
|
if (field) {
|
|
args->app = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "appArgs");
|
|
if (field) {
|
|
args->app_args = ast_json_string_get(field);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}/snoop/{snoopId}.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_snoop_channel_with_id_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_snoop_channel_with_id_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = get_params; i; i = i->next) {
|
|
if (strcmp(i->name, "spy") == 0) {
|
|
args.spy = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "whisper") == 0) {
|
|
args.whisper = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "app") == 0) {
|
|
args.app = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "appArgs") == 0) {
|
|
args.app_args = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "snoopId") == 0) {
|
|
args.snoop_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
/* Look for a JSON request entity */
|
|
body = ast_http_get_json(ser, headers);
|
|
if (!body) {
|
|
switch (errno) {
|
|
case EFBIG:
|
|
ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
|
|
goto fin;
|
|
case ENOMEM:
|
|
ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
|
|
goto fin;
|
|
case EIO:
|
|
ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
|
|
goto fin;
|
|
}
|
|
}
|
|
if (ast_ari_channels_snoop_channel_with_id_parse_body(body, &args)) {
|
|
ast_ari_response_alloc_failed(response);
|
|
goto fin;
|
|
}
|
|
ast_ari_channels_snoop_channel_with_id(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 400: /* Invalid parameters */
|
|
case 404: /* Channel not found */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_channel(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/snoop/{snoopId}\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/snoop/{snoopId}\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
int ast_ari_channels_dial_parse_body(
|
|
struct ast_json *body,
|
|
struct ast_ari_channels_dial_args *args)
|
|
{
|
|
struct ast_json *field;
|
|
/* Parse query parameters out of it */
|
|
field = ast_json_object_get(body, "caller");
|
|
if (field) {
|
|
args->caller = ast_json_string_get(field);
|
|
}
|
|
field = ast_json_object_get(body, "timeout");
|
|
if (field) {
|
|
args->timeout = ast_json_integer_get(field);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Parameter parsing callback for /channels/{channelId}/dial.
|
|
* \param get_params GET parameters in the HTTP request.
|
|
* \param path_vars Path variables extracted from the request.
|
|
* \param headers HTTP headers.
|
|
* \param[out] response Response to the HTTP request.
|
|
*/
|
|
static void ast_ari_channels_dial_cb(
|
|
struct ast_tcptls_session_instance *ser,
|
|
struct ast_variable *get_params, struct ast_variable *path_vars,
|
|
struct ast_variable *headers, struct ast_ari_response *response)
|
|
{
|
|
struct ast_ari_channels_dial_args args = {};
|
|
struct ast_variable *i;
|
|
RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
|
|
#if defined(AST_DEVMODE)
|
|
int is_valid;
|
|
int code;
|
|
#endif /* AST_DEVMODE */
|
|
|
|
for (i = get_params; i; i = i->next) {
|
|
if (strcmp(i->name, "caller") == 0) {
|
|
args.caller = (i->value);
|
|
} else
|
|
if (strcmp(i->name, "timeout") == 0) {
|
|
args.timeout = atoi(i->value);
|
|
} else
|
|
{}
|
|
}
|
|
for (i = path_vars; i; i = i->next) {
|
|
if (strcmp(i->name, "channelId") == 0) {
|
|
args.channel_id = (i->value);
|
|
} else
|
|
{}
|
|
}
|
|
/* Look for a JSON request entity */
|
|
body = ast_http_get_json(ser, headers);
|
|
if (!body) {
|
|
switch (errno) {
|
|
case EFBIG:
|
|
ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
|
|
goto fin;
|
|
case ENOMEM:
|
|
ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
|
|
goto fin;
|
|
case EIO:
|
|
ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
|
|
goto fin;
|
|
}
|
|
}
|
|
if (ast_ari_channels_dial_parse_body(body, &args)) {
|
|
ast_ari_response_alloc_failed(response);
|
|
goto fin;
|
|
}
|
|
ast_ari_channels_dial(headers, &args, response);
|
|
#if defined(AST_DEVMODE)
|
|
code = response->response_code;
|
|
|
|
switch (code) {
|
|
case 0: /* Implementation is still a stub, or the code wasn't set */
|
|
is_valid = response->message == NULL;
|
|
break;
|
|
case 500: /* Internal Server Error */
|
|
case 501: /* Not Implemented */
|
|
case 404: /* Channel cannot be found. */
|
|
case 409: /* Channel cannot be dialed. */
|
|
is_valid = 1;
|
|
break;
|
|
default:
|
|
if (200 <= code && code <= 299) {
|
|
is_valid = ast_ari_validate_void(
|
|
response->message);
|
|
} else {
|
|
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/dial\n", code);
|
|
is_valid = 0;
|
|
}
|
|
}
|
|
|
|
if (!is_valid) {
|
|
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/dial\n");
|
|
ast_ari_response_error(response, 500,
|
|
"Internal Server Error", "Response validation failed");
|
|
}
|
|
#endif /* AST_DEVMODE */
|
|
|
|
fin: __attribute__((unused))
|
|
return;
|
|
}
|
|
|
|
/*! \brief REST handler for /api-docs/channels.{format} */
|
|
static struct stasis_rest_handlers channels_create = {
|
|
.path_segment = "create",
|
|
.callbacks = {
|
|
[AST_HTTP_POST] = ast_ari_channels_create_cb,
|
|
},
|
|
.num_children = 0,
|
|
.children = { }
|
|
};
|
|
/*! \brief REST handler for /api-docs/channels.{format} */
|
|
static struct stasis_rest_handlers channels_channelId_continue = {
|
|
.path_segment = "continue",
|
|
.callbacks = {
|
|
[AST_HTTP_POST] = ast_ari_channels_continue_in_dialplan_cb,
|
|
},
|
|
.num_children = 0,
|
|
.children = { }
|
|
};
|
|
/*! \brief REST handler for /api-docs/channels.{format} */
|
|
static struct stasis_rest_handlers channels_channelId_redirect = {
|
|
.path_segment = "redirect",
|
|
.callbacks = {
|
|
[AST_HTTP_POST] = ast_ari_channels_redirect_cb,
|
|
},
|
|
.num_children = 0,
|
|
.children = { }
|
|
};
|
|
/*! \brief REST handler for /api-docs/channels.{format} */
|
|
static struct stasis_rest_handlers channels_channelId_answer = {
|
|
.path_segment = "answer",
|
|
.callbacks = {
|
|
[AST_HTTP_POST] = ast_ari_channels_answer_cb,
|
|
},
|
|
.num_children = 0,
|
|
.children = { }
|
|
};
|
|
/*! \brief REST handler for /api-docs/channels.{format} */
|
|
static struct stasis_rest_handlers channels_channelId_ring = {
|
|
.path_segment = "ring",
|
|
.callbacks = {
|
|
[AST_HTTP_POST] = ast_ari_channels_ring_cb,
|
|
[AST_HTTP_DELETE] = ast_ari_channels_ring_stop_cb,
|
|
},
|
|
.num_children = 0,
|
|
.children = { }
|
|
};
|
|
/*! \brief REST handler for /api-docs/channels.{format} */
|
|
static struct stasis_rest_handlers channels_channelId_dtmf = {
|
|
.path_segment = "dtmf",
|
|
.callbacks = {
|
|
[AST_HTTP_POST] = ast_ari_channels_send_dtmf_cb,
|
|
},
|
|
.num_children = 0,
|
|
.children = { }
|
|
};
|
|
/*! \brief REST handler for /api-docs/channels.{format} */
|
|
static struct stasis_rest_handlers channels_channelId_mute = {
|
|
.path_segment = "mute",
|
|
.callbacks = {
|
|
[AST_HTTP_POST] = ast_ari_channels_mute_cb,
|
|
[AST_HTTP_DELETE] = ast_ari_channels_unmute_cb,
|
|
},
|
|
.num_children = 0,
|
|
.children = { }
|
|
};
|
|
/*! \brief REST handler for /api-docs/channels.{format} */
|
|
static struct stasis_rest_handlers channels_channelId_hold = {
|
|
.path_segment = "hold",
|
|
.callbacks = {
|
|
[AST_HTTP_POST] = ast_ari_channels_hold_cb,
|
|
[AST_HTTP_DELETE] = ast_ari_channels_unhold_cb,
|
|
},
|
|
.num_children = 0,
|
|
.children = { }
|
|
};
|
|
/*! \brief REST handler for /api-docs/channels.{format} */
|
|
static struct stasis_rest_handlers channels_channelId_moh = {
|
|
.path_segment = "moh",
|
|
.callbacks = {
|
|
[AST_HTTP_POST] = ast_ari_channels_start_moh_cb,
|
|
[AST_HTTP_DELETE] = ast_ari_channels_stop_moh_cb,
|
|
},
|
|
.num_children = 0,
|
|
.children = { }
|
|
};
|
|
/*! \brief REST handler for /api-docs/channels.{format} */
|
|
static struct stasis_rest_handlers channels_channelId_silence = {
|
|
.path_segment = "silence",
|
|
.callbacks = {
|
|
[AST_HTTP_POST] = ast_ari_channels_start_silence_cb,
|
|
[AST_HTTP_DELETE] = ast_ari_channels_stop_silence_cb,
|
|
},
|
|
.num_children = 0,
|
|
.children = { }
|
|
};
|
|
/*! \brief REST handler for /api-docs/channels.{format} */
|
|
static struct stasis_rest_handlers channels_channelId_play_playbackId = {
|
|
.path_segment = "playbackId",
|
|
.is_wildcard = 1,
|
|
.callbacks = {
|
|
[AST_HTTP_POST] = ast_ari_channels_play_with_id_cb,
|
|
},
|
|
.num_children = 0,
|
|
.children = { }
|
|
};
|
|
/*! \brief REST handler for /api-docs/channels.{format} */
|
|
static struct stasis_rest_handlers channels_channelId_play = {
|
|
.path_segment = "play",
|
|
.callbacks = {
|
|
[AST_HTTP_POST] = ast_ari_channels_play_cb,
|
|
},
|
|
.num_children = 1,
|
|
.children = { &channels_channelId_play_playbackId, }
|
|
};
|
|
/*! \brief REST handler for /api-docs/channels.{format} */
|
|
static struct stasis_rest_handlers channels_channelId_record = {
|
|
.path_segment = "record",
|
|
.callbacks = {
|
|
[AST_HTTP_POST] = ast_ari_channels_record_cb,
|
|
},
|
|
.num_children = 0,
|
|
.children = { }
|
|
};
|
|
/*! \brief REST handler for /api-docs/channels.{format} */
|
|
static struct stasis_rest_handlers channels_channelId_variable = {
|
|
.path_segment = "variable",
|
|
.callbacks = {
|
|
[AST_HTTP_GET] = ast_ari_channels_get_channel_var_cb,
|
|
[AST_HTTP_POST] = ast_ari_channels_set_channel_var_cb,
|
|
},
|
|
.num_children = 0,
|
|
.children = { }
|
|
};
|
|
/*! \brief REST handler for /api-docs/channels.{format} */
|
|
static struct stasis_rest_handlers channels_channelId_snoop_snoopId = {
|
|
.path_segment = "snoopId",
|
|
.is_wildcard = 1,
|
|
.callbacks = {
|
|
[AST_HTTP_POST] = ast_ari_channels_snoop_channel_with_id_cb,
|
|
},
|
|
.num_children = 0,
|
|
.children = { }
|
|
};
|
|
/*! \brief REST handler for /api-docs/channels.{format} */
|
|
static struct stasis_rest_handlers channels_channelId_snoop = {
|
|
.path_segment = "snoop",
|
|
.callbacks = {
|
|
[AST_HTTP_POST] = ast_ari_channels_snoop_channel_cb,
|
|
},
|
|
.num_children = 1,
|
|
.children = { &channels_channelId_snoop_snoopId, }
|
|
};
|
|
/*! \brief REST handler for /api-docs/channels.{format} */
|
|
static struct stasis_rest_handlers channels_channelId_dial = {
|
|
.path_segment = "dial",
|
|
.callbacks = {
|
|
[AST_HTTP_POST] = ast_ari_channels_dial_cb,
|
|
},
|
|
.num_children = 0,
|
|
.children = { }
|
|
};
|
|
/*! \brief REST handler for /api-docs/channels.{format} */
|
|
static struct stasis_rest_handlers channels_channelId = {
|
|
.path_segment = "channelId",
|
|
.is_wildcard = 1,
|
|
.callbacks = {
|
|
[AST_HTTP_GET] = ast_ari_channels_get_cb,
|
|
[AST_HTTP_POST] = ast_ari_channels_originate_with_id_cb,
|
|
[AST_HTTP_DELETE] = ast_ari_channels_hangup_cb,
|
|
},
|
|
.num_children = 14,
|
|
.children = { &channels_channelId_continue,&channels_channelId_redirect,&channels_channelId_answer,&channels_channelId_ring,&channels_channelId_dtmf,&channels_channelId_mute,&channels_channelId_hold,&channels_channelId_moh,&channels_channelId_silence,&channels_channelId_play,&channels_channelId_record,&channels_channelId_variable,&channels_channelId_snoop,&channels_channelId_dial, }
|
|
};
|
|
/*! \brief REST handler for /api-docs/channels.{format} */
|
|
static struct stasis_rest_handlers channels = {
|
|
.path_segment = "channels",
|
|
.callbacks = {
|
|
[AST_HTTP_GET] = ast_ari_channels_list_cb,
|
|
[AST_HTTP_POST] = ast_ari_channels_originate_cb,
|
|
},
|
|
.num_children = 2,
|
|
.children = { &channels_create,&channels_channelId, }
|
|
};
|
|
|
|
static int load_module(void)
|
|
{
|
|
int res = 0;
|
|
stasis_app_ref();
|
|
res |= ast_ari_add_handler(&channels);
|
|
return res;
|
|
}
|
|
|
|
static int unload_module(void)
|
|
{
|
|
ast_ari_remove_handler(&channels);
|
|
stasis_app_unref();
|
|
return 0;
|
|
}
|
|
|
|
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Channel resources",
|
|
.support_level = AST_MODULE_SUPPORT_CORE,
|
|
.load = load_module,
|
|
.unload = unload_module,
|
|
.nonoptreq = "res_ari,res_stasis",
|
|
);
|