mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-18 18:58:22 +00:00
Update events to use Swagger 1.3 subtyping, and related aftermath
This patch started with the simple idea of changing the /events data model to be more sane. The original model would send out events like: { "stasis_start": { "args": [], "channel": { ... } } } The event discriminator was the field name instead of being a value in the object, due to limitations in how Swagger 1.1 could model objects. While technically sufficient in communicating event information, it was really difficult to deal with in terms of client side JSON handling. This patch takes advantage of a proposed extension[1] to Swagger which allows type variance through the use of a discriminator field. This had a domino effect that made this a surprisingly large patch. [1]: https://groups.google.com/d/msg/wordnik-api/EC3rGajE0os/ey_5dBI_jWcJ In changing the models, I also had to change the swagger_model.py processor so it can handle the type discriminator and subtyping. I took that a big step forward, and using that information to generate an ari_model module, which can validate a JSON object against the Swagger model. The REST and WebSocket generators were changed to take advantage of the validators. If compiled with AST_DEVMODE enabled, JSON objects that don't match their corresponding models will not be sent out. For REST API calls, a 500 Internal Server response is sent. For WebSockets, the invalid JSON message is replaced with an error message. Since this took over about half of the job of the existing JSON generators, and the .to_json virtual function on messages took over the other half, I reluctantly removed the generators. The validators turned up all sorts of errors and inconsistencies in our data models, and the code. These were cleaned up, with checks in the code generator avoid some of the consistency problems in the future. * The model for a channel snapshot was trimmed down to match the information sent via AMI. Many of the field being sent were not useful in the general case. * The model for a bridge snapshot was updated to be more consistent with the other ARI models. Another impact of introducing subtyping was that the swagger-codegen documentation generator was insufficient (at least until it catches up with Swagger 1.2). I wanted it to be easier to generate docs for the API anyways, so I ported the wiki pages to use the Asterisk Swagger generator. In the process, I was able to clean up many of the model links, which would occasionally give inconsistent results on the wiki. I also added error responses to the wiki docs, making the wiki documentation more complete. Finally, since Stasis-HTTP will now be named Asterisk REST Interface (ARI), any new functions and files I created carry the ari_ prefix. I changed a few stasis_http references to ari where it was non-intrusive and made sense. (closes issue ASTERISK-21885) Review: https://reviewboard.asterisk.org/r/2639/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@393529 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
11
Makefile
11
Makefile
@@ -416,6 +416,7 @@ _clean:
|
||||
rm -f main/version.c
|
||||
rm -f doc/core-en_US.xml
|
||||
rm -f doc/full-en_US.xml
|
||||
rm -f docs/rest-api/*.wiki
|
||||
@$(MAKE) -C menuselect clean
|
||||
cp -f .cleancount .lastclean
|
||||
|
||||
@@ -963,15 +964,15 @@ menuselect-tree: $(foreach dir,$(filter-out main,$(MOD_SUBDIRS)),$(wildcard $(di
|
||||
|
||||
# We don't want to require Python or Pystache for every build, so this is its
|
||||
# own target.
|
||||
stasis-stubs:
|
||||
ari-stubs:
|
||||
ifeq ($(PYTHON),:)
|
||||
@echo "--------------------------------------------------------------------------"
|
||||
@echo "--- Please install python to build Stasis HTTP stubs ---"
|
||||
@echo "--- Please install python to build ARI stubs ---"
|
||||
@echo "--------------------------------------------------------------------------"
|
||||
@false
|
||||
else
|
||||
$(PYTHON) rest-api-templates/make_stasis_http_stubs.py \
|
||||
rest-api/resources.json res/
|
||||
$(PYTHON) rest-api-templates/make_ari_stubs.py \
|
||||
rest-api/resources.json .
|
||||
endif
|
||||
|
||||
.PHONY: menuselect
|
||||
@@ -993,7 +994,7 @@ endif
|
||||
.PHONY: installdirs
|
||||
.PHONY: validate-docs
|
||||
.PHONY: _clean
|
||||
.PHONY: stasis-stubs
|
||||
.PHONY: ari-stubs
|
||||
.PHONY: $(SUBDIRS_INSTALL)
|
||||
.PHONY: $(SUBDIRS_DIST_CLEAN)
|
||||
.PHONY: $(SUBDIRS_CLEAN)
|
||||
|
@@ -158,6 +158,15 @@ enum ast_json_type
|
||||
*/
|
||||
enum ast_json_type ast_json_typeof(const struct ast_json *value);
|
||||
|
||||
/*!
|
||||
* \brief Get the string name for the given type.
|
||||
* \since 12.0.0
|
||||
* \param type Type to convert to string.
|
||||
* \return Simple string for the type name (object, array, string, etc.)
|
||||
* \return \c "?" for invalid types.
|
||||
*/
|
||||
const char *ast_json_typename(enum ast_json_type type);
|
||||
|
||||
/*!@}*/
|
||||
|
||||
/*!@{*/
|
||||
|
@@ -33,6 +33,12 @@
|
||||
#include "asterisk/json.h"
|
||||
#include "asterisk/http_websocket.h"
|
||||
|
||||
/*!
|
||||
* \brief Configured encoding format for JSON output.
|
||||
* \return JSON output encoding (compact, pretty, etc.)
|
||||
*/
|
||||
enum ast_json_encoding_format stasis_http_json_format(void);
|
||||
|
||||
struct stasis_http_response;
|
||||
|
||||
/*!
|
||||
@@ -141,12 +147,16 @@ struct ari_websocket_session;
|
||||
/*!
|
||||
* \brief Create an ARI WebSocket session.
|
||||
*
|
||||
* If \c NULL is given for the validator function, no validation will be
|
||||
* performed.
|
||||
*
|
||||
* \param ws_session Underlying WebSocket session.
|
||||
* \param validator Function to validate outgoing messages.
|
||||
* \return New ARI WebSocket session.
|
||||
* \return \c NULL on error.
|
||||
*/
|
||||
struct ari_websocket_session *ari_websocket_session_create(
|
||||
struct ast_websocket *ws_session);
|
||||
struct ast_websocket *ws_session, int (*validator)(struct ast_json *));
|
||||
|
||||
/*!
|
||||
* \brief Read a message from an ARI WebSocket.
|
||||
|
17
main/json.c
17
main/json.c
@@ -103,6 +103,23 @@ enum ast_json_type ast_json_typeof(const struct ast_json *json)
|
||||
return r;
|
||||
}
|
||||
|
||||
const char *ast_json_typename(enum ast_json_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case AST_JSON_OBJECT: return "object";
|
||||
case AST_JSON_ARRAY: return "array";
|
||||
case AST_JSON_STRING: return "string";
|
||||
case AST_JSON_INTEGER: return "integer";
|
||||
case AST_JSON_REAL: return "real";
|
||||
case AST_JSON_TRUE: return "boolean";
|
||||
case AST_JSON_FALSE: return "boolean";
|
||||
case AST_JSON_NULL: return "null";
|
||||
}
|
||||
ast_assert(0);
|
||||
return "?";
|
||||
}
|
||||
|
||||
|
||||
struct ast_json *ast_json_true(void)
|
||||
{
|
||||
return (struct ast_json *)json_true();
|
||||
|
@@ -657,10 +657,10 @@ struct ast_json *ast_bridge_snapshot_to_json(const struct ast_bridge_snapshot *s
|
||||
}
|
||||
|
||||
json_bridge = ast_json_pack("{s: s, s: s, s: s, s: s, s: o}",
|
||||
"bridgeUniqueid", snapshot->uniqueid,
|
||||
"bridgeTechnology", snapshot->technology,
|
||||
"bridgeType", capability2str(snapshot->capabilities),
|
||||
"bridgeClass", snapshot->subclass,
|
||||
"id", snapshot->uniqueid,
|
||||
"technology", snapshot->technology,
|
||||
"bridge_type", capability2str(snapshot->capabilities),
|
||||
"bridge_class", snapshot->subclass,
|
||||
"channels", json_channels);
|
||||
if (!json_bridge) {
|
||||
return NULL;
|
||||
|
@@ -32,10 +32,11 @@
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/stasis.h"
|
||||
#include "asterisk/astobj2.h"
|
||||
#include "asterisk/stasis_channels.h"
|
||||
#include "asterisk/json.h"
|
||||
#include "asterisk/pbx.h"
|
||||
#include "asterisk/stasis.h"
|
||||
#include "asterisk/stasis_channels.h"
|
||||
|
||||
/*** DOCUMENTATION
|
||||
<managerEvent language="en_US" name="VarSet">
|
||||
@@ -621,25 +622,25 @@ struct ast_json *ast_channel_snapshot_to_json(const struct ast_channel_snapshot
|
||||
return NULL;
|
||||
}
|
||||
|
||||
json_chan = ast_json_pack("{ s: s, s: s, s: s, s: s, s: s, s: s, s: s,"
|
||||
" s: s, s: s, s: s, s: s, s: o, s: o, s: o,"
|
||||
" s: o"
|
||||
"}",
|
||||
"name", snapshot->name,
|
||||
"state", ast_state2str(snapshot->state),
|
||||
"accountcode", snapshot->accountcode,
|
||||
"peeraccount", snapshot->peeraccount,
|
||||
"userfield", snapshot->userfield,
|
||||
"uniqueid", snapshot->uniqueid,
|
||||
"linkedid", snapshot->linkedid,
|
||||
"parkinglot", snapshot->parkinglot,
|
||||
"hangupsource", snapshot->hangupsource,
|
||||
"appl", snapshot->appl,
|
||||
"data", snapshot->data,
|
||||
"dialplan", ast_json_dialplan_cep(snapshot->context, snapshot->exten, snapshot->priority),
|
||||
"caller", ast_json_name_number(snapshot->caller_name, snapshot->caller_number),
|
||||
"connected", ast_json_name_number(snapshot->connected_name, snapshot->connected_number),
|
||||
"creationtime", ast_json_timeval(snapshot->creationtime, NULL));
|
||||
json_chan = ast_json_pack(
|
||||
/* Broken up into groups of three for readability */
|
||||
"{ s: s, s: s, s: s,"
|
||||
" s: o, s: o, s: s,"
|
||||
" s: o, s: o }",
|
||||
/* First line */
|
||||
"id", snapshot->uniqueid,
|
||||
"name", snapshot->name,
|
||||
"state", ast_state2str(snapshot->state),
|
||||
/* Second line */
|
||||
"caller", ast_json_name_number(
|
||||
snapshot->caller_name, snapshot->caller_number),
|
||||
"connected", ast_json_name_number(
|
||||
snapshot->connected_name, snapshot->connected_number),
|
||||
"accountcode", snapshot->accountcode,
|
||||
/* Third line */
|
||||
"dialplan", ast_json_dialplan_cep(
|
||||
snapshot->context, snapshot->exten, snapshot->priority),
|
||||
"creationtime", ast_json_timeval(snapshot->creationtime, NULL));
|
||||
|
||||
return ast_json_ref(json_chan);
|
||||
}
|
||||
@@ -675,6 +676,91 @@ int ast_channel_snapshot_caller_id_equal(
|
||||
strcmp(old_snapshot->caller_name, new_snapshot->caller_name) == 0;
|
||||
}
|
||||
|
||||
static struct ast_json *channel_blob_to_json(struct stasis_message *message,
|
||||
const char *type)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, out, NULL, ast_json_unref);
|
||||
struct ast_channel_blob *channel_blob = stasis_message_data(message);
|
||||
struct ast_json *blob = channel_blob->blob;
|
||||
struct ast_channel_snapshot *snapshot = channel_blob->snapshot;
|
||||
const struct timeval *tv = stasis_message_timestamp(message);
|
||||
int res = 0;
|
||||
|
||||
if (blob == NULL || ast_json_is_null(blob)) {
|
||||
out = ast_json_object_create();
|
||||
} else {
|
||||
/* blobs are immutable, so shallow copies are fine */
|
||||
out = ast_json_copy(blob);
|
||||
}
|
||||
|
||||
if (!out) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res |= ast_json_object_set(out, "type", ast_json_string_create(type));
|
||||
res |= ast_json_object_set(out, "timestamp",
|
||||
ast_json_timeval(*tv, NULL));
|
||||
|
||||
/* For global channel messages, the snapshot is optional */
|
||||
if (snapshot) {
|
||||
res |= ast_json_object_set(out, "channel",
|
||||
ast_channel_snapshot_to_json(snapshot));
|
||||
}
|
||||
|
||||
if (res != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_json_ref(out);
|
||||
}
|
||||
|
||||
static struct ast_json *dtmf_end_to_json(struct stasis_message *message)
|
||||
{
|
||||
struct ast_channel_blob *channel_blob = stasis_message_data(message);
|
||||
struct ast_json *blob = channel_blob->blob;
|
||||
struct ast_channel_snapshot *snapshot = channel_blob->snapshot;
|
||||
const char *direction =
|
||||
ast_json_string_get(ast_json_object_get(blob, "direction"));
|
||||
const struct timeval *tv = stasis_message_timestamp(message);
|
||||
|
||||
/* Only present received DTMF end events as JSON */
|
||||
if (strcasecmp("Received", direction) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_json_pack("{s: s, s: o, s: O, s: O, s: o}",
|
||||
"type", "ChannelDtmfReceived",
|
||||
"timestamp", ast_json_timeval(*tv, NULL),
|
||||
"digit", ast_json_object_get(blob, "digit"),
|
||||
"duration_ms", ast_json_object_get(blob, "duration_ms"),
|
||||
"channel", ast_channel_snapshot_to_json(snapshot));
|
||||
}
|
||||
|
||||
static struct ast_json *user_event_to_json(struct stasis_message *message)
|
||||
{
|
||||
struct ast_channel_blob *channel_blob = stasis_message_data(message);
|
||||
struct ast_json *blob = channel_blob->blob;
|
||||
struct ast_channel_snapshot *snapshot = channel_blob->snapshot;
|
||||
const struct timeval *tv = stasis_message_timestamp(message);
|
||||
|
||||
return ast_json_pack("{s: s, s: o, s: O, s: O, s: o}",
|
||||
"type", "ChannelUserevent",
|
||||
"timestamp", ast_json_timeval(*tv, NULL),
|
||||
"eventname", ast_json_object_get(blob, "eventname"),
|
||||
"userevent", blob,
|
||||
"channel", ast_channel_snapshot_to_json(snapshot));
|
||||
}
|
||||
|
||||
static struct ast_json *varset_to_json(struct stasis_message *message)
|
||||
{
|
||||
return channel_blob_to_json(message, "ChannelVarset");
|
||||
}
|
||||
|
||||
static struct ast_json *hangup_request_to_json(struct stasis_message *message)
|
||||
{
|
||||
return channel_blob_to_json(message, "ChannelHangupRequest");
|
||||
}
|
||||
|
||||
/*!
|
||||
* @{ \brief Define channel message types.
|
||||
*/
|
||||
@@ -682,11 +768,18 @@ STASIS_MESSAGE_TYPE_DEFN(ast_channel_snapshot_type);
|
||||
STASIS_MESSAGE_TYPE_DEFN(ast_channel_dial_type);
|
||||
STASIS_MESSAGE_TYPE_DEFN(ast_channel_varset_type,
|
||||
.to_ami = varset_to_ami,
|
||||
.to_json = varset_to_json,
|
||||
);
|
||||
STASIS_MESSAGE_TYPE_DEFN(ast_channel_user_event_type,
|
||||
.to_json = user_event_to_json,
|
||||
);
|
||||
STASIS_MESSAGE_TYPE_DEFN(ast_channel_hangup_request_type,
|
||||
.to_json = hangup_request_to_json,
|
||||
);
|
||||
STASIS_MESSAGE_TYPE_DEFN(ast_channel_user_event_type);
|
||||
STASIS_MESSAGE_TYPE_DEFN(ast_channel_hangup_request_type);
|
||||
STASIS_MESSAGE_TYPE_DEFN(ast_channel_dtmf_begin_type);
|
||||
STASIS_MESSAGE_TYPE_DEFN(ast_channel_dtmf_end_type);
|
||||
STASIS_MESSAGE_TYPE_DEFN(ast_channel_dtmf_end_type,
|
||||
.to_json = dtmf_end_to_json,
|
||||
);
|
||||
STASIS_MESSAGE_TYPE_DEFN(ast_channel_hold_type);
|
||||
STASIS_MESSAGE_TYPE_DEFN(ast_channel_unhold_type);
|
||||
STASIS_MESSAGE_TYPE_DEFN(ast_channel_chanspy_start_type);
|
||||
|
@@ -239,7 +239,7 @@ struct ast_json *ast_endpoint_snapshot_to_json(
|
||||
"technology", snapshot->tech,
|
||||
"resource", snapshot->resource,
|
||||
"state", ast_endpoint_state_to_string(snapshot->state),
|
||||
"channels");
|
||||
"channel_ids");
|
||||
|
||||
if (json == NULL) {
|
||||
return NULL;
|
||||
@@ -253,7 +253,7 @@ struct ast_json *ast_endpoint_snapshot_to_json(
|
||||
}
|
||||
}
|
||||
|
||||
channel_array = ast_json_object_get(json, "channels");
|
||||
channel_array = ast_json_object_get(json, "channel_ids");
|
||||
ast_assert(channel_array != NULL);
|
||||
for (i = 0; i < snapshot->num_channels; ++i) {
|
||||
int res = ast_json_array_append(channel_array,
|
||||
|
@@ -83,5 +83,8 @@ $(subst .c,.o,$(wildcard parking/*.c)): _ASTCFLAGS+=$(call MOD_ASTCFLAGS,res_par
|
||||
res_stasis_http.so: stasis_http/ari_websockets.o
|
||||
stasis_http/ari_websockets.o: _ASTCFLAGS+=$(call MOD_ASTCFLAGS,res_stasis_http_asterisk)
|
||||
|
||||
res_ari_model.so: stasis_http/ari_model_validators.o
|
||||
stasis_http/ari_model_validators.o: _ASTCFLAGS+=$(call MOD_ASTCFLAGS,res_ari_model)
|
||||
|
||||
# Dependencies for res_stasis_http_*.so are generated, so they're in this file
|
||||
include stasis_http.make
|
||||
|
207
res/res_ari_model.c
Normal file
207
res/res_ari_model.c
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Implementation Swagger validators.
|
||||
*
|
||||
* \author David M. Lee, II <dlee@digium.com>
|
||||
*/
|
||||
|
||||
/*** MODULEINFO
|
||||
<support_level>core</support_level>
|
||||
***/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "stasis_http/ari_model_validators.h"
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/utils.h"
|
||||
|
||||
#include <regex.h>
|
||||
|
||||
/* Regex to match date strings */
|
||||
static regex_t date_regex;
|
||||
|
||||
/* Regex for YYYY-MM-DD */
|
||||
#define REGEX_YMD "[0-9]{4}-[01][0-9]-[0-3][0-9]"
|
||||
|
||||
/* Regex for hh:mm(:ss(.s)); seconds and subseconds optional
|
||||
* Handles the probably impossible case of a leap second, too */
|
||||
#define REGEX_HMS "[0-2][0-9]:[0-5][0-9](:[0-6][0-9](.[0-9]+)?)?"
|
||||
|
||||
/* Regex for timezone: (+|-)hh(:mm), with optional colon. */
|
||||
#define REGEX_TZ "(Z|[-+][0-2][0-9](:?[0-5][0-9])?)"
|
||||
|
||||
/* REGEX for ISO 8601, the time specifier optional */
|
||||
#define ISO8601_PATTERN "^" REGEX_YMD "(T" REGEX_HMS REGEX_TZ ")?$"
|
||||
|
||||
static int check_type(struct ast_json *json, enum ast_json_type expected)
|
||||
{
|
||||
enum ast_json_type actual;
|
||||
|
||||
if (!json) {
|
||||
ast_log(LOG_ERROR, "Expected type %s, was NULL\n",
|
||||
ast_json_typename(expected));
|
||||
return 0;
|
||||
}
|
||||
|
||||
actual = ast_json_typeof(json);
|
||||
if (expected != actual) {
|
||||
ast_log(LOG_ERROR, "Expected type %s, was %s\n",
|
||||
ast_json_typename(expected), ast_json_typename(actual));
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int check_range(intmax_t minval, intmax_t maxval, struct ast_json *json)
|
||||
{
|
||||
intmax_t v;
|
||||
|
||||
if (!check_type(json, AST_JSON_INTEGER)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
v = ast_json_integer_get(json);
|
||||
|
||||
if (v < minval || maxval < v) {
|
||||
ast_log(LOG_ERROR, "Value out of range. Expected %jd <= %jd <= %jd\n", minval, v, maxval);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ari_validate_void(struct ast_json *json)
|
||||
{
|
||||
return check_type(json, AST_JSON_NULL);
|
||||
}
|
||||
|
||||
int ari_validate_byte(struct ast_json *json)
|
||||
{
|
||||
/* Java bytes are signed, which accounts for great fun for all */
|
||||
return check_range(-128, 255, json);
|
||||
}
|
||||
|
||||
int ari_validate_boolean(struct ast_json *json)
|
||||
{
|
||||
enum ast_json_type actual = ast_json_typeof(json);
|
||||
switch (actual) {
|
||||
case AST_JSON_TRUE:
|
||||
case AST_JSON_FALSE:
|
||||
return 1;
|
||||
default:
|
||||
ast_log(LOG_ERROR, "Expected type boolean, was %s\n",
|
||||
ast_json_typename(actual));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int ari_validate_int(struct ast_json *json)
|
||||
{
|
||||
/* Swagger int's are 32-bit */
|
||||
return check_range(-2147483648, 2147483647, json);
|
||||
}
|
||||
|
||||
int ari_validate_long(struct ast_json *json)
|
||||
{
|
||||
/* All integral values are valid longs. No need for range check. */
|
||||
return check_type(json, AST_JSON_INTEGER);
|
||||
}
|
||||
|
||||
int ari_validate_float(struct ast_json *json)
|
||||
{
|
||||
return check_type(json, AST_JSON_REAL);
|
||||
}
|
||||
|
||||
int ari_validate_double(struct ast_json *json)
|
||||
{
|
||||
return check_type(json, AST_JSON_REAL);
|
||||
}
|
||||
|
||||
int ari_validate_string(struct ast_json *json)
|
||||
{
|
||||
return check_type(json, AST_JSON_STRING);
|
||||
}
|
||||
|
||||
int ari_validate_date(struct ast_json *json)
|
||||
{
|
||||
/* Dates are ISO-8601 strings */
|
||||
const char *str;
|
||||
if (!check_type(json, AST_JSON_STRING)) {
|
||||
return 0;
|
||||
}
|
||||
str = ast_json_string_get(json);
|
||||
ast_assert(str != NULL);
|
||||
if (regexec(&date_regex, str, 0, NULL, 0) != 0) {
|
||||
ast_log(LOG_ERROR, "Date field is malformed: '%s'\n", str);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ari_validate_list(struct ast_json *json, int (*fn)(struct ast_json *))
|
||||
{
|
||||
int res = 1;
|
||||
size_t i;
|
||||
|
||||
if (!check_type(json, AST_JSON_ARRAY)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < ast_json_array_size(json); ++i) {
|
||||
int member_res;
|
||||
member_res = fn(ast_json_array_get(json, i));
|
||||
if (!member_res) {
|
||||
ast_log(LOG_ERROR,
|
||||
"Array member %zd failed validation\n", i);
|
||||
res = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
{
|
||||
int res;
|
||||
res = regcomp(&date_regex, ISO8601_PATTERN,
|
||||
REG_EXTENDED | REG_ICASE | REG_NOSUB);
|
||||
|
||||
if (res != 0) {
|
||||
return AST_MODULE_LOAD_FAILURE;
|
||||
}
|
||||
return AST_MODULE_LOAD_SUCCESS;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
{
|
||||
regfree(&date_regex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY,
|
||||
AST_MODFLAG_LOAD_ORDER | AST_MODFLAG_GLOBAL_SYMBOLS,
|
||||
"ARI Model validators",
|
||||
.load = load_module,
|
||||
.unload = unload_module,
|
||||
.load_pri = AST_MODPRI_APP_DEPEND,
|
||||
);
|
6
res/res_ari_model.exports.in
Normal file
6
res/res_ari_model.exports.in
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
global:
|
||||
LINKER_SYMBOL_PREFIXari_*;
|
||||
local:
|
||||
*;
|
||||
};
|
294
res/res_stasis.c
294
res/res_stasis.c
@@ -48,7 +48,6 @@
|
||||
*/
|
||||
|
||||
/*** MODULEINFO
|
||||
<depend>res_stasis_json_events</depend>
|
||||
<support_level>core</support_level>
|
||||
***/
|
||||
|
||||
@@ -66,7 +65,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/strings.h"
|
||||
#include "stasis/app.h"
|
||||
#include "stasis/control.h"
|
||||
#include "stasis_json/resource_events.h"
|
||||
|
||||
/*! Time to wait for a frame in the application */
|
||||
#define MAX_WAIT_MS 200
|
||||
@@ -233,28 +231,60 @@ static struct ao2_container *get_apps_watching_channel(const char *uniqueid)
|
||||
/*! \brief Typedef for callbacks that get called on channel snapshot updates */
|
||||
typedef struct ast_json *(*channel_snapshot_monitor)(
|
||||
struct ast_channel_snapshot *old_snapshot,
|
||||
struct ast_channel_snapshot *new_snapshot);
|
||||
struct ast_channel_snapshot *new_snapshot,
|
||||
const struct timeval *tv);
|
||||
|
||||
static struct ast_json *simple_channel_event(
|
||||
const char *type,
|
||||
struct ast_channel_snapshot *snapshot,
|
||||
const struct timeval *tv)
|
||||
{
|
||||
return ast_json_pack("{s: s, s: o, s: o}",
|
||||
"type", type,
|
||||
"timestamp", ast_json_timeval(*tv, NULL),
|
||||
"channel", ast_channel_snapshot_to_json(snapshot));
|
||||
}
|
||||
|
||||
static struct ast_json *channel_created_event(
|
||||
struct ast_channel_snapshot *snapshot,
|
||||
const struct timeval *tv)
|
||||
{
|
||||
return simple_channel_event("ChannelCreated", snapshot, tv);
|
||||
}
|
||||
|
||||
static struct ast_json *channel_destroyed_event(
|
||||
struct ast_channel_snapshot *snapshot,
|
||||
const struct timeval *tv)
|
||||
{
|
||||
return ast_json_pack("{s: s, s: o, s: i, s: s, s: o}",
|
||||
"type", "ChannelDestroyed",
|
||||
"timestamp", ast_json_timeval(*tv, NULL),
|
||||
"cause", snapshot->hangupcause,
|
||||
"cause_txt", ast_cause2str(snapshot->hangupcause),
|
||||
"channel", ast_channel_snapshot_to_json(snapshot));
|
||||
}
|
||||
|
||||
static struct ast_json *channel_state_change_event(
|
||||
struct ast_channel_snapshot *snapshot,
|
||||
const struct timeval *tv)
|
||||
{
|
||||
return simple_channel_event("ChannelStateChange", snapshot, tv);
|
||||
}
|
||||
|
||||
/*! \brief Handle channel state changes */
|
||||
static struct ast_json *channel_state(
|
||||
struct ast_channel_snapshot *old_snapshot,
|
||||
struct ast_channel_snapshot *new_snapshot)
|
||||
struct ast_channel_snapshot *new_snapshot,
|
||||
const struct timeval *tv)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
|
||||
struct ast_channel_snapshot *snapshot = new_snapshot ? new_snapshot : old_snapshot;
|
||||
|
||||
if (!old_snapshot) {
|
||||
return stasis_json_event_channel_created_create(snapshot);
|
||||
return channel_created_event(snapshot, tv);
|
||||
} else if (!new_snapshot) {
|
||||
json = ast_json_pack("{s: i, s: s}",
|
||||
"cause", snapshot->hangupcause,
|
||||
"cause_txt", ast_cause2str(snapshot->hangupcause));
|
||||
if (!json) {
|
||||
return NULL;
|
||||
}
|
||||
return stasis_json_event_channel_destroyed_create(snapshot, json);
|
||||
return channel_destroyed_event(snapshot, tv);
|
||||
} else if (old_snapshot->state != new_snapshot->state) {
|
||||
return stasis_json_event_channel_state_change_create(snapshot);
|
||||
return channel_state_change_event(snapshot, tv);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -262,7 +292,8 @@ static struct ast_json *channel_state(
|
||||
|
||||
static struct ast_json *channel_dialplan(
|
||||
struct ast_channel_snapshot *old_snapshot,
|
||||
struct ast_channel_snapshot *new_snapshot)
|
||||
struct ast_channel_snapshot *new_snapshot,
|
||||
const struct timeval *tv)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
|
||||
|
||||
@@ -280,19 +311,18 @@ static struct ast_json *channel_dialplan(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
json = ast_json_pack("{s: s, s: s}",
|
||||
"application", new_snapshot->appl,
|
||||
"application_data", new_snapshot->data);
|
||||
if (!json) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return stasis_json_event_channel_dialplan_create(new_snapshot, json);
|
||||
return ast_json_pack("{s: s, s: o, s: s, s: s, s: o}",
|
||||
"type", "ChannelDialplan",
|
||||
"timestamp", ast_json_timeval(*tv, NULL),
|
||||
"dialplan_app", new_snapshot->appl,
|
||||
"dialplan_app_data", new_snapshot->data,
|
||||
"channel", ast_channel_snapshot_to_json(new_snapshot));
|
||||
}
|
||||
|
||||
static struct ast_json *channel_callerid(
|
||||
struct ast_channel_snapshot *old_snapshot,
|
||||
struct ast_channel_snapshot *new_snapshot)
|
||||
struct ast_channel_snapshot *new_snapshot,
|
||||
const struct timeval *tv)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
|
||||
|
||||
@@ -305,29 +335,16 @@ static struct ast_json *channel_callerid(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
json = ast_json_pack("{s: i, s: s}",
|
||||
return ast_json_pack("{s: s, s: o, s: i, s: s, s: o}",
|
||||
"type", "ChannelCallerId",
|
||||
"timestamp", ast_json_timeval(*tv, NULL),
|
||||
"caller_presentation", new_snapshot->caller_pres,
|
||||
"caller_presentation_txt", ast_describe_caller_presentation(new_snapshot->caller_pres));
|
||||
if (!json) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return stasis_json_event_channel_caller_id_create(new_snapshot, json);
|
||||
}
|
||||
|
||||
static struct ast_json *channel_snapshot(
|
||||
struct ast_channel_snapshot *old_snapshot,
|
||||
struct ast_channel_snapshot *new_snapshot)
|
||||
{
|
||||
if (!new_snapshot) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return stasis_json_event_channel_snapshot_create(new_snapshot);
|
||||
"caller_presentation_txt", ast_describe_caller_presentation(
|
||||
new_snapshot->caller_pres),
|
||||
"channel", ast_channel_snapshot_to_json(new_snapshot));
|
||||
}
|
||||
|
||||
channel_snapshot_monitor channel_monitors[] = {
|
||||
channel_snapshot,
|
||||
channel_state,
|
||||
channel_dialplan,
|
||||
channel_callerid
|
||||
@@ -351,6 +368,9 @@ static void sub_channel_snapshot_handler(void *data,
|
||||
struct stasis_cache_update *update = stasis_message_data(message);
|
||||
struct ast_channel_snapshot *new_snapshot = stasis_message_data(update->new_snapshot);
|
||||
struct ast_channel_snapshot *old_snapshot = stasis_message_data(update->old_snapshot);
|
||||
/* Pull timestamp from the new snapshot, or from the update message
|
||||
* when there isn't one. */
|
||||
const struct timeval *tv = update->new_snapshot ? stasis_message_timestamp(update->new_snapshot) : stasis_message_timestamp(message);
|
||||
int i;
|
||||
|
||||
watching_apps = get_apps_watching_channel(new_snapshot ? new_snapshot->uniqueid : old_snapshot->uniqueid);
|
||||
@@ -361,7 +381,7 @@ static void sub_channel_snapshot_handler(void *data,
|
||||
for (i = 0; i < ARRAY_LEN(channel_monitors); ++i) {
|
||||
RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);
|
||||
|
||||
msg = channel_monitors[i](old_snapshot, new_snapshot);
|
||||
msg = channel_monitors[i](old_snapshot, new_snapshot, tv);
|
||||
if (msg) {
|
||||
ao2_callback(watching_apps, OBJ_NODATA, app_send_cb, msg);
|
||||
}
|
||||
@@ -373,22 +393,26 @@ static void distribute_message(struct ao2_container *apps, struct ast_json *msg)
|
||||
ao2_callback(apps, OBJ_NODATA, app_send_cb, msg);
|
||||
}
|
||||
|
||||
static void generic_blob_handler(struct ast_channel_blob *obj, channel_blob_handler_cb handler_cb)
|
||||
static void sub_channel_blob_handler(void *data,
|
||||
struct stasis_subscription *sub,
|
||||
struct stasis_topic *topic,
|
||||
struct stasis_message *message)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ao2_container *, watching_apps, NULL, ao2_cleanup);
|
||||
struct ast_channel_blob *obj = stasis_message_data(message);
|
||||
|
||||
if (!obj->snapshot) {
|
||||
return;
|
||||
}
|
||||
|
||||
watching_apps = get_apps_watching_channel(obj->snapshot->uniqueid);
|
||||
if (!watching_apps) {
|
||||
msg = stasis_message_to_json(message);
|
||||
if (!msg) {
|
||||
return;
|
||||
}
|
||||
|
||||
msg = handler_cb(obj);
|
||||
if (!msg) {
|
||||
watching_apps = get_apps_watching_channel(obj->snapshot->uniqueid);
|
||||
if (!watching_apps) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -446,7 +470,6 @@ int app_send_start_msg(struct app *app, struct ast_channel *chan,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
|
||||
|
||||
struct ast_json *json_args;
|
||||
@@ -460,13 +483,16 @@ int app_send_start_msg(struct app *app, struct ast_channel *chan,
|
||||
return -1;
|
||||
}
|
||||
|
||||
blob = ast_json_pack("{s: []}", "args");
|
||||
if (!blob) {
|
||||
msg = ast_json_pack("{s: s, s: [], s: o}",
|
||||
"type", "StasisStart",
|
||||
"args",
|
||||
"channel", ast_channel_snapshot_to_json(snapshot));
|
||||
if (!msg) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Append arguments to args array */
|
||||
json_args = ast_json_object_get(blob, "args");
|
||||
json_args = ast_json_object_get(msg, "args");
|
||||
ast_assert(json_args != NULL);
|
||||
for (i = 0; i < argc; ++i) {
|
||||
int r = ast_json_array_append(json_args,
|
||||
@@ -477,11 +503,6 @@ int app_send_start_msg(struct app *app, struct ast_channel *chan,
|
||||
}
|
||||
}
|
||||
|
||||
msg = stasis_json_event_stasis_start_create(snapshot, blob);
|
||||
if (!msg) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
app_send(app, msg);
|
||||
return 0;
|
||||
}
|
||||
@@ -499,7 +520,9 @@ int app_send_end_msg(struct app *app, struct ast_channel *chan)
|
||||
return -1;
|
||||
}
|
||||
|
||||
msg = stasis_json_event_stasis_end_create(snapshot);
|
||||
msg = ast_json_pack("{s: s, s: o}",
|
||||
"type", "StasisEnd",
|
||||
"channel", ast_channel_snapshot_to_json(snapshot));
|
||||
if (!msg) {
|
||||
return -1;
|
||||
}
|
||||
@@ -633,15 +656,13 @@ int stasis_app_register(const char *app_name, stasis_app_cb handler, void *data)
|
||||
app = ao2_find(apps_registry, app_name, OBJ_KEY | OBJ_NOLOCK);
|
||||
|
||||
if (app) {
|
||||
RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);
|
||||
|
||||
blob = ast_json_pack("{s: s}", "application", app_name);
|
||||
if (blob) {
|
||||
msg = stasis_json_event_application_replaced_create(blob);
|
||||
if (msg) {
|
||||
app_send(app, msg);
|
||||
}
|
||||
msg = ast_json_pack("{s: s, s: s}",
|
||||
"type", "ApplicationReplaced",
|
||||
"application", app_name);
|
||||
if (msg) {
|
||||
app_send(app, msg);
|
||||
}
|
||||
|
||||
app_update(app, handler, data);
|
||||
@@ -665,82 +686,6 @@ void stasis_app_unregister(const char *app_name)
|
||||
}
|
||||
}
|
||||
|
||||
static struct ast_json *handle_blob_dtmf(struct ast_channel_blob *obj)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);
|
||||
const char *direction;
|
||||
|
||||
/* To simplify events, we'll only generate on receive */
|
||||
direction = ast_json_string_get(
|
||||
ast_json_object_get(obj->blob, "direction"));
|
||||
|
||||
if (strcmp("Received", direction) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extra = ast_json_pack(
|
||||
"{s: o}",
|
||||
"digit", ast_json_ref(ast_json_object_get(obj->blob, "digit")));
|
||||
if (!extra) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return stasis_json_event_channel_dtmf_received_create(obj->snapshot, extra);
|
||||
}
|
||||
|
||||
/* To simplify events, we'll only generate on DTMF end (dtmf_end type) */
|
||||
static void sub_dtmf_handler(void *data,
|
||||
struct stasis_subscription *sub,
|
||||
struct stasis_topic *topic,
|
||||
struct stasis_message *message)
|
||||
{
|
||||
struct ast_channel_blob *obj = stasis_message_data(message);
|
||||
generic_blob_handler(obj, handle_blob_dtmf);
|
||||
}
|
||||
|
||||
static struct ast_json *handle_blob_userevent(struct ast_channel_blob *obj)
|
||||
{
|
||||
return stasis_json_event_channel_userevent_create(obj->snapshot, obj->blob);
|
||||
}
|
||||
|
||||
static void sub_userevent_handler(void *data,
|
||||
struct stasis_subscription *sub,
|
||||
struct stasis_topic *topic,
|
||||
struct stasis_message *message)
|
||||
{
|
||||
struct ast_channel_blob *obj = stasis_message_data(message);
|
||||
generic_blob_handler(obj, handle_blob_userevent);
|
||||
}
|
||||
|
||||
static struct ast_json *handle_blob_hangup_request(struct ast_channel_blob *obj)
|
||||
{
|
||||
return stasis_json_event_channel_hangup_request_create(obj->snapshot, obj->blob);
|
||||
}
|
||||
|
||||
static void sub_hangup_request_handler(void *data,
|
||||
struct stasis_subscription *sub,
|
||||
struct stasis_topic *topic,
|
||||
struct stasis_message *message)
|
||||
{
|
||||
struct ast_channel_blob *obj = stasis_message_data(message);
|
||||
generic_blob_handler(obj, handle_blob_hangup_request);
|
||||
}
|
||||
|
||||
static struct ast_json *handle_blob_varset(struct ast_channel_blob *obj)
|
||||
{
|
||||
return stasis_json_event_channel_varset_create(obj->snapshot, obj->blob);
|
||||
}
|
||||
|
||||
static void sub_varset_handler(void *data,
|
||||
struct stasis_subscription *sub,
|
||||
struct stasis_topic *topic,
|
||||
struct stasis_message *message)
|
||||
{
|
||||
struct ast_channel_blob *obj = stasis_message_data(message);
|
||||
generic_blob_handler(obj, handle_blob_varset);
|
||||
}
|
||||
|
||||
void stasis_app_ref(void)
|
||||
{
|
||||
ast_module_ref(ast_module_info->self);
|
||||
@@ -788,6 +733,30 @@ static int remove_bridge_cb(void *obj, void *arg, int flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ast_json *simple_bridge_event(
|
||||
const char *type,
|
||||
struct ast_bridge_snapshot *snapshot,
|
||||
const struct timeval *tv)
|
||||
{
|
||||
return ast_json_pack("{s: s, s: o, s: o}",
|
||||
"type", type,
|
||||
"timestamp", ast_json_timeval(*tv, NULL),
|
||||
"bridge", ast_bridge_snapshot_to_json(snapshot));
|
||||
}
|
||||
|
||||
static struct ast_json *simple_bridge_channel_event(
|
||||
const char *type,
|
||||
struct ast_bridge_snapshot *bridge_snapshot,
|
||||
struct ast_channel_snapshot *channel_snapshot,
|
||||
const struct timeval *tv)
|
||||
{
|
||||
return ast_json_pack("{s: s, s: o, s: o}",
|
||||
"type", type,
|
||||
"timestamp", ast_json_timeval(*tv, NULL),
|
||||
"bridge", ast_bridge_snapshot_to_json(bridge_snapshot),
|
||||
"channel", ast_channel_snapshot_to_json(channel_snapshot));
|
||||
}
|
||||
|
||||
static void sub_bridge_snapshot_handler(void *data,
|
||||
struct stasis_subscription *sub,
|
||||
struct stasis_topic *topic,
|
||||
@@ -797,6 +766,8 @@ static void sub_bridge_snapshot_handler(void *data,
|
||||
struct stasis_cache_update *update = stasis_message_data(message);
|
||||
struct ast_bridge_snapshot *new_snapshot = stasis_message_data(update->new_snapshot);
|
||||
struct ast_bridge_snapshot *old_snapshot = stasis_message_data(update->old_snapshot);
|
||||
const struct timeval *tv = update->new_snapshot ? stasis_message_timestamp(update->new_snapshot) : stasis_message_timestamp(message);
|
||||
|
||||
RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);
|
||||
|
||||
watching_apps = get_apps_watching_bridge(new_snapshot ? new_snapshot->uniqueid : old_snapshot->uniqueid);
|
||||
@@ -810,11 +781,11 @@ static void sub_bridge_snapshot_handler(void *data,
|
||||
/* The bridge has gone away. Create the message, make sure no apps are
|
||||
* watching this bridge anymore, and destroy the bridge's control
|
||||
* structure */
|
||||
msg = stasis_json_event_bridge_destroyed_create(old_snapshot);
|
||||
msg = simple_bridge_event("BridgeDestroyed", old_snapshot, tv);
|
||||
ao2_callback(watching_apps, OBJ_NODATA, remove_bridge_cb, bridge_id);
|
||||
stasis_app_bridge_destroy(old_snapshot->uniqueid);
|
||||
} else if (!old_snapshot) {
|
||||
msg = stasis_json_event_bridge_created_create(old_snapshot);
|
||||
msg = simple_bridge_event("BridgeCreated", old_snapshot, tv);
|
||||
}
|
||||
|
||||
if (!msg) {
|
||||
@@ -865,6 +836,7 @@ static void sub_bridge_merge_handler(void *data,
|
||||
struct ast_bridge_merge_message *merge = stasis_message_data(message);
|
||||
RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
|
||||
const struct timeval *tv = stasis_message_timestamp(message);
|
||||
|
||||
watching_apps_to = get_apps_watching_bridge(merge->to->uniqueid);
|
||||
if (watching_apps_to) {
|
||||
@@ -881,16 +853,16 @@ static void sub_bridge_merge_handler(void *data,
|
||||
return;
|
||||
}
|
||||
|
||||
/* The secondary bridge has to be packed into JSON by hand because the auto-generated
|
||||
* JSON event generator can only handle one instance of a given snapshot type in an
|
||||
* elegant way */
|
||||
blob = ast_json_pack("{s: o}", "bridge_from", ast_bridge_snapshot_to_json(merge->from));
|
||||
if (!blob) {
|
||||
msg = ast_json_pack("{s: s, s: o, s: o, s: o}",
|
||||
"type", "BridgeMerged",
|
||||
"timestamp", ast_json_timeval(*tv, NULL),
|
||||
"bridge", ast_bridge_snapshot_to_json(merge->to),
|
||||
"bridge_from", ast_bridge_snapshot_to_json(merge->from));
|
||||
|
||||
if (!msg) {
|
||||
return;
|
||||
}
|
||||
|
||||
msg = stasis_json_event_bridge_merged_create(merge->to, blob);
|
||||
|
||||
distribute_message(watching_apps_all, msg);
|
||||
}
|
||||
|
||||
@@ -920,7 +892,8 @@ static void sub_bridge_enter_handler(void *data,
|
||||
return;
|
||||
}
|
||||
|
||||
msg = stasis_json_event_channel_entered_bridge_create(obj->bridge, obj->channel);
|
||||
msg = simple_bridge_channel_event("ChannelEnteredBridge", obj->bridge,
|
||||
obj->channel, stasis_message_timestamp(message));
|
||||
|
||||
distribute_message(watching_apps_all, msg);
|
||||
}
|
||||
@@ -939,7 +912,8 @@ static void sub_bridge_leave_handler(void *data,
|
||||
return;
|
||||
}
|
||||
|
||||
msg = stasis_json_event_channel_left_bridge_create(obj->bridge, obj->channel);
|
||||
msg = simple_bridge_channel_event("ChannelLeftBridge", obj->bridge,
|
||||
obj->channel, stasis_message_timestamp(message));
|
||||
|
||||
distribute_message(watching_apps_bridge, msg);
|
||||
}
|
||||
@@ -972,10 +946,16 @@ static int load_module(void)
|
||||
}
|
||||
|
||||
r |= stasis_message_router_add(channel_router, stasis_cache_update_type(), sub_channel_snapshot_handler, NULL);
|
||||
r |= stasis_message_router_add(channel_router, ast_channel_user_event_type(), sub_userevent_handler, NULL);
|
||||
r |= stasis_message_router_add(channel_router, ast_channel_varset_type(), sub_varset_handler, NULL);
|
||||
r |= stasis_message_router_add(channel_router, ast_channel_dtmf_begin_type(), sub_dtmf_handler, NULL);
|
||||
r |= stasis_message_router_add(channel_router, ast_channel_hangup_request_type(), sub_hangup_request_handler, NULL);
|
||||
/* TODO: This could be handled a lot better. Instead of subscribing to
|
||||
* the one caching topic and filtering out messages by channel id, we
|
||||
* should have individual caching topics per-channel, with a shared
|
||||
* back-end cache. That would simplify a lot of what's going on right
|
||||
* here.
|
||||
*/
|
||||
r |= stasis_message_router_add(channel_router, ast_channel_user_event_type(), sub_channel_blob_handler, NULL);
|
||||
r |= stasis_message_router_add(channel_router, ast_channel_varset_type(), sub_channel_blob_handler, NULL);
|
||||
r |= stasis_message_router_add(channel_router, ast_channel_dtmf_end_type(), sub_channel_blob_handler, NULL);
|
||||
r |= stasis_message_router_add(channel_router, ast_channel_hangup_request_type(), sub_channel_blob_handler, NULL);
|
||||
if (r) {
|
||||
return AST_MODULE_LOAD_FAILURE;
|
||||
}
|
||||
|
@@ -324,7 +324,7 @@ void stasis_http_response_ok(struct stasis_http_response *response,
|
||||
|
||||
void stasis_http_response_no_content(struct stasis_http_response *response)
|
||||
{
|
||||
response->message = NULL;
|
||||
response->message = ast_json_null();
|
||||
response->response_code = 204;
|
||||
response->response_text = "No Content";
|
||||
}
|
||||
@@ -386,9 +386,7 @@ static void handle_options(struct stasis_rest_handlers *handler,
|
||||
|
||||
/* Regular OPTIONS response */
|
||||
add_allow_header(handler, response);
|
||||
response->response_code = 204;
|
||||
response->response_text = "No Content";
|
||||
response->message = NULL;
|
||||
stasis_http_response_no_content(response);
|
||||
|
||||
/* Parse CORS headers */
|
||||
for (header = headers; header != NULL; header = header->next) {
|
||||
@@ -797,6 +795,11 @@ static void process_cors_request(struct ast_variable *headers,
|
||||
*/
|
||||
}
|
||||
|
||||
enum ast_json_encoding_format stasis_http_json_format(void)
|
||||
{
|
||||
RAII_VAR(struct conf *, cfg, ao2_global_obj_ref(confs), ao2_cleanup);
|
||||
return cfg->global->format;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
@@ -819,7 +822,6 @@ static int stasis_http_callback(struct ast_tcptls_session_instance *ser,
|
||||
struct ast_variable *get_params,
|
||||
struct ast_variable *headers)
|
||||
{
|
||||
RAII_VAR(struct conf *, cfg, ao2_global_obj_ref(confs), ao2_cleanup);
|
||||
RAII_VAR(struct ast_str *, response_headers, ast_str_create(40), ast_free);
|
||||
RAII_VAR(struct ast_str *, response_body, ast_str_create(256), ast_free);
|
||||
struct stasis_http_response response = {};
|
||||
@@ -859,11 +861,10 @@ static int stasis_http_callback(struct ast_tcptls_session_instance *ser,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Leaving message unset is only allowed for 204 (No Content).
|
||||
* If you explicitly want to have no content for a different return
|
||||
* code, set message to ast_json_null().
|
||||
/* If you explicitly want to have no content, set message to
|
||||
* ast_json_null().
|
||||
*/
|
||||
ast_assert(response.response_code == 204 || response.message != NULL);
|
||||
ast_assert(response.message != NULL);
|
||||
ast_assert(response.response_code > 0);
|
||||
|
||||
ast_str_append(&response_headers, 0, "%s", ast_str_buffer(response.headers));
|
||||
@@ -874,7 +875,7 @@ static int stasis_http_callback(struct ast_tcptls_session_instance *ser,
|
||||
if (response.message && !ast_json_is_null(response.message)) {
|
||||
ast_str_append(&response_headers, 0,
|
||||
"Content-type: application/json\r\n");
|
||||
if (ast_json_dump_str_format(response.message, &response_body, cfg->global->format) != 0) {
|
||||
if (ast_json_dump_str_format(response.message, &response_body, stasis_http_json_format()) != 0) {
|
||||
/* Error encoding response */
|
||||
response.response_code = 500;
|
||||
response.response_text = "Internal Server Error";
|
||||
|
@@ -44,6 +44,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/stasis_app.h"
|
||||
#include "stasis_http/resource_asterisk.h"
|
||||
#if defined(AST_DEVMODE)
|
||||
#include "stasis_http/ari_model_validators.h"
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /asterisk/info.
|
||||
@@ -53,9 +56,14 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_get_asterisk_info_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_get_asterisk_info_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -66,6 +74,29 @@ static void stasis_http_get_asterisk_info_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_get_asterisk_info(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_asterisk_info(
|
||||
response->message);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/info\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /asterisk/info\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
|
||||
/*! \brief REST handler for /api-docs/asterisk.{format} */
|
||||
|
@@ -44,6 +44,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/stasis_app.h"
|
||||
#include "stasis_http/resource_bridges.h"
|
||||
#if defined(AST_DEVMODE)
|
||||
#include "stasis_http/ari_model_validators.h"
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /bridges.
|
||||
@@ -53,11 +56,39 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_get_bridges_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_get_bridges_args args = {};
|
||||
stasis_http_get_bridges(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_list(response->message,
|
||||
ari_validate_bridge);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /bridges\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /bridges\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /bridges.
|
||||
@@ -67,9 +98,14 @@ static void stasis_http_get_bridges_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_new_bridge_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_new_bridge_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -80,6 +116,29 @@ static void stasis_http_new_bridge_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_new_bridge(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_bridge(
|
||||
response->message);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /bridges\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /bridges\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /bridges/{bridgeId}.
|
||||
@@ -89,9 +148,14 @@ static void stasis_http_new_bridge_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_get_bridge_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_get_bridge_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -102,6 +166,30 @@ static void stasis_http_get_bridge_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_get_bridge(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
case 404: /* Bridge not found */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_bridge(
|
||||
response->message);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /bridges/{bridgeId}.
|
||||
@@ -111,9 +199,14 @@ static void stasis_http_get_bridge_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_delete_bridge_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_delete_bridge_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -124,6 +217,30 @@ static void stasis_http_delete_bridge_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_delete_bridge(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
case 404: /* Bridge not found */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_void(
|
||||
response->message);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /bridges/{bridgeId}/addChannel.
|
||||
@@ -133,9 +250,14 @@ static void stasis_http_delete_bridge_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_add_channel_to_bridge_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_add_channel_to_bridge_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -152,6 +274,32 @@ static void stasis_http_add_channel_to_bridge_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_add_channel_to_bridge(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
case 404: /* Bridge not found */
|
||||
case 409: /* Bridge not in Stasis application */
|
||||
case 422: /* Channel not found, or not in Stasis application */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_void(
|
||||
response->message);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/addChannel\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/addChannel\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /bridges/{bridgeId}/removeChannel.
|
||||
@@ -161,9 +309,14 @@ static void stasis_http_add_channel_to_bridge_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_remove_channel_from_bridge_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_remove_channel_from_bridge_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -180,6 +333,29 @@ static void stasis_http_remove_channel_from_bridge_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_remove_channel_from_bridge(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_void(
|
||||
response->message);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/removeChannel\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/removeChannel\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /bridges/{bridgeId}/record.
|
||||
@@ -189,9 +365,14 @@ static void stasis_http_remove_channel_from_bridge_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_record_bridge_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_record_bridge_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -223,6 +404,29 @@ static void stasis_http_record_bridge_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_record_bridge(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_live_recording(
|
||||
response->message);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/record\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/record\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
|
||||
/*! \brief REST handler for /api-docs/bridges.{format} */
|
||||
|
@@ -44,6 +44,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/stasis_app.h"
|
||||
#include "stasis_http/resource_channels.h"
|
||||
#if defined(AST_DEVMODE)
|
||||
#include "stasis_http/ari_model_validators.h"
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /channels.
|
||||
@@ -53,11 +56,39 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_get_channels_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_get_channels_args args = {};
|
||||
stasis_http_get_channels(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_list(response->message,
|
||||
ari_validate_channel);
|
||||
} 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");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /channels.
|
||||
@@ -67,9 +98,14 @@ static void stasis_http_get_channels_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_originate_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_originate_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -101,6 +137,29 @@ static void stasis_http_originate_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_originate(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_void(
|
||||
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");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /channels/{channelId}.
|
||||
@@ -110,9 +169,14 @@ static void stasis_http_originate_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_get_channel_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_get_channel_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -123,6 +187,30 @@ static void stasis_http_get_channel_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_get_channel(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
case 404: /* Channel not found */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = 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");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /channels/{channelId}.
|
||||
@@ -132,9 +220,14 @@ static void stasis_http_get_channel_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_delete_channel_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_delete_channel_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -145,6 +238,30 @@ static void stasis_http_delete_channel_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_delete_channel(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
case 404: /* Channel not found */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = 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");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /channels/{channelId}/dial.
|
||||
@@ -154,9 +271,14 @@ static void stasis_http_delete_channel_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_dial_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_dial_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -182,6 +304,31 @@ static void stasis_http_dial_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_dial(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
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 = ari_validate_dialed(
|
||||
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");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /channels/{channelId}/continue.
|
||||
@@ -191,9 +338,14 @@ static void stasis_http_dial_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_continue_in_dialplan_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_continue_in_dialplan_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -216,6 +368,31 @@ static void stasis_http_continue_in_dialplan_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_continue_in_dialplan(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
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 = 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");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /channels/{channelId}/answer.
|
||||
@@ -225,9 +402,14 @@ static void stasis_http_continue_in_dialplan_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_answer_channel_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_answer_channel_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -238,6 +420,31 @@ static void stasis_http_answer_channel_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_answer_channel(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
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 = 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");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /channels/{channelId}/mute.
|
||||
@@ -247,9 +454,14 @@ static void stasis_http_answer_channel_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_mute_channel_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_mute_channel_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -266,6 +478,31 @@ static void stasis_http_mute_channel_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_mute_channel(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
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 = 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");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /channels/{channelId}/unmute.
|
||||
@@ -275,9 +512,14 @@ static void stasis_http_mute_channel_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_unmute_channel_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_unmute_channel_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -294,6 +536,31 @@ static void stasis_http_unmute_channel_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_unmute_channel(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
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 = ari_validate_void(
|
||||
response->message);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/unmute\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/unmute\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /channels/{channelId}/hold.
|
||||
@@ -303,9 +570,14 @@ static void stasis_http_unmute_channel_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_hold_channel_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_hold_channel_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -316,6 +588,31 @@ static void stasis_http_hold_channel_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_hold_channel(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
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 = 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");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /channels/{channelId}/unhold.
|
||||
@@ -325,9 +622,14 @@ static void stasis_http_hold_channel_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_unhold_channel_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_unhold_channel_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -338,6 +640,31 @@ static void stasis_http_unhold_channel_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_unhold_channel(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
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 = ari_validate_void(
|
||||
response->message);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/unhold\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/unhold\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /channels/{channelId}/play.
|
||||
@@ -347,9 +674,14 @@ static void stasis_http_unhold_channel_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_play_on_channel_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_play_on_channel_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -375,6 +707,31 @@ static void stasis_http_play_on_channel_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_play_on_channel(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
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 = 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");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /channels/{channelId}/record.
|
||||
@@ -384,9 +741,14 @@ static void stasis_http_play_on_channel_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_record_channel_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_record_channel_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -421,6 +783,31 @@ static void stasis_http_record_channel_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_record_channel(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
case 404: /* Channel not found */
|
||||
case 409: /* Channel is not in a Stasis application, or the channel is currently bridged with other channels. */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_void(
|
||||
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");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
|
||||
/*! \brief REST handler for /api-docs/channels.{format} */
|
||||
|
@@ -44,6 +44,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/stasis_app.h"
|
||||
#include "stasis_http/resource_endpoints.h"
|
||||
#if defined(AST_DEVMODE)
|
||||
#include "stasis_http/ari_model_validators.h"
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /endpoints.
|
||||
@@ -53,11 +56,39 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_get_endpoints_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_get_endpoints_args args = {};
|
||||
stasis_http_get_endpoints(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_list(response->message,
|
||||
ari_validate_endpoint);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /endpoints\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /endpoints\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /endpoints/{tech}.
|
||||
@@ -67,9 +98,14 @@ static void stasis_http_get_endpoints_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_get_endpoints_by_tech_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_get_endpoints_by_tech_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -80,6 +116,29 @@ static void stasis_http_get_endpoints_by_tech_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_get_endpoints_by_tech(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_list(response->message,
|
||||
ari_validate_endpoint);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /endpoints/{tech}\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /endpoints/{tech}\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /endpoints/{tech}/{resource}.
|
||||
@@ -89,9 +148,14 @@ static void stasis_http_get_endpoints_by_tech_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_get_endpoint_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_get_endpoint_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -105,6 +169,29 @@ static void stasis_http_get_endpoint_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_get_endpoint(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_endpoint(
|
||||
response->message);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /endpoints/{tech}/{resource}\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /endpoints/{tech}/{resource}\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
|
||||
/*! \brief REST handler for /api-docs/endpoints.{format} */
|
||||
|
@@ -44,6 +44,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/stasis_app.h"
|
||||
#include "stasis_http/resource_events.h"
|
||||
#if defined(AST_DEVMODE)
|
||||
#include "stasis_http/ari_model_validators.h"
|
||||
#endif
|
||||
|
||||
static void stasis_http_event_websocket_ws_cb(struct ast_websocket *ws_session,
|
||||
struct ast_variable *get_params, struct ast_variable *headers)
|
||||
@@ -59,7 +62,12 @@ static void stasis_http_event_websocket_ws_cb(struct ast_websocket *ws_session,
|
||||
} else
|
||||
{}
|
||||
}
|
||||
session = ari_websocket_session_create(ws_session);
|
||||
#if defined(AST_DEVMODE)
|
||||
session = ari_websocket_session_create(ws_session,
|
||||
ari_validate_event);
|
||||
#else
|
||||
session = ari_websocket_session_create(ws_session, NULL);
|
||||
#endif
|
||||
if (!session) {
|
||||
ast_log(LOG_ERROR, "Failed to create ARI session\n");
|
||||
return;
|
||||
|
@@ -44,6 +44,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/stasis_app.h"
|
||||
#include "stasis_http/resource_playback.h"
|
||||
#if defined(AST_DEVMODE)
|
||||
#include "stasis_http/ari_model_validators.h"
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /playback/{playbackId}.
|
||||
@@ -53,9 +56,14 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_get_playback_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_get_playback_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -66,6 +74,29 @@ static void stasis_http_get_playback_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_get_playback(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_playback(
|
||||
response->message);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /playback/{playbackId}\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /playback/{playbackId}\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /playback/{playbackId}.
|
||||
@@ -75,9 +106,14 @@ static void stasis_http_get_playback_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_stop_playback_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_stop_playback_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -88,6 +124,29 @@ static void stasis_http_stop_playback_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_stop_playback(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_playback(
|
||||
response->message);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /playback/{playbackId}\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /playback/{playbackId}\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /playback/{playbackId}/control.
|
||||
@@ -97,9 +156,14 @@ static void stasis_http_stop_playback_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_control_playback_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_control_playback_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -116,6 +180,32 @@ static void stasis_http_control_playback_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_control_playback(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
case 400: /* The provided operation parameter was invalid */
|
||||
case 404: /* The playback cannot be found */
|
||||
case 409: /* The operation cannot be performed in the playback's current state */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_playback(
|
||||
response->message);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /playback/{playbackId}/control\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /playback/{playbackId}/control\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
|
||||
/*! \brief REST handler for /api-docs/playback.{format} */
|
||||
|
@@ -44,21 +44,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/stasis_app.h"
|
||||
#include "stasis_http/resource_recordings.h"
|
||||
#if defined(AST_DEVMODE)
|
||||
#include "stasis_http/ari_model_validators.h"
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /recordings.
|
||||
* \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 stasis_http_get_recordings_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
struct ast_get_recordings_args args = {};
|
||||
stasis_http_get_recordings(headers, &args, response);
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /recordings/stored.
|
||||
* \param get_params GET parameters in the HTTP request.
|
||||
@@ -67,11 +56,39 @@ static void stasis_http_get_recordings_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_get_stored_recordings_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_get_stored_recordings_args args = {};
|
||||
stasis_http_get_stored_recordings(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_list(response->message,
|
||||
ari_validate_stored_recording);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /recordings/stored\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /recordings/stored\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /recordings/stored/{recordingId}.
|
||||
@@ -81,9 +98,14 @@ static void stasis_http_get_stored_recordings_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_get_stored_recording_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_get_stored_recording_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -94,6 +116,29 @@ static void stasis_http_get_stored_recording_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_get_stored_recording(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_stored_recording(
|
||||
response->message);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /recordings/stored/{recordingId}\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /recordings/stored/{recordingId}\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /recordings/stored/{recordingId}.
|
||||
@@ -103,9 +148,14 @@ static void stasis_http_get_stored_recording_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_delete_stored_recording_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_delete_stored_recording_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -116,6 +166,29 @@ static void stasis_http_delete_stored_recording_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_delete_stored_recording(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_void(
|
||||
response->message);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /recordings/stored/{recordingId}\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /recordings/stored/{recordingId}\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /recordings/live.
|
||||
@@ -125,11 +198,39 @@ static void stasis_http_delete_stored_recording_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_get_live_recordings_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_get_live_recordings_args args = {};
|
||||
stasis_http_get_live_recordings(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_list(response->message,
|
||||
ari_validate_live_recording);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /recordings/live\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /recordings/live\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /recordings/live/{recordingId}.
|
||||
@@ -139,9 +240,14 @@ static void stasis_http_get_live_recordings_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_get_live_recording_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_get_live_recording_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -152,6 +258,29 @@ static void stasis_http_get_live_recording_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_get_live_recording(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_live_recording(
|
||||
response->message);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /recordings/live/{recordingId}\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /recordings/live/{recordingId}\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /recordings/live/{recordingId}.
|
||||
@@ -161,9 +290,14 @@ static void stasis_http_get_live_recording_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_cancel_recording_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_cancel_recording_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -174,6 +308,29 @@ static void stasis_http_cancel_recording_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_cancel_recording(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_void(
|
||||
response->message);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /recordings/live/{recordingId}\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /recordings/live/{recordingId}\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /recordings/live/{recordingId}/stop.
|
||||
@@ -183,9 +340,14 @@ static void stasis_http_cancel_recording_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_stop_recording_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_stop_recording_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -196,6 +358,29 @@ static void stasis_http_stop_recording_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_stop_recording(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_void(
|
||||
response->message);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /recordings/live/{recordingId}/stop\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /recordings/live/{recordingId}/stop\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /recordings/live/{recordingId}/pause.
|
||||
@@ -205,9 +390,14 @@ static void stasis_http_stop_recording_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_pause_recording_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_pause_recording_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -218,6 +408,29 @@ static void stasis_http_pause_recording_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_pause_recording(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_void(
|
||||
response->message);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /recordings/live/{recordingId}/pause\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /recordings/live/{recordingId}/pause\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /recordings/live/{recordingId}/unpause.
|
||||
@@ -227,9 +440,14 @@ static void stasis_http_pause_recording_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_unpause_recording_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_unpause_recording_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -240,6 +458,29 @@ static void stasis_http_unpause_recording_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_unpause_recording(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_void(
|
||||
response->message);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /recordings/live/{recordingId}/unpause\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /recordings/live/{recordingId}/unpause\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /recordings/live/{recordingId}/mute.
|
||||
@@ -249,9 +490,14 @@ static void stasis_http_unpause_recording_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_mute_recording_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_mute_recording_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -262,6 +508,29 @@ static void stasis_http_mute_recording_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_mute_recording(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_void(
|
||||
response->message);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /recordings/live/{recordingId}/mute\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /recordings/live/{recordingId}/mute\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /recordings/live/{recordingId}/unmute.
|
||||
@@ -271,9 +540,14 @@ static void stasis_http_mute_recording_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_unmute_recording_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_unmute_recording_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -284,6 +558,29 @@ static void stasis_http_unmute_recording_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_unmute_recording(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_void(
|
||||
response->message);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /recordings/live/{recordingId}/unmute\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /recordings/live/{recordingId}/unmute\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
|
||||
/*! \brief REST handler for /api-docs/recordings.{format} */
|
||||
@@ -375,7 +672,6 @@ static struct stasis_rest_handlers recordings_live = {
|
||||
static struct stasis_rest_handlers recordings = {
|
||||
.path_segment = "recordings",
|
||||
.callbacks = {
|
||||
[AST_HTTP_GET] = stasis_http_get_recordings_cb,
|
||||
},
|
||||
.num_children = 2,
|
||||
.children = { &recordings_stored,&recordings_live, }
|
||||
|
@@ -44,6 +44,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/stasis_app.h"
|
||||
#include "stasis_http/resource_sounds.h"
|
||||
#if defined(AST_DEVMODE)
|
||||
#include "stasis_http/ari_model_validators.h"
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /sounds.
|
||||
@@ -53,9 +56,14 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_get_sounds_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_get_sounds_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -69,6 +77,29 @@ static void stasis_http_get_sounds_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_get_sounds(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_list(response->message,
|
||||
ari_validate_sound);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /sounds\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /sounds\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
/*!
|
||||
* \brief Parameter parsing callback for /sounds/{soundId}.
|
||||
@@ -78,9 +109,14 @@ static void stasis_http_get_sounds_cb(
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_get_stored_sound_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
struct ast_get_stored_sound_args args = {};
|
||||
struct ast_variable *i;
|
||||
|
||||
@@ -91,6 +127,29 @@ static void stasis_http_get_stored_sound_cb(
|
||||
{}
|
||||
}
|
||||
stasis_http_get_stored_sound(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
is_valid = ari_validate_sound(
|
||||
response->message);
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for /sounds/{soundId}\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for /sounds/{soundId}\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
|
||||
/*! \brief REST handler for /api-docs/sounds.{format} */
|
||||
|
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* 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_stasis_http_resource.c.mustache
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Asterisk resources
|
||||
*
|
||||
* \author David M. Lee, II <dlee@digium.com>
|
||||
*/
|
||||
|
||||
/*** MODULEINFO
|
||||
<support_level>core</support_level>
|
||||
***/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/json.h"
|
||||
#include "stasis_json/resource_asterisk.h"
|
||||
static int load_module(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Stasis JSON Generators and Validators - Asterisk resources",
|
||||
.load = load_module,
|
||||
.unload = unload_module,
|
||||
.load_pri = AST_MODPRI_DEFAULT,
|
||||
);
|
@@ -1,4 +0,0 @@
|
||||
{
|
||||
local:
|
||||
*;
|
||||
};
|
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* 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_stasis_http_resource.c.mustache
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Bridge resources
|
||||
*
|
||||
* \author David M. Lee, II <dlee@digium.com>
|
||||
*/
|
||||
|
||||
/*** MODULEINFO
|
||||
<support_level>core</support_level>
|
||||
***/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/json.h"
|
||||
#include "stasis_json/resource_bridges.h"
|
||||
static int load_module(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Stasis JSON Generators and Validators - Bridge resources",
|
||||
.load = load_module,
|
||||
.unload = unload_module,
|
||||
.load_pri = AST_MODPRI_DEFAULT,
|
||||
);
|
@@ -1,4 +0,0 @@
|
||||
{
|
||||
local:
|
||||
*;
|
||||
};
|
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* 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_stasis_http_resource.c.mustache
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Channel resources
|
||||
*
|
||||
* \author David M. Lee, II <dlee@digium.com>
|
||||
*/
|
||||
|
||||
/*** MODULEINFO
|
||||
<support_level>core</support_level>
|
||||
***/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/json.h"
|
||||
#include "stasis_json/resource_channels.h"
|
||||
static int load_module(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Stasis JSON Generators and Validators - Channel resources",
|
||||
.load = load_module,
|
||||
.unload = unload_module,
|
||||
.load_pri = AST_MODPRI_DEFAULT,
|
||||
);
|
@@ -1,4 +0,0 @@
|
||||
{
|
||||
local:
|
||||
*;
|
||||
};
|
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* 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_stasis_http_resource.c.mustache
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Endpoint resources
|
||||
*
|
||||
* \author David M. Lee, II <dlee@digium.com>
|
||||
*/
|
||||
|
||||
/*** MODULEINFO
|
||||
<support_level>core</support_level>
|
||||
***/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/json.h"
|
||||
#include "stasis_json/resource_endpoints.h"
|
||||
static int load_module(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Stasis JSON Generators and Validators - Endpoint resources",
|
||||
.load = load_module,
|
||||
.unload = unload_module,
|
||||
.load_pri = AST_MODPRI_DEFAULT,
|
||||
);
|
@@ -1,4 +0,0 @@
|
||||
{
|
||||
local:
|
||||
*;
|
||||
};
|
@@ -1,818 +0,0 @@
|
||||
/*
|
||||
* 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_stasis_http_resource.c.mustache
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief WebSocket resource
|
||||
*
|
||||
* \author David M. Lee, II <dlee@digium.com>
|
||||
*/
|
||||
|
||||
/*** MODULEINFO
|
||||
<support_level>core</support_level>
|
||||
***/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/json.h"
|
||||
#include "stasis_json/resource_events.h"
|
||||
#include "asterisk/stasis_channels.h"
|
||||
#include "asterisk/stasis_bridging.h"
|
||||
|
||||
struct ast_json *stasis_json_event_channel_userevent_create(
|
||||
struct ast_channel_snapshot *channel_snapshot,
|
||||
struct ast_json *blob
|
||||
)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
|
||||
struct ast_json *validator;
|
||||
int ret;
|
||||
|
||||
ast_assert(channel_snapshot != NULL);
|
||||
ast_assert(blob != NULL);
|
||||
ast_assert(ast_json_object_get(blob, "channel") == NULL);
|
||||
ast_assert(ast_json_object_get(blob, "type") == NULL);
|
||||
|
||||
validator = ast_json_object_get(blob, "eventname");
|
||||
if (validator) {
|
||||
/* do validation? XXX */
|
||||
} else {
|
||||
/* fail message generation if the required parameter doesn't exist */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
event = ast_json_deep_copy(blob);
|
||||
if (!event) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = ast_json_object_set(event,
|
||||
"channel", ast_channel_snapshot_to_json(channel_snapshot));
|
||||
if (ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
message = ast_json_pack("{s: o}", "channel_userevent", ast_json_ref(event));
|
||||
if (!message) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_json_ref(message);
|
||||
}
|
||||
|
||||
struct ast_json *stasis_json_event_bridge_created_create(
|
||||
struct ast_bridge_snapshot *bridge_snapshot
|
||||
)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
|
||||
int ret;
|
||||
|
||||
ast_assert(bridge_snapshot != NULL);
|
||||
|
||||
event = ast_json_object_create();
|
||||
if (!event) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = ast_json_object_set(event,
|
||||
"bridge", ast_bridge_snapshot_to_json(bridge_snapshot));
|
||||
if (ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
message = ast_json_pack("{s: o}", "bridge_created", ast_json_ref(event));
|
||||
if (!message) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_json_ref(message);
|
||||
}
|
||||
|
||||
struct ast_json *stasis_json_event_playback_finished_create(
|
||||
struct ast_json *blob
|
||||
)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
|
||||
struct ast_json *validator;
|
||||
|
||||
ast_assert(blob != NULL);
|
||||
ast_assert(ast_json_object_get(blob, "type") == NULL);
|
||||
|
||||
validator = ast_json_object_get(blob, "playback");
|
||||
if (validator) {
|
||||
/* do validation? XXX */
|
||||
} else {
|
||||
/* fail message generation if the required parameter doesn't exist */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
event = ast_json_deep_copy(blob);
|
||||
if (!event) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
message = ast_json_pack("{s: o}", "playback_finished", ast_json_ref(event));
|
||||
if (!message) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_json_ref(message);
|
||||
}
|
||||
|
||||
struct ast_json *stasis_json_event_channel_snapshot_create(
|
||||
struct ast_channel_snapshot *channel_snapshot
|
||||
)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
|
||||
int ret;
|
||||
|
||||
ast_assert(channel_snapshot != NULL);
|
||||
|
||||
event = ast_json_object_create();
|
||||
if (!event) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = ast_json_object_set(event,
|
||||
"channel", ast_channel_snapshot_to_json(channel_snapshot));
|
||||
if (ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
message = ast_json_pack("{s: o}", "channel_snapshot", ast_json_ref(event));
|
||||
if (!message) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_json_ref(message);
|
||||
}
|
||||
|
||||
struct ast_json *stasis_json_event_channel_caller_id_create(
|
||||
struct ast_channel_snapshot *channel_snapshot,
|
||||
struct ast_json *blob
|
||||
)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
|
||||
struct ast_json *validator;
|
||||
int ret;
|
||||
|
||||
ast_assert(channel_snapshot != NULL);
|
||||
ast_assert(blob != NULL);
|
||||
ast_assert(ast_json_object_get(blob, "channel") == NULL);
|
||||
ast_assert(ast_json_object_get(blob, "type") == NULL);
|
||||
|
||||
validator = ast_json_object_get(blob, "caller_presentation_txt");
|
||||
if (validator) {
|
||||
/* do validation? XXX */
|
||||
} else {
|
||||
/* fail message generation if the required parameter doesn't exist */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
validator = ast_json_object_get(blob, "caller_presentation");
|
||||
if (validator) {
|
||||
/* do validation? XXX */
|
||||
} else {
|
||||
/* fail message generation if the required parameter doesn't exist */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
event = ast_json_deep_copy(blob);
|
||||
if (!event) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = ast_json_object_set(event,
|
||||
"channel", ast_channel_snapshot_to_json(channel_snapshot));
|
||||
if (ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
message = ast_json_pack("{s: o}", "channel_caller_id", ast_json_ref(event));
|
||||
if (!message) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_json_ref(message);
|
||||
}
|
||||
|
||||
struct ast_json *stasis_json_event_playback_started_create(
|
||||
struct ast_json *blob
|
||||
)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
|
||||
struct ast_json *validator;
|
||||
|
||||
ast_assert(blob != NULL);
|
||||
ast_assert(ast_json_object_get(blob, "type") == NULL);
|
||||
|
||||
validator = ast_json_object_get(blob, "playback");
|
||||
if (validator) {
|
||||
/* do validation? XXX */
|
||||
} else {
|
||||
/* fail message generation if the required parameter doesn't exist */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
event = ast_json_deep_copy(blob);
|
||||
if (!event) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
message = ast_json_pack("{s: o}", "playback_started", ast_json_ref(event));
|
||||
if (!message) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_json_ref(message);
|
||||
}
|
||||
|
||||
struct ast_json *stasis_json_event_channel_varset_create(
|
||||
struct ast_channel_snapshot *channel_snapshot,
|
||||
struct ast_json *blob
|
||||
)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
|
||||
struct ast_json *validator;
|
||||
int ret;
|
||||
|
||||
ast_assert(channel_snapshot != NULL);
|
||||
ast_assert(blob != NULL);
|
||||
ast_assert(ast_json_object_get(blob, "channel") == NULL);
|
||||
ast_assert(ast_json_object_get(blob, "type") == NULL);
|
||||
|
||||
validator = ast_json_object_get(blob, "variable");
|
||||
if (validator) {
|
||||
/* do validation? XXX */
|
||||
} else {
|
||||
/* fail message generation if the required parameter doesn't exist */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
validator = ast_json_object_get(blob, "value");
|
||||
if (validator) {
|
||||
/* do validation? XXX */
|
||||
} else {
|
||||
/* fail message generation if the required parameter doesn't exist */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
event = ast_json_deep_copy(blob);
|
||||
if (!event) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = ast_json_object_set(event,
|
||||
"channel", ast_channel_snapshot_to_json(channel_snapshot));
|
||||
if (ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
message = ast_json_pack("{s: o}", "channel_varset", ast_json_ref(event));
|
||||
if (!message) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_json_ref(message);
|
||||
}
|
||||
|
||||
struct ast_json *stasis_json_event_bridge_destroyed_create(
|
||||
struct ast_bridge_snapshot *bridge_snapshot
|
||||
)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
|
||||
int ret;
|
||||
|
||||
ast_assert(bridge_snapshot != NULL);
|
||||
|
||||
event = ast_json_object_create();
|
||||
if (!event) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = ast_json_object_set(event,
|
||||
"bridge", ast_bridge_snapshot_to_json(bridge_snapshot));
|
||||
if (ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
message = ast_json_pack("{s: o}", "bridge_destroyed", ast_json_ref(event));
|
||||
if (!message) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_json_ref(message);
|
||||
}
|
||||
|
||||
struct ast_json *stasis_json_event_application_replaced_create(
|
||||
struct ast_json *blob
|
||||
)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
|
||||
struct ast_json *validator;
|
||||
|
||||
ast_assert(blob != NULL);
|
||||
ast_assert(ast_json_object_get(blob, "type") == NULL);
|
||||
|
||||
validator = ast_json_object_get(blob, "application");
|
||||
if (validator) {
|
||||
/* do validation? XXX */
|
||||
} else {
|
||||
/* fail message generation if the required parameter doesn't exist */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
event = ast_json_deep_copy(blob);
|
||||
if (!event) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
message = ast_json_pack("{s: o}", "application_replaced", ast_json_ref(event));
|
||||
if (!message) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_json_ref(message);
|
||||
}
|
||||
|
||||
struct ast_json *stasis_json_event_channel_destroyed_create(
|
||||
struct ast_channel_snapshot *channel_snapshot,
|
||||
struct ast_json *blob
|
||||
)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
|
||||
struct ast_json *validator;
|
||||
int ret;
|
||||
|
||||
ast_assert(channel_snapshot != NULL);
|
||||
ast_assert(blob != NULL);
|
||||
ast_assert(ast_json_object_get(blob, "channel") == NULL);
|
||||
ast_assert(ast_json_object_get(blob, "type") == NULL);
|
||||
|
||||
validator = ast_json_object_get(blob, "cause");
|
||||
if (validator) {
|
||||
/* do validation? XXX */
|
||||
} else {
|
||||
/* fail message generation if the required parameter doesn't exist */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
validator = ast_json_object_get(blob, "cause_txt");
|
||||
if (validator) {
|
||||
/* do validation? XXX */
|
||||
} else {
|
||||
/* fail message generation if the required parameter doesn't exist */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
event = ast_json_deep_copy(blob);
|
||||
if (!event) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = ast_json_object_set(event,
|
||||
"channel", ast_channel_snapshot_to_json(channel_snapshot));
|
||||
if (ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
message = ast_json_pack("{s: o}", "channel_destroyed", ast_json_ref(event));
|
||||
if (!message) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_json_ref(message);
|
||||
}
|
||||
|
||||
struct ast_json *stasis_json_event_bridge_merged_create(
|
||||
struct ast_bridge_snapshot *bridge_snapshot,
|
||||
struct ast_json *blob
|
||||
)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
|
||||
struct ast_json *validator;
|
||||
int ret;
|
||||
|
||||
ast_assert(bridge_snapshot != NULL);
|
||||
ast_assert(blob != NULL);
|
||||
ast_assert(ast_json_object_get(blob, "bridge") == NULL);
|
||||
ast_assert(ast_json_object_get(blob, "type") == NULL);
|
||||
|
||||
validator = ast_json_object_get(blob, "bridge_from");
|
||||
if (validator) {
|
||||
/* do validation? XXX */
|
||||
} else {
|
||||
/* fail message generation if the required parameter doesn't exist */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
event = ast_json_deep_copy(blob);
|
||||
if (!event) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = ast_json_object_set(event,
|
||||
"bridge", ast_bridge_snapshot_to_json(bridge_snapshot));
|
||||
if (ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
message = ast_json_pack("{s: o}", "bridge_merged", ast_json_ref(event));
|
||||
if (!message) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_json_ref(message);
|
||||
}
|
||||
|
||||
struct ast_json *stasis_json_event_channel_left_bridge_create(
|
||||
struct ast_bridge_snapshot *bridge_snapshot,
|
||||
struct ast_channel_snapshot *channel_snapshot
|
||||
)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
|
||||
int ret;
|
||||
|
||||
ast_assert(channel_snapshot != NULL);
|
||||
ast_assert(bridge_snapshot != NULL);
|
||||
|
||||
event = ast_json_object_create();
|
||||
if (!event) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = ast_json_object_set(event,
|
||||
"channel", ast_channel_snapshot_to_json(channel_snapshot));
|
||||
if (ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = ast_json_object_set(event,
|
||||
"bridge", ast_bridge_snapshot_to_json(bridge_snapshot));
|
||||
if (ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
message = ast_json_pack("{s: o}", "channel_left_bridge", ast_json_ref(event));
|
||||
if (!message) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_json_ref(message);
|
||||
}
|
||||
|
||||
struct ast_json *stasis_json_event_channel_created_create(
|
||||
struct ast_channel_snapshot *channel_snapshot
|
||||
)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
|
||||
int ret;
|
||||
|
||||
ast_assert(channel_snapshot != NULL);
|
||||
|
||||
event = ast_json_object_create();
|
||||
if (!event) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = ast_json_object_set(event,
|
||||
"channel", ast_channel_snapshot_to_json(channel_snapshot));
|
||||
if (ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
message = ast_json_pack("{s: o}", "channel_created", ast_json_ref(event));
|
||||
if (!message) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_json_ref(message);
|
||||
}
|
||||
|
||||
struct ast_json *stasis_json_event_stasis_start_create(
|
||||
struct ast_channel_snapshot *channel_snapshot,
|
||||
struct ast_json *blob
|
||||
)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
|
||||
struct ast_json *validator;
|
||||
int ret;
|
||||
|
||||
ast_assert(channel_snapshot != NULL);
|
||||
ast_assert(blob != NULL);
|
||||
ast_assert(ast_json_object_get(blob, "channel") == NULL);
|
||||
ast_assert(ast_json_object_get(blob, "type") == NULL);
|
||||
|
||||
validator = ast_json_object_get(blob, "args");
|
||||
if (validator) {
|
||||
/* do validation? XXX */
|
||||
} else {
|
||||
/* fail message generation if the required parameter doesn't exist */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
event = ast_json_deep_copy(blob);
|
||||
if (!event) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = ast_json_object_set(event,
|
||||
"channel", ast_channel_snapshot_to_json(channel_snapshot));
|
||||
if (ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
message = ast_json_pack("{s: o}", "stasis_start", ast_json_ref(event));
|
||||
if (!message) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_json_ref(message);
|
||||
}
|
||||
|
||||
struct ast_json *stasis_json_event_channel_dialplan_create(
|
||||
struct ast_channel_snapshot *channel_snapshot,
|
||||
struct ast_json *blob
|
||||
)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
|
||||
struct ast_json *validator;
|
||||
int ret;
|
||||
|
||||
ast_assert(channel_snapshot != NULL);
|
||||
ast_assert(blob != NULL);
|
||||
ast_assert(ast_json_object_get(blob, "channel") == NULL);
|
||||
ast_assert(ast_json_object_get(blob, "type") == NULL);
|
||||
|
||||
validator = ast_json_object_get(blob, "application");
|
||||
if (validator) {
|
||||
/* do validation? XXX */
|
||||
} else {
|
||||
/* fail message generation if the required parameter doesn't exist */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
validator = ast_json_object_get(blob, "application_data");
|
||||
if (validator) {
|
||||
/* do validation? XXX */
|
||||
} else {
|
||||
/* fail message generation if the required parameter doesn't exist */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
event = ast_json_deep_copy(blob);
|
||||
if (!event) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = ast_json_object_set(event,
|
||||
"channel", ast_channel_snapshot_to_json(channel_snapshot));
|
||||
if (ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
message = ast_json_pack("{s: o}", "channel_dialplan", ast_json_ref(event));
|
||||
if (!message) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_json_ref(message);
|
||||
}
|
||||
|
||||
struct ast_json *stasis_json_event_channel_state_change_create(
|
||||
struct ast_channel_snapshot *channel_snapshot
|
||||
)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
|
||||
int ret;
|
||||
|
||||
ast_assert(channel_snapshot != NULL);
|
||||
|
||||
event = ast_json_object_create();
|
||||
if (!event) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = ast_json_object_set(event,
|
||||
"channel", ast_channel_snapshot_to_json(channel_snapshot));
|
||||
if (ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
message = ast_json_pack("{s: o}", "channel_state_change", ast_json_ref(event));
|
||||
if (!message) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_json_ref(message);
|
||||
}
|
||||
|
||||
struct ast_json *stasis_json_event_channel_hangup_request_create(
|
||||
struct ast_channel_snapshot *channel_snapshot,
|
||||
struct ast_json *blob
|
||||
)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
|
||||
struct ast_json *validator;
|
||||
int ret;
|
||||
|
||||
ast_assert(channel_snapshot != NULL);
|
||||
ast_assert(blob != NULL);
|
||||
ast_assert(ast_json_object_get(blob, "channel") == NULL);
|
||||
ast_assert(ast_json_object_get(blob, "type") == NULL);
|
||||
|
||||
validator = ast_json_object_get(blob, "soft");
|
||||
if (validator) {
|
||||
/* do validation? XXX */
|
||||
}
|
||||
|
||||
validator = ast_json_object_get(blob, "cause");
|
||||
if (validator) {
|
||||
/* do validation? XXX */
|
||||
}
|
||||
|
||||
event = ast_json_deep_copy(blob);
|
||||
if (!event) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = ast_json_object_set(event,
|
||||
"channel", ast_channel_snapshot_to_json(channel_snapshot));
|
||||
if (ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
message = ast_json_pack("{s: o}", "channel_hangup_request", ast_json_ref(event));
|
||||
if (!message) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_json_ref(message);
|
||||
}
|
||||
|
||||
struct ast_json *stasis_json_event_channel_entered_bridge_create(
|
||||
struct ast_bridge_snapshot *bridge_snapshot,
|
||||
struct ast_channel_snapshot *channel_snapshot
|
||||
)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
|
||||
int ret;
|
||||
|
||||
ast_assert(channel_snapshot != NULL);
|
||||
ast_assert(bridge_snapshot != NULL);
|
||||
|
||||
event = ast_json_object_create();
|
||||
if (!event) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = ast_json_object_set(event,
|
||||
"channel", ast_channel_snapshot_to_json(channel_snapshot));
|
||||
if (ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = ast_json_object_set(event,
|
||||
"bridge", ast_bridge_snapshot_to_json(bridge_snapshot));
|
||||
if (ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
message = ast_json_pack("{s: o}", "channel_entered_bridge", ast_json_ref(event));
|
||||
if (!message) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_json_ref(message);
|
||||
}
|
||||
|
||||
struct ast_json *stasis_json_event_channel_dtmf_received_create(
|
||||
struct ast_channel_snapshot *channel_snapshot,
|
||||
struct ast_json *blob
|
||||
)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
|
||||
struct ast_json *validator;
|
||||
int ret;
|
||||
|
||||
ast_assert(channel_snapshot != NULL);
|
||||
ast_assert(blob != NULL);
|
||||
ast_assert(ast_json_object_get(blob, "channel") == NULL);
|
||||
ast_assert(ast_json_object_get(blob, "type") == NULL);
|
||||
|
||||
validator = ast_json_object_get(blob, "digit");
|
||||
if (validator) {
|
||||
/* do validation? XXX */
|
||||
} else {
|
||||
/* fail message generation if the required parameter doesn't exist */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
event = ast_json_deep_copy(blob);
|
||||
if (!event) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = ast_json_object_set(event,
|
||||
"channel", ast_channel_snapshot_to_json(channel_snapshot));
|
||||
if (ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
message = ast_json_pack("{s: o}", "channel_dtmf_received", ast_json_ref(event));
|
||||
if (!message) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_json_ref(message);
|
||||
}
|
||||
|
||||
struct ast_json *stasis_json_event_stasis_end_create(
|
||||
struct ast_channel_snapshot *channel_snapshot
|
||||
)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
|
||||
int ret;
|
||||
|
||||
ast_assert(channel_snapshot != NULL);
|
||||
|
||||
event = ast_json_object_create();
|
||||
if (!event) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = ast_json_object_set(event,
|
||||
"channel", ast_channel_snapshot_to_json(channel_snapshot));
|
||||
if (ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
message = ast_json_pack("{s: o}", "stasis_end", ast_json_ref(event));
|
||||
if (!message) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_json_ref(message);
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Stasis JSON Generators and Validators - WebSocket resource",
|
||||
.load = load_module,
|
||||
.unload = unload_module,
|
||||
.load_pri = AST_MODPRI_DEFAULT,
|
||||
);
|
@@ -1,25 +0,0 @@
|
||||
{
|
||||
global:
|
||||
LINKER_SYMBOL_PREFIXstasis_json_event_channel_userevent_create;
|
||||
LINKER_SYMBOL_PREFIXstasis_json_event_bridge_created_create;
|
||||
LINKER_SYMBOL_PREFIXstasis_json_event_playback_finished_create;
|
||||
LINKER_SYMBOL_PREFIXstasis_json_event_channel_snapshot_create;
|
||||
LINKER_SYMBOL_PREFIXstasis_json_event_channel_caller_id_create;
|
||||
LINKER_SYMBOL_PREFIXstasis_json_event_playback_started_create;
|
||||
LINKER_SYMBOL_PREFIXstasis_json_event_channel_varset_create;
|
||||
LINKER_SYMBOL_PREFIXstasis_json_event_bridge_destroyed_create;
|
||||
LINKER_SYMBOL_PREFIXstasis_json_event_application_replaced_create;
|
||||
LINKER_SYMBOL_PREFIXstasis_json_event_channel_destroyed_create;
|
||||
LINKER_SYMBOL_PREFIXstasis_json_event_bridge_merged_create;
|
||||
LINKER_SYMBOL_PREFIXstasis_json_event_channel_left_bridge_create;
|
||||
LINKER_SYMBOL_PREFIXstasis_json_event_channel_created_create;
|
||||
LINKER_SYMBOL_PREFIXstasis_json_event_stasis_start_create;
|
||||
LINKER_SYMBOL_PREFIXstasis_json_event_channel_dialplan_create;
|
||||
LINKER_SYMBOL_PREFIXstasis_json_event_channel_state_change_create;
|
||||
LINKER_SYMBOL_PREFIXstasis_json_event_channel_hangup_request_create;
|
||||
LINKER_SYMBOL_PREFIXstasis_json_event_channel_entered_bridge_create;
|
||||
LINKER_SYMBOL_PREFIXstasis_json_event_channel_dtmf_received_create;
|
||||
LINKER_SYMBOL_PREFIXstasis_json_event_stasis_end_create;
|
||||
local:
|
||||
*;
|
||||
};
|
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* 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_stasis_http_resource.c.mustache
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Playback control resources
|
||||
*
|
||||
* \author David M. Lee, II <dlee@digium.com>
|
||||
*/
|
||||
|
||||
/*** MODULEINFO
|
||||
<support_level>core</support_level>
|
||||
***/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/json.h"
|
||||
#include "stasis_json/resource_playback.h"
|
||||
static int load_module(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Stasis JSON Generators and Validators - Playback control resources",
|
||||
.load = load_module,
|
||||
.unload = unload_module,
|
||||
.load_pri = AST_MODPRI_DEFAULT,
|
||||
);
|
@@ -1,4 +0,0 @@
|
||||
{
|
||||
local:
|
||||
*;
|
||||
};
|
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* 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_stasis_http_resource.c.mustache
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Recording resources
|
||||
*
|
||||
* \author David M. Lee, II <dlee@digium.com>
|
||||
*/
|
||||
|
||||
/*** MODULEINFO
|
||||
<support_level>core</support_level>
|
||||
***/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/json.h"
|
||||
#include "stasis_json/resource_recordings.h"
|
||||
static int load_module(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Stasis JSON Generators and Validators - Recording resources",
|
||||
.load = load_module,
|
||||
.unload = unload_module,
|
||||
.load_pri = AST_MODPRI_DEFAULT,
|
||||
);
|
@@ -1,4 +0,0 @@
|
||||
{
|
||||
local:
|
||||
*;
|
||||
};
|
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* 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_stasis_http_resource.c.mustache
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Sound resources
|
||||
*
|
||||
* \author David M. Lee, II <dlee@digium.com>
|
||||
*/
|
||||
|
||||
/*** MODULEINFO
|
||||
<support_level>core</support_level>
|
||||
***/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/json.h"
|
||||
#include "stasis_json/resource_sounds.h"
|
||||
static int load_module(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Stasis JSON Generators and Validators - Sound resources",
|
||||
.load = load_module,
|
||||
.unload = unload_module,
|
||||
.load_pri = AST_MODPRI_DEFAULT,
|
||||
);
|
@@ -1,4 +0,0 @@
|
||||
{
|
||||
local:
|
||||
*;
|
||||
};
|
2567
res/stasis_http/ari_model_validators.c
Normal file
2567
res/stasis_http/ari_model_validators.c
Normal file
File diff suppressed because it is too large
Load Diff
659
res/stasis_http/ari_model_validators.h
Normal file
659
res/stasis_http/ari_model_validators.h
Normal file
@@ -0,0 +1,659 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2013, Digium, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Generated file - Build validators for ARI model objects.
|
||||
*/
|
||||
|
||||
/*
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* !!!!! DO NOT EDIT !!!!!
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* This file is generated by a mustache template. Please see the original
|
||||
* template in rest-api-templates/ari_model_validators.h.mustache
|
||||
*/
|
||||
|
||||
#ifndef _ASTERISK_ARI_MODEL_H
|
||||
#define _ASTERISK_ARI_MODEL_H
|
||||
|
||||
#include "asterisk/json.h"
|
||||
|
||||
/*! @{ */
|
||||
|
||||
/*!
|
||||
* \brief Validator for native Swagger void.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_void(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for native Swagger byte.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_byte(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for native Swagger boolean.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_boolean(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for native Swagger int.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_int(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for native Swagger long.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_long(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for native Swagger float.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_float(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for native Swagger double.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_double(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for native Swagger string.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_string(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for native Swagger date.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_date(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for a Swagger List[]/JSON array.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \param fn Validator to call on every element in the array.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_list(struct ast_json *json, int (*fn)(struct ast_json *));
|
||||
|
||||
/*! @} */
|
||||
|
||||
/*!
|
||||
* \brief Validator for AsteriskInfo.
|
||||
*
|
||||
* Asterisk system information
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_asterisk_info(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for Endpoint.
|
||||
*
|
||||
* An external device that may offer/accept calls to/from Asterisk.
|
||||
*
|
||||
* Unlike most resources, which have a single unique identifier, an endpoint is uniquely identified by the technology/resource pair.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_endpoint(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for CallerID.
|
||||
*
|
||||
* Caller identification
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_caller_id(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for Channel.
|
||||
*
|
||||
* A specific communication connection between Asterisk and an Endpoint.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_channel(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for Dialed.
|
||||
*
|
||||
* Dialed channel information.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_dialed(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for DialplanCEP.
|
||||
*
|
||||
* Dialplan location (context/extension/priority)
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_dialplan_cep(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for Bridge.
|
||||
*
|
||||
* The merging of media from one or more channels.
|
||||
*
|
||||
* Everyone on the bridge receives the same audio.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_bridge(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for LiveRecording.
|
||||
*
|
||||
* A recording that is in progress
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_live_recording(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for StoredRecording.
|
||||
*
|
||||
* A past recording that may be played back.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_stored_recording(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for FormatLangPair.
|
||||
*
|
||||
* Identifies the format and language of a sound file
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_format_lang_pair(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for Sound.
|
||||
*
|
||||
* A media file that may be played back.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_sound(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for Playback.
|
||||
*
|
||||
* Object representing the playback of media to a channel
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_playback(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for ApplicationReplaced.
|
||||
*
|
||||
* Notification that another WebSocket has taken over for an application.
|
||||
*
|
||||
* An application may only be subscribed to by a single WebSocket at a time. If multiple WebSockets attempt to subscribe to the same application, the newer WebSocket wins, and the older one receives this event.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_application_replaced(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for BridgeCreated.
|
||||
*
|
||||
* Notification that a bridge has been created.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_bridge_created(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for BridgeDestroyed.
|
||||
*
|
||||
* Notification that a bridge has been destroyed.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_bridge_destroyed(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for BridgeMerged.
|
||||
*
|
||||
* Notification that one bridge has merged into another.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_bridge_merged(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for ChannelCallerId.
|
||||
*
|
||||
* Channel changed Caller ID.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_channel_caller_id(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for ChannelCreated.
|
||||
*
|
||||
* Notification that a channel has been created.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_channel_created(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for ChannelDestroyed.
|
||||
*
|
||||
* Notification that a channel has been destroyed.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_channel_destroyed(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for ChannelDialplan.
|
||||
*
|
||||
* Channel changed location in the dialplan.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_channel_dialplan(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for ChannelDtmfReceived.
|
||||
*
|
||||
* DTMF received on a channel.
|
||||
*
|
||||
* This event is sent when the DTMF ends. There is no notification about the start of DTMF
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_channel_dtmf_received(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for ChannelEnteredBridge.
|
||||
*
|
||||
* Notification that a channel has entered a bridge.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_channel_entered_bridge(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for ChannelHangupRequest.
|
||||
*
|
||||
* A hangup was requested on the channel.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_channel_hangup_request(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for ChannelLeftBridge.
|
||||
*
|
||||
* Notification that a channel has left a bridge.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_channel_left_bridge(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for ChannelStateChange.
|
||||
*
|
||||
* Notification of a channel's state change.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_channel_state_change(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for ChannelUserevent.
|
||||
*
|
||||
* User-generated event with additional user-defined fields in the object.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_channel_userevent(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for ChannelVarset.
|
||||
*
|
||||
* Channel variable changed.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_channel_varset(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for Event.
|
||||
*
|
||||
* Base type for asynchronous events from Asterisk.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_event(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for PlaybackFinished.
|
||||
*
|
||||
* Event showing the completion of a media playback operation.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_playback_finished(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for PlaybackStarted.
|
||||
*
|
||||
* Event showing the start of a media playback operation.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_playback_started(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for StasisEnd.
|
||||
*
|
||||
* Notification that a channel has left a Stasis appliction.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_stasis_end(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for StasisStart.
|
||||
*
|
||||
* Notification that a channel has entered a Stasis appliction.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_stasis_start(struct ast_json *json);
|
||||
|
||||
/*
|
||||
* JSON models
|
||||
*
|
||||
* AsteriskInfo
|
||||
* Endpoint
|
||||
* - channel_ids: List[string] (required)
|
||||
* - resource: string (required)
|
||||
* - state: string
|
||||
* - technology: string (required)
|
||||
* CallerID
|
||||
* - name: string (required)
|
||||
* - number: string (required)
|
||||
* Channel
|
||||
* - accountcode: string (required)
|
||||
* - caller: CallerID (required)
|
||||
* - connected: CallerID (required)
|
||||
* - creationtime: Date (required)
|
||||
* - dialplan: DialplanCEP (required)
|
||||
* - id: string (required)
|
||||
* - name: string (required)
|
||||
* - state: string (required)
|
||||
* Dialed
|
||||
* DialplanCEP
|
||||
* - context: string (required)
|
||||
* - exten: string (required)
|
||||
* - priority: long (required)
|
||||
* Bridge
|
||||
* - bridge_class: string (required)
|
||||
* - bridge_type: string (required)
|
||||
* - channels: List[string] (required)
|
||||
* - id: string (required)
|
||||
* - technology: string (required)
|
||||
* LiveRecording
|
||||
* - id: string (required)
|
||||
* StoredRecording
|
||||
* - duration_seconds: int
|
||||
* - formats: List[string] (required)
|
||||
* - id: string (required)
|
||||
* - time: Date
|
||||
* FormatLangPair
|
||||
* - format: string (required)
|
||||
* - language: string (required)
|
||||
* Sound
|
||||
* - formats: List[FormatLangPair] (required)
|
||||
* - id: string (required)
|
||||
* - text: string
|
||||
* Playback
|
||||
* - id: string (required)
|
||||
* - language: string
|
||||
* - media_uri: string (required)
|
||||
* - state: string (required)
|
||||
* - target_uri: string (required)
|
||||
* ApplicationReplaced
|
||||
* - application: string (required)
|
||||
* - timestamp: Date
|
||||
* - type: string (required)
|
||||
* BridgeCreated
|
||||
* - application: string (required)
|
||||
* - timestamp: Date
|
||||
* - type: string (required)
|
||||
* - bridge: Bridge (required)
|
||||
* BridgeDestroyed
|
||||
* - application: string (required)
|
||||
* - timestamp: Date
|
||||
* - type: string (required)
|
||||
* - bridge: Bridge (required)
|
||||
* BridgeMerged
|
||||
* - application: string (required)
|
||||
* - timestamp: Date
|
||||
* - type: string (required)
|
||||
* - bridge: Bridge (required)
|
||||
* - bridge_from: Bridge (required)
|
||||
* ChannelCallerId
|
||||
* - application: string (required)
|
||||
* - timestamp: Date
|
||||
* - type: string (required)
|
||||
* - caller_presentation: int (required)
|
||||
* - caller_presentation_txt: string (required)
|
||||
* - channel: Channel (required)
|
||||
* ChannelCreated
|
||||
* - application: string (required)
|
||||
* - timestamp: Date
|
||||
* - type: string (required)
|
||||
* - channel: Channel (required)
|
||||
* ChannelDestroyed
|
||||
* - application: string (required)
|
||||
* - timestamp: Date
|
||||
* - type: string (required)
|
||||
* - cause: int (required)
|
||||
* - cause_txt: string (required)
|
||||
* - channel: Channel (required)
|
||||
* ChannelDialplan
|
||||
* - application: string (required)
|
||||
* - timestamp: Date
|
||||
* - type: string (required)
|
||||
* - channel: Channel (required)
|
||||
* - dialplan_app: string (required)
|
||||
* - dialplan_app_data: string (required)
|
||||
* ChannelDtmfReceived
|
||||
* - application: string (required)
|
||||
* - timestamp: Date
|
||||
* - type: string (required)
|
||||
* - channel: Channel (required)
|
||||
* - digit: string (required)
|
||||
* - duration_ms: int (required)
|
||||
* ChannelEnteredBridge
|
||||
* - application: string (required)
|
||||
* - timestamp: Date
|
||||
* - type: string (required)
|
||||
* - bridge: Bridge (required)
|
||||
* - channel: Channel
|
||||
* ChannelHangupRequest
|
||||
* - application: string (required)
|
||||
* - timestamp: Date
|
||||
* - type: string (required)
|
||||
* - cause: int
|
||||
* - channel: Channel (required)
|
||||
* - soft: boolean
|
||||
* ChannelLeftBridge
|
||||
* - application: string (required)
|
||||
* - timestamp: Date
|
||||
* - type: string (required)
|
||||
* - bridge: Bridge (required)
|
||||
* - channel: Channel (required)
|
||||
* ChannelStateChange
|
||||
* - application: string (required)
|
||||
* - timestamp: Date
|
||||
* - type: string (required)
|
||||
* - channel: Channel (required)
|
||||
* ChannelUserevent
|
||||
* - application: string (required)
|
||||
* - timestamp: Date
|
||||
* - type: string (required)
|
||||
* - channel: Channel (required)
|
||||
* - eventname: string (required)
|
||||
* ChannelVarset
|
||||
* - application: string (required)
|
||||
* - timestamp: Date
|
||||
* - type: string (required)
|
||||
* - channel: Channel
|
||||
* - value: string (required)
|
||||
* - variable: string (required)
|
||||
* Event
|
||||
* - application: string (required)
|
||||
* - timestamp: Date
|
||||
* - type: string (required)
|
||||
* PlaybackFinished
|
||||
* - application: string (required)
|
||||
* - timestamp: Date
|
||||
* - type: string (required)
|
||||
* - playback: Playback (required)
|
||||
* PlaybackStarted
|
||||
* - application: string (required)
|
||||
* - timestamp: Date
|
||||
* - type: string (required)
|
||||
* - playback: Playback (required)
|
||||
* StasisEnd
|
||||
* - application: string (required)
|
||||
* - timestamp: Date
|
||||
* - type: string (required)
|
||||
* - channel: Channel (required)
|
||||
* StasisStart
|
||||
* - application: string (required)
|
||||
* - timestamp: Date
|
||||
* - type: string (required)
|
||||
* - args: List[string] (required)
|
||||
* - channel: Channel (required)
|
||||
*/
|
||||
|
||||
#endif /* _ASTERISK_ARI_MODEL_H */
|
@@ -31,6 +31,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
struct ari_websocket_session {
|
||||
struct ast_websocket *ws_session;
|
||||
int (*validator)(struct ast_json *);
|
||||
};
|
||||
|
||||
static void websocket_session_dtor(void *obj)
|
||||
@@ -41,8 +42,16 @@ static void websocket_session_dtor(void *obj)
|
||||
session->ws_session = NULL;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Validator that always succeeds.
|
||||
*/
|
||||
static int null_validator(struct ast_json *json)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct ari_websocket_session *ari_websocket_session_create(
|
||||
struct ast_websocket *ws_session)
|
||||
struct ast_websocket *ws_session, int (*validator)(struct ast_json *))
|
||||
{
|
||||
RAII_VAR(struct ari_websocket_session *, session, NULL, ao2_cleanup);
|
||||
|
||||
@@ -50,6 +59,10 @@ struct ari_websocket_session *ari_websocket_session_create(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (validator == NULL) {
|
||||
validator = null_validator;
|
||||
}
|
||||
|
||||
if (ast_websocket_set_nonblock(ws_session) != 0) {
|
||||
ast_log(LOG_ERROR,
|
||||
"Stasis web socket failed to set nonblock; closing\n");
|
||||
@@ -63,6 +76,7 @@ struct ari_websocket_session *ari_websocket_session_create(
|
||||
|
||||
ao2_ref(ws_session, +1);
|
||||
session->ws_session = ws_session;
|
||||
session->validator = validator;
|
||||
|
||||
ao2_ref(session, +1);
|
||||
return session;
|
||||
@@ -109,10 +123,24 @@ struct ast_json *ari_websocket_session_read(
|
||||
return ast_json_ref(message);
|
||||
}
|
||||
|
||||
#define VALIDATION_FAILED \
|
||||
"{ \"error\": \"Outgoing message failed validation\" }"
|
||||
|
||||
int ari_websocket_session_write(struct ari_websocket_session *session,
|
||||
struct ast_json *message)
|
||||
{
|
||||
RAII_VAR(char *, str, ast_json_dump_string(message), ast_free);
|
||||
RAII_VAR(char *, str, NULL, ast_free);
|
||||
|
||||
#ifdef AST_DEVMODE
|
||||
if (!session->validator(message)) {
|
||||
ast_log(LOG_ERROR, "Outgoing message failed validation\n");
|
||||
return ast_websocket_write(session->ws_session,
|
||||
AST_WEBSOCKET_OPCODE_TEXT, VALIDATION_FAILED,
|
||||
strlen(VALIDATION_FAILED));
|
||||
}
|
||||
#endif
|
||||
|
||||
str = ast_json_dump_string_format(message, stasis_http_json_format());
|
||||
|
||||
if (str == NULL) {
|
||||
ast_log(LOG_ERROR, "Failed to encode JSON object\n");
|
||||
|
@@ -29,10 +29,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "resource_recordings.h"
|
||||
|
||||
void stasis_http_get_recordings(struct ast_variable *headers, struct ast_get_recordings_args *args, struct stasis_http_response *response)
|
||||
{
|
||||
ast_log(LOG_ERROR, "TODO: stasis_http_get_recordings\n");
|
||||
}
|
||||
void stasis_http_get_stored_recordings(struct ast_variable *headers, struct ast_get_stored_recordings_args *args, struct stasis_http_response *response)
|
||||
{
|
||||
ast_log(LOG_ERROR, "TODO: stasis_http_get_stored_recordings\n");
|
||||
|
@@ -39,17 +39,6 @@
|
||||
|
||||
#include "asterisk/stasis_http.h"
|
||||
|
||||
/*! \brief Argument struct for stasis_http_get_recordings() */
|
||||
struct ast_get_recordings_args {
|
||||
};
|
||||
/*!
|
||||
* \brief List all recordings.
|
||||
*
|
||||
* \param headers HTTP headers
|
||||
* \param args Swagger parameters
|
||||
* \param[out] response HTTP response
|
||||
*/
|
||||
void stasis_http_get_recordings(struct ast_variable *headers, struct ast_get_recordings_args *args, struct stasis_http_response *response);
|
||||
/*! \brief Argument struct for stasis_http_get_stored_recordings() */
|
||||
struct ast_get_stored_recordings_args {
|
||||
};
|
||||
|
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Generated file - declares stubs to be implemented in
|
||||
* res/stasis_json/resource_asterisk.c
|
||||
*
|
||||
* Asterisk resources
|
||||
*
|
||||
* \author David M. Lee, II <dlee@digium.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* !!!!! DO NOT EDIT !!!!!
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* This file is generated by a mustache template. Please see the original
|
||||
* template in rest-api-templates/stasis_http_resource.h.mustache
|
||||
*/
|
||||
|
||||
#ifndef _ASTERISK_RESOURCE_ASTERISK_H
|
||||
#define _ASTERISK_RESOURCE_ASTERISK_H
|
||||
|
||||
/*
|
||||
* JSON models
|
||||
*
|
||||
* AsteriskInfo
|
||||
*/
|
||||
|
||||
#endif /* _ASTERISK_RESOURCE_ASTERISK_H */
|
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Generated file - declares stubs to be implemented in
|
||||
* res/stasis_json/resource_bridges.c
|
||||
*
|
||||
* Bridge resources
|
||||
*
|
||||
* \author David M. Lee, II <dlee@digium.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* !!!!! DO NOT EDIT !!!!!
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* This file is generated by a mustache template. Please see the original
|
||||
* template in rest-api-templates/stasis_http_resource.h.mustache
|
||||
*/
|
||||
|
||||
#ifndef _ASTERISK_RESOURCE_BRIDGES_H
|
||||
#define _ASTERISK_RESOURCE_BRIDGES_H
|
||||
|
||||
/*
|
||||
* JSON models
|
||||
*
|
||||
* Bridge
|
||||
* - channels: List[string] (required)
|
||||
* - bridgeType: string (required)
|
||||
*/
|
||||
|
||||
#endif /* _ASTERISK_RESOURCE_BRIDGES_H */
|
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Generated file - declares stubs to be implemented in
|
||||
* res/stasis_json/resource_channels.c
|
||||
*
|
||||
* Channel resources
|
||||
*
|
||||
* \author David M. Lee, II <dlee@digium.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* !!!!! DO NOT EDIT !!!!!
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* This file is generated by a mustache template. Please see the original
|
||||
* template in rest-api-templates/stasis_http_resource.h.mustache
|
||||
*/
|
||||
|
||||
#ifndef _ASTERISK_RESOURCE_CHANNELS_H
|
||||
#define _ASTERISK_RESOURCE_CHANNELS_H
|
||||
|
||||
/*
|
||||
* JSON models
|
||||
*
|
||||
* DialplanCEP
|
||||
* - priority: long (required)
|
||||
* - exten: string (required)
|
||||
* - context: string (required)
|
||||
* Playback
|
||||
* - language: string
|
||||
* - media_uri: string (required)
|
||||
* - id: string (required)
|
||||
* - target_uri: string (required)
|
||||
* - state: string (required)
|
||||
* Channel
|
||||
* - accountcode: string (required)
|
||||
* - linkedid: string (required)
|
||||
* - name: string (required)
|
||||
* - userfield: string (required)
|
||||
* - caller: CallerID (required)
|
||||
* - creationtime: Date (required)
|
||||
* - state: string (required)
|
||||
* - parkinglot: string (required)
|
||||
* - peeraccount: string (required)
|
||||
* - appl: string (required)
|
||||
* - connected: CallerID (required)
|
||||
* - uniqueid: string (required)
|
||||
* - hangupsource: string (required)
|
||||
* - dialplan: DialplanCEP (required)
|
||||
* - data: string (required)
|
||||
* CallerID
|
||||
* - name: string (required)
|
||||
* - number: string (required)
|
||||
* Dialed
|
||||
*/
|
||||
|
||||
#endif /* _ASTERISK_RESOURCE_CHANNELS_H */
|
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Generated file - declares stubs to be implemented in
|
||||
* res/stasis_json/resource_endpoints.c
|
||||
*
|
||||
* Endpoint resources
|
||||
*
|
||||
* \author David M. Lee, II <dlee@digium.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* !!!!! DO NOT EDIT !!!!!
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* This file is generated by a mustache template. Please see the original
|
||||
* template in rest-api-templates/stasis_http_resource.h.mustache
|
||||
*/
|
||||
|
||||
#ifndef _ASTERISK_RESOURCE_ENDPOINTS_H
|
||||
#define _ASTERISK_RESOURCE_ENDPOINTS_H
|
||||
|
||||
/*
|
||||
* JSON models
|
||||
*
|
||||
* Endpoint
|
||||
* - resource: string (required)
|
||||
* - technology: string (required)
|
||||
*/
|
||||
|
||||
#endif /* _ASTERISK_RESOURCE_ENDPOINTS_H */
|
@@ -1,386 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Generated file - declares stubs to be implemented in
|
||||
* res/stasis_json/resource_events.c
|
||||
*
|
||||
* WebSocket resource
|
||||
*
|
||||
* \author David M. Lee, II <dlee@digium.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* !!!!! DO NOT EDIT !!!!!
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* This file is generated by a mustache template. Please see the original
|
||||
* template in rest-api-templates/stasis_http_resource.h.mustache
|
||||
*/
|
||||
|
||||
#ifndef _ASTERISK_RESOURCE_EVENTS_H
|
||||
#define _ASTERISK_RESOURCE_EVENTS_H
|
||||
|
||||
struct ast_channel_snapshot;
|
||||
struct ast_bridge_snapshot;
|
||||
|
||||
/*!
|
||||
* \brief User-generated event with additional user-defined fields in the object.
|
||||
*
|
||||
* \param channel The channel that signaled the user event.
|
||||
* \param blob JSON blob containing the following parameters:
|
||||
* - eventname: string - The name of the user event. (required)
|
||||
*
|
||||
* \retval NULL on error
|
||||
* \retval JSON (ast_json) describing the event
|
||||
*/
|
||||
struct ast_json *stasis_json_event_channel_userevent_create(
|
||||
struct ast_channel_snapshot *channel_snapshot,
|
||||
struct ast_json *blob
|
||||
);
|
||||
|
||||
/*!
|
||||
* \brief Notification that a bridge has been created.
|
||||
*
|
||||
* \param bridge The bridge to be used to generate this event
|
||||
*
|
||||
* \retval NULL on error
|
||||
* \retval JSON (ast_json) describing the event
|
||||
*/
|
||||
struct ast_json *stasis_json_event_bridge_created_create(
|
||||
struct ast_bridge_snapshot *bridge_snapshot
|
||||
);
|
||||
|
||||
/*!
|
||||
* \brief Event showing the completion of a media playback operation.
|
||||
*
|
||||
* \param blob JSON blob containing the following parameters:
|
||||
* - playback: Playback - Playback control object (required)
|
||||
*
|
||||
* \retval NULL on error
|
||||
* \retval JSON (ast_json) describing the event
|
||||
*/
|
||||
struct ast_json *stasis_json_event_playback_finished_create(
|
||||
struct ast_json *blob
|
||||
);
|
||||
|
||||
/*!
|
||||
* \brief Some part of channel state changed.
|
||||
*
|
||||
* \param channel The channel to be used to generate this event
|
||||
*
|
||||
* \retval NULL on error
|
||||
* \retval JSON (ast_json) describing the event
|
||||
*/
|
||||
struct ast_json *stasis_json_event_channel_snapshot_create(
|
||||
struct ast_channel_snapshot *channel_snapshot
|
||||
);
|
||||
|
||||
/*!
|
||||
* \brief Channel changed Caller ID.
|
||||
*
|
||||
* \param channel The channel that changed Caller ID.
|
||||
* \param blob JSON blob containing the following parameters:
|
||||
* - caller_presentation_txt: string - The text representation of the Caller Presentation value. (required)
|
||||
* - caller_presentation: integer - The integer representation of the Caller Presentation value. (required)
|
||||
*
|
||||
* \retval NULL on error
|
||||
* \retval JSON (ast_json) describing the event
|
||||
*/
|
||||
struct ast_json *stasis_json_event_channel_caller_id_create(
|
||||
struct ast_channel_snapshot *channel_snapshot,
|
||||
struct ast_json *blob
|
||||
);
|
||||
|
||||
/*!
|
||||
* \brief Event showing the start of a media playback operation.
|
||||
*
|
||||
* \param blob JSON blob containing the following parameters:
|
||||
* - playback: Playback - Playback control object (required)
|
||||
*
|
||||
* \retval NULL on error
|
||||
* \retval JSON (ast_json) describing the event
|
||||
*/
|
||||
struct ast_json *stasis_json_event_playback_started_create(
|
||||
struct ast_json *blob
|
||||
);
|
||||
|
||||
/*!
|
||||
* \brief Channel variable changed.
|
||||
*
|
||||
* \param channel The channel on which the variable was set.
|
||||
* \param blob JSON blob containing the following parameters:
|
||||
* - variable: string - The variable that changed. (required)
|
||||
* - value: string - The new value of the variable. (required)
|
||||
*
|
||||
* \retval NULL on error
|
||||
* \retval JSON (ast_json) describing the event
|
||||
*/
|
||||
struct ast_json *stasis_json_event_channel_varset_create(
|
||||
struct ast_channel_snapshot *channel_snapshot,
|
||||
struct ast_json *blob
|
||||
);
|
||||
|
||||
/*!
|
||||
* \brief Notification that a bridge has been destroyed.
|
||||
*
|
||||
* \param bridge The bridge to be used to generate this event
|
||||
*
|
||||
* \retval NULL on error
|
||||
* \retval JSON (ast_json) describing the event
|
||||
*/
|
||||
struct ast_json *stasis_json_event_bridge_destroyed_create(
|
||||
struct ast_bridge_snapshot *bridge_snapshot
|
||||
);
|
||||
|
||||
/*!
|
||||
* \brief Notification that another WebSocket has taken over for an application.
|
||||
*
|
||||
* \param blob JSON blob containing the following parameters:
|
||||
* - application: string (required)
|
||||
*
|
||||
* \retval NULL on error
|
||||
* \retval JSON (ast_json) describing the event
|
||||
*/
|
||||
struct ast_json *stasis_json_event_application_replaced_create(
|
||||
struct ast_json *blob
|
||||
);
|
||||
|
||||
/*!
|
||||
* \brief Notification that a channel has been destroyed.
|
||||
*
|
||||
* \param channel The channel to be used to generate this event
|
||||
* \param blob JSON blob containing the following parameters:
|
||||
* - cause: integer - Integer representation of the cause of the hangup (required)
|
||||
* - cause_txt: string - Text representation of the cause of the hangup (required)
|
||||
*
|
||||
* \retval NULL on error
|
||||
* \retval JSON (ast_json) describing the event
|
||||
*/
|
||||
struct ast_json *stasis_json_event_channel_destroyed_create(
|
||||
struct ast_channel_snapshot *channel_snapshot,
|
||||
struct ast_json *blob
|
||||
);
|
||||
|
||||
/*!
|
||||
* \brief Notification that one bridge has merged into another.
|
||||
*
|
||||
* \param bridge The bridge to be used to generate this event
|
||||
* \param blob JSON blob containing the following parameters:
|
||||
* - bridge_from: Bridge (required)
|
||||
*
|
||||
* \retval NULL on error
|
||||
* \retval JSON (ast_json) describing the event
|
||||
*/
|
||||
struct ast_json *stasis_json_event_bridge_merged_create(
|
||||
struct ast_bridge_snapshot *bridge_snapshot,
|
||||
struct ast_json *blob
|
||||
);
|
||||
|
||||
/*!
|
||||
* \brief Notification that a channel has left a bridge.
|
||||
*
|
||||
* \param channel The channel to be used to generate this event
|
||||
* \param bridge The bridge to be used to generate this event
|
||||
*
|
||||
* \retval NULL on error
|
||||
* \retval JSON (ast_json) describing the event
|
||||
*/
|
||||
struct ast_json *stasis_json_event_channel_left_bridge_create(
|
||||
struct ast_bridge_snapshot *bridge_snapshot,
|
||||
struct ast_channel_snapshot *channel_snapshot
|
||||
);
|
||||
|
||||
/*!
|
||||
* \brief Notification that a channel has been created.
|
||||
*
|
||||
* \param channel The channel to be used to generate this event
|
||||
*
|
||||
* \retval NULL on error
|
||||
* \retval JSON (ast_json) describing the event
|
||||
*/
|
||||
struct ast_json *stasis_json_event_channel_created_create(
|
||||
struct ast_channel_snapshot *channel_snapshot
|
||||
);
|
||||
|
||||
/*!
|
||||
* \brief Notification that a channel has entered a Stasis appliction.
|
||||
*
|
||||
* \param channel The channel to be used to generate this event
|
||||
* \param blob JSON blob containing the following parameters:
|
||||
* - args: List[string] - Arguments to the application (required)
|
||||
*
|
||||
* \retval NULL on error
|
||||
* \retval JSON (ast_json) describing the event
|
||||
*/
|
||||
struct ast_json *stasis_json_event_stasis_start_create(
|
||||
struct ast_channel_snapshot *channel_snapshot,
|
||||
struct ast_json *blob
|
||||
);
|
||||
|
||||
/*!
|
||||
* \brief Channel changed location in the dialplan.
|
||||
*
|
||||
* \param channel The channel that changed dialplan location.
|
||||
* \param blob JSON blob containing the following parameters:
|
||||
* - application: string - The application that the channel is currently in. (required)
|
||||
* - application_data: string - The data that was passed to the application when it was invoked. (required)
|
||||
*
|
||||
* \retval NULL on error
|
||||
* \retval JSON (ast_json) describing the event
|
||||
*/
|
||||
struct ast_json *stasis_json_event_channel_dialplan_create(
|
||||
struct ast_channel_snapshot *channel_snapshot,
|
||||
struct ast_json *blob
|
||||
);
|
||||
|
||||
/*!
|
||||
* \brief Notification of a channel's state change.
|
||||
*
|
||||
* \param channel The channel to be used to generate this event
|
||||
*
|
||||
* \retval NULL on error
|
||||
* \retval JSON (ast_json) describing the event
|
||||
*/
|
||||
struct ast_json *stasis_json_event_channel_state_change_create(
|
||||
struct ast_channel_snapshot *channel_snapshot
|
||||
);
|
||||
|
||||
/*!
|
||||
* \brief A hangup was requested on the channel.
|
||||
*
|
||||
* \param channel The channel on which the hangup was requested.
|
||||
* \param blob JSON blob containing the following parameters:
|
||||
* - soft: boolean - Whether the hangup request was a soft hangup request.
|
||||
* - cause: integer - Integer representation of the cause of the hangup.
|
||||
*
|
||||
* \retval NULL on error
|
||||
* \retval JSON (ast_json) describing the event
|
||||
*/
|
||||
struct ast_json *stasis_json_event_channel_hangup_request_create(
|
||||
struct ast_channel_snapshot *channel_snapshot,
|
||||
struct ast_json *blob
|
||||
);
|
||||
|
||||
/*!
|
||||
* \brief Notification that a channel has entered a bridge.
|
||||
*
|
||||
* \param channel The channel to be used to generate this event
|
||||
* \param bridge The bridge to be used to generate this event
|
||||
*
|
||||
* \retval NULL on error
|
||||
* \retval JSON (ast_json) describing the event
|
||||
*/
|
||||
struct ast_json *stasis_json_event_channel_entered_bridge_create(
|
||||
struct ast_bridge_snapshot *bridge_snapshot,
|
||||
struct ast_channel_snapshot *channel_snapshot
|
||||
);
|
||||
|
||||
/*!
|
||||
* \brief DTMF received on a channel.
|
||||
*
|
||||
* \param channel The channel on which DTMF was received
|
||||
* \param blob JSON blob containing the following parameters:
|
||||
* - digit: string - DTMF digit received (0-9, A-E, # or *) (required)
|
||||
*
|
||||
* \retval NULL on error
|
||||
* \retval JSON (ast_json) describing the event
|
||||
*/
|
||||
struct ast_json *stasis_json_event_channel_dtmf_received_create(
|
||||
struct ast_channel_snapshot *channel_snapshot,
|
||||
struct ast_json *blob
|
||||
);
|
||||
|
||||
/*!
|
||||
* \brief Notification that a channel has left a Stasis appliction.
|
||||
*
|
||||
* \param channel The channel to be used to generate this event
|
||||
*
|
||||
* \retval NULL on error
|
||||
* \retval JSON (ast_json) describing the event
|
||||
*/
|
||||
struct ast_json *stasis_json_event_stasis_end_create(
|
||||
struct ast_channel_snapshot *channel_snapshot
|
||||
);
|
||||
|
||||
/*
|
||||
* JSON models
|
||||
*
|
||||
* ChannelUserevent
|
||||
* - eventname: string (required)
|
||||
* BridgeCreated
|
||||
* PlaybackFinished
|
||||
* - playback: Playback (required)
|
||||
* ChannelSnapshot
|
||||
* ChannelCallerId
|
||||
* - caller_presentation_txt: string (required)
|
||||
* - caller_presentation: integer (required)
|
||||
* PlaybackStarted
|
||||
* - playback: Playback (required)
|
||||
* ChannelVarset
|
||||
* - variable: string (required)
|
||||
* - value: string (required)
|
||||
* BridgeDestroyed
|
||||
* ApplicationReplaced
|
||||
* - application: string (required)
|
||||
* ChannelDestroyed
|
||||
* - cause: integer (required)
|
||||
* - cause_txt: string (required)
|
||||
* BridgeMerged
|
||||
* - bridge_from: Bridge (required)
|
||||
* ChannelLeftBridge
|
||||
* ChannelCreated
|
||||
* StasisStart
|
||||
* - args: List[string] (required)
|
||||
* ChannelDialplan
|
||||
* - application: string (required)
|
||||
* - application_data: string (required)
|
||||
* ChannelStateChange
|
||||
* ChannelHangupRequest
|
||||
* - soft: boolean
|
||||
* - cause: integer
|
||||
* ChannelEnteredBridge
|
||||
* ChannelDtmfReceived
|
||||
* - digit: string (required)
|
||||
* Event
|
||||
* - channel_varset: ChannelVarset
|
||||
* - channel_created: ChannelCreated
|
||||
* - channel_destroyed: ChannelDestroyed
|
||||
* - channel_entered_bridge: ChannelEnteredBridge
|
||||
* - channel_left_bridge: ChannelLeftBridge
|
||||
* - bridge_merged: BridgeMerged
|
||||
* - channel_dialplan: ChannelDialplan
|
||||
* - application_replaced: ApplicationReplaced
|
||||
* - channel_state_change: ChannelStateChange
|
||||
* - bridge_created: BridgeCreated
|
||||
* - application: string (required)
|
||||
* - channel_hangup_request: ChannelHangupRequest
|
||||
* - channel_userevent: ChannelUserevent
|
||||
* - stasis_start: StasisStart
|
||||
* - channel_snapshot: ChannelSnapshot
|
||||
* - channel_dtmf_received: ChannelDtmfReceived
|
||||
* - channel_caller_id: ChannelCallerId
|
||||
* - bridge_destroyed: BridgeDestroyed
|
||||
* - playback_started: PlaybackStarted
|
||||
* - playback_finished: PlaybackFinished
|
||||
* - stasis_end: StasisEnd
|
||||
* StasisEnd
|
||||
*/
|
||||
|
||||
#endif /* _ASTERISK_RESOURCE_EVENTS_H */
|
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Generated file - declares stubs to be implemented in
|
||||
* res/stasis_json/resource_playback.c
|
||||
*
|
||||
* Playback control resources
|
||||
*
|
||||
* \author David M. Lee, II <dlee@digium.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* !!!!! DO NOT EDIT !!!!!
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* This file is generated by a mustache template. Please see the original
|
||||
* template in rest-api-templates/stasis_http_resource.h.mustache
|
||||
*/
|
||||
|
||||
#ifndef _ASTERISK_RESOURCE_PLAYBACK_H
|
||||
#define _ASTERISK_RESOURCE_PLAYBACK_H
|
||||
|
||||
/*
|
||||
* JSON models
|
||||
*
|
||||
* Playback
|
||||
* - id: string (required)
|
||||
*/
|
||||
|
||||
#endif /* _ASTERISK_RESOURCE_PLAYBACK_H */
|
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Generated file - declares stubs to be implemented in
|
||||
* res/stasis_json/resource_recordings.c
|
||||
*
|
||||
* Recording resources
|
||||
*
|
||||
* \author David M. Lee, II <dlee@digium.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* !!!!! DO NOT EDIT !!!!!
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* This file is generated by a mustache template. Please see the original
|
||||
* template in rest-api-templates/stasis_http_resource.h.mustache
|
||||
*/
|
||||
|
||||
#ifndef _ASTERISK_RESOURCE_RECORDINGS_H
|
||||
#define _ASTERISK_RESOURCE_RECORDINGS_H
|
||||
|
||||
/*
|
||||
* JSON models
|
||||
*
|
||||
* Recording
|
||||
* - id: string (required)
|
||||
* StoredRecording
|
||||
* - durationSeconds: int
|
||||
* - time: Date
|
||||
* - id: string (required)
|
||||
* - formats: List[string] (required)
|
||||
* LiveRecording
|
||||
* - id: string (required)
|
||||
*/
|
||||
|
||||
#endif /* _ASTERISK_RESOURCE_RECORDINGS_H */
|
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Generated file - declares stubs to be implemented in
|
||||
* res/stasis_json/resource_sounds.c
|
||||
*
|
||||
* Sound resources
|
||||
*
|
||||
* \author David M. Lee, II <dlee@digium.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* !!!!! DO NOT EDIT !!!!!
|
||||
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
* This file is generated by a mustache template. Please see the original
|
||||
* template in rest-api-templates/stasis_http_resource.h.mustache
|
||||
*/
|
||||
|
||||
#ifndef _ASTERISK_RESOURCE_SOUNDS_H
|
||||
#define _ASTERISK_RESOURCE_SOUNDS_H
|
||||
|
||||
/*
|
||||
* JSON models
|
||||
*
|
||||
* Sound
|
||||
* - text: string
|
||||
* - id: string (required)
|
||||
* - formats: List[FormatLangPair] (required)
|
||||
* FormatLangPair
|
||||
* - language: string (required)
|
||||
* - format: string (required)
|
||||
*/
|
||||
|
||||
#endif /* _ASTERISK_RESOURCE_SOUNDS_H */
|
47
rest-api-templates/api.wiki.mustache
Normal file
47
rest-api-templates/api.wiki.mustache
Normal file
@@ -0,0 +1,47 @@
|
||||
{{#api_declaration}}
|
||||
h1. {{name_title}}
|
||||
|
||||
|| Method || Path || Return Model || Summary ||
|
||||
{{#apis}}
|
||||
{{#operations}}
|
||||
| {{http_method}} | [{{wiki_path}}|#{{nickname}}] | {{#response_class}}{{#is_primitive}}{{name}}{{/is_primitive}}{{^is_primitive}}[{{wiki_name}}|{{wiki_prefix}} REST Data Models#{{singular_name}}]{{/is_primitive}}{{/response_class}} | {{summary}} |
|
||||
{{/operations}}
|
||||
{{/apis}}
|
||||
{{#apis}}
|
||||
{{#operations}}
|
||||
|
||||
{anchor:{{nickname}}}
|
||||
h2. {{http_method}} {{wiki_path}}
|
||||
|
||||
{{{summary}}}{{#notes}} {{{notes}}}{{/notes}}
|
||||
{{#has_path_parameters}}
|
||||
|
||||
h3. Path parameters
|
||||
{{#path_parameters}}
|
||||
* {{name}}: {{data_type}}{{#default_value}} = {{default_value}}{{/default_value}} - {{description}}
|
||||
{{/path_parameters}}
|
||||
{{/has_path_parameters}}
|
||||
{{#has_query_parameters}}
|
||||
|
||||
h3. Query parameters
|
||||
{{#query_parameters}}
|
||||
* {{name}}: {{data_type}}{{#default_value}} = {{default_value}}{{/default_value}} -{{#required}} *(required)*{{/required}} {{description}}
|
||||
{{/query_parameters}}
|
||||
{{/has_query_parameters}}
|
||||
{{#has_header_parameters}}
|
||||
|
||||
h3. Header parameters
|
||||
{{#header_parameters}}
|
||||
* {{name}}: {{data_type}}{{#default_value}} = {{default_value}}{{/default_value}} -{{#required}} *(required)*{{/required}} {{description}}
|
||||
{{/header_parameters}}
|
||||
{{/has_header_parameters}}
|
||||
{{#has_error_responses}}
|
||||
|
||||
h3. Error Responses
|
||||
{{#error_responses}}
|
||||
* {{code}} - {{{reason}}}
|
||||
{{/error_responses}}
|
||||
{{/has_error_responses}}
|
||||
{{/operations}}
|
||||
{{/apis}}
|
||||
{{/api_declaration}}
|
117
rest-api-templates/ari_model_validators.c.mustache
Normal file
117
rest-api-templates/ari_model_validators.c.mustache
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2013, Digium, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Generated file - Build validators for ARI model objects.
|
||||
*/
|
||||
|
||||
/*
|
||||
{{> do-not-edit}}
|
||||
* This file is generated by a mustache template. Please see the original
|
||||
* template in rest-api-templates/ari_model_validators.h.mustache
|
||||
*/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/logger.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "ari_model_validators.h"
|
||||
{{#apis}}
|
||||
{{#api_declaration}}
|
||||
{{#models}}
|
||||
|
||||
int ari_validate_{{c_id}}(struct ast_json *json)
|
||||
{
|
||||
int res = 1;
|
||||
struct ast_json_iter *iter;
|
||||
{{#properties}}
|
||||
{{#required}}
|
||||
int has_{{name}} = 0;
|
||||
{{/required}}
|
||||
{{/properties}}
|
||||
{{#has_subtypes}}
|
||||
const char *discriminator;
|
||||
|
||||
discriminator = ast_json_string_get(ast_json_object_get(json, "{{discriminator.name}}"));
|
||||
if (!discriminator) {
|
||||
ast_log(LOG_ERROR, "ARI {{id}} missing required field {{discriminator.name}}");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp("{{id}}", discriminator) == 0) {
|
||||
/* Self type; fall through */
|
||||
} else
|
||||
{{#subtypes}}
|
||||
if (strcmp("{{id}}", discriminator) == 0) {
|
||||
return ari_validate_{{c_id}}(json);
|
||||
} else
|
||||
{{/subtypes}}
|
||||
{
|
||||
ast_log(LOG_ERROR, "ARI {{id}} has undocumented subtype %s\n",
|
||||
discriminator);
|
||||
res = 0;
|
||||
}
|
||||
{{/has_subtypes}}
|
||||
|
||||
for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) {
|
||||
{{#properties}}
|
||||
if (strcmp("{{name}}", ast_json_object_iter_key(iter)) == 0) {
|
||||
int prop_is_valid;
|
||||
{{#required}}
|
||||
has_{{name}} = 1;
|
||||
{{/required}}
|
||||
{{#type}}
|
||||
{{#is_list}}
|
||||
prop_is_valid = ari_validate_list(
|
||||
ast_json_object_iter_value(iter),
|
||||
ari_validate_{{c_singular_name}});
|
||||
{{/is_list}}
|
||||
{{^is_list}}
|
||||
prop_is_valid = ari_validate_{{c_name}}(
|
||||
ast_json_object_iter_value(iter));
|
||||
{{/is_list}}
|
||||
{{/type}}
|
||||
if (!prop_is_valid) {
|
||||
ast_log(LOG_ERROR, "ARI {{id}} field {{name}} failed validation\n");
|
||||
res = 0;
|
||||
}
|
||||
} else
|
||||
{{/properties}}
|
||||
{
|
||||
ast_log(LOG_ERROR,
|
||||
"ARI {{id}} has undocumented field %s\n",
|
||||
ast_json_object_iter_key(iter));
|
||||
res = 0;
|
||||
}
|
||||
}
|
||||
|
||||
{{#properties}}
|
||||
{{#required}}
|
||||
if (!has_{{name}}) {
|
||||
ast_log(LOG_ERROR, "ARI {{id}} missing required field {{name}}\n");
|
||||
res = 0;
|
||||
}
|
||||
|
||||
{{/required}}
|
||||
{{/properties}}
|
||||
return res;
|
||||
}
|
||||
{{/models}}
|
||||
{{/api_declaration}}
|
||||
{{/apis}}
|
159
rest-api-templates/ari_model_validators.h.mustache
Normal file
159
rest-api-templates/ari_model_validators.h.mustache
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2013, Digium, Inc.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Generated file - Build validators for ARI model objects.
|
||||
*/
|
||||
|
||||
/*
|
||||
{{> do-not-edit}}
|
||||
* This file is generated by a mustache template. Please see the original
|
||||
* template in rest-api-templates/ari_model_validators.h.mustache
|
||||
*/
|
||||
|
||||
#ifndef _ASTERISK_ARI_MODEL_H
|
||||
#define _ASTERISK_ARI_MODEL_H
|
||||
|
||||
#include "asterisk/json.h"
|
||||
|
||||
/*! @{ */
|
||||
|
||||
/*!
|
||||
* \brief Validator for native Swagger void.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_void(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for native Swagger byte.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_byte(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for native Swagger boolean.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_boolean(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for native Swagger int.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_int(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for native Swagger long.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_long(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for native Swagger float.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_float(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for native Swagger double.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_double(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for native Swagger string.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_string(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for native Swagger date.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_date(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Validator for a Swagger List[]/JSON array.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \param fn Validator to call on every element in the array.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_list(struct ast_json *json, int (*fn)(struct ast_json *));
|
||||
|
||||
/*! @} */
|
||||
{{#apis}}
|
||||
{{#api_declaration}}
|
||||
{{#models}}
|
||||
|
||||
/*!
|
||||
* \brief Validator for {{id}}.
|
||||
*
|
||||
* {{{description_dox}}}
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ari_validate_{{c_id}}(struct ast_json *json);
|
||||
{{/models}}
|
||||
{{/api_declaration}}
|
||||
{{/apis}}
|
||||
|
||||
/*
|
||||
* JSON models
|
||||
*
|
||||
{{#apis}}
|
||||
{{#api_declaration}}
|
||||
{{#models}}
|
||||
* {{id}}
|
||||
{{#properties}}
|
||||
* - {{name}}: {{type.name}}{{#required}} (required){{/required}}
|
||||
{{/properties}}
|
||||
{{/models}}
|
||||
{{/api_declaration}}
|
||||
{{/apis}} */
|
||||
|
||||
#endif /* _ASTERISK_ARI_MODEL_H */
|
@@ -24,6 +24,11 @@ import re
|
||||
|
||||
from swagger_model import *
|
||||
|
||||
try:
|
||||
from collections import OrderedDict
|
||||
except ImportError:
|
||||
from odict import OrderedDict
|
||||
|
||||
|
||||
def simple_name(name):
|
||||
"""Removes the {markers} from a path segement.
|
||||
@@ -35,6 +40,14 @@ def simple_name(name):
|
||||
return name
|
||||
|
||||
|
||||
def wikify(str):
|
||||
"""Escapes a string for the wiki.
|
||||
|
||||
@param str: String to escape
|
||||
"""
|
||||
return re.sub(r'([{}\[\]])', r'\\\1', str)
|
||||
|
||||
|
||||
def snakify(name):
|
||||
"""Helper to take a camelCase or dash-seperated name and make it
|
||||
snake_case.
|
||||
@@ -107,6 +120,7 @@ class PathSegment(Stringify):
|
||||
"""
|
||||
return len(self.__children)
|
||||
|
||||
|
||||
class AsteriskProcessor(SwaggerPostProcessor):
|
||||
"""A SwaggerPostProcessor which adds fields needed to generate Asterisk
|
||||
RESTful HTTP binding code.
|
||||
@@ -131,12 +145,17 @@ class AsteriskProcessor(SwaggerPostProcessor):
|
||||
'double': 'atof',
|
||||
}
|
||||
|
||||
def process_api(self, resource_api, context):
|
||||
def __init__(self, wiki_prefix):
|
||||
self.wiki_prefix = wiki_prefix
|
||||
|
||||
def process_resource_api(self, resource_api, context):
|
||||
resource_api.wiki_prefix = self.wiki_prefix
|
||||
# Derive a resource name from the API declaration's filename
|
||||
resource_api.name = re.sub('\..*', '',
|
||||
os.path.basename(resource_api.path))
|
||||
# Now in all caps, from include guard
|
||||
# Now in all caps, for include guard
|
||||
resource_api.name_caps = resource_api.name.upper()
|
||||
resource_api.name_title = resource_api.name.capitalize()
|
||||
# Construct the PathSegement tree for the API.
|
||||
if resource_api.api_declaration:
|
||||
resource_api.root_path = PathSegment('', None)
|
||||
@@ -145,17 +164,6 @@ class AsteriskProcessor(SwaggerPostProcessor):
|
||||
for operation in api.operations:
|
||||
segment.operations.append(operation)
|
||||
api.full_name = segment.full_name
|
||||
resource_api.api_declaration.has_events = False
|
||||
for model in resource_api.api_declaration.models:
|
||||
if model.id == "Event":
|
||||
resource_api.api_declaration.has_events = True
|
||||
break
|
||||
if resource_api.api_declaration.has_events:
|
||||
resource_api.api_declaration.events = \
|
||||
[self.process_model(model, context) for model in \
|
||||
resource_api.api_declaration.models if model.id != "Event"]
|
||||
else:
|
||||
resource_api.api_declaration.events = []
|
||||
|
||||
# Since every API path should start with /[resource], root should
|
||||
# have exactly one child.
|
||||
@@ -169,6 +177,9 @@ class AsteriskProcessor(SwaggerPostProcessor):
|
||||
"API declaration name should match", context)
|
||||
resource_api.root_full_name = resource_api.root_path.full_name
|
||||
|
||||
def process_api(self, api, context):
|
||||
api.wiki_path = wikify(api.path)
|
||||
|
||||
def process_operation(self, operation, context):
|
||||
# Nicknames are camelcase, Asterisk coding is snake case
|
||||
operation.c_nickname = snakify(operation.nickname)
|
||||
@@ -179,7 +190,7 @@ class AsteriskProcessor(SwaggerPostProcessor):
|
||||
def process_parameter(self, parameter, context):
|
||||
if not parameter.data_type in self.type_mapping:
|
||||
raise SwaggerError(
|
||||
"Invalid parameter type %s" % paramter.data_type, context)
|
||||
"Invalid parameter type %s" % parameter.data_type, context)
|
||||
# Parameter names are camelcase, Asterisk convention is snake case
|
||||
parameter.c_name = snakify(parameter.name)
|
||||
parameter.c_data_type = self.type_mapping[parameter.data_type]
|
||||
@@ -191,41 +202,19 @@ class AsteriskProcessor(SwaggerPostProcessor):
|
||||
parameter.c_space = ' '
|
||||
|
||||
def process_model(self, model, context):
|
||||
model.description_dox = model.description.replace('\n', '\n * ')
|
||||
model.description_dox = re.sub(' *\n', '\n', model.description_dox)
|
||||
model.c_id = snakify(model.id)
|
||||
model.channel = False
|
||||
model.channel_desc = ""
|
||||
model.bridge = False
|
||||
model.bridge_desc = ""
|
||||
model.properties = [self.process_property(model, prop, context) for prop in model.properties]
|
||||
model.properties = [prop for prop in model.properties if prop]
|
||||
model.has_properties = (len(model.properties) != 0)
|
||||
return model
|
||||
|
||||
def process_property(self, model, prop, context):
|
||||
# process channel separately since it will be pulled out
|
||||
if prop.name == 'channel' and prop.type == 'Channel':
|
||||
model.channel = True
|
||||
model.channel_desc = prop.description or ""
|
||||
return None
|
||||
def process_property(self, prop, context):
|
||||
if "-" in prop.name:
|
||||
raise SwaggerError("Property names cannot have dashes", context)
|
||||
if prop.name != prop.name.lower():
|
||||
raise SwaggerError("Property name should be all lowercase",
|
||||
context)
|
||||
|
||||
# process bridge separately since it will be pulled out
|
||||
if prop.name == 'bridge' and prop.type == 'Bridge':
|
||||
model.bridge = True
|
||||
model.bridge_desc = prop.description or ""
|
||||
return None
|
||||
|
||||
prop.c_name = snakify(prop.name)
|
||||
if prop.type in self.type_mapping:
|
||||
prop.c_type = self.type_mapping[prop.type]
|
||||
prop.c_convert = self.convert_mapping[prop.c_type]
|
||||
else:
|
||||
prop.c_type = "Property type %s not mappable to a C type" % (prop.type)
|
||||
prop.c_convert = "Property type %s not mappable to a C conversion" % (prop.type)
|
||||
#raise SwaggerError(
|
||||
# "Invalid property type %s" % prop.type, context)
|
||||
# You shouldn't put a space between 'char *' and the variable
|
||||
if prop.c_type.endswith('*'):
|
||||
prop.c_space = ''
|
||||
else:
|
||||
prop.c_space = ' '
|
||||
return prop
|
||||
def process_type(self, swagger_type, context):
|
||||
swagger_type.c_name = snakify(swagger_type.name)
|
||||
swagger_type.c_singular_name = snakify(swagger_type.singular_name)
|
||||
swagger_type.wiki_name = wikify(swagger_type.name)
|
||||
|
@@ -1,10 +0,0 @@
|
||||
struct ast_json *stasis_json_event_{{c_id}}_create(
|
||||
{{#bridge}}
|
||||
struct ast_bridge_snapshot *bridge_snapshot{{#channel}},{{/channel}}{{^channel}}{{#has_properties}},{{/has_properties}}{{/channel}}
|
||||
{{/bridge}}
|
||||
{{#channel}}
|
||||
struct ast_channel_snapshot *channel_snapshot{{#has_properties}},{{/has_properties}}
|
||||
{{/channel}}
|
||||
{{#has_properties}}
|
||||
struct ast_json *blob
|
||||
{{/has_properties}}
|
@@ -22,7 +22,6 @@ except ImportError:
|
||||
print >> sys.stderr, "Pystache required. Please sudo pip install pystache."
|
||||
|
||||
import os.path
|
||||
import pystache
|
||||
import sys
|
||||
|
||||
from asterisk_processor import AsteriskProcessor
|
||||
@@ -40,23 +39,27 @@ def rel(file):
|
||||
"""
|
||||
return os.path.join(TOPDIR, file)
|
||||
|
||||
WIKI_PREFIX = 'Asterisk 12'
|
||||
|
||||
API_TRANSFORMS = [
|
||||
Transform(rel('api.wiki.mustache'),
|
||||
'doc/rest-api/%s {{name_title}} REST API.wiki' % WIKI_PREFIX),
|
||||
Transform(rel('res_stasis_http_resource.c.mustache'),
|
||||
'res_stasis_http_{{name}}.c'),
|
||||
'res/res_stasis_http_{{name}}.c'),
|
||||
Transform(rel('stasis_http_resource.h.mustache'),
|
||||
'stasis_http/resource_{{name}}.h'),
|
||||
'res/stasis_http/resource_{{name}}.h'),
|
||||
Transform(rel('stasis_http_resource.c.mustache'),
|
||||
'stasis_http/resource_{{name}}.c', False),
|
||||
Transform(rel('res_stasis_json_resource.c.mustache'),
|
||||
'res_stasis_json_{{name}}.c'),
|
||||
Transform(rel('res_stasis_json_resource.exports.mustache'),
|
||||
'res_stasis_json_{{name}}.exports.in'),
|
||||
Transform(rel('stasis_json_resource.h.mustache'),
|
||||
'stasis_json/resource_{{name}}.h'),
|
||||
'res/stasis_http/resource_{{name}}.c', overwrite=False),
|
||||
]
|
||||
|
||||
RESOURCES_TRANSFORMS = [
|
||||
Transform(rel('stasis_http.make.mustache'), 'stasis_http.make'),
|
||||
Transform(rel('models.wiki.mustache'),
|
||||
'doc/rest-api/%s REST Data Models.wiki' % WIKI_PREFIX),
|
||||
Transform(rel('stasis_http.make.mustache'), 'res/stasis_http.make'),
|
||||
Transform(rel('ari_model_validators.h.mustache'),
|
||||
'res/stasis_http/ari_model_validators.h'),
|
||||
Transform(rel('ari_model_validators.c.mustache'),
|
||||
'res/stasis_http/ari_model_validators.c'),
|
||||
]
|
||||
|
||||
|
||||
@@ -71,7 +74,7 @@ def main(argv):
|
||||
source = args[1]
|
||||
dest_dir = args[2]
|
||||
renderer = pystache.Renderer(search_dirs=[TOPDIR], missing_tags='strict')
|
||||
processor = AsteriskProcessor()
|
||||
processor = AsteriskProcessor(wiki_prefix=WIKI_PREFIX)
|
||||
|
||||
# Build the models
|
||||
base_dir = os.path.dirname(source)
|
22
rest-api-templates/models.wiki.mustache
Normal file
22
rest-api-templates/models.wiki.mustache
Normal file
@@ -0,0 +1,22 @@
|
||||
{toc}
|
||||
|
||||
{{#apis}}
|
||||
{{#api_declaration}}
|
||||
{{#models}}
|
||||
h1. {{id}}
|
||||
{{#extends}}Base type: [{{extends}}|#{{extends}}]{{/extends}}
|
||||
{{#has_subtypes}}Subtypes:{{#subtypes}} [{{id}}|#{{id}}]{{/subtypes}}{{/has_subtypes}}
|
||||
{{#description}}
|
||||
|
||||
{{{description}}}
|
||||
{{/description}}
|
||||
{code:language=javascript|collapse=true}
|
||||
{{{model_json}}}
|
||||
{code}
|
||||
{{#properties}}
|
||||
* {{name}}: {{#type}}{{#is_primitive}}{{wiki_name}}{{/is_primitive}}{{^is_primitive}}[{{wiki_name}}|#{{singular_name}}]{{/is_primitive}}{{/type}}{{^required}} _(optional)_{{/required}}{{#description}} - {{{description}}}{{/description}}
|
||||
{{/properties}}
|
||||
|
||||
{{/models}}
|
||||
{{/api_declaration}}
|
||||
{{/apis}}
|
@@ -49,6 +49,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/stasis_app.h"
|
||||
#include "stasis_http/resource_{{name}}.h"
|
||||
#if defined(AST_DEVMODE)
|
||||
#include "stasis_http/ari_model_validators.h"
|
||||
#endif
|
||||
|
||||
{{#apis}}
|
||||
{{#operations}}
|
||||
@@ -61,11 +64,50 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
* \param[out] response Response to the HTTP request.
|
||||
*/
|
||||
static void stasis_http_{{c_nickname}}_cb(
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
struct ast_variable *get_params, struct ast_variable *path_vars,
|
||||
struct ast_variable *headers, struct stasis_http_response *response)
|
||||
{
|
||||
#if defined(AST_DEVMODE)
|
||||
int is_valid;
|
||||
int code;
|
||||
#endif /* AST_DEVMODE */
|
||||
|
||||
{{> param_parsing}}
|
||||
stasis_http_{{c_nickname}}(headers, &args, response);
|
||||
#if defined(AST_DEVMODE)
|
||||
code = response->response_code;
|
||||
|
||||
switch (code) {
|
||||
case 500: /* Internal server error */
|
||||
{{#error_responses}}
|
||||
case {{code}}: /* {{{reason}}} */
|
||||
{{/error_responses}}
|
||||
is_valid = 1;
|
||||
break;
|
||||
default:
|
||||
if (200 <= code && code <= 299) {
|
||||
{{#response_class}}
|
||||
{{#is_list}}
|
||||
is_valid = ari_validate_list(response->message,
|
||||
ari_validate_{{c_singular_name}});
|
||||
{{/is_list}}
|
||||
{{^is_list}}
|
||||
is_valid = ari_validate_{{c_name}}(
|
||||
response->message);
|
||||
{{/is_list}}
|
||||
{{/response_class}}
|
||||
} else {
|
||||
ast_log(LOG_ERROR, "Invalid error response %d for {{path}}\n", code);
|
||||
is_valid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid) {
|
||||
ast_log(LOG_ERROR, "Response validation failed for {{path}}\n");
|
||||
stasis_http_response_error(response, 500,
|
||||
"Internal Server Error", "Response validation failed");
|
||||
}
|
||||
#endif /* AST_DEVMODE */
|
||||
}
|
||||
{{/is_req}}
|
||||
{{#is_websocket}}
|
||||
@@ -81,7 +123,12 @@ static void stasis_http_{{c_nickname}}_ws_cb(struct ast_websocket *ws_session,
|
||||
struct ast_variable *path_vars = NULL;
|
||||
{{/has_path_parameters}}
|
||||
{{> param_parsing}}
|
||||
session = ari_websocket_session_create(ws_session);
|
||||
#if defined(AST_DEVMODE)
|
||||
session = ari_websocket_session_create(ws_session,
|
||||
ari_validate_{{response_class.c_name}});
|
||||
#else
|
||||
session = ari_websocket_session_create(ws_session, NULL);
|
||||
#endif
|
||||
if (!session) {
|
||||
ast_log(LOG_ERROR, "Failed to create ARI session\n");
|
||||
return;
|
||||
|
@@ -1,151 +0,0 @@
|
||||
{{#api_declaration}}
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* {{{copyright}}}
|
||||
*
|
||||
* {{{author}}}
|
||||
{{! Template Copyright
|
||||
* Copyright (C) 2013, Digium, Inc.
|
||||
*
|
||||
* Kinsey Moore <kmoore@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.
|
||||
*/
|
||||
|
||||
{{! Template for rendering the res_ module for an HTTP resource. }}
|
||||
/*
|
||||
{{> do-not-edit}}
|
||||
* This file is generated by a mustache template. Please see the original
|
||||
* template in rest-api-templates/res_stasis_http_resource.c.mustache
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief {{{description}}}
|
||||
*
|
||||
* \author {{{author}}}
|
||||
*/
|
||||
|
||||
/*** MODULEINFO
|
||||
<support_level>core</support_level>
|
||||
***/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/json.h"
|
||||
#include "stasis_json/resource_{{name}}.h"
|
||||
{{#has_events}}
|
||||
#include "asterisk/stasis_channels.h"
|
||||
#include "asterisk/stasis_bridging.h"
|
||||
|
||||
{{#events}}
|
||||
{{> event_function_decl}}
|
||||
)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
|
||||
{{#has_properties}}
|
||||
struct ast_json *validator;
|
||||
{{/has_properties}}
|
||||
{{#channel}}
|
||||
int ret;
|
||||
{{/channel}}
|
||||
{{#bridge}}
|
||||
{{^channel}}
|
||||
int ret;
|
||||
{{/channel}}
|
||||
{{/bridge}}
|
||||
|
||||
{{#channel}}
|
||||
ast_assert(channel_snapshot != NULL);
|
||||
{{/channel}}
|
||||
{{#bridge}}
|
||||
ast_assert(bridge_snapshot != NULL);
|
||||
{{/bridge}}
|
||||
{{#has_properties}}
|
||||
ast_assert(blob != NULL);
|
||||
{{#channel}}
|
||||
ast_assert(ast_json_object_get(blob, "channel") == NULL);
|
||||
{{/channel}}
|
||||
{{#bridge}}
|
||||
ast_assert(ast_json_object_get(blob, "bridge") == NULL);
|
||||
{{/bridge}}
|
||||
ast_assert(ast_json_object_get(blob, "type") == NULL);
|
||||
{{#properties}}
|
||||
|
||||
validator = ast_json_object_get(blob, "{{name}}");
|
||||
if (validator) {
|
||||
/* do validation? XXX */
|
||||
{{#required}}
|
||||
} else {
|
||||
/* fail message generation if the required parameter doesn't exist */
|
||||
return NULL;
|
||||
{{/required}}
|
||||
}
|
||||
{{/properties}}
|
||||
|
||||
event = ast_json_deep_copy(blob);
|
||||
{{/has_properties}}
|
||||
{{^has_properties}}
|
||||
|
||||
event = ast_json_object_create();
|
||||
{{/has_properties}}
|
||||
if (!event) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
{{#channel}}
|
||||
ret = ast_json_object_set(event,
|
||||
"channel", ast_channel_snapshot_to_json(channel_snapshot));
|
||||
if (ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
{{/channel}}
|
||||
{{#bridge}}
|
||||
ret = ast_json_object_set(event,
|
||||
"bridge", ast_bridge_snapshot_to_json(bridge_snapshot));
|
||||
if (ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
{{/bridge}}
|
||||
message = ast_json_pack("{s: o}", "{{c_id}}", ast_json_ref(event));
|
||||
if (!message) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ast_json_ref(message);
|
||||
}
|
||||
|
||||
{{/events}}
|
||||
{{/has_events}}
|
||||
static int load_module(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Stasis JSON Generators and Validators - {{{description}}}",
|
||||
.load = load_module,
|
||||
.unload = unload_module,
|
||||
.load_pri = AST_MODPRI_DEFAULT,
|
||||
);
|
||||
{{/api_declaration}}
|
@@ -1,12 +0,0 @@
|
||||
{
|
||||
{{#api_declaration}}
|
||||
{{#has_events}}
|
||||
global:
|
||||
{{#events}}
|
||||
LINKER_SYMBOL_PREFIXstasis_json_event_{{c_id}}_create;
|
||||
{{/events}}
|
||||
{{/has_events}}
|
||||
{{/api_declaration}}
|
||||
local:
|
||||
*;
|
||||
};
|
@@ -1,83 +0,0 @@
|
||||
{{#api_declaration}}
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* {{{copyright}}}
|
||||
*
|
||||
* {{{author}}}
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*! \file
|
||||
*
|
||||
* \brief Generated file - declares stubs to be implemented in
|
||||
* res/stasis_json/resource_{{name}}.c
|
||||
*
|
||||
* {{{description}}}
|
||||
*
|
||||
* \author {{{author}}}
|
||||
*/
|
||||
|
||||
/*
|
||||
{{> do-not-edit}}
|
||||
* This file is generated by a mustache template. Please see the original
|
||||
* template in rest-api-templates/stasis_http_resource.h.mustache
|
||||
*/
|
||||
|
||||
#ifndef _ASTERISK_RESOURCE_{{name_caps}}_H
|
||||
#define _ASTERISK_RESOURCE_{{name_caps}}_H
|
||||
|
||||
{{#has_events}}
|
||||
struct ast_channel_snapshot;
|
||||
struct ast_bridge_snapshot;
|
||||
|
||||
{{#events}}
|
||||
/*!
|
||||
* \brief {{description}}
|
||||
{{#notes}}
|
||||
*
|
||||
* {{{notes}}}
|
||||
{{/notes}}
|
||||
*
|
||||
{{#channel}}
|
||||
* \param channel {{#channel_desc}}{{channel_desc}}{{/channel_desc}}{{^channel_desc}}The channel to be used to generate this event{{/channel_desc}}
|
||||
{{/channel}}
|
||||
{{#bridge}}
|
||||
* \param bridge {{#bridge_desc}}{{bridge_desc}}{{/bridge_desc}}{{^bridge_desc}}The bridge to be used to generate this event{{/bridge_desc}}
|
||||
{{/bridge}}
|
||||
{{#has_properties}}
|
||||
* \param blob JSON blob containing the following parameters:
|
||||
{{/has_properties}}
|
||||
{{#properties}}
|
||||
* - {{name}}: {{type}} {{#description}}- {{description}}{{/description}}{{#required}} (required){{/required}}
|
||||
{{/properties}}
|
||||
*
|
||||
* \retval NULL on error
|
||||
* \retval JSON (ast_json) describing the event
|
||||
*/
|
||||
{{> event_function_decl}}
|
||||
);
|
||||
|
||||
{{/events}}
|
||||
{{/has_events}}
|
||||
/*
|
||||
* JSON models
|
||||
*
|
||||
{{#models}}
|
||||
* {{id}}
|
||||
{{#properties}}
|
||||
* - {{name}}: {{type}}{{#required}} (required){{/required}}
|
||||
{{/properties}}
|
||||
{{/models}} */
|
||||
|
||||
#endif /* _ASTERISK_RESOURCE_{{name_caps}}_H */
|
||||
{{/api_declaration}}
|
@@ -29,16 +29,101 @@ See https://github.com/wordnik/swagger-core/wiki/API-Declaration for the spec.
|
||||
import json
|
||||
import os.path
|
||||
import pprint
|
||||
import re
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
try:
|
||||
from collections import OrderedDict
|
||||
except ImportError:
|
||||
from odict import OrderedDict
|
||||
# I'm not quite sure what was in Swagger 1.2, but apparently I missed it
|
||||
SWAGGER_VERSIONS = ["1.1", "1.3"]
|
||||
|
||||
SWAGGER_PRIMITIVES = [
|
||||
'void',
|
||||
'string',
|
||||
'boolean',
|
||||
'number',
|
||||
'int',
|
||||
'long',
|
||||
'double',
|
||||
'float',
|
||||
'Date',
|
||||
]
|
||||
|
||||
|
||||
SWAGGER_VERSION = "1.1"
|
||||
class Stringify(object):
|
||||
"""Simple mix-in to make the repr of the model classes more meaningful.
|
||||
"""
|
||||
def __repr__(self):
|
||||
return "%s(%s)" % (self.__class__, pprint.saferepr(self.__dict__))
|
||||
|
||||
|
||||
def compare_versions(lhs, rhs):
|
||||
'''Performs a lexicographical comparison between two version numbers.
|
||||
|
||||
This properly handles simple major.minor.whatever.sure.why.not version
|
||||
numbers, but fails miserably if there's any letters in there.
|
||||
|
||||
For reference:
|
||||
1.0 == 1.0
|
||||
1.0 < 1.0.1
|
||||
1.2 < 1.10
|
||||
|
||||
@param lhs Left hand side of the comparison
|
||||
@param rhs Right hand side of the comparison
|
||||
@return < 0 if lhs < rhs
|
||||
@return == 0 if lhs == rhs
|
||||
@return > 0 if lhs > rhs
|
||||
'''
|
||||
lhs = [int(v) for v in lhs.split('.')]
|
||||
rhs = [int(v) for v in rhs.split('.')]
|
||||
return cmp(lhs, rhs)
|
||||
|
||||
|
||||
class ParsingContext(object):
|
||||
"""Context information for parsing.
|
||||
|
||||
This object is immutable. To change contexts (like adding an item to the
|
||||
stack), use the next() and next_stack() functions to build a new one.
|
||||
"""
|
||||
|
||||
def __init__(self, swagger_version, stack):
|
||||
self.__swagger_version = swagger_version
|
||||
self.__stack = stack
|
||||
|
||||
def __repr__(self):
|
||||
return "ParsingContext(swagger_version=%s, stack=%s)" % (
|
||||
self.swagger_version, self.stack)
|
||||
|
||||
def get_swagger_version(self):
|
||||
return self.__swagger_version
|
||||
|
||||
def get_stack(self):
|
||||
return self.__stack
|
||||
|
||||
swagger_version = property(get_swagger_version)
|
||||
|
||||
stack = property(get_stack)
|
||||
|
||||
def version_less_than(self, ver):
|
||||
return compare_versions(self.swagger_version, ver) < 0
|
||||
|
||||
def next_stack(self, json, id_field):
|
||||
"""Returns a new item pushed to the stack.
|
||||
|
||||
@param json: Current JSON object.
|
||||
@param id_field: Field identifying this object.
|
||||
@return New context with additional item in the stack.
|
||||
"""
|
||||
if not id_field in json:
|
||||
raise SwaggerError("Missing id_field: %s" % id_field, self)
|
||||
new_stack = self.stack + ['%s=%s' % (id_field, str(json[id_field]))]
|
||||
return ParsingContext(self.swagger_version, new_stack)
|
||||
|
||||
def next(self, version=None, stack=None):
|
||||
if version is None:
|
||||
version = self.version
|
||||
if stack is None:
|
||||
stack = self.stack
|
||||
return ParsingContext(version, stack)
|
||||
|
||||
|
||||
class SwaggerError(Exception):
|
||||
@@ -50,7 +135,7 @@ class SwaggerError(Exception):
|
||||
"""Ctor.
|
||||
|
||||
@param msg: String message for the error.
|
||||
@param context: Array of strings for current context in the API.
|
||||
@param context: ParsingContext object
|
||||
@param cause: Optional exception that caused this one.
|
||||
"""
|
||||
super(Exception, self).__init__(msg, context, cause)
|
||||
@@ -61,7 +146,7 @@ class SwaggerPostProcessor(object):
|
||||
fields to model objects for additional information to use in the
|
||||
templates.
|
||||
"""
|
||||
def process_api(self, resource_api, context):
|
||||
def process_resource_api(self, resource_api, context):
|
||||
"""Post process a ResourceApi object.
|
||||
|
||||
@param resource_api: ResourceApi object.
|
||||
@@ -69,6 +154,14 @@ class SwaggerPostProcessor(object):
|
||||
"""
|
||||
pass
|
||||
|
||||
def process_api(self, api, context):
|
||||
"""Post process an Api object.
|
||||
|
||||
@param api: Api object.
|
||||
@param context: Current context in the API.
|
||||
"""
|
||||
pass
|
||||
|
||||
def process_operation(self, operation, context):
|
||||
"""Post process a Operation object.
|
||||
|
||||
@@ -85,12 +178,37 @@ class SwaggerPostProcessor(object):
|
||||
"""
|
||||
pass
|
||||
|
||||
def process_model(self, model, context):
|
||||
"""Post process a Model object.
|
||||
|
||||
class Stringify(object):
|
||||
"""Simple mix-in to make the repr of the model classes more meaningful.
|
||||
"""
|
||||
def __repr__(self):
|
||||
return "%s(%s)" % (self.__class__, pprint.saferepr(self.__dict__))
|
||||
@param model: Model object.
|
||||
@param context: Current context in the API.
|
||||
"""
|
||||
pass
|
||||
|
||||
def process_property(self, property, context):
|
||||
"""Post process a Property object.
|
||||
|
||||
@param property: Property object.
|
||||
@param context: Current context in the API.
|
||||
"""
|
||||
pass
|
||||
|
||||
def process_type(self, swagger_type, context):
|
||||
"""Post process a SwaggerType object.
|
||||
|
||||
@param swagger_type: ResourceListing object.
|
||||
@param context: Current context in the API.
|
||||
"""
|
||||
pass
|
||||
|
||||
def process_resource_listing(self, resource_listing, context):
|
||||
"""Post process the overall ResourceListing object.
|
||||
|
||||
@param resource_listing: ResourceListing object.
|
||||
@param context: Current context in the API.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class AllowableRange(Stringify):
|
||||
@@ -158,17 +276,22 @@ class Parameter(Stringify):
|
||||
self.allow_multiple = None
|
||||
|
||||
def load(self, parameter_json, processor, context):
|
||||
context = add_context(context, parameter_json, 'name')
|
||||
context = context.next_stack(parameter_json, 'name')
|
||||
validate_required_fields(parameter_json, self.required_fields, context)
|
||||
self.name = parameter_json.get('name')
|
||||
self.param_type = parameter_json.get('paramType')
|
||||
self.description = parameter_json.get('description') or ''
|
||||
self.data_type = parameter_json.get('dataType')
|
||||
self.required = parameter_json.get('required') or False
|
||||
self.default_value = parameter_json.get('defaultValue')
|
||||
self.allowable_values = load_allowable_values(
|
||||
parameter_json.get('allowableValues'), context)
|
||||
self.allow_multiple = parameter_json.get('allowMultiple') or False
|
||||
processor.process_parameter(self, context)
|
||||
if parameter_json.get('allowedValues'):
|
||||
raise SwaggerError(
|
||||
"Field 'allowedValues' invalid; use 'allowableValues'",
|
||||
context)
|
||||
return self
|
||||
|
||||
def is_type(self, other_type):
|
||||
@@ -188,13 +311,41 @@ class ErrorResponse(Stringify):
|
||||
self.reason = None
|
||||
|
||||
def load(self, err_json, processor, context):
|
||||
context = add_context(context, err_json, 'code')
|
||||
context = context.next_stack(err_json, 'code')
|
||||
validate_required_fields(err_json, self.required_fields, context)
|
||||
self.code = err_json.get('code')
|
||||
self.reason = err_json.get('reason')
|
||||
return self
|
||||
|
||||
|
||||
class SwaggerType(Stringify):
|
||||
"""Model of a data type.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.name = None
|
||||
self.is_discriminator = None
|
||||
self.is_list = None
|
||||
self.singular_name = None
|
||||
self.is_primitive = None
|
||||
|
||||
def load(self, type_name, processor, context):
|
||||
# Some common errors
|
||||
if type_name == 'integer':
|
||||
raise SwaggerError("The type for integer should be 'int'", context)
|
||||
|
||||
self.name = type_name
|
||||
type_param = get_list_parameter_type(self.name)
|
||||
self.is_list = type_param is not None
|
||||
if self.is_list:
|
||||
self.singular_name = type_param
|
||||
else:
|
||||
self.singular_name = self.name
|
||||
self.is_primitive = self.singular_name in SWAGGER_PRIMITIVES
|
||||
processor.process_type(self, context)
|
||||
return self
|
||||
|
||||
|
||||
class Operation(Stringify):
|
||||
"""Model of an operation on an API
|
||||
|
||||
@@ -213,11 +364,14 @@ class Operation(Stringify):
|
||||
self.error_responses = []
|
||||
|
||||
def load(self, op_json, processor, context):
|
||||
context = add_context(context, op_json, 'nickname')
|
||||
context = context.next_stack(op_json, 'nickname')
|
||||
validate_required_fields(op_json, self.required_fields, context)
|
||||
self.http_method = op_json.get('httpMethod')
|
||||
self.nickname = op_json.get('nickname')
|
||||
self.response_class = op_json.get('responseClass')
|
||||
response_class = op_json.get('responseClass')
|
||||
self.response_class = response_class and SwaggerType().load(
|
||||
response_class, processor, context)
|
||||
|
||||
# Specifying WebSocket URL's is our own extension
|
||||
self.is_websocket = op_json.get('upgrade') == 'websocket'
|
||||
self.is_req = not self.is_websocket
|
||||
@@ -247,6 +401,7 @@ class Operation(Stringify):
|
||||
err_json = op_json.get('errorResponses') or []
|
||||
self.error_responses = [
|
||||
ErrorResponse().load(j, processor, context) for j in err_json]
|
||||
self.has_error_responses = self.error_responses != []
|
||||
processor.process_operation(self, context)
|
||||
return self
|
||||
|
||||
@@ -265,7 +420,7 @@ class Api(Stringify):
|
||||
self.operations = []
|
||||
|
||||
def load(self, api_json, processor, context):
|
||||
context = add_context(context, api_json, 'path')
|
||||
context = context.next_stack(api_json, 'path')
|
||||
validate_required_fields(api_json, self.required_fields, context)
|
||||
self.path = api_json.get('path')
|
||||
self.description = api_json.get('description')
|
||||
@@ -274,9 +429,20 @@ class Api(Stringify):
|
||||
Operation().load(j, processor, context) for j in op_json]
|
||||
self.has_websocket = \
|
||||
filter(lambda op: op.is_websocket, self.operations) != []
|
||||
processor.process_api(self, context)
|
||||
return self
|
||||
|
||||
|
||||
def get_list_parameter_type(type_string):
|
||||
"""Returns the type parameter if the given type_string is List[].
|
||||
|
||||
@param type_string: Type string to parse
|
||||
@returns Type parameter of the list, or None if not a List.
|
||||
"""
|
||||
list_match = re.match('^List\[(.*)\]$', type_string)
|
||||
return list_match and list_match.group(1)
|
||||
|
||||
|
||||
class Property(Stringify):
|
||||
"""Model of a Swagger property.
|
||||
|
||||
@@ -293,9 +459,15 @@ class Property(Stringify):
|
||||
|
||||
def load(self, property_json, processor, context):
|
||||
validate_required_fields(property_json, self.required_fields, context)
|
||||
self.type = property_json.get('type')
|
||||
# Bit of a hack, but properties do not self-identify
|
||||
context = context.next_stack({'name': self.name}, 'name')
|
||||
self.description = property_json.get('description') or ''
|
||||
self.required = property_json.get('required') or False
|
||||
|
||||
type = property_json.get('type')
|
||||
self.type = type and SwaggerType().load(type, processor, context)
|
||||
|
||||
processor.process_property(self, context)
|
||||
return self
|
||||
|
||||
|
||||
@@ -305,24 +477,95 @@ class Model(Stringify):
|
||||
See https://github.com/wordnik/swagger-core/wiki/datatypes
|
||||
"""
|
||||
|
||||
required_fields = ['description', 'properties']
|
||||
|
||||
def __init__(self):
|
||||
self.id = None
|
||||
self.extends = None
|
||||
self.extends_type = None
|
||||
self.notes = None
|
||||
self.description = None
|
||||
self.properties = None
|
||||
self.__properties = None
|
||||
self.__discriminator = None
|
||||
self.__subtypes = []
|
||||
|
||||
def load(self, id, model_json, processor, context):
|
||||
context = add_context(context, model_json, 'id')
|
||||
# This arrangement is required by the Swagger API spec
|
||||
context = context.next_stack(model_json, 'id')
|
||||
validate_required_fields(model_json, self.required_fields, context)
|
||||
# The duplication of the model's id is required by the Swagger spec.
|
||||
self.id = model_json.get('id')
|
||||
if id != self.id:
|
||||
raise SwaggerError("Model id doesn't match name", c)
|
||||
raise SwaggerError("Model id doesn't match name", context)
|
||||
self.extends = model_json.get('extends')
|
||||
if self.extends and context.version_less_than("1.3"):
|
||||
raise SwaggerError("Type extension support added in Swagger 1.3",
|
||||
context)
|
||||
self.description = model_json.get('description')
|
||||
props = model_json.get('properties').items() or []
|
||||
self.properties = [
|
||||
self.__properties = [
|
||||
Property(k).load(j, processor, context) for (k, j) in props]
|
||||
self.__properties = sorted(self.__properties, key=lambda p: p.name)
|
||||
|
||||
discriminator = model_json.get('discriminator')
|
||||
|
||||
if discriminator:
|
||||
if context.version_less_than("1.3"):
|
||||
raise SwaggerError("Discriminator support added in Swagger 1.3",
|
||||
context)
|
||||
|
||||
discr_props = [p for p in self.__properties if p.name == discriminator]
|
||||
if not discr_props:
|
||||
raise SwaggerError(
|
||||
"Discriminator '%s' does not name a property of '%s'" % (
|
||||
discriminator, self.id),
|
||||
context)
|
||||
|
||||
self.__discriminator = discr_props[0]
|
||||
|
||||
self.model_json = json.dumps(model_json,
|
||||
indent=2, separators=(',', ': '))
|
||||
|
||||
processor.process_model(self, context)
|
||||
return self
|
||||
|
||||
def add_subtype(self, subtype):
|
||||
"""Add subtype to this model.
|
||||
|
||||
@param subtype: Model instance for the subtype.
|
||||
"""
|
||||
self.__subtypes.append(subtype)
|
||||
|
||||
def set_extends_type(self, extends_type):
|
||||
self.extends_type = extends_type
|
||||
|
||||
def discriminator(self):
|
||||
"""Returns the discriminator, digging through base types if needed.
|
||||
"""
|
||||
return self.__discriminator or \
|
||||
self.extends_type and self.extends_type.discriminator()
|
||||
|
||||
def properties(self):
|
||||
base_props = []
|
||||
if self.extends_type:
|
||||
base_props = self.extends_type.properties()
|
||||
return base_props + self.__properties
|
||||
|
||||
def has_properties(self):
|
||||
return len(self.properties()) > 0
|
||||
|
||||
def subtypes(self):
|
||||
"""Returns the full list of all subtypes.
|
||||
"""
|
||||
res = self.__subtypes + \
|
||||
[subsubtypes for subtype in self.__subtypes
|
||||
for subsubtypes in subtype.subtypes()]
|
||||
return sorted(res, key=lambda m: m.id)
|
||||
|
||||
def has_subtypes(self):
|
||||
"""Returns True if type has any subtypes.
|
||||
"""
|
||||
return len(self.subtypes()) > 0
|
||||
|
||||
|
||||
class ApiDeclaration(Stringify):
|
||||
"""Model class for an API Declaration.
|
||||
@@ -345,8 +588,8 @@ class ApiDeclaration(Stringify):
|
||||
self.apis = []
|
||||
self.models = []
|
||||
|
||||
def load_file(self, api_declaration_file, processor, context=[]):
|
||||
context = context + [api_declaration_file]
|
||||
def load_file(self, api_declaration_file, processor):
|
||||
context = ParsingContext(None, [api_declaration_file])
|
||||
try:
|
||||
return self.__load_file(api_declaration_file, processor, context)
|
||||
except SwaggerError:
|
||||
@@ -376,9 +619,10 @@ class ApiDeclaration(Stringify):
|
||||
"""
|
||||
# If the version doesn't match, all bets are off.
|
||||
self.swagger_version = api_decl_json.get('swaggerVersion')
|
||||
if self.swagger_version != SWAGGER_VERSION:
|
||||
context = context.next(version=self.swagger_version)
|
||||
if not self.swagger_version in SWAGGER_VERSIONS:
|
||||
raise SwaggerError(
|
||||
"Unsupported Swagger version %s" % swagger_version, context)
|
||||
"Unsupported Swagger version %s" % self.swagger_version, context)
|
||||
|
||||
validate_required_fields(api_decl_json, self.required_fields, context)
|
||||
|
||||
@@ -391,9 +635,19 @@ class ApiDeclaration(Stringify):
|
||||
self.apis = [
|
||||
Api().load(j, processor, context) for j in api_json]
|
||||
models = api_decl_json.get('models').items() or []
|
||||
self.models = [
|
||||
Model().load(k, j, processor, context) for (k, j) in models]
|
||||
|
||||
self.models = [Model().load(id, json, processor, context)
|
||||
for (id, json) in models]
|
||||
self.models = sorted(self.models, key=lambda m: m.id)
|
||||
# Now link all base/extended types
|
||||
model_dict = dict((m.id, m) for m in self.models)
|
||||
for m in self.models:
|
||||
if m.extends:
|
||||
extends_type = model_dict.get(m.extends)
|
||||
if not extends_type:
|
||||
raise SwaggerError("%s extends non-existing model %s",
|
||||
m.id, m.extends)
|
||||
extends_type.add_subtype(m)
|
||||
m.set_extends_type(extends_type)
|
||||
return self
|
||||
|
||||
|
||||
@@ -409,20 +663,20 @@ class ResourceApi(Stringify):
|
||||
self.api_declaration = None
|
||||
|
||||
def load(self, api_json, processor, context):
|
||||
context = add_context(context, api_json, 'path')
|
||||
context = context.next_stack(api_json, 'path')
|
||||
validate_required_fields(api_json, self.required_fields, context)
|
||||
self.path = api_json['path']
|
||||
self.description = api_json['description']
|
||||
|
||||
if not self.path or self.path[0] != '/':
|
||||
raise SwaggerError("Path must start with /", context)
|
||||
processor.process_api(self, context)
|
||||
processor.process_resource_api(self, context)
|
||||
return self
|
||||
|
||||
def load_api_declaration(self, base_dir, processor):
|
||||
self.file = (base_dir + self.path).replace('{format}', 'json')
|
||||
self.api_declaration = ApiDeclaration().load_file(self.file, processor)
|
||||
processor.process_api(self, [self.file])
|
||||
processor.process_resource_api(self, [self.file])
|
||||
|
||||
|
||||
class ResourceListing(Stringify):
|
||||
@@ -438,7 +692,7 @@ class ResourceListing(Stringify):
|
||||
self.apis = None
|
||||
|
||||
def load_file(self, resource_file, processor):
|
||||
context = [resource_file]
|
||||
context = ParsingContext(None, [resource_file])
|
||||
try:
|
||||
return self.__load_file(resource_file, processor, context)
|
||||
except SwaggerError:
|
||||
@@ -455,7 +709,7 @@ class ResourceListing(Stringify):
|
||||
def load(self, resources_json, processor, context):
|
||||
# If the version doesn't match, all bets are off.
|
||||
self.swagger_version = resources_json.get('swaggerVersion')
|
||||
if self.swagger_version != SWAGGER_VERSION:
|
||||
if not self.swagger_version in SWAGGER_VERSIONS:
|
||||
raise SwaggerError(
|
||||
"Unsupported Swagger version %s" % swagger_version, context)
|
||||
|
||||
@@ -465,6 +719,7 @@ class ResourceListing(Stringify):
|
||||
apis_json = resources_json['apis']
|
||||
self.apis = [
|
||||
ResourceApi().load(j, processor, context) for j in apis_json]
|
||||
processor.process_resource_listing(self, context)
|
||||
return self
|
||||
|
||||
|
||||
@@ -482,16 +737,3 @@ def validate_required_fields(json, required_fields, context):
|
||||
if missing_fields:
|
||||
raise SwaggerError(
|
||||
"Missing fields: %s" % ', '.join(missing_fields), context)
|
||||
|
||||
|
||||
def add_context(context, json, id_field):
|
||||
"""Returns a new context with a new item added to it.
|
||||
|
||||
@param context: Old context.
|
||||
@param json: Current JSON object.
|
||||
@param id_field: Field identifying this object.
|
||||
@return New context with additional item.
|
||||
"""
|
||||
if not id_field in json:
|
||||
raise SwaggerError("Missing id_field: %s" % id_field, context)
|
||||
return context + ['%s=%s' % (id_field, str(json[id_field]))]
|
||||
|
@@ -16,8 +16,11 @@
|
||||
# at the top of the source tree.
|
||||
#
|
||||
|
||||
import filecmp
|
||||
import os.path
|
||||
import pystache
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
|
||||
class Transform(object):
|
||||
@@ -46,8 +49,14 @@ class Transform(object):
|
||||
"""
|
||||
dest_file = pystache.render(self.dest_file_template, model)
|
||||
dest_file = os.path.join(dest_dir, dest_file)
|
||||
if os.path.exists(dest_file) and not self.overwrite:
|
||||
dest_exists = os.path.exists(dest_file)
|
||||
if dest_exists and not self.overwrite:
|
||||
return
|
||||
print "Rendering %s" % dest_file
|
||||
with open(dest_file, "w") as out:
|
||||
tmp_file = tempfile.mkstemp()
|
||||
with tempfile.NamedTemporaryFile() as out:
|
||||
out.write(renderer.render(self.template, model))
|
||||
out.flush()
|
||||
|
||||
if not dest_exists or not filecmp.cmp(out.name, dest_file):
|
||||
print "Writing %s" % dest_file
|
||||
shutil.copyfile(out.name, dest_file)
|
||||
|
@@ -41,6 +41,7 @@
|
||||
"models": {
|
||||
"AsteriskInfo": {
|
||||
"id": "AsteriskInfo",
|
||||
"description": "Asterisk system information",
|
||||
"properties": {}
|
||||
}
|
||||
}
|
||||
|
@@ -31,8 +31,8 @@
|
||||
"required": false,
|
||||
"allowMultiple": false,
|
||||
"dataType": "string",
|
||||
"allowedValues": {
|
||||
"type": "LIST",
|
||||
"allowableValues": {
|
||||
"valueType": "LIST",
|
||||
"values": [
|
||||
"mixing",
|
||||
"holding"
|
||||
@@ -61,6 +61,12 @@
|
||||
"allowMultiple": false,
|
||||
"dataType": "string"
|
||||
}
|
||||
],
|
||||
"errorResponses": [
|
||||
{
|
||||
"code": 404,
|
||||
"reason": "Bridge not found"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -78,6 +84,12 @@
|
||||
"allowMultiple": false,
|
||||
"dataType": "string"
|
||||
}
|
||||
],
|
||||
"errorResponses": [
|
||||
{
|
||||
"code": 404,
|
||||
"reason": "Bridge not found"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -108,6 +120,20 @@
|
||||
"allowMultiple": true,
|
||||
"dataType": "string"
|
||||
}
|
||||
],
|
||||
"errorResponses": [
|
||||
{
|
||||
"code": 404,
|
||||
"reason": "Bridge not found"
|
||||
},
|
||||
{
|
||||
"code": 409,
|
||||
"reason": "Bridge not in Stasis application"
|
||||
},
|
||||
{
|
||||
"code": 422,
|
||||
"reason": "Channel not found, or not in Stasis application"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -231,19 +257,35 @@
|
||||
"models": {
|
||||
"Bridge": {
|
||||
"id": "Bridge",
|
||||
"description": "The merging of media from one or more channels.\n\nEveryone on the bridge receives the same audio.",
|
||||
"properties": {
|
||||
"bridgeType": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "Unique identifier for this bridge",
|
||||
"required": true
|
||||
},
|
||||
"technology": {
|
||||
"type": "string",
|
||||
"description": "Name of the current bridging technology",
|
||||
"required": true
|
||||
},
|
||||
"bridge_type": {
|
||||
"type": "string",
|
||||
"description": "Type of bridge technology",
|
||||
"required": true,
|
||||
"allowedValues": {
|
||||
"type": "LIST",
|
||||
"allowableValues": {
|
||||
"valueType": "LIST",
|
||||
"values": [
|
||||
"mixing",
|
||||
"holding"
|
||||
]
|
||||
}
|
||||
},
|
||||
"bridge_class": {
|
||||
"type": "string",
|
||||
"description": "Bridging class",
|
||||
"required": true
|
||||
},
|
||||
"channels": {
|
||||
"type": "List[string]",
|
||||
"description": "Id's of channels participating in this bridge",
|
||||
|
@@ -286,6 +286,10 @@
|
||||
{
|
||||
"code": 404,
|
||||
"reason": "Channel not found"
|
||||
},
|
||||
{
|
||||
"code": 409,
|
||||
"reason": "Channel not in a Stasis application"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -616,11 +620,7 @@
|
||||
},
|
||||
{
|
||||
"code": 409,
|
||||
"reason": "Channel is not in a Stasis application."
|
||||
},
|
||||
{
|
||||
"code": 409,
|
||||
"reason": "The channel is currently bridged with other channels."
|
||||
"reason": "Channel is not in a Stasis application, or the channel is currently bridged with other channels."
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -630,10 +630,12 @@
|
||||
"models": {
|
||||
"Dialed": {
|
||||
"id": "Dialed",
|
||||
"description": "Dialed channel information.",
|
||||
"properties": {}
|
||||
},
|
||||
"DialplanCEP": {
|
||||
"id": "DialplanCEP",
|
||||
"description": "Dialplan location (context/extension/priority)",
|
||||
"properties": {
|
||||
"context": {
|
||||
"required": true,
|
||||
@@ -654,6 +656,7 @@
|
||||
},
|
||||
"CallerID": {
|
||||
"id": "CallerID",
|
||||
"description": "Caller identification",
|
||||
"properties": {
|
||||
"name": {
|
||||
"required": true,
|
||||
@@ -667,11 +670,12 @@
|
||||
},
|
||||
"Channel": {
|
||||
"id": "Channel",
|
||||
"description": "A specific communication connection between Asterisk and an Endpoint.",
|
||||
"properties": {
|
||||
"uniqueid": {
|
||||
"id": {
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"description": "Unique identifier of the channel"
|
||||
"description": "Unique identifier of the channel.\n\nThis is the same as the Uniqueid field in AMI."
|
||||
},
|
||||
"name": {
|
||||
"required": true,
|
||||
@@ -679,47 +683,24 @@
|
||||
"description": "Name of the channel (i.e. SIP/foo-0000a7e3)"
|
||||
},
|
||||
"state": {
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
"accountcode": {
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
"peeraccount": {
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
"userfield": {
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
"linkedid": {
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
"parkinglot": {
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
"hangupsource": {
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
"appl": {
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"description": "Currently executing dialplan application"
|
||||
},
|
||||
"data": {
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"description": "Arguments passed to appl"
|
||||
},
|
||||
"dialplan": {
|
||||
"required": true,
|
||||
"type": "DialplanCEP",
|
||||
"description": "Current location in the dialplan"
|
||||
"allowableValues": {
|
||||
"valueType": "LIST",
|
||||
"values": [
|
||||
"Down",
|
||||
"Rsrved",
|
||||
"OffHook",
|
||||
"Dialing",
|
||||
"Ring",
|
||||
"Ringing",
|
||||
"Up",
|
||||
"Busy",
|
||||
"Dialing Offhook",
|
||||
"Pre-ring",
|
||||
"Unknown"
|
||||
]
|
||||
}
|
||||
},
|
||||
"caller": {
|
||||
"required": true,
|
||||
@@ -729,50 +710,21 @@
|
||||
"required": true,
|
||||
"type": "CallerID"
|
||||
},
|
||||
"accountcode": {
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
"dialplan": {
|
||||
"required": true,
|
||||
"type": "DialplanCEP",
|
||||
"description": "Current location in the dialplan"
|
||||
},
|
||||
"creationtime": {
|
||||
"required": true,
|
||||
"type": "Date",
|
||||
"description": "Timestamp when channel was created"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Playback": {
|
||||
"id": "Playback",
|
||||
"description": "Object representing the playback of media to a channel",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "ID for this playback operation",
|
||||
"required": true
|
||||
},
|
||||
"media_uri": {
|
||||
"type": "string",
|
||||
"description": "URI for the media to play back.",
|
||||
"required": true
|
||||
},
|
||||
"target_uri": {
|
||||
"type": "string",
|
||||
"description": "URI for the channel or bridge to play the media on",
|
||||
"required": true
|
||||
},
|
||||
"language": {
|
||||
"type": "string",
|
||||
"description": "For media types that support multiple languages, the language requested for playback."
|
||||
},
|
||||
"state": {
|
||||
"type": "string",
|
||||
"description": "Current state of the playback operation.",
|
||||
"required": true,
|
||||
"allowableValues": {
|
||||
"valueType": "LIST",
|
||||
"values": [
|
||||
"queued",
|
||||
"playing",
|
||||
"complete"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -69,7 +69,7 @@
|
||||
"models": {
|
||||
"Endpoint": {
|
||||
"id": "Endpoint",
|
||||
"description": "A snapshot of an endpoint. Unlike most resources, which have a single unique identifier, an endpoint is uniquely identified by the technology/resource pair.",
|
||||
"description": "An external device that may offer/accept calls to/from Asterisk.\n\nUnlike most resources, which have a single unique identifier, an endpoint is uniquely identified by the technology/resource pair.",
|
||||
"properties": {
|
||||
"technology": {
|
||||
"type": "string",
|
||||
@@ -80,6 +80,24 @@
|
||||
"type": "string",
|
||||
"description": "Identifier of the endpoint, specific to the given technology.",
|
||||
"required": true
|
||||
},
|
||||
"state": {
|
||||
"type": "string",
|
||||
"description": "Endpoint's state",
|
||||
"required": false,
|
||||
"allowableValues": {
|
||||
"valueType": "LIST",
|
||||
"values": [
|
||||
"unknown",
|
||||
"offline",
|
||||
"online"
|
||||
]
|
||||
}
|
||||
},
|
||||
"channel_ids": {
|
||||
"type": "List[string]",
|
||||
"description": "Id's of channels associated with this endpoint",
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
"_author": "David M. Lee, II <dlee@digium.com>",
|
||||
"_svn_revision": "$Revision$",
|
||||
"apiVersion": "0.0.1",
|
||||
"swaggerVersion": "1.1",
|
||||
"swaggerVersion": "1.3",
|
||||
"basePath": "http://localhost:8088/stasis",
|
||||
"resourcePath": "/api-docs/events.{format}",
|
||||
"apis": [
|
||||
@@ -35,37 +35,29 @@
|
||||
"models": {
|
||||
"Event": {
|
||||
"id": "Event",
|
||||
"description": "Asynchronous events from Asterisk. The non-required fields of this object are mutually exclusive.",
|
||||
"description": "Base type for asynchronous events from Asterisk.",
|
||||
"discriminator": "type",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"description": "Indicates the type of this event."
|
||||
},
|
||||
"application": {
|
||||
"type": "string",
|
||||
"description": "Name of the application receiving the event.",
|
||||
"required": true
|
||||
},
|
||||
"application_replaced": { "type": "ApplicationReplaced" },
|
||||
"bridge_created": { "type": "BridgeCreated" },
|
||||
"bridge_destroyed": { "type": "BridgeDestroyed" },
|
||||
"bridge_merged": { "type": "BridgeMerged" },
|
||||
"channel_created": { "type": "ChannelCreated" },
|
||||
"channel_destroyed": { "type": "ChannelDestroyed" },
|
||||
"channel_snapshot": { "type": "ChannelSnapshot" },
|
||||
"channel_entered_bridge": { "type": "ChannelEnteredBridge" },
|
||||
"channel_left_bridge": { "type": "ChannelLeftBridge" },
|
||||
"channel_state_change": { "type": "ChannelStateChange" },
|
||||
"channel_dtmf_received": { "type": "ChannelDtmfReceived" },
|
||||
"channel_dialplan": { "type": "ChannelDialplan" },
|
||||
"channel_caller_id": { "type": "ChannelCallerId" },
|
||||
"channel_userevent": { "type": "ChannelUserevent" },
|
||||
"channel_hangup_request": { "type": "ChannelHangupRequest" },
|
||||
"channel_varset": { "type": "ChannelVarset" },
|
||||
"stasis_end": { "type": "StasisEnd" },
|
||||
"stasis_start": { "type": "StasisStart" },
|
||||
"playback_started": { "type": "PlaybackStarted" },
|
||||
"playback_finished": { "type": "PlaybackFinished" }
|
||||
"timestamp": {
|
||||
"type": "Date",
|
||||
"description": "Time at which this event was created.",
|
||||
"required": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"PlaybackStarted": {
|
||||
"id": "PlaybackStarted",
|
||||
"extends": "Event",
|
||||
"description": "Event showing the start of a media playback operation.",
|
||||
"properties": {
|
||||
"playback": {
|
||||
@@ -77,6 +69,7 @@
|
||||
},
|
||||
"PlaybackFinished": {
|
||||
"id": "PlaybackFinished",
|
||||
"extends": "Event",
|
||||
"description": "Event showing the completion of a media playback operation.",
|
||||
"properties": {
|
||||
"playback": {
|
||||
@@ -88,17 +81,13 @@
|
||||
},
|
||||
"ApplicationReplaced": {
|
||||
"id": "ApplicationReplaced",
|
||||
"description": "Notification that another WebSocket has taken over for an application.",
|
||||
"notes": "An application may only be subscribed to by a single WebSocket at a time. If multiple WebSockets attempt to subscribe to the same application, the newer WebSocket wins, and the older one receives this event.",
|
||||
"properties": {
|
||||
"application": {
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
"extends": "Event",
|
||||
"description": "Notification that another WebSocket has taken over for an application.\n\nAn application may only be subscribed to by a single WebSocket at a time. If multiple WebSockets attempt to subscribe to the same application, the newer WebSocket wins, and the older one receives this event.",
|
||||
"properties": {}
|
||||
},
|
||||
"BridgeCreated": {
|
||||
"id": "BridgeCreated",
|
||||
"extends": "Event",
|
||||
"description": "Notification that a bridge has been created.",
|
||||
"properties": {
|
||||
"bridge": {
|
||||
@@ -109,6 +98,7 @@
|
||||
},
|
||||
"BridgeDestroyed": {
|
||||
"id": "BridgeDestroyed",
|
||||
"extends": "Event",
|
||||
"description": "Notification that a bridge has been destroyed.",
|
||||
"properties": {
|
||||
"bridge": {
|
||||
@@ -119,6 +109,7 @@
|
||||
},
|
||||
"BridgeMerged": {
|
||||
"id": "BridgeMerged",
|
||||
"extends": "Event",
|
||||
"description": "Notification that one bridge has merged into another.",
|
||||
"properties": {
|
||||
"bridge": {
|
||||
@@ -133,6 +124,7 @@
|
||||
},
|
||||
"ChannelCreated": {
|
||||
"id": "ChannelCreated",
|
||||
"extends": "Event",
|
||||
"description": "Notification that a channel has been created.",
|
||||
"properties": {
|
||||
"channel": {
|
||||
@@ -141,24 +133,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"ChannelSnapshot": {
|
||||
"id": "ChannelSnapshot",
|
||||
"description": "Some part of channel state changed.",
|
||||
"properties": {
|
||||
"channel": {
|
||||
"required": true,
|
||||
"type": "Channel"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ChannelDestroyed": {
|
||||
"id": "ChannelDestroyed",
|
||||
"extends": "Event",
|
||||
"description": "Notification that a channel has been destroyed.",
|
||||
"properties": {
|
||||
"cause": {
|
||||
"required": true,
|
||||
"description": "Integer representation of the cause of the hangup",
|
||||
"type": "integer"
|
||||
"type": "int"
|
||||
},
|
||||
"cause_txt": {
|
||||
"required": true,
|
||||
@@ -173,6 +156,7 @@
|
||||
},
|
||||
"ChannelEnteredBridge": {
|
||||
"id": "ChannelEnteredBridge",
|
||||
"extends": "Event",
|
||||
"description": "Notification that a channel has entered a bridge.",
|
||||
"properties": {
|
||||
"bridge": {
|
||||
@@ -186,6 +170,7 @@
|
||||
},
|
||||
"ChannelLeftBridge": {
|
||||
"id": "ChannelLeftBridge",
|
||||
"extends": "Event",
|
||||
"description": "Notification that a channel has left a bridge.",
|
||||
"properties": {
|
||||
"bridge": {
|
||||
@@ -200,6 +185,7 @@
|
||||
},
|
||||
"ChannelStateChange": {
|
||||
"id": "ChannelStateChange",
|
||||
"extends": "Event",
|
||||
"description": "Notification of a channel's state change.",
|
||||
"properties": {
|
||||
"channel": {
|
||||
@@ -210,14 +196,19 @@
|
||||
},
|
||||
"ChannelDtmfReceived": {
|
||||
"id": "ChannelDtmfReceived",
|
||||
"description": "DTMF received on a channel.",
|
||||
"notes": "This event is sent when the DTMF ends. There is no notification about the start of DTMF",
|
||||
"extends": "Event",
|
||||
"description": "DTMF received on a channel.\n\nThis event is sent when the DTMF ends. There is no notification about the start of DTMF",
|
||||
"properties": {
|
||||
"digit": {
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"description": "DTMF digit received (0-9, A-E, # or *)"
|
||||
},
|
||||
"duration_ms": {
|
||||
"required": true,
|
||||
"type": "int",
|
||||
"description": "Number of milliseconds DTMF was received"
|
||||
},
|
||||
"channel": {
|
||||
"required": true,
|
||||
"type": "Channel",
|
||||
@@ -227,32 +218,34 @@
|
||||
},
|
||||
"ChannelDialplan": {
|
||||
"id": "ChannelDialplan",
|
||||
"extends": "Event",
|
||||
"description": "Channel changed location in the dialplan.",
|
||||
"properties": {
|
||||
"application": {
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"description": "The application that the channel is currently in."
|
||||
},
|
||||
"application_data": {
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"description": "The data that was passed to the application when it was invoked."
|
||||
},
|
||||
"channel": {
|
||||
"required": true,
|
||||
"type": "Channel",
|
||||
"description": "The channel that changed dialplan location."
|
||||
},
|
||||
"dialplan_app": {
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"description": "The application about to be executed."
|
||||
},
|
||||
"dialplan_app_data": {
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"description": "The data to be passed to the application."
|
||||
}
|
||||
}
|
||||
},
|
||||
"ChannelCallerId": {
|
||||
"id": "ChannelCallerId",
|
||||
"extends": "Event",
|
||||
"description": "Channel changed Caller ID.",
|
||||
"properties": {
|
||||
"caller_presentation": {
|
||||
"required": true,
|
||||
"type": "integer",
|
||||
"type": "int",
|
||||
"description": "The integer representation of the Caller Presentation value."
|
||||
},
|
||||
"caller_presentation_txt": {
|
||||
@@ -269,6 +262,7 @@
|
||||
},
|
||||
"ChannelUserevent": {
|
||||
"id": "ChannelUserevent",
|
||||
"extends": "Event",
|
||||
"description": "User-generated event with additional user-defined fields in the object.",
|
||||
"properties": {
|
||||
"eventname": {
|
||||
@@ -285,10 +279,11 @@
|
||||
},
|
||||
"ChannelHangupRequest": {
|
||||
"id": "ChannelHangupRequest",
|
||||
"extends": "Event",
|
||||
"description": "A hangup was requested on the channel.",
|
||||
"properties": {
|
||||
"cause": {
|
||||
"type": "integer",
|
||||
"type": "int",
|
||||
"description": "Integer representation of the cause of the hangup."
|
||||
},
|
||||
"soft": {
|
||||
@@ -304,6 +299,7 @@
|
||||
},
|
||||
"ChannelVarset": {
|
||||
"id": "ChannelVarset",
|
||||
"extends": "Event",
|
||||
"description": "Channel variable changed.",
|
||||
"properties": {
|
||||
"variable": {
|
||||
@@ -317,14 +313,15 @@
|
||||
"description": "The new value of the variable."
|
||||
},
|
||||
"channel": {
|
||||
"required": true,
|
||||
"required": false,
|
||||
"type": "Channel",
|
||||
"description": "The channel on which the variable was set."
|
||||
"description": "The channel on which the variable was set.\n\nIf missing, the variable is a global variable."
|
||||
}
|
||||
}
|
||||
},
|
||||
"StasisEnd": {
|
||||
"id": "StasisEnd",
|
||||
"extends": "Event",
|
||||
"description": "Notification that a channel has left a Stasis appliction.",
|
||||
"properties": {
|
||||
"channel": {
|
||||
@@ -335,6 +332,7 @@
|
||||
},
|
||||
"StasisStart": {
|
||||
"id": "StasisStart",
|
||||
"extends": "Event",
|
||||
"description": "Notification that a channel has entered a Stasis appliction.",
|
||||
"properties": {
|
||||
"args": {
|
||||
|
@@ -103,11 +103,39 @@
|
||||
"models": {
|
||||
"Playback": {
|
||||
"id": "Playback",
|
||||
"description": "Object representing the playback of media to a channel",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "ID for this playback operation",
|
||||
"required": true
|
||||
},
|
||||
"media_uri": {
|
||||
"type": "string",
|
||||
"description": "URI for the media to play back.",
|
||||
"required": true
|
||||
},
|
||||
"target_uri": {
|
||||
"type": "string",
|
||||
"description": "URI for the channel or bridge to play the media on",
|
||||
"required": true
|
||||
},
|
||||
"language": {
|
||||
"type": "string",
|
||||
"description": "For media types that support multiple languages, the language requested for playback."
|
||||
},
|
||||
"state": {
|
||||
"type": "string",
|
||||
"description": "Current state of the playback operation.",
|
||||
"required": true,
|
||||
"description": "Playback's identifier.",
|
||||
"type": "string"
|
||||
"allowableValues": {
|
||||
"valueType": "LIST",
|
||||
"values": [
|
||||
"queued",
|
||||
"playing",
|
||||
"complete"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -7,18 +7,6 @@
|
||||
"basePath": "http://localhost:8088/stasis",
|
||||
"resourcePath": "/api-docs/recordings.{format}",
|
||||
"apis": [
|
||||
{
|
||||
"path": "/recordings",
|
||||
"description": "Recordings",
|
||||
"operations": [
|
||||
{
|
||||
"httpMethod": "GET",
|
||||
"summary": "List all recordings.",
|
||||
"nickname": "getRecordings",
|
||||
"responseClass": "List[Recording]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"path": "/recordings/stored",
|
||||
"description": "Recordings",
|
||||
@@ -226,17 +214,9 @@
|
||||
}
|
||||
],
|
||||
"models": {
|
||||
"Recording": {
|
||||
"id": "Recording",
|
||||
"properties": {
|
||||
"id": {
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"StoredRecording": {
|
||||
"id": "StoredRecording",
|
||||
"description": "A past recording that may be played back.",
|
||||
"properties": {
|
||||
"id": {
|
||||
"required": true,
|
||||
@@ -246,7 +226,7 @@
|
||||
"required": true,
|
||||
"type": "List[string]"
|
||||
},
|
||||
"durationSeconds": {
|
||||
"duration_seconds": {
|
||||
"required": false,
|
||||
"type": "int"
|
||||
},
|
||||
@@ -259,6 +239,7 @@
|
||||
},
|
||||
"LiveRecording": {
|
||||
"id": "LiveRecording",
|
||||
"description": "A recording that is in progress",
|
||||
"properties": {
|
||||
"id": {
|
||||
"required": true,
|
||||
|
@@ -60,6 +60,7 @@
|
||||
"models": {
|
||||
"FormatLangPair": {
|
||||
"id": "FormatLangPair",
|
||||
"description": "Identifies the format and language of a sound file",
|
||||
"properties": {
|
||||
"language": {
|
||||
"required": true,
|
||||
@@ -73,6 +74,7 @@
|
||||
},
|
||||
"Sound": {
|
||||
"id": "Sound",
|
||||
"description": "A media file that may be played back.",
|
||||
"properties": {
|
||||
"id": {
|
||||
"required": true,
|
||||
|
431
tests/test_ari_model.c
Normal file
431
tests/test_ari_model.c
Normal file
@@ -0,0 +1,431 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \file
|
||||
* \brief Test the native ARI JSON validators.
|
||||
*
|
||||
* \author David M. Lee, II <dlee@digium.com>
|
||||
*/
|
||||
|
||||
/*** MODULEINFO
|
||||
<depend>TEST_FRAMEWORK</depend>
|
||||
<depend>res_ari_model</depend>
|
||||
<support_level>core</support_level>
|
||||
***/
|
||||
|
||||
#include "asterisk.h"
|
||||
|
||||
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
|
||||
#include "asterisk/utils.h"
|
||||
#include "asterisk/module.h"
|
||||
#include "asterisk/test.h"
|
||||
#include "../res/stasis_http/ari_model_validators.h"
|
||||
|
||||
AST_TEST_DEFINE(validate_byte)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
|
||||
int res;
|
||||
|
||||
switch (cmd) {
|
||||
case TEST_INIT:
|
||||
info->name = __func__;
|
||||
info->category = "/ari/validators/";
|
||||
info->summary = "Test byte validation";
|
||||
info->description =
|
||||
"Test byte validation";
|
||||
return AST_TEST_NOT_RUN;
|
||||
case TEST_EXECUTE:
|
||||
break;
|
||||
}
|
||||
|
||||
uut = ast_json_integer_create(-128);
|
||||
ast_test_validate(test, NULL != uut);
|
||||
ast_test_validate(test, ari_validate_byte(uut));
|
||||
|
||||
res = ast_json_integer_set(uut, 0);
|
||||
ast_test_validate(test, 0 == res);
|
||||
ast_test_validate(test, ari_validate_byte(uut));
|
||||
|
||||
res = ast_json_integer_set(uut, 255);
|
||||
ast_test_validate(test, 0 == res);
|
||||
ast_test_validate(test, ari_validate_byte(uut));
|
||||
|
||||
res = ast_json_integer_set(uut, -129);
|
||||
ast_test_validate(test, 0 == res);
|
||||
ast_test_validate(test, !ari_validate_byte(uut));
|
||||
|
||||
res = ast_json_integer_set(uut, 256);
|
||||
ast_test_validate(test, 0 == res);
|
||||
ast_test_validate(test, !ari_validate_byte(uut));
|
||||
|
||||
str = ast_json_string_create("not a byte");
|
||||
ast_test_validate(test, NULL != str);
|
||||
ast_test_validate(test, !ari_validate_byte(str));
|
||||
|
||||
/* Even if the string has an integral value */
|
||||
res = ast_json_string_set(str, "0");
|
||||
ast_test_validate(test, 0 == res);
|
||||
ast_test_validate(test, !ari_validate_byte(str));
|
||||
|
||||
ast_test_validate(test, !ari_validate_byte(ast_json_null()));
|
||||
|
||||
return AST_TEST_PASS;
|
||||
}
|
||||
|
||||
AST_TEST_DEFINE(validate_boolean)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
|
||||
int res;
|
||||
|
||||
switch (cmd) {
|
||||
case TEST_INIT:
|
||||
info->name = __func__;
|
||||
info->category = "/ari/validators/";
|
||||
info->summary = "Test byte validation";
|
||||
info->description =
|
||||
"Test byte validation";
|
||||
return AST_TEST_NOT_RUN;
|
||||
case TEST_EXECUTE:
|
||||
break;
|
||||
}
|
||||
|
||||
ast_test_validate(test, ari_validate_boolean(ast_json_true()));
|
||||
ast_test_validate(test, ari_validate_boolean(ast_json_false()));
|
||||
|
||||
str = ast_json_string_create("not a bool");
|
||||
ast_test_validate(test, NULL != str);
|
||||
ast_test_validate(test, !ari_validate_boolean(str));
|
||||
|
||||
/* Even if the string has a boolean value */
|
||||
res = ast_json_string_set(str, "true");
|
||||
ast_test_validate(test, 0 == res);
|
||||
ast_test_validate(test, !ari_validate_boolean(str));
|
||||
|
||||
/* Even if the string has a boolean text in it */
|
||||
res = ast_json_string_set(str, "true");
|
||||
ast_test_validate(test, 0 == res);
|
||||
ast_test_validate(test, !ari_validate_boolean(str));
|
||||
|
||||
ast_test_validate(test, !ari_validate_boolean(ast_json_null()));
|
||||
|
||||
return AST_TEST_PASS;
|
||||
}
|
||||
|
||||
AST_TEST_DEFINE(validate_int)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
|
||||
int res;
|
||||
|
||||
switch (cmd) {
|
||||
case TEST_INIT:
|
||||
info->name = __func__;
|
||||
info->category = "/ari/validators/";
|
||||
info->summary = "Test int validation";
|
||||
info->description =
|
||||
"Test int validation";
|
||||
return AST_TEST_NOT_RUN;
|
||||
case TEST_EXECUTE:
|
||||
break;
|
||||
}
|
||||
|
||||
uut = ast_json_integer_create(-2147483648);
|
||||
ast_test_validate(test, NULL != uut);
|
||||
ast_test_validate(test, ari_validate_int(uut));
|
||||
|
||||
res = ast_json_integer_set(uut, 0);
|
||||
ast_test_validate(test, 0 == res);
|
||||
ast_test_validate(test, ari_validate_int(uut));
|
||||
|
||||
res = ast_json_integer_set(uut, 2147483647);
|
||||
ast_test_validate(test, 0 == res);
|
||||
ast_test_validate(test, ari_validate_int(uut));
|
||||
|
||||
res = ast_json_integer_set(uut, -2147483649LL);
|
||||
ast_test_validate(test, 0 == res);
|
||||
ast_test_validate(test, !ari_validate_int(uut));
|
||||
|
||||
res = ast_json_integer_set(uut, 2147483648LL);
|
||||
ast_test_validate(test, 0 == res);
|
||||
ast_test_validate(test, !ari_validate_int(uut));
|
||||
|
||||
str = ast_json_string_create("not a int");
|
||||
ast_test_validate(test, NULL != str);
|
||||
ast_test_validate(test, !ari_validate_int(str));
|
||||
|
||||
/* Even if the string has an integral value */
|
||||
res = ast_json_string_set(str, "0");
|
||||
ast_test_validate(test, 0 == res);
|
||||
ast_test_validate(test, !ari_validate_int(str));
|
||||
|
||||
ast_test_validate(test, !ari_validate_int(ast_json_null()));
|
||||
|
||||
return AST_TEST_PASS;
|
||||
}
|
||||
|
||||
AST_TEST_DEFINE(validate_long)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
|
||||
int res;
|
||||
|
||||
switch (cmd) {
|
||||
case TEST_INIT:
|
||||
info->name = __func__;
|
||||
info->category = "/ari/validators/";
|
||||
info->summary = "Test long validation";
|
||||
info->description =
|
||||
"Test long validation";
|
||||
return AST_TEST_NOT_RUN;
|
||||
case TEST_EXECUTE:
|
||||
break;
|
||||
}
|
||||
|
||||
uut = ast_json_integer_create(0);
|
||||
ast_test_validate(test, NULL != uut);
|
||||
ast_test_validate(test, ari_validate_long(uut));
|
||||
|
||||
str = ast_json_string_create("not a long");
|
||||
ast_test_validate(test, NULL != str);
|
||||
ast_test_validate(test, !ari_validate_long(str));
|
||||
|
||||
/* Even if the string has an integral value */
|
||||
res = ast_json_string_set(str, "0");
|
||||
ast_test_validate(test, 0 == res);
|
||||
ast_test_validate(test, !ari_validate_long(str));
|
||||
|
||||
ast_test_validate(test, !ari_validate_long(ast_json_null()));
|
||||
|
||||
return AST_TEST_PASS;
|
||||
}
|
||||
|
||||
AST_TEST_DEFINE(validate_string)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
|
||||
int res;
|
||||
|
||||
switch (cmd) {
|
||||
case TEST_INIT:
|
||||
info->name = __func__;
|
||||
info->category = "/ari/validators/";
|
||||
info->summary = "Test string validation";
|
||||
info->description =
|
||||
"Test string validation";
|
||||
return AST_TEST_NOT_RUN;
|
||||
case TEST_EXECUTE:
|
||||
break;
|
||||
}
|
||||
|
||||
uut = ast_json_string_create("text");
|
||||
ast_test_validate(test, NULL != uut);
|
||||
ast_test_validate(test, ari_validate_string(uut));
|
||||
|
||||
res = ast_json_string_set(uut, "");
|
||||
ast_test_validate(test, 0 == res);
|
||||
ast_test_validate(test, ari_validate_string(uut));
|
||||
|
||||
ast_test_validate(test, !ari_validate_string(ast_json_null()));
|
||||
|
||||
return AST_TEST_PASS;
|
||||
}
|
||||
|
||||
AST_TEST_DEFINE(validate_date)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
|
||||
enum ast_test_result_state test_res;
|
||||
int res;
|
||||
int i;
|
||||
const char *valid_dates[] = {
|
||||
/* Time is optional */
|
||||
"2013-06-17",
|
||||
/* Seconds are optional */
|
||||
"2013-06-17T23:59Z",
|
||||
/* Subseconds are optional */
|
||||
"2013-06-17T23:59:59Z",
|
||||
/* Leap seconds are valid */
|
||||
"2013-06-30T23:59:61Z",
|
||||
/* Subseconds are allowed */
|
||||
"2013-06-17T23:59:59.999999Z",
|
||||
/* Now with -06:00 for the timezone */
|
||||
"2013-06-17T23:59-06:00",
|
||||
"2013-06-17T23:59:59-06:00",
|
||||
"2013-06-30T23:59:61-06:00",
|
||||
"2013-06-17T23:59:59.999999-06:00",
|
||||
/* Again, with +06:30 for the timezone */
|
||||
"2013-06-17T23:59+06:30",
|
||||
"2013-06-17T23:59:59+06:30",
|
||||
"2013-06-30T23:59:61+06:30",
|
||||
"2013-06-17T23:59:59.999999+06:30",
|
||||
/* So the colon in the timezone is optional */
|
||||
"2013-06-17T23:59-0600",
|
||||
"2013-06-17T23:59:59-0600",
|
||||
"2013-06-30T23:59:61-0600",
|
||||
"2013-06-17T23:59:59.999999-0600",
|
||||
/* Sure, why not */
|
||||
"2013-06-17T23:59+0630",
|
||||
"2013-06-17T23:59:59+0630",
|
||||
"2013-06-30T23:59:61+0630",
|
||||
"2013-06-17T23:59:59.999999+0630",
|
||||
"9999-12-31T23:59:61.999999Z",
|
||||
/* In fact, you don't even have to specify minutes */
|
||||
"2013-06-17T23:59-06",
|
||||
"2013-06-17T23:59:59-06",
|
||||
"2013-06-30T23:59:61-06",
|
||||
"2013-06-17T23:59:59.999999-06",
|
||||
};
|
||||
|
||||
/* There are lots of invalid dates that the validator lets through.
|
||||
* Those would be strings properly formatted as a ridiculous date. Such
|
||||
* as 0000-00-00, or 9999-19-39. Those are harder to catch with a regex,
|
||||
* and actually aren't as important. So long as the valid dates pass the
|
||||
* validator, and poorly formatted dates are rejected, it's fine.
|
||||
* Catching the occasional ridiculous date is just bonus.
|
||||
*/
|
||||
const char *invalid_dates[] = {
|
||||
"",
|
||||
"Not a date",
|
||||
"2013-06-17T", /* Missing time, but has T */
|
||||
"2013-06-17T23:59:59.Z", /* Missing subsecond, but has dot */
|
||||
"2013-06-17T23:59", /* Missing timezone, but has time */
|
||||
"2013-06-17T23:59:59.999999", /* Missing timezone */
|
||||
"9999-99-31T23:59:61.999999Z", /* Invalid month */
|
||||
"9999-12-99T23:59:61.999999Z", /* Invalid day */
|
||||
"9999-12-31T99:59:61.999999Z", /* Invalid hour */
|
||||
"9999-12-31T23:99:61.999999Z", /* Invalid minute */
|
||||
"9999-12-31T23:59:99.999999Z", /* Invalid second */
|
||||
"2013-06-17T23:59:59.999999-99:00", /* Invalid timezone */
|
||||
"2013-06-17T23:59:59.999999-06:99", /* Invalid timezone */
|
||||
"2013-06-17T23:59:59.999999-06:", /* Invalid timezone */
|
||||
"2013-06-17T23:59:59.999999-06:0", /* Invalid timezone */
|
||||
"2013-06-17T23:59:59.999999-060", /* Invalid timezone */
|
||||
};
|
||||
|
||||
switch (cmd) {
|
||||
case TEST_INIT:
|
||||
info->name = __func__;
|
||||
info->category = "/ari/validators/";
|
||||
info->summary = "Test date validation";
|
||||
info->description =
|
||||
"Test date validation";
|
||||
return AST_TEST_NOT_RUN;
|
||||
case TEST_EXECUTE:
|
||||
break;
|
||||
}
|
||||
|
||||
uut = ast_json_string_create("");
|
||||
ast_test_validate(test, NULL != uut);
|
||||
|
||||
/* Instead of using ast_test_validate, we'll collect the results from
|
||||
* several test cases, since we have so many */
|
||||
test_res = AST_TEST_PASS;
|
||||
for (i = 0; i < ARRAY_LEN(valid_dates); ++i) {
|
||||
res = ast_json_string_set(uut, valid_dates[i]);
|
||||
ast_test_validate(test, 0 == res);
|
||||
if (!ari_validate_date(uut)) {
|
||||
ast_test_status_update(test,
|
||||
"Expected '%s' to be a valid date\n",
|
||||
valid_dates[i]);
|
||||
test_res = AST_TEST_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_LEN(invalid_dates); ++i) {
|
||||
res = ast_json_string_set(uut, invalid_dates[i]);
|
||||
ast_test_validate(test, 0 == res);
|
||||
if (ari_validate_date(uut)) {
|
||||
ast_test_status_update(test,
|
||||
"Expected '%s' to be an invalid date\n",
|
||||
invalid_dates[i]);
|
||||
test_res = AST_TEST_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
ast_test_validate(test, !ari_validate_string(ast_json_null()));
|
||||
|
||||
return test_res;
|
||||
}
|
||||
|
||||
AST_TEST_DEFINE(validate_list)
|
||||
{
|
||||
RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
|
||||
RAII_VAR(struct ast_json *, str, NULL, ast_json_unref);
|
||||
int res;
|
||||
|
||||
switch (cmd) {
|
||||
case TEST_INIT:
|
||||
info->name = __func__;
|
||||
info->category = "/ari/validators/";
|
||||
info->summary = "Test list validation";
|
||||
info->description =
|
||||
"Test list validation";
|
||||
return AST_TEST_NOT_RUN;
|
||||
case TEST_EXECUTE:
|
||||
break;
|
||||
}
|
||||
|
||||
uut = ast_json_array_create();
|
||||
ast_test_validate(test, NULL != uut);
|
||||
ast_test_validate(test, ari_validate_list(uut, ari_validate_string));
|
||||
ast_test_validate(test, ari_validate_list(uut, ari_validate_int));
|
||||
|
||||
res = ast_json_array_append(uut, ast_json_string_create(""));
|
||||
ast_test_validate(test, 0 == res);
|
||||
ast_test_validate(test, ari_validate_list(uut, ari_validate_string));
|
||||
ast_test_validate(test, !ari_validate_list(uut, ari_validate_int));
|
||||
|
||||
res = ast_json_array_append(uut, ast_json_integer_create(0));
|
||||
ast_test_validate(test, 0 == res);
|
||||
ast_test_validate(test, !ari_validate_list(uut, ari_validate_string));
|
||||
ast_test_validate(test, !ari_validate_list(uut, ari_validate_int));
|
||||
|
||||
ast_test_validate(test,
|
||||
!ari_validate_list(ast_json_null(), ari_validate_string));
|
||||
|
||||
return AST_TEST_PASS;
|
||||
}
|
||||
|
||||
static int unload_module(void)
|
||||
{
|
||||
AST_TEST_UNREGISTER(validate_byte);
|
||||
AST_TEST_UNREGISTER(validate_boolean);
|
||||
AST_TEST_UNREGISTER(validate_int);
|
||||
AST_TEST_UNREGISTER(validate_long);
|
||||
AST_TEST_UNREGISTER(validate_string);
|
||||
AST_TEST_UNREGISTER(validate_date);
|
||||
AST_TEST_UNREGISTER(validate_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load_module(void)
|
||||
{
|
||||
AST_TEST_REGISTER(validate_byte);
|
||||
AST_TEST_REGISTER(validate_boolean);
|
||||
AST_TEST_REGISTER(validate_int);
|
||||
AST_TEST_REGISTER(validate_long);
|
||||
AST_TEST_REGISTER(validate_string);
|
||||
AST_TEST_REGISTER(validate_date);
|
||||
AST_TEST_REGISTER(validate_list);
|
||||
return AST_MODULE_LOAD_SUCCESS;
|
||||
}
|
||||
|
||||
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Skeleton (sample) Test");
|
@@ -157,7 +157,9 @@ AST_TEST_DEFINE(app_replaced)
|
||||
|
||||
stasis_app_register(app_name, test_handler, app_data1);
|
||||
stasis_app_register(app_name, test_handler, app_data2);
|
||||
expected_message1 = ast_json_pack("[{s: {s: s}}]", "application_replaced", "application", app_name);
|
||||
expected_message1 = ast_json_pack("[{s: s, s: s}]",
|
||||
"type", "ApplicationReplaced",
|
||||
"application", app_name);
|
||||
message = ast_json_pack("{ s: o }", "test-message", ast_json_null());
|
||||
expected_message2 = ast_json_pack("[o]", ast_json_ref(message));
|
||||
|
||||
|
@@ -256,8 +256,7 @@ AST_TEST_DEFINE(channel_snapshot_json)
|
||||
ast_test_validate(test, NULL != snapshot);
|
||||
|
||||
actual = ast_channel_snapshot_to_json(snapshot);
|
||||
expected = ast_json_pack("{ s: s, s: s, s: s, s: s, s: s, s: s, s: s,"
|
||||
" s: s, s: s, s: s, s: s,"
|
||||
expected = ast_json_pack("{ s: s, s: s, s: s, s: s,"
|
||||
" s: { s: s, s: s, s: i },"
|
||||
" s: { s: s, s: s },"
|
||||
" s: { s: s, s: s },"
|
||||
@@ -266,14 +265,7 @@ AST_TEST_DEFINE(channel_snapshot_json)
|
||||
"name", "TEST/name",
|
||||
"state", "Down",
|
||||
"accountcode", "acctcode",
|
||||
"peeraccount", "",
|
||||
"userfield", "",
|
||||
"uniqueid", ast_channel_uniqueid(chan),
|
||||
"linkedid", ast_channel_uniqueid(chan),
|
||||
"parkinglot", "",
|
||||
"hangupsource", "",
|
||||
"appl", "",
|
||||
"data", "",
|
||||
"id", ast_channel_uniqueid(chan),
|
||||
"dialplan",
|
||||
"context", "context",
|
||||
"exten", "exten",
|
||||
|
Reference in New Issue
Block a user