Rename everything Stasis-HTTP to ARI

This renames all files and API calls from several variants of
Stasis-HTTP to ARI including:
* Stasis-HTTP -> ARI
* STASIS_HTTP -> ARI
* stasis_http -> ari (ast_ari for global symbols, file names as well)
* stasis http -> ARI

Review: https://reviewboard.asterisk.org/r/2706/
(closes issue ASTERISK-22136)


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@395603 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Kinsey Moore
2013-07-27 23:11:02 +00:00
parent fc05248bd1
commit d8956f690e
53 changed files with 1636 additions and 1637 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,962 @@
/*
* 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.
*
* In addition to the normal validation functions one would normally expect,
* each validator has a ast_ari_validate_{id}_fn() companion function that returns
* the validator's function pointer.
*
* The reason for this seamingly useless indirection is the way function
* pointers interfere with module loading. Asterisk attempts to dlopen() each
* module using \c RTLD_LAZY in order to read some metadata from the module.
* Unfortunately, if you take the address of a function, the function has to be
* resolvable at load time, even if \c RTLD_LAZY is specified. By moving the
* function-address-taking into this module, we can once again be lazy.
*/
/*
* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
* !!!!! 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 ast_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 ast_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 ast_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 ast_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 ast_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 ast_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 ast_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 ast_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 ast_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 ast_ari_validate_list(struct ast_json *json, int (*fn)(struct ast_json *));
/*! @} */
/*!
* \brief Function type for validator functions. Allows for
*/
typedef int (*ari_validator)(struct ast_json *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 ast_ari_validate_asterisk_info(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_asterisk_info().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_asterisk_info_fn(void);
/*!
* \brief Validator for Variable.
*
* The value of a channel variable
*
* \param json JSON object to validate.
* \returns True (non-zero) if valid.
* \returns False (zero) if invalid.
*/
int ast_ari_validate_variable(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_variable().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_variable_fn(void);
/*!
* \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 ast_ari_validate_endpoint(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_endpoint().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_endpoint_fn(void);
/*!
* \brief Validator for CallerID.
*
* Caller identification
*
* \param json JSON object to validate.
* \returns True (non-zero) if valid.
* \returns False (zero) if invalid.
*/
int ast_ari_validate_caller_id(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_caller_id().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_caller_id_fn(void);
/*!
* \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 ast_ari_validate_channel(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_channel().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_channel_fn(void);
/*!
* \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 ast_ari_validate_dialed(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_dialed().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_dialed_fn(void);
/*!
* \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 ast_ari_validate_dialplan_cep(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_dialplan_cep().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_dialplan_cep_fn(void);
/*!
* \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 ast_ari_validate_bridge(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_bridge().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_bridge_fn(void);
/*!
* \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 ast_ari_validate_live_recording(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_live_recording().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_live_recording_fn(void);
/*!
* \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 ast_ari_validate_stored_recording(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_stored_recording().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_stored_recording_fn(void);
/*!
* \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 ast_ari_validate_format_lang_pair(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_format_lang_pair().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_format_lang_pair_fn(void);
/*!
* \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 ast_ari_validate_sound(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_sound().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_sound_fn(void);
/*!
* \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 ast_ari_validate_playback(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_playback().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_playback_fn(void);
/*!
* \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 ast_ari_validate_application_replaced(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_application_replaced().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_application_replaced_fn(void);
/*!
* \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 ast_ari_validate_bridge_created(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_bridge_created().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_bridge_created_fn(void);
/*!
* \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 ast_ari_validate_bridge_destroyed(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_bridge_destroyed().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_bridge_destroyed_fn(void);
/*!
* \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 ast_ari_validate_bridge_merged(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_bridge_merged().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_bridge_merged_fn(void);
/*!
* \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 ast_ari_validate_channel_caller_id(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_channel_caller_id().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_channel_caller_id_fn(void);
/*!
* \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 ast_ari_validate_channel_created(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_channel_created().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_channel_created_fn(void);
/*!
* \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 ast_ari_validate_channel_destroyed(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_channel_destroyed().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_channel_destroyed_fn(void);
/*!
* \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 ast_ari_validate_channel_dialplan(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_channel_dialplan().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_channel_dialplan_fn(void);
/*!
* \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 ast_ari_validate_channel_dtmf_received(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_channel_dtmf_received().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_channel_dtmf_received_fn(void);
/*!
* \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 ast_ari_validate_channel_entered_bridge(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_channel_entered_bridge().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_channel_entered_bridge_fn(void);
/*!
* \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 ast_ari_validate_channel_hangup_request(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_channel_hangup_request().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_channel_hangup_request_fn(void);
/*!
* \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 ast_ari_validate_channel_left_bridge(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_channel_left_bridge().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_channel_left_bridge_fn(void);
/*!
* \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 ast_ari_validate_channel_state_change(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_channel_state_change().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_channel_state_change_fn(void);
/*!
* \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 ast_ari_validate_channel_userevent(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_channel_userevent().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_channel_userevent_fn(void);
/*!
* \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 ast_ari_validate_channel_varset(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_channel_varset().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_channel_varset_fn(void);
/*!
* \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 ast_ari_validate_event(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_event().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_event_fn(void);
/*!
* \brief Validator for Message.
*
* Base type for errors and events
*
* \param json JSON object to validate.
* \returns True (non-zero) if valid.
* \returns False (zero) if invalid.
*/
int ast_ari_validate_message(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_message().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_message_fn(void);
/*!
* \brief Validator for MissingParams.
*
* Error event sent when required params are missing.
*
* \param json JSON object to validate.
* \returns True (non-zero) if valid.
* \returns False (zero) if invalid.
*/
int ast_ari_validate_missing_params(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_missing_params().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_missing_params_fn(void);
/*!
* \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 ast_ari_validate_playback_finished(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_playback_finished().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_playback_finished_fn(void);
/*!
* \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 ast_ari_validate_playback_started(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_playback_started().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_playback_started_fn(void);
/*!
* \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 ast_ari_validate_stasis_end(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_stasis_end().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_stasis_end_fn(void);
/*!
* \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 ast_ari_validate_stasis_start(struct ast_json *json);
/*!
* \brief Function pointer to ast_ari_validate_stasis_start().
*
* See \ref ast_ari_model_validators.h for more details.
*/
ari_validator ast_ari_validate_stasis_start_fn(void);
/*
* JSON models
*
* AsteriskInfo
* Variable
* - value: string (required)
* 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
* - format: string (required)
* - name: string (required)
* - state: 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
* - type: string (required)
* - application: string (required)
* - timestamp: Date
* BridgeCreated
* - type: string (required)
* - application: string (required)
* - timestamp: Date
* - bridge: Bridge (required)
* BridgeDestroyed
* - type: string (required)
* - application: string (required)
* - timestamp: Date
* - bridge: Bridge (required)
* BridgeMerged
* - type: string (required)
* - application: string (required)
* - timestamp: Date
* - bridge: Bridge (required)
* - bridge_from: Bridge (required)
* ChannelCallerId
* - type: string (required)
* - application: string (required)
* - timestamp: Date
* - caller_presentation: int (required)
* - caller_presentation_txt: string (required)
* - channel: Channel (required)
* ChannelCreated
* - type: string (required)
* - application: string (required)
* - timestamp: Date
* - channel: Channel (required)
* ChannelDestroyed
* - type: string (required)
* - application: string (required)
* - timestamp: Date
* - cause: int (required)
* - cause_txt: string (required)
* - channel: Channel (required)
* ChannelDialplan
* - type: string (required)
* - application: string (required)
* - timestamp: Date
* - channel: Channel (required)
* - dialplan_app: string (required)
* - dialplan_app_data: string (required)
* ChannelDtmfReceived
* - type: string (required)
* - application: string (required)
* - timestamp: Date
* - channel: Channel (required)
* - digit: string (required)
* - duration_ms: int (required)
* ChannelEnteredBridge
* - type: string (required)
* - application: string (required)
* - timestamp: Date
* - bridge: Bridge (required)
* - channel: Channel
* ChannelHangupRequest
* - type: string (required)
* - application: string (required)
* - timestamp: Date
* - cause: int
* - channel: Channel (required)
* - soft: boolean
* ChannelLeftBridge
* - type: string (required)
* - application: string (required)
* - timestamp: Date
* - bridge: Bridge (required)
* - channel: Channel (required)
* ChannelStateChange
* - type: string (required)
* - application: string (required)
* - timestamp: Date
* - channel: Channel (required)
* ChannelUserevent
* - type: string (required)
* - application: string (required)
* - timestamp: Date
* - channel: Channel (required)
* - eventname: string (required)
* ChannelVarset
* - type: string (required)
* - application: string (required)
* - timestamp: Date
* - channel: Channel
* - value: string (required)
* - variable: string (required)
* Event
* - type: string (required)
* - application: string (required)
* - timestamp: Date
* Message
* - type: string (required)
* MissingParams
* - type: string (required)
* - params: List[string] (required)
* PlaybackFinished
* - type: string (required)
* - application: string (required)
* - timestamp: Date
* - playback: Playback (required)
* PlaybackStarted
* - type: string (required)
* - application: string (required)
* - timestamp: Date
* - playback: Playback (required)
* StasisEnd
* - type: string (required)
* - application: string (required)
* - timestamp: Date
* - channel: Channel (required)
* StasisStart
* - type: string (required)
* - application: string (required)
* - timestamp: Date
* - args: List[string] (required)
* - channel: Channel (required)
*/
#endif /* _ASTERISK_ARI_MODEL_H */

165
res/ari/ari_websockets.c Normal file
View File

@@ -0,0 +1,165 @@
/*
* 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.
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/astobj2.h"
#include "asterisk/ari.h"
/*! \file
*
* \brief WebSocket support for RESTful API's.
* \author David M. Lee, II <dlee@digium.com>
*/
struct ast_ari_websocket_session {
struct ast_websocket *ws_session;
int (*validator)(struct ast_json *);
};
static void websocket_session_dtor(void *obj)
{
struct ast_ari_websocket_session *session = obj;
ast_websocket_unref(session->ws_session);
session->ws_session = NULL;
}
/*!
* \brief Validator that always succeeds.
*/
static int null_validator(struct ast_json *json)
{
return 1;
}
struct ast_ari_websocket_session *ast_ari_websocket_session_create(
struct ast_websocket *ws_session, int (*validator)(struct ast_json *))
{
RAII_VAR(struct ast_ari_websocket_session *, session, NULL, ao2_cleanup);
if (ws_session == NULL) {
return NULL;
}
if (validator == NULL) {
validator = null_validator;
}
if (ast_websocket_set_nonblock(ws_session) != 0) {
ast_log(LOG_ERROR,
"ARI web socket failed to set nonblock; closing: %s\n",
strerror(errno));
return NULL;
}
session = ao2_alloc(sizeof(*session), websocket_session_dtor);
if (!session) {
return NULL;
}
ao2_ref(ws_session, +1);
session->ws_session = ws_session;
session->validator = validator;
ao2_ref(session, +1);
return session;
}
struct ast_json *ast_ari_websocket_session_read(
struct ast_ari_websocket_session *session)
{
RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
while (!message) {
int res;
char *payload;
uint64_t payload_len;
enum ast_websocket_opcode opcode;
int fragmented;
res = ast_wait_for_input(
ast_websocket_fd(session->ws_session), -1);
if (res <= 0) {
ast_log(LOG_WARNING, "WebSocket poll error: %s\n",
strerror(errno));
return NULL;
}
res = ast_websocket_read(session->ws_session, &payload,
&payload_len, &opcode, &fragmented);
if (res != 0) {
ast_log(LOG_WARNING, "WebSocket read error: %s\n",
strerror(errno));
return NULL;
}
switch (opcode) {
case AST_WEBSOCKET_OPCODE_CLOSE:
ast_debug(1, "WebSocket closed by peer\n");
return NULL;
case AST_WEBSOCKET_OPCODE_TEXT:
message = ast_json_load_buf(payload, payload_len, NULL);
if (message == NULL) {
ast_log(LOG_WARNING,
"WebSocket input failed to parse\n");
}
break;
default:
/* Ignore all other message types */
break;
}
}
return ast_json_ref(message);
}
#define VALIDATION_FAILED \
"{" \
" \"error\": \"InvalidMessage\"," \
" \"message\": \"Message validation failed\"" \
"}"
int ast_ari_websocket_session_write(struct ast_ari_websocket_session *session,
struct ast_json *message)
{
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, ast_ari_json_format());
if (str == NULL) {
ast_log(LOG_ERROR, "Failed to encode JSON object\n");
return -1;
}
return ast_websocket_write(session->ws_session,
AST_WEBSOCKET_OPCODE_TEXT, str, strlen(str));
}

267
res/ari/cli.c Normal file
View File

@@ -0,0 +1,267 @@
/*
* 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 Command line for ARI.
* \author David M. Lee, II <dlee@digium.com>
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/astobj2.h"
#include "asterisk/cli.h"
#include "internal.h"
static char *ari_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
RAII_VAR(struct ast_ari_conf *, conf, NULL, ao2_cleanup);
switch (cmd) {
case CLI_INIT:
e->command = "ari show status";
e->usage =
"Usage: ari show status\n"
" Shows all ARI settings\n";
return NULL;
case CLI_GENERATE:
return NULL;
default:
break;
}
if (a->argc != 3) {
return CLI_SHOWUSAGE;
}
conf = ast_ari_config_get();
if (!conf) {
ast_cli(a->fd, "Error getting ARI configuration\n");
return CLI_FAILURE;
}
ast_cli(a->fd, "ARI Status:\n");
ast_cli(a->fd, "Enabled: %s\n", AST_CLI_YESNO(conf->general->enabled));
ast_cli(a->fd, "Output format: ");
switch (conf->general->format) {
case AST_JSON_COMPACT:
ast_cli(a->fd, "compact");
break;
case AST_JSON_PRETTY:
ast_cli(a->fd, "pretty");
break;
}
ast_cli(a->fd, "\n");
ast_cli(a->fd, "Auth realm: %s\n", conf->general->auth_realm);
ast_cli(a->fd, "Allowed Origins: %s\n", conf->general->allowed_origins);
ast_cli(a->fd, "User count: %d\n", ao2_container_count(conf->users));
return CLI_SUCCESS;
}
static int show_users_cb(void *obj, void *arg, int flags)
{
struct ast_ari_conf_user *user = obj;
struct ast_cli_args *a = arg;
ast_cli(a->fd, "%-4s %s\n",
AST_CLI_YESNO(user->read_only),
user->username);
return 0;
}
static char *ari_show_users(struct ast_cli_entry *e, int cmd,
struct ast_cli_args *a)
{
RAII_VAR(struct ast_ari_conf *, conf, NULL, ao2_cleanup);
switch (cmd) {
case CLI_INIT:
e->command = "ari show users";
e->usage =
"Usage: ari show users\n"
" Shows all ARI users\n";
return NULL;
case CLI_GENERATE:
return NULL;
default:
break;
}
if (a->argc != 3) {
return CLI_SHOWUSAGE;
}
conf = ast_ari_config_get();
if (!conf) {
ast_cli(a->fd, "Error getting ARI configuration\n");
return CLI_FAILURE;
}
ast_cli(a->fd, "r/o? Username\n");
ast_cli(a->fd, "---- --------\n");
ao2_callback(conf->users, OBJ_NODATA, show_users_cb, a);
return CLI_SUCCESS;
}
struct user_complete {
/*! Nth user to search for */
int state;
/*! Which user currently on */
int which;
};
static int complete_ari_user_search(void *obj, void *arg, void *data, int flags)
{
struct user_complete *search = data;
if (++search->which > search->state) {
return CMP_MATCH;
}
return 0;
}
static char *complete_ari_user(struct ast_cli_args *a)
{
RAII_VAR(struct ast_ari_conf *, conf, NULL, ao2_cleanup);
RAII_VAR(struct ast_ari_conf_user *, user, NULL, ao2_cleanup);
struct user_complete search = {
.state = a->n,
};
conf = ast_ari_config_get();
if (!conf) {
ast_cli(a->fd, "Error getting ARI configuration\n");
return CLI_FAILURE;
}
user = ao2_callback_data(conf->users,
ast_strlen_zero(a->word) ? 0 : OBJ_PARTIAL_KEY,
complete_ari_user_search, (char*)a->word, &search);
return user ? ast_strdup(user->username) : NULL;
}
static char *complete_ari_show_user(struct ast_cli_args *a)
{
if (a->pos == 3) {
return complete_ari_user(a);
}
return NULL;
}
static char *ari_show_user(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
RAII_VAR(struct ast_ari_conf *, conf, NULL, ao2_cleanup);
RAII_VAR(struct ast_ari_conf_user *, user, NULL, ao2_cleanup);
switch (cmd) {
case CLI_INIT:
e->command = "ari show user";
e->usage =
"Usage: ari show user <username>\n"
" Shows a specific ARI user\n";
return NULL;
case CLI_GENERATE:
return complete_ari_show_user(a);
default:
break;
}
if (a->argc != 4) {
return CLI_SHOWUSAGE;
}
conf = ast_ari_config_get();
if (!conf) {
ast_cli(a->fd, "Error getting ARI configuration\n");
return CLI_FAILURE;
}
user = ao2_find(conf->users, a->argv[3], OBJ_KEY);
if (!user) {
ast_cli(a->fd, "User '%s' not found\n", a->argv[3]);
return CLI_SUCCESS;
}
ast_cli(a->fd, "Username: %s\n", user->username);
ast_cli(a->fd, "Read only?: %s\n", AST_CLI_YESNO(user->read_only));
return CLI_SUCCESS;
}
static char *ari_mkpasswd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
RAII_VAR(char *, crypted, NULL, ast_free);
switch (cmd) {
case CLI_INIT:
e->command = "ari mkpasswd";
e->usage =
"Usage: ari mkpasswd <password>\n"
" Encrypts a password for use in ari.conf\n"
" Be aware that the password will be shown in the\n"
" command line history. The mkpasswd shell command\n"
" may be preferable.\n"
;
return NULL;
case CLI_GENERATE:
return NULL;
default:
break;
}
if (a->argc != 3) {
return CLI_SHOWUSAGE;
}
crypted = ast_crypt_encrypt(a->argv[2]);
if (!crypted) {
ast_cli(a->fd, "Failed to encrypt password\n");
return CLI_FAILURE;
}
ast_cli(a->fd,
"; Copy the following two lines into ari.conf\n");
ast_cli(a->fd, "password_format = crypt\n");
ast_cli(a->fd, "password = %s\n", crypted);
return CLI_SUCCESS;
}
static struct ast_cli_entry cli_ari[] = {
AST_CLI_DEFINE(ari_show, "Show ARI settings"),
AST_CLI_DEFINE(ari_show_users, "List ARI users"),
AST_CLI_DEFINE(ari_show_user, "List single ARI user"),
AST_CLI_DEFINE(ari_mkpasswd, "Encrypts a password"),
};
int ast_ari_cli_register(void) {
return ast_cli_register_multiple(cli_ari, ARRAY_LEN(cli_ari));
}
void ast_ari_cli_unregister(void) {
ast_cli_unregister_multiple(cli_ari, ARRAY_LEN(cli_ari));
}

345
res/ari/config.c Normal file
View File

@@ -0,0 +1,345 @@
/*
* 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 Config framework stuffz for ARI.
* \author David M. Lee, II <dlee@digium.com>
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/config_options.h"
#include "internal.h"
/*! \brief Locking container for safe configuration access. */
static AO2_GLOBAL_OBJ_STATIC(confs);
/*! \brief Mapping of the ARI conf struct's globals to the
* general context in the config file. */
static struct aco_type general_option = {
.type = ACO_GLOBAL,
.name = "general",
.item_offset = offsetof(struct ast_ari_conf, general),
.category = "^general$",
.category_match = ACO_WHITELIST,
};
static struct aco_type *general_options[] = ACO_TYPES(&general_option);
/*! \brief Encoding format handler converts from boolean to enum. */
static int encoding_format_handler(const struct aco_option *opt,
struct ast_variable *var, void *obj)
{
struct ast_ari_conf_general *general = obj;
if (!strcasecmp(var->name, "pretty")) {
general->format = ast_true(var->value) ?
AST_JSON_PRETTY : AST_JSON_COMPACT;
} else {
return -1;
}
return 0;
}
/*! \brief Parses the ast_ari_password_format enum from a config file */
static int password_format_handler(const struct aco_option *opt,
struct ast_variable *var, void *obj)
{
struct ast_ari_conf_user *user = obj;
if (strcasecmp(var->value, "plain") == 0) {
user->password_format = ARI_PASSWORD_FORMAT_PLAIN;
} else if (strcasecmp(var->value, "crypt") == 0) {
user->password_format = ARI_PASSWORD_FORMAT_CRYPT;
} else {
return -1;
}
return 0;
}
/*! \brief Destructor for \ref ast_ari_conf_user */
static void user_dtor(void *obj)
{
struct ast_ari_conf_user *user = obj;
ast_debug(3, "Disposing of user %s\n", user->username);
ast_free(user->username);
}
/*! \brief Allocate an \ref ast_ari_conf_user for config parsing */
static void *user_alloc(const char *cat)
{
RAII_VAR(struct ast_ari_conf_user *, user, NULL, ao2_cleanup);
if (!cat) {
return NULL;
}
ast_debug(3, "Allocating user %s\n", cat);
user = ao2_alloc_options(sizeof(*user), user_dtor,
AO2_ALLOC_OPT_LOCK_NOLOCK);
if (!user) {
return NULL;
}
user->username = ast_strdup(cat);
if (!user->username) {
return NULL;
}
ao2_ref(user, +1);
return user;
}
/*! \brief Sorting function for use with red/black tree */
static int user_sort_cmp(const void *obj_left, const void *obj_right, int flags)
{
const struct ast_ari_conf_user *user_left = obj_left;
if (flags & OBJ_PARTIAL_KEY) {
const char *key_right = obj_right;
return strncasecmp(user_left->username, key_right,
strlen(key_right));
} else if (flags & OBJ_KEY) {
const char *key_right = obj_right;
return strcasecmp(user_left->username, key_right);
} else {
const struct ast_ari_conf_user *user_right = obj_right;
const char *key_right = user_right->username;
return strcasecmp(user_left->username, key_right);
}
}
/*! \brief \ref aco_type item_find function */
static void *user_find(struct ao2_container *tmp_container, const char *cat)
{
if (!cat) {
return NULL;
}
return ao2_find(tmp_container, cat, OBJ_KEY);
}
static struct aco_type user_option = {
.type = ACO_ITEM,
.name = "user",
.category_match = ACO_BLACKLIST,
.category = "^general$",
.matchfield = "type",
.matchvalue = "user",
.item_alloc = user_alloc,
.item_find = user_find,
.item_offset = offsetof(struct ast_ari_conf, users),
};
static struct aco_type *user[] = ACO_TYPES(&user_option);
/*! \brief \ref ast_ari_conf destructor. */
static void conf_destructor(void *obj)
{
struct ast_ari_conf *cfg = obj;
ast_string_field_free_memory(cfg->general);
ao2_cleanup(cfg->general);
ao2_cleanup(cfg->users);
}
/*! \brief Allocate an \ref ast_ari_conf for config parsing */
static void *conf_alloc(void)
{
RAII_VAR(struct ast_ari_conf *, cfg, NULL, ao2_cleanup);
cfg = ao2_alloc_options(sizeof(*cfg), conf_destructor,
AO2_ALLOC_OPT_LOCK_NOLOCK);
if (!cfg) {
return NULL;
}
cfg->general = ao2_alloc_options(sizeof(*cfg->general), NULL,
AO2_ALLOC_OPT_LOCK_NOLOCK);
if (!cfg->general) {
return NULL;
}
aco_set_defaults(&general_option, "general", cfg->general);
if (ast_string_field_init(cfg->general, 64)) {
return NULL;
}
cfg->users = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_NOLOCK,
AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, user_sort_cmp, NULL);
ao2_ref(cfg, +1);
return cfg;
}
#define CONF_FILENAME "ari.conf"
/*! \brief The conf file that's processed for the module. */
static struct aco_file conf_file = {
/*! The config file name. */
.filename = CONF_FILENAME,
/*! The mapping object types to be processed. */
.types = ACO_TYPES(&general_option, &user_option),
};
CONFIG_INFO_STANDARD(cfg_info, confs, conf_alloc,
.files = ACO_FILES(&conf_file));
struct ast_ari_conf *ast_ari_config_get(void)
{
struct ast_ari_conf *res = ao2_global_obj_ref(confs);
if (!res) {
ast_log(LOG_ERROR,
"Error obtaining config from " CONF_FILENAME "\n");
}
return res;
}
struct ast_ari_conf_user *ast_ari_config_validate_user(const char *username,
const char *password)
{
RAII_VAR(struct ast_ari_conf *, conf, NULL, ao2_cleanup);
RAII_VAR(struct ast_ari_conf_user *, user, NULL, ao2_cleanup);
int is_valid = 0;
conf = ast_ari_config_get();
if (!conf) {
return NULL;
}
user = ao2_find(conf->users, username, OBJ_KEY);
if (!user) {
return NULL;
}
if (ast_strlen_zero(user->password)) {
ast_log(LOG_WARNING,
"User '%s' missing password; authentication failed\n",
user->username);
return NULL;
}
switch (user->password_format) {
case ARI_PASSWORD_FORMAT_PLAIN:
is_valid = strcmp(password, user->password) == 0;
break;
case ARI_PASSWORD_FORMAT_CRYPT:
is_valid = ast_crypt_validate(password, user->password);
break;
}
if (!is_valid) {
return NULL;
}
ao2_ref(user, +1);
return user;
}
/*! \brief Callback to validate a user object */
static int validate_user_cb(void *obj, void *arg, int flags)
{
struct ast_ari_conf_user *user = obj;
if (ast_strlen_zero(user->password)) {
ast_log(LOG_WARNING, "User '%s' missing password\n",
user->username);
}
return 0;
}
/*! \brief Load (or reload) configuration. */
static int process_config(int reload)
{
RAII_VAR(struct ast_ari_conf *, conf, NULL, ao2_cleanup);
switch (aco_process_config(&cfg_info, reload)) {
case ACO_PROCESS_ERROR:
return -1;
case ACO_PROCESS_OK:
case ACO_PROCESS_UNCHANGED:
break;
}
conf = ast_ari_config_get();
if (!conf) {
ast_assert(0); /* We just configured; it should be there */
return -1;
}
if (ao2_container_count(conf->users) == 0) {
ast_log(LOG_ERROR, "No configured users for ARI\n");
}
ao2_callback(conf->users, OBJ_NODATA, validate_user_cb, NULL);
return 0;
}
int ast_ari_config_init(void)
{
if (aco_info_init(&cfg_info)) {
aco_info_destroy(&cfg_info);
return -1;
}
aco_option_register(&cfg_info, "enabled", ACO_EXACT, general_options,
"yes", OPT_BOOL_T, 1,
FLDSET(struct ast_ari_conf_general, enabled));
aco_option_register_custom(&cfg_info, "pretty", ACO_EXACT,
general_options, "no", encoding_format_handler, 0);
aco_option_register(&cfg_info, "auth_realm", ACO_EXACT, general_options,
"Asterisk REST Interface", OPT_CHAR_ARRAY_T, 0,
FLDSET(struct ast_ari_conf_general, auth_realm),
ARI_AUTH_REALM_LEN);
aco_option_register(&cfg_info, "allowed_origins", ACO_EXACT, general_options,
"", OPT_STRINGFIELD_T, 0,
STRFLDSET(struct ast_ari_conf_general, allowed_origins));
aco_option_register(&cfg_info, "type", ACO_EXACT, user, NULL,
OPT_NOOP_T, 0, 0);
aco_option_register(&cfg_info, "read_only", ACO_EXACT, user,
"no", OPT_BOOL_T, 1,
FLDSET(struct ast_ari_conf_user, read_only));
aco_option_register(&cfg_info, "password", ACO_EXACT, user,
"", OPT_CHAR_ARRAY_T, 0,
FLDSET(struct ast_ari_conf_user, password), ARI_PASSWORD_LEN);
aco_option_register_custom(&cfg_info, "password_format", ACO_EXACT,
user, "plain", password_format_handler, 0);
return process_config(0);
}
int ast_ari_config_reload(void)
{
return process_config(1);
}
void ast_ari_config_destroy(void)
{
aco_info_destroy(&cfg_info);
ao2_global_obj_release(confs);
}

143
res/ari/internal.h Normal file
View File

@@ -0,0 +1,143 @@
/*
* 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.
*/
#ifndef ARI_INTERNAL_H_
#define ARI_INTERNAL_H_
/*! \file
*
* \brief Internal API's for res_ari.
* \author David M. Lee, II <dlee@digium.com>
*/
#include "asterisk/json.h"
/*! @{ */
/*!
* \brief Register CLI commands for ARI.
*
* \return 0 on success.
* \return Non-zero on error.
*/
int ast_ari_cli_register(void);
/*!
* \brief Unregister CLI commands for ARI.
*/
void ast_ari_cli_unregister(void);
/*! @} */
/*! @{ */
struct ast_ari_conf_general;
/*! \brief All configuration options for ARI. */
struct ast_ari_conf {
/*! The general section configuration options. */
struct ast_ari_conf_general *general;
/*! Configured users */
struct ao2_container *users;
};
/*! Max length for auth_realm field */
#define ARI_AUTH_REALM_LEN 80
/*! \brief Global configuration options for ARI. */
struct ast_ari_conf_general {
/*! Enabled by default, disabled if false. */
int enabled;
/*! Encoding format used during output (default compact). */
enum ast_json_encoding_format format;
/*! Authentication realm */
char auth_realm[ARI_AUTH_REALM_LEN];
AST_DECLARE_STRING_FIELDS(
AST_STRING_FIELD(allowed_origins);
);
};
/*! \brief Password format */
enum ast_ari_password_format {
/*! \brief Plaintext password */
ARI_PASSWORD_FORMAT_PLAIN,
/*! crypt(3) password */
ARI_PASSWORD_FORMAT_CRYPT,
};
/*!
* \brief User's password mx length.
*
* If 256 seems like a lot, a crypt SHA-512 has over 106 characters.
*/
#define ARI_PASSWORD_LEN 256
/*! \brief Per-user configuration options */
struct ast_ari_conf_user {
/*! Username for authentication */
char *username;
/*! User's password. */
char password[ARI_PASSWORD_LEN];
/*! Format for the password field */
enum ast_ari_password_format password_format;
/*! If true, user cannot execute change operations */
int read_only;
};
/*!
* \brief Initialize the ARI configuration
*/
int ast_ari_config_init(void);
/*!
* \brief Reload the ARI configuration
*/
int ast_ari_config_reload(void);
/*!
* \brief Destroy the ARI configuration
*/
void ast_ari_config_destroy(void);
/*!
* \brief Get the current ARI configuration.
*
* This is an immutable object, so don't modify it. It is AO2 managed, so
* ao2_cleanup() when you're done with it.
*
* \return ARI configuration object.
* \return \c NULL on error.
*/
struct ast_ari_conf *ast_ari_config_get(void);
/*!
* \brief Validated a user's credentials.
*
* \param username Name of the user.
* \param password User's password.
* \return User object.
* \return \c NULL if username or password is invalid.
*/
struct ast_ari_conf_user *ast_ari_config_validate_user(const char *username,
const char *password);
/*! @} */
#endif /* ARI_INTERNAL_H_ */

View File

@@ -0,0 +1,80 @@
/* -*- C -*-
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2012 - 2013, Digium, Inc.
*
* David M. Lee, II <dlee@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief Implementation for ARI stubs.
*
* \author David M. Lee, II <dlee@digium.com>
*/
/*** MODULEINFO
<support_level>core</support_level>
***/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "resource_asterisk.h"
#include "asterisk/pbx.h"
void ast_ari_get_asterisk_info(struct ast_variable *headers, struct ast_get_asterisk_info_args *args, struct ast_ari_response *response)
{
ast_log(LOG_ERROR, "TODO: ari_get_asterisk_info\n");
}
void ast_ari_get_global_var(struct ast_variable *headers, struct ast_get_global_var_args *args, struct ast_ari_response *response)
{
RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
RAII_VAR(struct ast_str *, tmp, ast_str_create(32), ast_free);
const char *value;
ast_assert(response != NULL);
if (!tmp) {
ast_ari_response_alloc_failed(response);
return;
}
value = ast_str_retrieve_variable(&tmp, 0, NULL, NULL, args->variable);
if (!(json = ast_json_pack("{s: s}", "value", S_OR(value, "")))) {
ast_ari_response_alloc_failed(response);
return;
}
ast_ari_response_ok(response, ast_json_ref(json));
}
void ast_ari_set_global_var(struct ast_variable *headers, struct ast_set_global_var_args *args, struct ast_ari_response *response)
{
ast_assert(response != NULL);
if (ast_strlen_zero(args->variable)) {
ast_ari_response_error(
response, 400, "Bad Request",
"Variable name is required");
return;
}
pbx_builtin_setvar_helper(NULL, args->variable, args->value);
ast_ari_response_no_content(response);
}

View File

@@ -0,0 +1,84 @@
/*
* 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/ari/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/ari_resource.h.mustache
*/
#ifndef _ASTERISK_RESOURCE_ASTERISK_H
#define _ASTERISK_RESOURCE_ASTERISK_H
#include "asterisk/ari.h"
/*! \brief Argument struct for ast_ari_get_asterisk_info() */
struct ast_get_asterisk_info_args {
/*! \brief Filter information returned */
const char *only;
};
/*!
* \brief Gets Asterisk system information.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_get_asterisk_info(struct ast_variable *headers, struct ast_get_asterisk_info_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_get_global_var() */
struct ast_get_global_var_args {
/*! \brief The variable to get */
const char *variable;
};
/*!
* \brief Get the value of a global variable.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_get_global_var(struct ast_variable *headers, struct ast_get_global_var_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_set_global_var() */
struct ast_set_global_var_args {
/*! \brief The variable to set */
const char *variable;
/*! \brief The value to set the variable to */
const char *value;
};
/*!
* \brief Set the value of a global variable.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_set_global_var(struct ast_variable *headers, struct ast_set_global_var_args *args, struct ast_ari_response *response);
#endif /* _ASTERISK_RESOURCE_ASTERISK_H */

514
res/ari/resource_bridges.c Normal file
View File

@@ -0,0 +1,514 @@
/* -*- C -*-
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2012 - 2013, Digium, Inc.
*
* David M. Lee, II <dlee@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief Implementation for ARI stubs.
*
* \author David M. Lee, II <dlee@digium.com>
*/
/*** MODULEINFO
<support_level>core</support_level>
***/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "resource_bridges.h"
#include "asterisk/stasis.h"
#include "asterisk/stasis_bridges.h"
#include "asterisk/stasis_app.h"
#include "asterisk/stasis_app_playback.h"
#include "asterisk/stasis_app_recording.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/core_unreal.h"
#include "asterisk/channel.h"
#include "asterisk/bridge.h"
#include "asterisk/format_cap.h"
#include "asterisk/file.h"
/*!
* \brief Finds a bridge, filling the response with an error, if appropriate.
*
* \param[out] response Response to fill with an error if control is not found.
* \param bridge_id ID of the bridge to lookup.
*
* \return Bridget.
* \return \c NULL if bridge does not exist.
*/
static struct ast_bridge *find_bridge(
struct ast_ari_response *response,
const char *bridge_id)
{
RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
ast_assert(response != NULL);
bridge = stasis_app_bridge_find_by_id(bridge_id);
if (bridge == NULL) {
RAII_VAR(struct ast_bridge_snapshot *, snapshot,
ast_bridge_snapshot_get_latest(bridge_id), ao2_cleanup);
if (!snapshot) {
ast_ari_response_error(response, 404, "Not found",
"Bridge not found");
return NULL;
}
ast_ari_response_error(response, 409, "Conflict",
"Bridge not in Stasis application");
return NULL;
}
ao2_ref(bridge, +1);
return bridge;
}
/*!
* \brief Finds the control object for a channel, filling the response with an
* error, if appropriate.
* \param[out] response Response to fill with an error if control is not found.
* \param channel_id ID of the channel to lookup.
* \return Channel control object.
* \return \c NULL if control object does not exist.
*/
static struct stasis_app_control *find_channel_control(
struct ast_ari_response *response,
const char *channel_id)
{
RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
ast_assert(response != NULL);
control = stasis_app_control_find_by_channel_id(channel_id);
if (control == NULL) {
ast_ari_response_error(response, 422, "Unprocessable Entity",
"Channel not in Stasis application");
return NULL;
}
ao2_ref(control, +1);
return control;
}
void ast_ari_add_channel_to_bridge(struct ast_variable *headers, struct ast_add_channel_to_bridge_args *args, struct ast_ari_response *response)
{
RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
if (!bridge) {
return;
}
control = find_channel_control(response, args->channel);
if (!control) {
return;
}
stasis_app_control_add_channel_to_bridge(control, bridge);
ast_ari_response_no_content(response);
}
void ast_ari_remove_channel_from_bridge(struct ast_variable *headers, struct ast_remove_channel_from_bridge_args *args, struct ast_ari_response *response)
{
RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
if (!bridge) {
return;
}
control = find_channel_control(response, args->channel);
if (!control) {
return;
}
/* BUGBUG this should make sure the bridge requested for removal is actually
* the bridge the channel is in. This will be possible once the bridge uniqueid
* is added to the channel snapshot. A 409 response should be issued if the bridge
* uniqueids don't match */
if (stasis_app_control_remove_channel_from_bridge(control, bridge)) {
ast_ari_response_error(response, 500, "Internal Error",
"Could not remove channel from bridge");
return;
}
ast_ari_response_no_content(response);
}
struct bridge_channel_control_thread_data {
struct ast_channel *bridge_channel;
struct stasis_app_control *control;
};
static void *bridge_channel_control_thread(void *data)
{
struct bridge_channel_control_thread_data *thread_data = data;
struct ast_channel *bridge_channel = thread_data->bridge_channel;
struct stasis_app_control *control = thread_data->control;
RAII_VAR(struct ast_callid *, callid, ast_channel_callid(bridge_channel), ast_callid_cleanup);
if (callid) {
ast_callid_threadassoc_add(callid);
}
ast_free(thread_data);
thread_data = NULL;
stasis_app_control_execute_until_exhausted(bridge_channel, control);
ast_hangup(bridge_channel);
ao2_cleanup(control);
return NULL;
}
static struct ast_channel *prepare_bridge_media_channel(const char *type)
{
RAII_VAR(struct ast_format_cap *, cap, NULL, ast_format_cap_destroy);
struct ast_format format;
cap = ast_format_cap_alloc_nolock();
if (!cap) {
return NULL;
}
ast_format_cap_add(cap, ast_format_set(&format, AST_FORMAT_SLINEAR, 0));
if (!cap) {
return NULL;
}
return ast_request(type, cap, NULL, "ARI", NULL);
}
void ast_ari_play_on_bridge(struct ast_variable *headers, struct ast_play_on_bridge_args *args, struct ast_ari_response *response)
{
RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
RAII_VAR(struct ast_channel *, play_channel, NULL, ast_hangup);
RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);
RAII_VAR(char *, playback_url, NULL, ast_free);
RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
struct bridge_channel_control_thread_data *thread_data;
const char *language;
pthread_t threadid;
ast_assert(response != NULL);
if (!bridge) {
return;
}
if (!(play_channel = prepare_bridge_media_channel("Announcer"))) {
ast_ari_response_error(
response, 500, "Internal Error", "Could not create playback channel");
return;
}
ast_debug(1, "Created announcer channel '%s'\n", ast_channel_name(play_channel));
if (ast_unreal_channel_push_to_bridge(play_channel, bridge)) {
ast_ari_response_error(
response, 500, "Internal Error", "Failed to put playback channel into the bridge");
return;
}
control = stasis_app_control_create(play_channel);
if (control == NULL) {
ast_ari_response_alloc_failed(response);
return;
}
snapshot = stasis_app_control_get_snapshot(control);
if (!snapshot) {
ast_ari_response_error(
response, 500, "Internal Error", "Failed to get control snapshot");
return;
}
language = S_OR(args->lang, snapshot->language);
playback = stasis_app_control_play_uri(control, args->media, language,
args->bridge_id, STASIS_PLAYBACK_TARGET_BRIDGE, args->skipms,
args->offsetms);
if (!playback) {
ast_ari_response_alloc_failed(response);
return;
}
ast_asprintf(&playback_url, "/playback/%s",
stasis_app_playback_get_id(playback));
if (!playback_url) {
ast_ari_response_alloc_failed(response);
return;
}
json = stasis_app_playback_to_json(playback);
if (!json) {
ast_ari_response_alloc_failed(response);
return;
}
/* Give play_channel and control reference to the thread data */
thread_data = ast_calloc(1, sizeof(*thread_data));
if (!thread_data) {
ast_ari_response_alloc_failed(response);
return;
}
thread_data->bridge_channel = play_channel;
thread_data->control = control;
if (ast_pthread_create_detached(&threadid, NULL, bridge_channel_control_thread, thread_data)) {
ast_ari_response_alloc_failed(response);
ast_free(thread_data);
return;
}
/* These are owned by the other thread now, so we don't want RAII_VAR disposing of them. */
play_channel = NULL;
control = NULL;
ast_ari_response_created(response, playback_url, json);
}
void ast_ari_record_bridge(struct ast_variable *headers, struct ast_record_bridge_args *args, struct ast_ari_response *response)
{
RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
RAII_VAR(struct ast_channel *, record_channel, NULL, ast_hangup);
RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
RAII_VAR(char *, recording_url, NULL, ast_free);
RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
RAII_VAR(struct stasis_app_recording_options *, options, NULL, ao2_cleanup);
RAII_VAR(char *, uri_encoded_name, NULL, ast_free);
size_t uri_name_maxlen;
struct bridge_channel_control_thread_data *thread_data;
pthread_t threadid;
ast_assert(response != NULL);
if (bridge == NULL) {
return;
}
if (!(record_channel = prepare_bridge_media_channel("Recorder"))) {
ast_ari_response_error(
response, 500, "Internal Server Error", "Failed to create recording channel");
return;
}
if (ast_unreal_channel_push_to_bridge(record_channel, bridge)) {
ast_ari_response_error(
response, 500, "Internal Error", "Failed to put recording channel into the bridge");
return;
}
control = stasis_app_control_create(record_channel);
if (control == NULL) {
ast_ari_response_alloc_failed(response);
return;
}
options = stasis_app_recording_options_create(args->name, args->format);
if (options == NULL) {
ast_ari_response_alloc_failed(response);
return;
}
options->max_silence_seconds = args->max_silence_seconds;
options->max_duration_seconds = args->max_duration_seconds;
options->terminate_on =
stasis_app_recording_termination_parse(args->terminate_on);
options->if_exists =
stasis_app_recording_if_exists_parse(args->if_exists);
options->beep = args->beep;
recording = stasis_app_control_record(control, options);
if (recording == NULL) {
switch(errno) {
case EINVAL:
/* While the arguments are invalid, we should have
* caught them prior to calling record.
*/
ast_ari_response_error(
response, 500, "Internal Server Error",
"Error parsing request");
break;
case EEXIST:
ast_ari_response_error(response, 409, "Conflict",
"Recording '%s' already in progress",
args->name);
break;
case ENOMEM:
ast_ari_response_alloc_failed(response);
break;
case EPERM:
ast_ari_response_error(
response, 400, "Bad Request",
"Recording name invalid");
break;
default:
ast_log(LOG_WARNING,
"Unrecognized recording error: %s\n",
strerror(errno));
ast_ari_response_error(
response, 500, "Internal Server Error",
"Internal Server Error");
break;
}
return;
}
uri_name_maxlen = strlen(args->name) * 3;
uri_encoded_name = ast_malloc(uri_name_maxlen);
if (!uri_encoded_name) {
ast_ari_response_alloc_failed(response);
return;
}
ast_uri_encode(args->name, uri_encoded_name, uri_name_maxlen, ast_uri_http);
ast_asprintf(&recording_url, "/recordings/live/%s", uri_encoded_name);
if (!recording_url) {
ast_ari_response_alloc_failed(response);
return;
}
json = stasis_app_recording_to_json(recording);
if (!json) {
ast_ari_response_alloc_failed(response);
return;
}
thread_data = ast_calloc(1, sizeof(*thread_data));
if (!thread_data) {
ast_ari_response_alloc_failed(response);
return;
}
thread_data->bridge_channel = record_channel;
thread_data->control = control;
if (ast_pthread_create_detached(&threadid, NULL, bridge_channel_control_thread, thread_data)) {
ast_ari_response_alloc_failed(response);
ast_free(thread_data);
return;
}
/* These are owned by the other thread now, so we don't want RAII_VAR disposing of them. */
record_channel = NULL;
control = NULL;
ast_ari_response_created(response, recording_url, json);
}
void ast_ari_get_bridge(struct ast_variable *headers, struct ast_get_bridge_args *args, struct ast_ari_response *response)
{
RAII_VAR(struct ast_bridge_snapshot *, snapshot, ast_bridge_snapshot_get_latest(args->bridge_id), ao2_cleanup);
if (!snapshot) {
ast_ari_response_error(
response, 404, "Not Found",
"Bridge not found");
return;
}
ast_ari_response_ok(response,
ast_bridge_snapshot_to_json(snapshot));
}
void ast_ari_delete_bridge(struct ast_variable *headers, struct ast_delete_bridge_args *args, struct ast_ari_response *response)
{
RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
if (!bridge) {
return;
}
stasis_app_bridge_destroy(args->bridge_id);
ast_ari_response_no_content(response);
}
void ast_ari_get_bridges(struct ast_variable *headers, struct ast_get_bridges_args *args, struct ast_ari_response *response)
{
RAII_VAR(struct stasis_caching_topic *, caching_topic, NULL, ao2_cleanup);
RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup);
RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
struct ao2_iterator i;
void *obj;
caching_topic = ast_bridge_topic_all_cached();
if (!caching_topic) {
ast_ari_response_error(
response, 500, "Internal Server Error",
"Message bus not initialized");
return;
}
ao2_ref(caching_topic, +1);
snapshots = stasis_cache_dump(caching_topic, ast_bridge_snapshot_type());
if (!snapshots) {
ast_ari_response_alloc_failed(response);
return;
}
json = ast_json_array_create();
if (!json) {
ast_ari_response_alloc_failed(response);
return;
}
i = ao2_iterator_init(snapshots, 0);
while ((obj = ao2_iterator_next(&i))) {
RAII_VAR(struct stasis_message *, msg, obj, ao2_cleanup);
struct ast_bridge_snapshot *snapshot = stasis_message_data(msg);
if (ast_json_array_append(json, ast_bridge_snapshot_to_json(snapshot))) {
ast_ari_response_alloc_failed(response);
return;
}
}
ao2_iterator_destroy(&i);
ast_ari_response_ok(response, ast_json_ref(json));
}
void ast_ari_new_bridge(struct ast_variable *headers, struct ast_new_bridge_args *args, struct ast_ari_response *response)
{
RAII_VAR(struct ast_bridge *, bridge, stasis_app_bridge_create(args->type), ao2_cleanup);
RAII_VAR(struct ast_bridge_snapshot *, snapshot, NULL, ao2_cleanup);
if (!bridge) {
ast_ari_response_error(
response, 500, "Internal Error",
"Unable to create bridge");
return;
}
snapshot = ast_bridge_snapshot_create(bridge);
if (!snapshot) {
ast_ari_response_error(
response, 500, "Internal Error",
"Unable to create snapshot for new bridge");
return;
}
ast_ari_response_ok(response,
ast_bridge_snapshot_to_json(snapshot));
}

179
res/ari/resource_bridges.h Normal file
View File

@@ -0,0 +1,179 @@
/*
* 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/ari/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/ari_resource.h.mustache
*/
#ifndef _ASTERISK_RESOURCE_BRIDGES_H
#define _ASTERISK_RESOURCE_BRIDGES_H
#include "asterisk/ari.h"
/*! \brief Argument struct for ast_ari_get_bridges() */
struct ast_get_bridges_args {
};
/*!
* \brief List active bridges.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_get_bridges(struct ast_variable *headers, struct ast_get_bridges_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_new_bridge() */
struct ast_new_bridge_args {
/*! \brief Type of bridge to create. */
const char *type;
};
/*!
* \brief Create a new bridge.
*
* This bridge persists until it has been shut down, or Asterisk has been shut down.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_new_bridge(struct ast_variable *headers, struct ast_new_bridge_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_get_bridge() */
struct ast_get_bridge_args {
/*! \brief Bridge's id */
const char *bridge_id;
};
/*!
* \brief Get bridge details.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_get_bridge(struct ast_variable *headers, struct ast_get_bridge_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_delete_bridge() */
struct ast_delete_bridge_args {
/*! \brief Bridge's id */
const char *bridge_id;
};
/*!
* \brief Shut down a bridge.
*
* If any channels are in this bridge, they will be removed and resume whatever they were doing beforehand.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_delete_bridge(struct ast_variable *headers, struct ast_delete_bridge_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_add_channel_to_bridge() */
struct ast_add_channel_to_bridge_args {
/*! \brief Bridge's id */
const char *bridge_id;
/*! \brief Channel's id */
const char *channel;
};
/*!
* \brief Add a channel to a bridge.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_add_channel_to_bridge(struct ast_variable *headers, struct ast_add_channel_to_bridge_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_remove_channel_from_bridge() */
struct ast_remove_channel_from_bridge_args {
/*! \brief Bridge's id */
const char *bridge_id;
/*! \brief Channel's id */
const char *channel;
};
/*!
* \brief Remove a channel from a bridge.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_remove_channel_from_bridge(struct ast_variable *headers, struct ast_remove_channel_from_bridge_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_play_on_bridge() */
struct ast_play_on_bridge_args {
/*! \brief Bridge's id */
const char *bridge_id;
/*! \brief Media's URI to play. */
const char *media;
/*! \brief For sounds, selects language for sound. */
const char *lang;
/*! \brief Number of media to skip before playing. */
int offsetms;
/*! \brief Number of milliseconds to skip for forward/reverse operations. */
int skipms;
};
/*!
* \brief Start playback of media on a bridge.
*
* The media URI may be any of a number of URI's. You may use http: and https: URI's, as well as sound: and recording: URI's. This operation creates a playback resource that can be used to control the playback of media (pause, rewind, fast forward, etc.)
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_play_on_bridge(struct ast_variable *headers, struct ast_play_on_bridge_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_record_bridge() */
struct ast_record_bridge_args {
/*! \brief Bridge's id */
const char *bridge_id;
/*! \brief Recording's filename */
const char *name;
/*! \brief Format to encode audio in */
const char *format;
/*! \brief Maximum duration of the recording, in seconds. 0 for no limit. */
int max_duration_seconds;
/*! \brief Maximum duration of silence, in seconds. 0 for no limit. */
int max_silence_seconds;
/*! \brief Action to take if a recording with the same name already exists. */
const char *if_exists;
/*! \brief Play beep when recording begins */
int beep;
/*! \brief DTMF input to terminate recording. */
const char *terminate_on;
};
/*!
* \brief Start a recording.
*
* This records the mixed audio from all channels participating in this bridge.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_record_bridge(struct ast_variable *headers, struct ast_record_bridge_args *args, struct ast_ari_response *response);
#endif /* _ASTERISK_RESOURCE_BRIDGES_H */

693
res/ari/resource_channels.c Normal file
View File

@@ -0,0 +1,693 @@
/*
* 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 Implementation for ARI stubs.
*
* \author David M. Lee, II <dlee@digium.com>
*/
/*** MODULEINFO
<depend type="module">res_stasis_app_playback</depend>
<support_level>core</support_level>
***/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/file.h"
#include "asterisk/pbx.h"
#include "asterisk/dial.h"
#include "asterisk/bridge.h"
#include "asterisk/callerid.h"
#include "asterisk/stasis_app.h"
#include "asterisk/stasis_app_playback.h"
#include "asterisk/stasis_app_recording.h"
#include "asterisk/stasis_channels.h"
#include "resource_channels.h"
#include <limits.h>
/*!
* \brief Finds the control object for a channel, filling the response with an
* error, if appropriate.
* \param[out] response Response to fill with an error if control is not found.
* \param channel_id ID of the channel to lookup.
* \return Channel control object.
* \return \c NULL if control object does not exist.
*/
static struct stasis_app_control *find_control(
struct ast_ari_response *response,
const char *channel_id)
{
RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
ast_assert(response != NULL);
control = stasis_app_control_find_by_channel_id(channel_id);
if (control == NULL) {
/* Distinguish between 404 and 409 errors */
RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
chan = ast_channel_get_by_name(channel_id);
if (chan == NULL) {
ast_ari_response_error(response, 404, "Not Found",
"Channel not found");
return NULL;
}
ast_ari_response_error(response, 409, "Conflict",
"Channel not in Stasis application");
return NULL;
}
ao2_ref(control, +1);
return control;
}
void ast_ari_dial(struct ast_variable *headers, struct ast_dial_args *args, struct ast_ari_response *response)
{
struct stasis_app_control *control;
control = find_control(response, args->channel_id);
if (control == NULL) {
return;
}
if (stasis_app_control_dial(control, args->endpoint, args->timeout)) {
ast_ari_response_alloc_failed(response);
return;
}
ast_ari_response_no_content(response);
}
void ast_ari_continue_in_dialplan(
struct ast_variable *headers,
struct ast_continue_in_dialplan_args *args,
struct ast_ari_response *response)
{
RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
ast_assert(response != NULL);
control = find_control(response, args->channel_id);
if (control == NULL) {
return;
}
if (stasis_app_control_continue(control, args->context, args->extension, args->priority)) {
ast_ari_response_alloc_failed(response);
return;
}
ast_ari_response_no_content(response);
}
void ast_ari_answer_channel(struct ast_variable *headers,
struct ast_answer_channel_args *args,
struct ast_ari_response *response)
{
RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
control = find_control(response, args->channel_id);
if (control == NULL) {
return;
}
if (stasis_app_control_answer(control) != 0) {
ast_ari_response_error(
response, 500, "Internal Server Error",
"Failed to answer channel");
return;
}
ast_ari_response_no_content(response);
}
void ast_ari_mute_channel(struct ast_variable *headers, struct ast_mute_channel_args *args, struct ast_ari_response *response)
{
RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
unsigned int direction = 0;
enum ast_frame_type frametype = AST_FRAME_VOICE;
control = find_control(response, args->channel_id);
if (control == NULL) {
return;
}
if (!strcmp(args->direction, "in")) {
direction = AST_MUTE_DIRECTION_READ;
} else if (!strcmp(args->direction, "out")) {
direction = AST_MUTE_DIRECTION_WRITE;
} else if (!strcmp(args->direction, "both")) {
direction = AST_MUTE_DIRECTION_READ | AST_MUTE_DIRECTION_WRITE;
} else {
ast_ari_response_error(
response, 400, "Bad Request",
"Invalid direction specified");
return;
}
stasis_app_control_mute(control, direction, frametype);
ast_ari_response_no_content(response);
}
void ast_ari_unmute_channel(struct ast_variable *headers, struct ast_unmute_channel_args *args, struct ast_ari_response *response)
{
RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
unsigned int direction = 0;
enum ast_frame_type frametype = AST_FRAME_VOICE;
control = find_control(response, args->channel_id);
if (control == NULL) {
return;
}
if (!strcmp(args->direction, "in")) {
direction = AST_MUTE_DIRECTION_READ;
} else if (!strcmp(args->direction, "out")) {
direction = AST_MUTE_DIRECTION_WRITE;
} else if (!strcmp(args->direction, "both")) {
direction = AST_MUTE_DIRECTION_READ | AST_MUTE_DIRECTION_WRITE;
} else {
ast_ari_response_error(
response, 400, "Bad Request",
"Invalid direction specified");
return;
}
stasis_app_control_unmute(control, direction, frametype);
ast_ari_response_no_content(response);
}
void ast_ari_hold_channel(struct ast_variable *headers, struct ast_hold_channel_args *args, struct ast_ari_response *response)
{
RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
control = find_control(response, args->channel_id);
if (control == NULL) {
/* Response filled in by find_control */
return;
}
stasis_app_control_hold(control);
ast_ari_response_no_content(response);
}
void ast_ari_unhold_channel(struct ast_variable *headers, struct ast_unhold_channel_args *args, struct ast_ari_response *response)
{
RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
control = find_control(response, args->channel_id);
if (control == NULL) {
/* Response filled in by find_control */
return;
}
stasis_app_control_unhold(control);
ast_ari_response_no_content(response);
}
void ast_ari_moh_start_channel(struct ast_variable *headers, struct ast_moh_start_channel_args *args, struct ast_ari_response *response)
{
RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
control = find_control(response, args->channel_id);
if (control == NULL) {
/* Response filled in by find_control */
return;
}
stasis_app_control_moh_start(control, args->moh_class);
ast_ari_response_no_content(response);
}
void ast_ari_moh_stop_channel(struct ast_variable *headers, struct ast_moh_stop_channel_args *args, struct ast_ari_response *response)
{
RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
control = find_control(response, args->channel_id);
if (control == NULL) {
/* Response filled in by find_control */
return;
}
stasis_app_control_moh_stop(control);
ast_ari_response_no_content(response);
}
void ast_ari_play_on_channel(struct ast_variable *headers,
struct ast_play_on_channel_args *args,
struct ast_ari_response *response)
{
RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);
RAII_VAR(char *, playback_url, NULL, ast_free);
RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
const char *language;
ast_assert(response != NULL);
control = find_control(response, args->channel_id);
if (control == NULL) {
/* Response filled in by find_control */
return;
}
snapshot = stasis_app_control_get_snapshot(control);
if (!snapshot) {
ast_ari_response_error(
response, 404, "Not Found",
"Channel not found");
return;
}
if (args->skipms < 0) {
ast_ari_response_error(
response, 400, "Bad Request",
"skipms cannot be negative");
return;
}
if (args->offsetms < 0) {
ast_ari_response_error(
response, 400, "Bad Request",
"offsetms cannot be negative");
return;
}
language = S_OR(args->lang, snapshot->language);
playback = stasis_app_control_play_uri(control, args->media, language,
args->channel_id, STASIS_PLAYBACK_TARGET_CHANNEL, args->skipms, args->offsetms);
if (!playback) {
ast_ari_response_error(
response, 500, "Internal Server Error",
"Failed to queue media for playback");
return;
}
ast_asprintf(&playback_url, "/playback/%s",
stasis_app_playback_get_id(playback));
if (!playback_url) {
ast_ari_response_error(
response, 500, "Internal Server Error",
"Out of memory");
return;
}
json = stasis_app_playback_to_json(playback);
if (!json) {
ast_ari_response_error(
response, 500, "Internal Server Error",
"Out of memory");
return;
}
ast_ari_response_created(response, playback_url, json);
}
void ast_ari_record_channel(struct ast_variable *headers,
struct ast_record_channel_args *args,
struct ast_ari_response *response)
{
RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
RAII_VAR(char *, recording_url, NULL, ast_free);
RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
RAII_VAR(struct stasis_app_recording_options *, options, NULL,
ao2_cleanup);
RAII_VAR(char *, uri_encoded_name, NULL, ast_free);
size_t uri_name_maxlen;
ast_assert(response != NULL);
if (args->max_duration_seconds < 0) {
ast_ari_response_error(
response, 400, "Bad Request",
"max_duration_seconds cannot be negative");
return;
}
if (args->max_silence_seconds < 0) {
ast_ari_response_error(
response, 400, "Bad Request",
"max_silence_seconds cannot be negative");
return;
}
control = find_control(response, args->channel_id);
if (control == NULL) {
/* Response filled in by find_control */
return;
}
options = stasis_app_recording_options_create(args->name, args->format);
if (options == NULL) {
ast_ari_response_error(
response, 500, "Internal Server Error",
"Out of memory");
}
options->max_silence_seconds = args->max_silence_seconds;
options->max_duration_seconds = args->max_duration_seconds;
options->terminate_on =
stasis_app_recording_termination_parse(args->terminate_on);
options->if_exists =
stasis_app_recording_if_exists_parse(args->if_exists);
options->beep = args->beep;
if (options->terminate_on == STASIS_APP_RECORDING_TERMINATE_INVALID) {
ast_ari_response_error(
response, 400, "Bad Request",
"terminateOn invalid");
return;
}
if (options->if_exists == -1) {
ast_ari_response_error(
response, 400, "Bad Request",
"ifExists invalid");
return;
}
recording = stasis_app_control_record(control, options);
if (recording == NULL) {
switch(errno) {
case EINVAL:
/* While the arguments are invalid, we should have
* caught them prior to calling record.
*/
ast_ari_response_error(
response, 500, "Internal Server Error",
"Error parsing request");
break;
case EEXIST:
ast_ari_response_error(response, 409, "Conflict",
"Recording '%s' already in progress",
args->name);
break;
case ENOMEM:
ast_ari_response_error(
response, 500, "Internal Server Error",
"Out of memory");
break;
case EPERM:
ast_ari_response_error(
response, 400, "Bad Request",
"Recording name invalid");
break;
default:
ast_log(LOG_WARNING,
"Unrecognized recording error: %s\n",
strerror(errno));
ast_ari_response_error(
response, 500, "Internal Server Error",
"Internal Server Error");
break;
}
return;
}
uri_name_maxlen = strlen(args->name) * 3;
uri_encoded_name = ast_malloc(uri_name_maxlen);
if (!uri_encoded_name) {
ast_ari_response_error(
response, 500, "Internal Server Error",
"Out of memory");
return;
}
ast_uri_encode(args->name, uri_encoded_name, uri_name_maxlen,
ast_uri_http);
ast_asprintf(&recording_url, "/recordings/live/%s", uri_encoded_name);
if (!recording_url) {
ast_ari_response_error(
response, 500, "Internal Server Error",
"Out of memory");
return;
}
json = stasis_app_recording_to_json(recording);
if (!json) {
ast_ari_response_error(
response, 500, "Internal Server Error",
"Out of memory");
return;
}
ast_ari_response_created(response, recording_url, json);
}
void ast_ari_get_channel(struct ast_variable *headers,
struct ast_get_channel_args *args,
struct ast_ari_response *response)
{
RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
struct stasis_caching_topic *caching_topic;
struct ast_channel_snapshot *snapshot;
caching_topic = ast_channel_topic_all_cached();
if (!caching_topic) {
ast_ari_response_error(
response, 500, "Internal Server Error",
"Message bus not initialized");
return;
}
msg = stasis_cache_get(caching_topic, ast_channel_snapshot_type(),
args->channel_id);
if (!msg) {
ast_ari_response_error(
response, 404, "Not Found",
"Channel not found");
return;
}
snapshot = stasis_message_data(msg);
ast_assert(snapshot != NULL);
ast_ari_response_ok(response,
ast_channel_snapshot_to_json(snapshot));
}
void ast_ari_delete_channel(struct ast_variable *headers,
struct ast_delete_channel_args *args,
struct ast_ari_response *response)
{
RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
chan = ast_channel_get_by_name(args->channel_id);
if (chan == NULL) {
ast_ari_response_error(
response, 404, "Not Found",
"Channel not found");
return;
}
ast_softhangup(chan, AST_SOFTHANGUP_EXPLICIT);
ast_ari_response_no_content(response);
}
void ast_ari_get_channels(struct ast_variable *headers,
struct ast_get_channels_args *args,
struct ast_ari_response *response)
{
RAII_VAR(struct stasis_caching_topic *, caching_topic, NULL, ao2_cleanup);
RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup);
RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
struct ao2_iterator i;
void *obj;
caching_topic = ast_channel_topic_all_cached();
if (!caching_topic) {
ast_ari_response_error(
response, 500, "Internal Server Error",
"Message bus not initialized");
return;
}
ao2_ref(caching_topic, +1);
snapshots = stasis_cache_dump(caching_topic, ast_channel_snapshot_type());
if (!snapshots) {
ast_ari_response_alloc_failed(response);
return;
}
json = ast_json_array_create();
if (!json) {
ast_ari_response_alloc_failed(response);
return;
}
i = ao2_iterator_init(snapshots, 0);
while ((obj = ao2_iterator_next(&i))) {
RAII_VAR(struct stasis_message *, msg, obj, ao2_cleanup);
struct ast_channel_snapshot *snapshot = stasis_message_data(msg);
int r = ast_json_array_append(
json, ast_channel_snapshot_to_json(snapshot));
if (r != 0) {
ast_ari_response_alloc_failed(response);
return;
}
}
ao2_iterator_destroy(&i);
ast_ari_response_ok(response, ast_json_ref(json));
}
void ast_ari_originate(struct ast_variable *headers,
struct ast_originate_args *args,
struct ast_ari_response *response)
{
char *dialtech;
char dialdevice[AST_CHANNEL_NAME];
char *caller_id = NULL;
char *cid_num = NULL;
char *cid_name = NULL;
int timeout = 30000;
char *stuff;
if (ast_strlen_zero(args->endpoint)) {
ast_ari_response_error(response, 400, "Bad Request",
"Endpoint must be specified");
return;
}
dialtech = ast_strdupa(args->endpoint);
if ((stuff = strchr(dialtech, '/'))) {
*stuff++ = '\0';
ast_copy_string(dialdevice, stuff, sizeof(dialdevice));
}
if (ast_strlen_zero(dialtech) || ast_strlen_zero(dialdevice)) {
ast_ari_response_error(response, 400, "Bad Request",
"Invalid endpoint specified");
return;
}
if (args->timeout > 0) {
timeout = args->timeout * 1000;
} else if (args->timeout == -1) {
timeout = -1;
}
if (!ast_strlen_zero(args->caller_id)) {
caller_id = ast_strdupa(args->caller_id);
ast_callerid_parse(caller_id, &cid_name, &cid_num);
if (ast_is_shrinkable_phonenumber(cid_num)) {
ast_shrink_phone_number(cid_num);
}
}
if (!ast_strlen_zero(args->app)) {
const char *app = "Stasis";
RAII_VAR(struct ast_str *, appdata, ast_str_create(64), ast_free);
if (!appdata) {
ast_ari_response_alloc_failed(response);
return;
}
ast_str_set(&appdata, 0, "%s", args->app);
if (!ast_strlen_zero(args->app_args)) {
ast_str_append(&appdata, 0, ",%s", args->app_args);
}
/* originate a channel, putting it into an application */
if (ast_pbx_outgoing_app(dialtech, NULL, dialdevice, timeout, app, ast_str_buffer(appdata), NULL, 0, cid_num, cid_name, NULL, NULL, NULL)) {
ast_ari_response_alloc_failed(response);
return;
}
} else if (!ast_strlen_zero(args->extension)) {
/* originate a channel, sending it to an extension */
if (ast_pbx_outgoing_exten(dialtech, NULL, dialdevice, timeout, S_OR(args->context, "default"), args->extension, args->priority ? args->priority : 1, NULL, 0, cid_num, cid_name, NULL, NULL, NULL, 0)) {
ast_ari_response_alloc_failed(response);
return;
}
} else {
ast_ari_response_error(response, 400, "Bad Request",
"Application or extension must be specified");
return;
}
ast_ari_response_no_content(response);
}
void ast_ari_get_channel_var(struct ast_variable *headers, struct ast_get_channel_var_args *args, struct ast_ari_response *response)
{
RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
RAII_VAR(char *, value, NULL, ast_free);
ast_assert(response != NULL);
control = find_control(response, args->channel_id);
if (control == NULL) {
return;
}
value = stasis_app_control_get_channel_var(control, args->variable);
if (!(json = ast_json_pack("{s: s}", "value", S_OR(value, "")))) {
ast_ari_response_alloc_failed(response);
return;
}
ast_ari_response_ok(response, ast_json_ref(json));
}
void ast_ari_set_channel_var(struct ast_variable *headers, struct ast_set_channel_var_args *args, struct ast_ari_response *response)
{
RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
ast_assert(response != NULL);
control = find_control(response, args->channel_id);
if (control == NULL) {
return;
}
if (ast_strlen_zero(args->variable)) {
ast_ari_response_error(
response, 400, "Bad Request",
"Variable name is required");
return;
}
if (stasis_app_control_set_channel_var(control, args->variable, args->value)) {
ast_ari_response_error(
response, 400, "Bad Request",
"Failed to execute function");
return;
}
ast_ari_response_no_content(response);
}

330
res/ari/resource_channels.h Normal file
View File

@@ -0,0 +1,330 @@
/*
* 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/ari/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/ari_resource.h.mustache
*/
#ifndef _ASTERISK_RESOURCE_CHANNELS_H
#define _ASTERISK_RESOURCE_CHANNELS_H
#include "asterisk/ari.h"
/*! \brief Argument struct for ast_ari_get_channels() */
struct ast_get_channels_args {
};
/*!
* \brief List active channels.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_get_channels(struct ast_variable *headers, struct ast_get_channels_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_originate() */
struct ast_originate_args {
/*! \brief Endpoint to call. */
const char *endpoint;
/*! \brief The extension to dial after the endpoint answers */
const char *extension;
/*! \brief The context to dial after the endpoint answers. If omitted, uses 'default' */
const char *context;
/*! \brief The priority to dial after the endpoint answers. If omitted, uses 1 */
long priority;
/*! \brief The application name to pass to the Stasis application. */
const char *app;
/*! \brief The application arguments to pass to the Stasis application. */
const char *app_args;
/*! \brief CallerID to use when dialing the endpoint or extension. */
const char *caller_id;
/*! \brief Timeout (in seconds) before giving up dialing, or -1 for no timeout. */
int timeout;
};
/*!
* \brief Create a new channel (originate).
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_originate(struct ast_variable *headers, struct ast_originate_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_get_channel() */
struct ast_get_channel_args {
/*! \brief Channel's id */
const char *channel_id;
};
/*!
* \brief Channel details.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_get_channel(struct ast_variable *headers, struct ast_get_channel_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_delete_channel() */
struct ast_delete_channel_args {
/*! \brief Channel's id */
const char *channel_id;
};
/*!
* \brief Delete (i.e. hangup) a channel.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_delete_channel(struct ast_variable *headers, struct ast_delete_channel_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_dial() */
struct ast_dial_args {
/*! \brief Channel's id */
const char *channel_id;
/*! \brief Endpoint to call. If not specified, dial is routed via dialplan */
const char *endpoint;
/*! \brief Extension to dial */
const char *extension;
/*! \brief When routing via dialplan, the context use. If omitted, uses 'default' */
const char *context;
/*! \brief Timeout (in seconds) before giving up dialing, or -1 for no timeout. */
int timeout;
};
/*!
* \brief Create a new channel (originate) and bridge to this channel.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_dial(struct ast_variable *headers, struct ast_dial_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_continue_in_dialplan() */
struct ast_continue_in_dialplan_args {
/*! \brief Channel's id */
const char *channel_id;
/*! \brief The context to continue to. */
const char *context;
/*! \brief The extension to continue to. */
const char *extension;
/*! \brief The priority to continue to. */
int priority;
};
/*!
* \brief Exit application; continue execution in the dialplan.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_continue_in_dialplan(struct ast_variable *headers, struct ast_continue_in_dialplan_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_answer_channel() */
struct ast_answer_channel_args {
/*! \brief Channel's id */
const char *channel_id;
};
/*!
* \brief Answer a channel.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_answer_channel(struct ast_variable *headers, struct ast_answer_channel_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_mute_channel() */
struct ast_mute_channel_args {
/*! \brief Channel's id */
const char *channel_id;
/*! \brief Direction in which to mute audio */
const char *direction;
};
/*!
* \brief Mute a channel.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_mute_channel(struct ast_variable *headers, struct ast_mute_channel_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_unmute_channel() */
struct ast_unmute_channel_args {
/*! \brief Channel's id */
const char *channel_id;
/*! \brief Direction in which to unmute audio */
const char *direction;
};
/*!
* \brief Unmute a channel.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_unmute_channel(struct ast_variable *headers, struct ast_unmute_channel_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_hold_channel() */
struct ast_hold_channel_args {
/*! \brief Channel's id */
const char *channel_id;
};
/*!
* \brief Hold a channel.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_hold_channel(struct ast_variable *headers, struct ast_hold_channel_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_unhold_channel() */
struct ast_unhold_channel_args {
/*! \brief Channel's id */
const char *channel_id;
};
/*!
* \brief Remove a channel from hold.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_unhold_channel(struct ast_variable *headers, struct ast_unhold_channel_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_moh_start_channel() */
struct ast_moh_start_channel_args {
/*! \brief Channel's id */
const char *channel_id;
/*! \brief Music on hold class to use */
const char *moh_class;
};
/*!
* \brief Play music on hold to a channel.
*
* Using media operations such as playOnChannel on a channel playing MOH in this manner will suspend MOH without resuming automatically. If continuing music on hold is desired, the stasis application must reinitiate music on hold.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_moh_start_channel(struct ast_variable *headers, struct ast_moh_start_channel_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_moh_stop_channel() */
struct ast_moh_stop_channel_args {
/*! \brief Channel's id */
const char *channel_id;
};
/*!
* \brief Stop playing music on hold to a channel.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_moh_stop_channel(struct ast_variable *headers, struct ast_moh_stop_channel_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_play_on_channel() */
struct ast_play_on_channel_args {
/*! \brief Channel's id */
const char *channel_id;
/*! \brief Media's URI to play. */
const char *media;
/*! \brief For sounds, selects language for sound. */
const char *lang;
/*! \brief Number of media to skip before playing. */
int offsetms;
/*! \brief Number of milliseconds to skip for forward/reverse operations. */
int skipms;
};
/*!
* \brief Start playback of media.
*
* The media URI may be any of a number of URI's. You may use http: and https: URI's, as well as sound: and recording: URI's. This operation creates a playback resource that can be used to control the playback of media (pause, rewind, fast forward, etc.)
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_play_on_channel(struct ast_variable *headers, struct ast_play_on_channel_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_record_channel() */
struct ast_record_channel_args {
/*! \brief Channel's id */
const char *channel_id;
/*! \brief Recording's filename */
const char *name;
/*! \brief Format to encode audio in */
const char *format;
/*! \brief Maximum duration of the recording, in seconds. 0 for no limit */
int max_duration_seconds;
/*! \brief Maximum duration of silence, in seconds. 0 for no limit */
int max_silence_seconds;
/*! \brief Action to take if a recording with the same name already exists. */
const char *if_exists;
/*! \brief Play beep when recording begins */
int beep;
/*! \brief DTMF input to terminate recording */
const char *terminate_on;
};
/*!
* \brief Start a recording.
*
* Record audio from a channel. Note that this will not capture audio sent to the channel. The bridge itself has a record feature if that's what you want.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_record_channel(struct ast_variable *headers, struct ast_record_channel_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_get_channel_var() */
struct ast_get_channel_var_args {
/*! \brief Channel's id */
const char *channel_id;
/*! \brief The channel variable or function to get */
const char *variable;
};
/*!
* \brief Get the value of a channel variable or function.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_get_channel_var(struct ast_variable *headers, struct ast_get_channel_var_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_set_channel_var() */
struct ast_set_channel_var_args {
/*! \brief Channel's id */
const char *channel_id;
/*! \brief The channel variable or function to set */
const char *variable;
/*! \brief The value to set the variable to */
const char *value;
};
/*!
* \brief Set the value of a channel variable or function.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_set_channel_var(struct ast_variable *headers, struct ast_set_channel_var_args *args, struct ast_ari_response *response);
#endif /* _ASTERISK_RESOURCE_CHANNELS_H */

View File

@@ -0,0 +1,157 @@
/*
* 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 /api-docs/endpoints.{format} implementation- Endpoint resources
*
* \author David M. Lee, II <dlee@digium.com>
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "resource_endpoints.h"
#include "asterisk/astobj2.h"
#include "asterisk/stasis.h"
#include "asterisk/stasis_endpoints.h"
void ast_ari_get_endpoints(struct ast_variable *headers,
struct ast_get_endpoints_args *args,
struct ast_ari_response *response)
{
RAII_VAR(struct stasis_caching_topic *, caching_topic, NULL, ao2_cleanup);
RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup);
RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
struct ao2_iterator i;
void *obj;
caching_topic = ast_endpoint_topic_all_cached();
if (!caching_topic) {
ast_ari_response_error(
response, 500, "Internal Server Error",
"Message bus not initialized");
return;
}
ao2_ref(caching_topic, +1);
snapshots = stasis_cache_dump(caching_topic, ast_endpoint_snapshot_type());
if (!snapshots) {
ast_ari_response_alloc_failed(response);
return;
}
json = ast_json_array_create();
if (!json) {
ast_ari_response_alloc_failed(response);
return;
}
i = ao2_iterator_init(snapshots, 0);
while ((obj = ao2_iterator_next(&i))) {
RAII_VAR(struct stasis_message *, msg, obj, ao2_cleanup);
struct ast_endpoint_snapshot *snapshot = stasis_message_data(msg);
int r = ast_json_array_append(
json, ast_endpoint_snapshot_to_json(snapshot));
if (r != 0) {
ast_ari_response_alloc_failed(response);
return;
}
}
ao2_iterator_destroy(&i);
ast_ari_response_ok(response, ast_json_ref(json));
}
void ast_ari_get_endpoints_by_tech(struct ast_variable *headers,
struct ast_get_endpoints_by_tech_args *args,
struct ast_ari_response *response)
{
RAII_VAR(struct stasis_caching_topic *, caching_topic, NULL, ao2_cleanup);
RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup);
RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
struct ao2_iterator i;
void *obj;
/* TODO - if tech isn't a recognized type of endpoint, it should 404 */
caching_topic = ast_endpoint_topic_all_cached();
if (!caching_topic) {
ast_ari_response_error(
response, 500, "Internal Server Error",
"Message bus not initialized");
return;
}
ao2_ref(caching_topic, +1);
snapshots = stasis_cache_dump(caching_topic, ast_endpoint_snapshot_type());
if (!snapshots) {
ast_ari_response_alloc_failed(response);
return;
}
json = ast_json_array_create();
if (!json) {
ast_ari_response_alloc_failed(response);
return;
}
i = ao2_iterator_init(snapshots, 0);
while ((obj = ao2_iterator_next(&i))) {
RAII_VAR(struct stasis_message *, msg, obj, ao2_cleanup);
struct ast_endpoint_snapshot *snapshot = stasis_message_data(msg);
int r;
if (strcmp(args->tech, snapshot->tech) != 0) {
continue;
}
r = ast_json_array_append(
json, ast_endpoint_snapshot_to_json(snapshot));
if (r != 0) {
ast_ari_response_alloc_failed(response);
return;
}
}
ao2_iterator_destroy(&i);
ast_ari_response_ok(response, ast_json_ref(json));
}
void ast_ari_get_endpoint(struct ast_variable *headers,
struct ast_get_endpoint_args *args,
struct ast_ari_response *response)
{
RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
RAII_VAR(struct ast_endpoint_snapshot *, snapshot, NULL, ao2_cleanup);
snapshot = ast_endpoint_latest_snapshot(args->tech, args->resource, 0);
if (!snapshot) {
ast_ari_response_error(response, 404, "Not Found",
"Endpoint not found");
return;
}
json = ast_endpoint_snapshot_to_json(snapshot);
if (!json) {
ast_ari_response_alloc_failed(response);
return;
}
ast_ari_response_ok(response, ast_json_ref(json));
}

View File

@@ -0,0 +1,82 @@
/*
* 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/ari/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/ari_resource.h.mustache
*/
#ifndef _ASTERISK_RESOURCE_ENDPOINTS_H
#define _ASTERISK_RESOURCE_ENDPOINTS_H
#include "asterisk/ari.h"
/*! \brief Argument struct for ast_ari_get_endpoints() */
struct ast_get_endpoints_args {
};
/*!
* \brief List all endoints.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_get_endpoints(struct ast_variable *headers, struct ast_get_endpoints_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_get_endpoints_by_tech() */
struct ast_get_endpoints_by_tech_args {
/*! \brief Technology of the endpoints (sip,iax2,...) */
const char *tech;
};
/*!
* \brief List available endoints for a given endpoint technology.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_get_endpoints_by_tech(struct ast_variable *headers, struct ast_get_endpoints_by_tech_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_get_endpoint() */
struct ast_get_endpoint_args {
/*! \brief Technology of the endpoint */
const char *tech;
/*! \brief ID of the endpoint */
const char *resource;
};
/*!
* \brief Details for an endpoint.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_get_endpoint(struct ast_variable *headers, struct ast_get_endpoint_args *args, struct ast_ari_response *response);
#endif /* _ASTERISK_RESOURCE_ENDPOINTS_H */

218
res/ari/resource_events.c Normal file
View File

@@ -0,0 +1,218 @@
/*
* 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 /api-docs/events.{format} implementation- WebSocket resource
*
* \author David M. Lee, II <dlee@digium.com>
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/astobj2.h"
#include "asterisk/stasis_app.h"
#include "resource_events.h"
/*! Number of buckets for the Stasis application hash table. Remember to keep it
* a prime number!
*/
#define APPS_NUM_BUCKETS 7
/*! \brief A connection to the event WebSocket */
struct event_session {
struct ast_ari_websocket_session *ws_session;
struct ao2_container *websocket_apps;
};
/*!
* \brief Explicitly shutdown a session.
*
* An explicit shutdown is necessary, since stasis-app has a reference to this
* session. We also need to be sure to null out the \c ws_session field, since
* the websocket is about to go away.
*
* \param session Session info struct.
*/
static void session_shutdown(struct event_session *session)
{
struct ao2_iterator i;
char *app;
SCOPED_AO2LOCK(lock, session);
i = ao2_iterator_init(session->websocket_apps, 0);
while ((app = ao2_iterator_next(&i))) {
stasis_app_unregister(app);
ao2_cleanup(app);
}
ao2_iterator_destroy(&i);
ao2_cleanup(session->websocket_apps);
session->websocket_apps = NULL;
session->ws_session = NULL;
}
static void session_dtor(void *obj)
{
#ifdef AST_DEVMODE /* Avoid unused variable warning */
struct event_session *session = obj;
#endif
/* session_shutdown should have been called before */
ast_assert(session->ws_session == NULL);
ast_assert(session->websocket_apps == NULL);
}
static void session_cleanup(struct event_session *session)
{
session_shutdown(session);
ao2_cleanup(session);
}
static struct event_session *session_create(
struct ast_ari_websocket_session *ws_session)
{
RAII_VAR(struct event_session *, session, NULL, ao2_cleanup);
session = ao2_alloc(sizeof(*session), session_dtor);
session->ws_session = ws_session;
session->websocket_apps =
ast_str_container_alloc(APPS_NUM_BUCKETS);
if (!session->websocket_apps) {
return NULL;
}
ao2_ref(session, +1);
return session;
}
/*!
* \brief Callback handler for Stasis application messages.
*/
static void app_handler(void *data, const char *app_name,
struct ast_json *message)
{
struct event_session *session = data;
int res;
const char *msg_type = S_OR(
ast_json_string_get(ast_json_object_get(message, "type")),
"");
const char *msg_application = S_OR(
ast_json_string_get(ast_json_object_get(message, "application")),
"");
/* Determine if we've been replaced */
if (strcmp(msg_type, "ApplicationReplaced") == 0 &&
strcmp(msg_application, app_name) == 0) {
ao2_find(session->websocket_apps, msg_application,
OBJ_UNLINK | OBJ_NODATA);
}
res = ast_json_object_set(message, "application",
ast_json_string_create(app_name));
if(res != 0) {
return;
}
ao2_lock(session);
if (session->ws_session) {
ast_ari_websocket_session_write(session->ws_session, message);
}
ao2_unlock(session);
}
/*!
* \brief Register for all of the apps given.
* \param session Session info struct.
* \param app_list Comma seperated list of app names to register.
*/
static int session_register_apps(struct event_session *session,
const char *app_list)
{
RAII_VAR(char *, to_free, NULL, ast_free);
char *apps, *app_name;
SCOPED_AO2LOCK(lock, session);
ast_assert(session->ws_session != NULL);
ast_assert(session->websocket_apps != NULL);
if (!app_list) {
return -1;
}
to_free = apps = ast_strdup(app_list);
if (!apps) {
ast_ari_websocket_session_write(session->ws_session, ast_ari_oom_json());
return -1;
}
while ((app_name = strsep(&apps, ","))) {
if (ast_str_container_add(session->websocket_apps, app_name)) {
ast_ari_websocket_session_write(session->ws_session, ast_ari_oom_json());
return -1;
}
stasis_app_register(app_name, app_handler, session);
}
return 0;
}
void ast_ari_websocket_event_websocket(struct ast_ari_websocket_session *ws_session,
struct ast_variable *headers,
struct ast_event_websocket_args *args)
{
RAII_VAR(struct event_session *, session, NULL, session_cleanup);
struct ast_json *msg;
int res;
ast_debug(3, "/events WebSocket connection\n");
session = session_create(ws_session);
if (!session) {
ast_ari_websocket_session_write(ws_session, ast_ari_oom_json());
return;
}
if (!args->app) {
RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);
msg = ast_json_pack("{s: s, s: [s]}",
"type", "MissingParams",
"params", "app");
if (!msg) {
msg = ast_json_ref(ast_ari_oom_json());
}
ast_ari_websocket_session_write(session->ws_session, msg);
return;
}
res = session_register_apps(session, args->app);
if (res != 0) {
ast_ari_websocket_session_write(ws_session, ast_ari_oom_json());
return;
}
/* We don't process any input, but we'll consume it waiting for EOF */
while ((msg = ast_ari_websocket_session_read(ws_session))) {
ast_json_unref(msg);
}
}

56
res/ari/resource_events.h Normal file
View File

@@ -0,0 +1,56 @@
/*
* 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/ari/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/ari_resource.h.mustache
*/
#ifndef _ASTERISK_RESOURCE_EVENTS_H
#define _ASTERISK_RESOURCE_EVENTS_H
#include "asterisk/ari.h"
/*! \brief Argument struct for ast_ari_event_websocket() */
struct ast_event_websocket_args {
/*! \brief Comma seperated list of applications to subscribe to. */
const char *app;
};
/*!
* \brief WebSocket connection for events.
*
* \param session ARI WebSocket.
* \param headers HTTP headers.
* \param args Swagger parameters.
*/
void ast_ari_websocket_event_websocket(struct ast_ari_websocket_session *session, struct ast_variable *headers, struct ast_event_websocket_args *args);
#endif /* _ASTERISK_RESOURCE_EVENTS_H */

137
res/ari/resource_playback.c Normal file
View File

@@ -0,0 +1,137 @@
/*
* 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 /api-docs/playback.{format} implementation- Playback control resources
*
* \author David M. Lee, II <dlee@digium.com>
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stasis_app_playback.h"
#include "resource_playback.h"
void ast_ari_get_playback(struct ast_variable *headers,
struct ast_get_playback_args *args,
struct ast_ari_response *response)
{
RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);
RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
playback = stasis_app_playback_find_by_id(args->playback_id);
if (playback == NULL) {
ast_ari_response_error(response, 404, "Not Found",
"Playback not found");
return;
}
json = stasis_app_playback_to_json(playback);
if (json == NULL) {
ast_ari_response_error(response, 500,
"Internal Server Error", "Error building response");
return;
}
ast_ari_response_ok(response, ast_json_ref(json));
}
void ast_ari_stop_playback(struct ast_variable *headers,
struct ast_stop_playback_args *args,
struct ast_ari_response *response)
{
RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);
enum stasis_playback_oper_results res;
playback = stasis_app_playback_find_by_id(args->playback_id);
if (playback == NULL) {
ast_ari_response_error(response, 404, "Not Found",
"Playback not found");
return;
}
res = stasis_app_playback_operation(playback, STASIS_PLAYBACK_STOP);
switch (res) {
case STASIS_PLAYBACK_OPER_OK:
ast_ari_response_no_content(response);
return;
case STASIS_PLAYBACK_OPER_FAILED:
ast_ari_response_error(response, 500,
"Internal Server Error", "Could not stop playback");
return;
case STASIS_PLAYBACK_OPER_NOT_PLAYING:
/* Stop operation should be valid even when not playing */
ast_assert(0);
ast_ari_response_error(response, 500,
"Internal Server Error", "Could not stop playback");
return;
}
}
void ast_ari_control_playback(struct ast_variable *headers,
struct ast_control_playback_args *args,
struct ast_ari_response *response)
{
RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);
enum stasis_app_playback_media_operation oper;
enum stasis_playback_oper_results res;
if (strcmp(args->operation, "unpause") == 0) {
oper = STASIS_PLAYBACK_UNPAUSE;
} else if (strcmp(args->operation, "pause") == 0) {
oper = STASIS_PLAYBACK_PAUSE;
} else if (strcmp(args->operation, "restart") == 0) {
oper = STASIS_PLAYBACK_RESTART;
} else if (strcmp(args->operation, "reverse") == 0) {
oper = STASIS_PLAYBACK_REVERSE;
} else if (strcmp(args->operation, "forward") == 0) {
oper = STASIS_PLAYBACK_FORWARD;
} else {
ast_ari_response_error(response, 400,
"Bad Request", "Invalid operation %s",
args->operation);
return;
}
playback = stasis_app_playback_find_by_id(args->playback_id);
if (playback == NULL) {
ast_ari_response_error(response, 404, "Not Found",
"Playback not found");
return;
}
res = stasis_app_playback_operation(playback, oper);
switch (res) {
case STASIS_PLAYBACK_OPER_OK:
ast_ari_response_no_content(response);
return;
case STASIS_PLAYBACK_OPER_FAILED:
ast_ari_response_error(response, 500,
"Internal Server Error", "Could not %s playback",
args->operation);
return;
case STASIS_PLAYBACK_OPER_NOT_PLAYING:
ast_ari_response_error(response, 409, "Conflict",
"Can only %s while media is playing", args->operation);
return;
}
}

View File

@@ -0,0 +1,84 @@
/*
* 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/ari/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/ari_resource.h.mustache
*/
#ifndef _ASTERISK_RESOURCE_PLAYBACK_H
#define _ASTERISK_RESOURCE_PLAYBACK_H
#include "asterisk/ari.h"
/*! \brief Argument struct for ast_ari_get_playback() */
struct ast_get_playback_args {
/*! \brief Playback's id */
const char *playback_id;
};
/*!
* \brief Get a playback's details.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_get_playback(struct ast_variable *headers, struct ast_get_playback_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_stop_playback() */
struct ast_stop_playback_args {
/*! \brief Playback's id */
const char *playback_id;
};
/*!
* \brief Stop a playback.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_stop_playback(struct ast_variable *headers, struct ast_stop_playback_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_control_playback() */
struct ast_control_playback_args {
/*! \brief Playback's id */
const char *playback_id;
/*! \brief Operation to perform on the playback. */
const char *operation;
};
/*!
* \brief Get a playback's details.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_control_playback(struct ast_variable *headers, struct ast_control_playback_args *args, struct ast_ari_response *response);
#endif /* _ASTERISK_RESOURCE_PLAYBACK_H */

View File

@@ -0,0 +1,97 @@
/*
* 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 /api-docs/recordings.{format} implementation- Recording resources
*
* \author David M. Lee, II <dlee@digium.com>
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stasis_app_recording.h"
#include "resource_recordings.h"
void ast_ari_get_stored_recordings(struct ast_variable *headers, struct ast_get_stored_recordings_args *args, struct ast_ari_response *response)
{
ast_log(LOG_ERROR, "TODO: ast_ari_get_stored_recordings\n");
}
void ast_ari_get_stored_recording(struct ast_variable *headers, struct ast_get_stored_recording_args *args, struct ast_ari_response *response)
{
ast_log(LOG_ERROR, "TODO: ast_ari_get_stored_recording\n");
}
void ast_ari_delete_stored_recording(struct ast_variable *headers, struct ast_delete_stored_recording_args *args, struct ast_ari_response *response)
{
ast_log(LOG_ERROR, "TODO: ast_ari_delete_stored_recording\n");
}
void ast_ari_get_live_recordings(struct ast_variable *headers, struct ast_get_live_recordings_args *args, struct ast_ari_response *response)
{
ast_log(LOG_ERROR, "TODO: ast_ari_get_live_recordings\n");
}
void ast_ari_get_live_recording(struct ast_variable *headers,
struct ast_get_live_recording_args *args,
struct ast_ari_response *response)
{
RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
recording = stasis_app_recording_find_by_name(args->recording_name);
if (recording == NULL) {
ast_ari_response_error(response, 404, "Not Found",
"Recording not found");
return;
}
json = stasis_app_recording_to_json(recording);
if (json == NULL) {
ast_ari_response_error(response, 500,
"Internal Server Error", "Error building response");
return;
}
ast_ari_response_ok(response, ast_json_ref(json));
}
void ast_ari_cancel_recording(struct ast_variable *headers, struct ast_cancel_recording_args *args, struct ast_ari_response *response)
{
ast_log(LOG_ERROR, "TODO: ast_ari_cancel_recording\n");
}
void ast_ari_stop_recording(struct ast_variable *headers, struct ast_stop_recording_args *args, struct ast_ari_response *response)
{
ast_log(LOG_ERROR, "TODO: ast_ari_stop_recording\n");
}
void ast_ari_pause_recording(struct ast_variable *headers, struct ast_pause_recording_args *args, struct ast_ari_response *response)
{
ast_log(LOG_ERROR, "TODO: ast_ari_pause_recording\n");
}
void ast_ari_unpause_recording(struct ast_variable *headers, struct ast_unpause_recording_args *args, struct ast_ari_response *response)
{
ast_log(LOG_ERROR, "TODO: ast_ari_unpause_recording\n");
}
void ast_ari_mute_recording(struct ast_variable *headers, struct ast_mute_recording_args *args, struct ast_ari_response *response)
{
ast_log(LOG_ERROR, "TODO: ast_ari_mute_recording\n");
}
void ast_ari_unmute_recording(struct ast_variable *headers, struct ast_unmute_recording_args *args, struct ast_ari_response *response)
{
ast_log(LOG_ERROR, "TODO: ast_ari_unmute_recording\n");
}

View File

@@ -0,0 +1,186 @@
/*
* 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/ari/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/ari_resource.h.mustache
*/
#ifndef _ASTERISK_RESOURCE_RECORDINGS_H
#define _ASTERISK_RESOURCE_RECORDINGS_H
#include "asterisk/ari.h"
/*! \brief Argument struct for ast_ari_get_stored_recordings() */
struct ast_get_stored_recordings_args {
};
/*!
* \brief List recordings that are complete.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_get_stored_recordings(struct ast_variable *headers, struct ast_get_stored_recordings_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_get_stored_recording() */
struct ast_get_stored_recording_args {
/*! \brief The name of the recording */
const char *recording_name;
};
/*!
* \brief Get a stored recording's details.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_get_stored_recording(struct ast_variable *headers, struct ast_get_stored_recording_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_delete_stored_recording() */
struct ast_delete_stored_recording_args {
/*! \brief The name of the recording */
const char *recording_name;
};
/*!
* \brief Delete a stored recording.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_delete_stored_recording(struct ast_variable *headers, struct ast_delete_stored_recording_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_get_live_recordings() */
struct ast_get_live_recordings_args {
};
/*!
* \brief List libe recordings.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_get_live_recordings(struct ast_variable *headers, struct ast_get_live_recordings_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_get_live_recording() */
struct ast_get_live_recording_args {
/*! \brief The name of the recording */
const char *recording_name;
};
/*!
* \brief List live recordings.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_get_live_recording(struct ast_variable *headers, struct ast_get_live_recording_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_cancel_recording() */
struct ast_cancel_recording_args {
/*! \brief The name of the recording */
const char *recording_name;
};
/*!
* \brief Stop a live recording and discard it.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_cancel_recording(struct ast_variable *headers, struct ast_cancel_recording_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_stop_recording() */
struct ast_stop_recording_args {
/*! \brief The name of the recording */
const char *recording_name;
};
/*!
* \brief Stop a live recording and store it.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_stop_recording(struct ast_variable *headers, struct ast_stop_recording_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_pause_recording() */
struct ast_pause_recording_args {
/*! \brief The name of the recording */
const char *recording_name;
};
/*!
* \brief Pause a live recording.
*
* Pausing a recording suspends silence detection, which will be restarted when the recording is unpaused.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_pause_recording(struct ast_variable *headers, struct ast_pause_recording_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_unpause_recording() */
struct ast_unpause_recording_args {
/*! \brief The name of the recording */
const char *recording_name;
};
/*!
* \brief Unpause a live recording.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_unpause_recording(struct ast_variable *headers, struct ast_unpause_recording_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_mute_recording() */
struct ast_mute_recording_args {
/*! \brief The name of the recording */
const char *recording_name;
};
/*!
* \brief Mute a live recording.
*
* Muting a recording suspends silence detection, which will be restarted when the recording is unmuted.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_mute_recording(struct ast_variable *headers, struct ast_mute_recording_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_unmute_recording() */
struct ast_unmute_recording_args {
/*! \brief The name of the recording */
const char *recording_name;
};
/*!
* \brief Unmute a live recording.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_unmute_recording(struct ast_variable *headers, struct ast_unmute_recording_args *args, struct ast_ari_response *response);
#endif /* _ASTERISK_RESOURCE_RECORDINGS_H */

220
res/ari/resource_sounds.c Normal file
View File

@@ -0,0 +1,220 @@
/*
* 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 /api-docs/sounds.{format} implementation- Sound resources
*
* \author David M. Lee, II <dlee@digium.com>
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "resource_sounds.h"
#include "asterisk/media_index.h"
#include "asterisk/sounds_index.h"
#include "asterisk/format.h"
#include "asterisk/format_cap.h"
#include "asterisk/json.h"
/*! \brief arguments that are necessary for adding format/lang pairs */
struct lang_format_info {
struct ast_json *format_list; /*!< The embedded array to which format/lang pairs should be added */
const char *filename; /*!< Name of the file for which to add format/lang pairs */
const char *format_filter; /*!< Format filter provided in the request */
};
/*! \brief Add format/lang pairs to the array embedded in the sound object */
static int add_format_information_cb(void *obj, void *arg, int flags)
{
char *language = obj;
struct lang_format_info *args = arg;
struct ast_format format;
RAII_VAR(struct ast_format_cap *, cap, NULL, ast_format_cap_destroy);
RAII_VAR(struct ast_media_index *, sounds_index, ast_sounds_get_index(), ao2_cleanup);
if (!sounds_index) {
return CMP_STOP;
}
cap = ast_media_get_format_cap(sounds_index, args->filename, language);
if (!cap) {
return CMP_STOP;
}
ast_format_cap_iter_start(cap);
while (!ast_format_cap_iter_next(cap, &format)) {
struct ast_json *lang_format_pair;
const char *format_name = ast_getformatname(&format);
if (!ast_strlen_zero(args->format_filter)
&& strcmp(args->format_filter, format_name)) {
continue;
}
lang_format_pair = ast_json_pack("{s: s, s: s}",
"language", language,
"format", format_name);
if (!lang_format_pair) {
ast_format_cap_iter_end(cap);
return CMP_STOP;
}
ast_json_array_append(args->format_list, lang_format_pair);
}
ast_format_cap_iter_end(cap);
return 0;
}
/*! \brief Filter out all languages not matching the specified language */
static int filter_langs_cb(void *obj, void *arg, int flags)
{
char *lang_filter = arg;
char *lang = obj;
if (strcmp(lang, lang_filter)) {
return CMP_MATCH;
}
return 0;
}
/*! \brief Generate a Sound structure as documented in sounds.json for the specified filename */
static struct ast_json *create_sound_blob(const char *filename, struct ast_get_sounds_args *args)
{
RAII_VAR(struct ast_json *, sound, NULL, ast_json_unref);
RAII_VAR(struct ao2_container *, languages, NULL, ao2_cleanup);
const char *description;
struct ast_json *format_lang_list;
struct lang_format_info info;
RAII_VAR(struct ast_media_index *, sounds_index, ast_sounds_get_index(), ao2_cleanup);
if (!sounds_index) {
return NULL;
}
description = ast_media_get_description(sounds_index, filename, "en");
if (ast_strlen_zero(description)) {
sound = ast_json_pack("{s: s, s: []}",
"id", filename,
"formats");
} else {
sound = ast_json_pack("{s: s, s: s, s: []}",
"id", filename,
"text", description,
"formats");
}
if (!sound) {
return NULL;
}
format_lang_list = ast_json_object_get(sound, "formats");
if (!format_lang_list) {
return NULL;
}
languages = ast_media_get_variants(sounds_index, filename);
if (!languages || !ao2_container_count(languages)) {
return NULL;
}
/* filter requested languages */
if (args && !ast_strlen_zero(args->lang)) {
char *lang_filter = ast_strdupa(args->lang);
ao2_callback(languages, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, filter_langs_cb, lang_filter);
if (!languages || !ao2_container_count(languages)) {
return NULL;
}
}
info.filename = filename;
info.format_list = format_lang_list;
info.format_filter = NULL;
if (args) {
info.format_filter = args->format;
}
ao2_callback(languages, OBJ_NODATA, add_format_information_cb, &info);
/* no format/lang pairs for this sound so nothing to return */
if (!ast_json_array_size(format_lang_list)) {
return NULL;
}
return ast_json_ref(sound);
}
/*! \brief Generate a Sound structure and append it to the output blob */
static int append_sound_cb(void *obj, void *arg, void *data, int flags)
{
struct ast_json *sounds_array = arg;
char *filename = obj;
struct ast_get_sounds_args *args = data;
struct ast_json *sound_blob = create_sound_blob(filename, args);
if (!sound_blob) {
return 0;
}
ast_json_array_append(sounds_array, sound_blob);
return 0;
}
void ast_ari_get_sounds(struct ast_variable *headers, struct ast_get_sounds_args *args, struct ast_ari_response *response)
{
RAII_VAR(struct ao2_container *, sound_files, NULL, ao2_cleanup);
struct ast_json *sounds_blob;
RAII_VAR(struct ast_media_index *, sounds_index, ast_sounds_get_index(), ao2_cleanup);
if (!sounds_index) {
ast_ari_response_error(response, 500, "Internal Error", "Sounds index not available");
return;
}
sound_files = ast_media_get_media(sounds_index);
if (!sound_files) {
ast_ari_response_error(response, 500, "Internal Error", "Allocation Error");
return;
}
sounds_blob = ast_json_array_create();
if (!sounds_blob) {
ast_ari_response_error(response, 500, "Internal Error", "Allocation Error");
return;
}
ao2_callback_data(sound_files, OBJ_NODATA, append_sound_cb, sounds_blob, args);
if (!ast_json_array_size(sounds_blob)) {
ast_ari_response_error(response, 404, "Not Found", "No sounds found that matched the query");
return;
}
ast_ari_response_ok(response, sounds_blob);
}
void ast_ari_get_stored_sound(struct ast_variable *headers, struct ast_get_stored_sound_args *args, struct ast_ari_response *response)
{
struct ast_json *sound_blob;
sound_blob = create_sound_blob(args->sound_id, NULL);
if (!sound_blob) {
ast_ari_response_error(response, 404, "Not Found", "Sound not found");
return;
}
ast_ari_response_ok(response, sound_blob);
}

69
res/ari/resource_sounds.h Normal file
View File

@@ -0,0 +1,69 @@
/*
* 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/ari/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/ari_resource.h.mustache
*/
#ifndef _ASTERISK_RESOURCE_SOUNDS_H
#define _ASTERISK_RESOURCE_SOUNDS_H
#include "asterisk/ari.h"
/*! \brief Argument struct for ast_ari_get_sounds() */
struct ast_get_sounds_args {
const char *lang;
const char *format;
};
/*!
* \brief List all sounds.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_get_sounds(struct ast_variable *headers, struct ast_get_sounds_args *args, struct ast_ari_response *response);
/*! \brief Argument struct for ast_ari_get_stored_sound() */
struct ast_get_stored_sound_args {
/*! \brief Sound's id */
const char *sound_id;
};
/*!
* \brief Get a sound's details.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_get_stored_sound(struct ast_variable *headers, struct ast_get_stored_sound_args *args, struct ast_ari_response *response);
#endif /* _ASTERISK_RESOURCE_SOUNDS_H */