Asterisk - The Open Source Telephony Project  21.4.1
Macros | Functions | Variables
res_ari.c File Reference

HTTP binding for the Stasis API. More...

#include "asterisk.h"
#include "ari/internal.h"
#include "asterisk/ari.h"
#include "asterisk/astobj2.h"
#include "asterisk/module.h"
#include "asterisk/paths.h"
#include "asterisk/stasis_app.h"
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

Go to the source code of this file.

Macros

#define ACA_HEADERS   "Access-Control-Allow-Headers"
 
#define ACA_METHODS   "Access-Control-Allow-Methods"
 
#define ACR_HEADERS   "Access-Control-Request-Headers"
 
#define ACR_METHOD   "Access-Control-Request-Method"
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static void add_allow_header (struct stasis_rest_handlers *handler, struct ast_ari_response *response)
 
int ast_ari_add_handler (struct stasis_rest_handlers *handler)
 
static int ast_ari_callback (struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
 
void ast_ari_get_docs (const char *uri, const char *prefix, struct ast_variable *headers, struct ast_ari_response *response)
 
void ast_ari_invoke (struct ast_tcptls_session_instance *ser, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
 
enum ast_json_encoding_format ast_ari_json_format (void)
 Configured encoding format for JSON output. More...
 
struct ast_jsonast_ari_oom_json (void)
 The stock message to return when out of memory. More...
 
int ast_ari_remove_handler (struct stasis_rest_handlers *handler)
 
void ast_ari_response_accepted (struct ast_ari_response *response)
 Fill in a Accepted (202) ast_ari_response.
 
void ast_ari_response_alloc_failed (struct ast_ari_response *response)
 Fill in response with a 500 message for allocation failures. More...
 
void ast_ari_response_created (struct ast_ari_response *response, const char *url, struct ast_json *message)
 Fill in a Created (201) ast_ari_response. More...
 
void ast_ari_response_error (struct ast_ari_response *response, int response_code, const char *response_text, const char *message_fmt,...)
 Fill in an error ast_ari_response. More...
 
void ast_ari_response_no_content (struct ast_ari_response *response)
 Fill in a No Content (204) ast_ari_response.
 
void ast_ari_response_ok (struct ast_ari_response *response, struct ast_json *message)
 Fill in an OK (200) ast_ari_response. More...
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static struct ast_ari_conf_userauthenticate_api_key (const char *api_key)
 Authenticate a ?api_key=userid:password More...
 
static struct ast_ari_conf_userauthenticate_user (struct ast_variable *get_params, struct ast_variable *headers)
 Authenticate an HTTP request. More...
 
static struct stasis_rest_handlersget_root_handler (void)
 
static void handle_options (struct stasis_rest_handlers *handler, struct ast_variable *headers, struct ast_ari_response *response)
 Handle OPTIONS request, mainly for CORS preflight requests. More...
 
static int is_enabled (void)
 Helper function to check if module is enabled.
 
static int load_module (void)
 
static int origin_allowed (const char *origin)
 
static void process_cors_request (struct ast_variable *headers, struct ast_ari_response *response)
 Handle CORS headers for simple requests. More...
 
static int reload_module (void)
 
static void remove_trailing_slash (const char *uri, struct ast_ari_response *response)
 
static struct stasis_rest_handlersroot_handler_create (void)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .description = "Asterisk RESTful Interface" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "da6642af068ee5e6490c5b1d2cc1d238" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload_module, .optional_modules = "res_http_websocket", .requires = "http,res_stasis", .load_pri = AST_MODPRI_APP_DEPEND, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_http_uri http_uri
 
static struct ast_jsonoom_json
 
static struct stasis_rest_handlersroot_handler
 
static ast_mutex_t root_handler_lock
 

Detailed Description

HTTP binding for the Stasis API.

Author
David M. Lee, II dlee@.nosp@m.digi.nosp@m.um.co.nosp@m.m

The API itself is documented using Swagger, a lightweight mechanism for documenting RESTful API's using JSON. This allows us to use swagger-ui to provide executable documentation for the API, generate client bindings in different languages, and generate a lot of the boilerplate code for implementing the RESTful bindings. The API docs live in the rest-api/ directory.

The RESTful bindings are generated from the Swagger API docs using a set of Mustache templates. The code generator is written in Python, and uses the Python implementation pystache. Pystache has no dependencies, and be installed easily using pip. Code generation code lives in rest-api-templates/.

The generated code reduces a lot of boilerplate when it comes to handling HTTP requests. It also helps us have greater consistency in the REST API.

The structure of the generated code is:

The basic flow of an HTTP request is:

Definition in file res_ari.c.

Function Documentation

int ast_ari_add_handler ( struct stasis_rest_handlers handler)

Add a resource for REST handling.

Parameters
handlerHandler to add.
Return values
0on success.
non-zeroon failure.

Definition at line 179 of file res_ari.c.

References ao2_ref, lock, stasis_rest_handlers::num_children, RAII_VAR, and SCOPED_MUTEX.

Referenced by setup_invocation_test().

180 {
181  RAII_VAR(struct stasis_rest_handlers *, new_handler, NULL, ao2_cleanup);
182  size_t old_size, new_size;
183 
185 
186  old_size = sizeof(*new_handler) + root_handler->num_children * sizeof(handler);
187  new_size = old_size + sizeof(handler);
188 
189  new_handler = ao2_alloc(new_size, NULL);
190  if (!new_handler) {
191  return -1;
192  }
193  memcpy(new_handler, root_handler, old_size);
194  new_handler->children[new_handler->num_children++] = handler;
195 
196  ao2_cleanup(root_handler);
197  ao2_ref(new_handler, +1);
198  root_handler = new_handler;
199  return 0;
200 }
ast_mutex_t lock
#define SCOPED_MUTEX(varname, lock)
scoped lock specialization for mutexes
Definition: lock.h:589
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
static struct stasis_rest_handlers * root_handler
Definition: res_ari.c:169
size_t num_children
Definition: ari.h:84
static ast_mutex_t root_handler_lock
Definition: res_ari.c:166
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
Handler for a single RESTful path segment.
Definition: ari.h:69
enum ast_json_encoding_format ast_ari_json_format ( void  )

Configured encoding format for JSON output.

Returns
JSON output encoding (compact, pretty, etc.)

Definition at line 806 of file res_ari.c.

References ast_ari_config_get(), and RAII_VAR.

Referenced by ast_ari_websocket_session_write(), and stasis_app_message_handler().

807 {
808  RAII_VAR(struct ast_ari_conf *, cfg, NULL, ao2_cleanup);
809  cfg = ast_ari_config_get();
810  return cfg->general->format;
811 }
struct ast_ari_conf * ast_ari_config_get(void)
Get the current ARI configuration.
All configuration options for ARI.
Definition: internal.h:54
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
struct ast_json* ast_ari_oom_json ( void  )

The stock message to return when out of memory.

The refcount is NOT bumped on this object, so ast_json_ref() if you want to keep the reference.

Returns
JSON message specifying an out-of-memory error.

Definition at line 174 of file res_ari.c.

References oom_json.

175 {
176  return oom_json;
177 }
static struct ast_json * oom_json
Definition: res_ari.c:172
int ast_ari_remove_handler ( struct stasis_rest_handlers handler)

Remove a resource for REST handling.

Parameters
handlerHandler to add.
Return values
0on success.
non-zeroon failure.

Definition at line 202 of file res_ari.c.

References stasis_rest_handlers::children, and stasis_rest_handlers::num_children.

Referenced by tear_down_invocation_test().

203 {
204  struct stasis_rest_handlers *new_handler;
205  size_t size;
206  size_t i;
207  size_t j;
208 
209  ast_assert(root_handler != NULL);
210 
211  ast_mutex_lock(&root_handler_lock);
212  size = sizeof(*new_handler) + root_handler->num_children * sizeof(handler);
213 
214  new_handler = ao2_alloc(size, NULL);
215  if (!new_handler) {
216  ast_mutex_unlock(&root_handler_lock);
217  return -1;
218  }
219 
220  /* Create replacement root_handler less the handler to remove. */
221  memcpy(new_handler, root_handler, sizeof(*new_handler));
222  for (i = 0, j = 0; i < root_handler->num_children; ++i) {
223  if (root_handler->children[i] == handler) {
224  continue;
225  }
226  new_handler->children[j++] = root_handler->children[i];
227  }
228  new_handler->num_children = j;
229 
230  /* Replace the old root_handler with the new. */
231  ao2_cleanup(root_handler);
232  root_handler = new_handler;
233 
234  ast_mutex_unlock(&root_handler_lock);
235  return 0;
236 }
static struct stasis_rest_handlers * root_handler
Definition: res_ari.c:169
size_t num_children
Definition: ari.h:84
struct stasis_rest_handlers * children[]
Definition: ari.h:86
static ast_mutex_t root_handler_lock
Definition: res_ari.c:166
Handler for a single RESTful path segment.
Definition: ari.h:69
void ast_ari_response_alloc_failed ( struct ast_ari_response response)

Fill in response with a 500 message for allocation failures.

Parameters
responseResponse to fill in.

Definition at line 298 of file res_ari.c.

References ast_json_ref(), ast_ari_response::message, ast_ari_response::response_code, and ast_ari_response::response_text.

Referenced by ari_bridges_play_helper(), ast_ari_applications_subscribe_cb(), ast_ari_applications_unsubscribe_cb(), ast_ari_asterisk_add_log_cb(), ast_ari_asterisk_get_global_var(), ast_ari_asterisk_get_global_var_cb(), ast_ari_asterisk_get_info(), ast_ari_asterisk_get_info_cb(), ast_ari_asterisk_get_module(), ast_ari_asterisk_list_modules(), ast_ari_asterisk_set_global_var_cb(), ast_ari_asterisk_update_object(), ast_ari_bridges_add_channel(), ast_ari_bridges_add_channel_cb(), ast_ari_bridges_create_cb(), ast_ari_bridges_create_with_id_cb(), ast_ari_bridges_list(), ast_ari_bridges_play_cb(), ast_ari_bridges_play_with_id_cb(), ast_ari_bridges_record(), ast_ari_bridges_record_cb(), ast_ari_bridges_remove_channel_cb(), ast_ari_bridges_start_moh(), ast_ari_bridges_start_moh_cb(), ast_ari_channels_continue_in_dialplan(), ast_ari_channels_continue_in_dialplan_cb(), ast_ari_channels_create(), ast_ari_channels_dial(), ast_ari_channels_dial_cb(), ast_ari_channels_get_channel_var(), ast_ari_channels_get_channel_var_cb(), ast_ari_channels_hangup_cb(), ast_ari_channels_list(), ast_ari_channels_move_cb(), ast_ari_channels_mute_cb(), ast_ari_channels_play_cb(), ast_ari_channels_play_with_id_cb(), ast_ari_channels_record_cb(), ast_ari_channels_redirect_cb(), ast_ari_channels_send_dtmf_cb(), ast_ari_channels_set_channel_var_cb(), ast_ari_channels_snoop_channel_cb(), ast_ari_channels_snoop_channel_with_id_cb(), ast_ari_channels_start_moh_cb(), ast_ari_channels_unmute_cb(), ast_ari_device_states_update_cb(), ast_ari_endpoints_get(), ast_ari_endpoints_list(), ast_ari_endpoints_list_by_tech(), ast_ari_events_user_event_cb(), ast_ari_mailboxes_update_cb(), ast_ari_playbacks_control_cb(), ast_ari_recordings_copy_stored_cb(), ast_ari_recordings_list_stored(), ast_ari_sounds_list_cb(), and handle_options().

299 {
300  response->message = ast_json_ref(oom_json);
301  response->response_code = 500;
302  response->response_text = "Internal Server Error";
303 }
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition: json.c:67
int response_code
Definition: ari.h:99
static struct ast_json * oom_json
Definition: res_ari.c:172
const char * response_text
Definition: ari.h:103
struct ast_json * message
Definition: ari.h:94
void ast_ari_response_created ( struct ast_ari_response response,
const char *  url,
struct ast_json message 
)

Fill in a Created (201) ast_ari_response.

Parameters
responseResponse to fill in.
urlURL to the created resource.
messageJSON response. This reference is stolen, so just ast_json_ref if you need to keep a reference to it.

Definition at line 305 of file res_ari.c.

References ast_str_append(), ast_ari_response::headers, ast_ari_response::message, RAII_VAR, ast_ari_response::response_code, and ast_ari_response::response_text.

Referenced by ari_bridges_play_found(), ast_ari_bridges_record(), and ast_ari_channels_record().

307 {
308  RAII_VAR(struct stasis_rest_handlers *, root, get_root_handler(), ao2_cleanup);
309  response->message = message;
310  response->response_code = 201;
311  response->response_text = "Created";
312  ast_str_append(&response->headers, 0, "Location: /%s%s\r\n", root->path_segment, url);
313 }
struct ast_str * headers
Definition: ari.h:96
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
int response_code
Definition: ari.h:99
const char * response_text
Definition: ari.h:103
struct ast_json * message
Definition: ari.h:94
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
Handler for a single RESTful path segment.
Definition: ari.h:69
void ast_ari_response_error ( struct ast_ari_response response,
int  response_code,
const char *  response_text,
const char *  message_fmt,
  ... 
)

Fill in an error ast_ari_response.

Parameters
responseResponse to fill in.
response_codeHTTP response code.
response_textText corresponding to the HTTP response code.
message_fmtError message format string.

Definition at line 259 of file res_ari.c.

References ast_json_pack(), ast_json_ref(), ast_json_unref(), ast_json_vstringf(), ast_ari_response::message, RAII_VAR, ast_ari_response::response_code, and ast_ari_response::response_text.

Referenced by ari_bridges_play_helper(), ast_ari_applications_filter(), ast_ari_applications_filter_cb(), ast_ari_applications_get(), ast_ari_applications_get_cb(), ast_ari_applications_list(), ast_ari_applications_list_cb(), ast_ari_applications_subscribe(), ast_ari_applications_subscribe_cb(), ast_ari_applications_unsubscribe(), ast_ari_applications_unsubscribe_cb(), ast_ari_asterisk_add_log(), ast_ari_asterisk_add_log_cb(), ast_ari_asterisk_delete_log(), ast_ari_asterisk_delete_log_cb(), ast_ari_asterisk_delete_object(), ast_ari_asterisk_delete_object_cb(), ast_ari_asterisk_get_global_var(), ast_ari_asterisk_get_global_var_cb(), ast_ari_asterisk_get_info_cb(), ast_ari_asterisk_get_module(), ast_ari_asterisk_get_module_cb(), ast_ari_asterisk_get_object(), ast_ari_asterisk_get_object_cb(), ast_ari_asterisk_list_log_channels(), ast_ari_asterisk_list_log_channels_cb(), ast_ari_asterisk_list_modules_cb(), ast_ari_asterisk_load_module(), ast_ari_asterisk_load_module_cb(), ast_ari_asterisk_ping_cb(), ast_ari_asterisk_reload_module(), ast_ari_asterisk_reload_module_cb(), ast_ari_asterisk_rotate_log(), ast_ari_asterisk_rotate_log_cb(), ast_ari_asterisk_set_global_var(), ast_ari_asterisk_set_global_var_cb(), ast_ari_asterisk_unload_module(), ast_ari_asterisk_unload_module_cb(), ast_ari_asterisk_update_object(), ast_ari_asterisk_update_object_cb(), ast_ari_bridges_add_channel_cb(), ast_ari_bridges_clear_video_source_cb(), ast_ari_bridges_create(), ast_ari_bridges_create_cb(), ast_ari_bridges_create_with_id(), ast_ari_bridges_create_with_id_cb(), ast_ari_bridges_destroy_cb(), ast_ari_bridges_get(), ast_ari_bridges_get_cb(), ast_ari_bridges_list_cb(), ast_ari_bridges_play_cb(), ast_ari_bridges_play_with_id_cb(), ast_ari_bridges_record(), ast_ari_bridges_record_cb(), ast_ari_bridges_remove_channel(), ast_ari_bridges_remove_channel_cb(), ast_ari_bridges_set_video_source(), ast_ari_bridges_set_video_source_cb(), ast_ari_bridges_start_moh_cb(), ast_ari_bridges_stop_moh(), ast_ari_bridges_stop_moh_cb(), ast_ari_channels_answer(), ast_ari_channels_answer_cb(), ast_ari_channels_continue_in_dialplan(), ast_ari_channels_continue_in_dialplan_cb(), ast_ari_channels_create(), ast_ari_channels_create_cb(), ast_ari_channels_dial(), ast_ari_channels_dial_cb(), ast_ari_channels_external_media(), ast_ari_channels_external_media_cb(), ast_ari_channels_get(), ast_ari_channels_get_cb(), ast_ari_channels_get_channel_var(), ast_ari_channels_get_channel_var_cb(), ast_ari_channels_hangup(), ast_ari_channels_hangup_cb(), ast_ari_channels_hold_cb(), ast_ari_channels_list_cb(), ast_ari_channels_move(), ast_ari_channels_move_cb(), ast_ari_channels_mute(), ast_ari_channels_mute_cb(), ast_ari_channels_originate_cb(), ast_ari_channels_originate_with_id_cb(), ast_ari_channels_play_cb(), ast_ari_channels_play_with_id_cb(), ast_ari_channels_record(), ast_ari_channels_record_cb(), ast_ari_channels_redirect(), ast_ari_channels_redirect_cb(), ast_ari_channels_ring_cb(), ast_ari_channels_ring_stop_cb(), ast_ari_channels_rtpstatistics(), ast_ari_channels_rtpstatistics_cb(), ast_ari_channels_send_dtmf(), ast_ari_channels_send_dtmf_cb(), ast_ari_channels_set_channel_var(), ast_ari_channels_set_channel_var_cb(), ast_ari_channels_snoop_channel_cb(), ast_ari_channels_snoop_channel_with_id_cb(), ast_ari_channels_start_moh_cb(), ast_ari_channels_start_silence_cb(), ast_ari_channels_stop_moh_cb(), ast_ari_channels_stop_silence_cb(), ast_ari_channels_unhold_cb(), ast_ari_channels_unmute(), ast_ari_channels_unmute_cb(), ast_ari_device_states_delete(), ast_ari_device_states_delete_cb(), ast_ari_device_states_get(), ast_ari_device_states_get_cb(), ast_ari_device_states_list(), ast_ari_device_states_list_cb(), ast_ari_device_states_update(), ast_ari_device_states_update_cb(), ast_ari_endpoints_get(), ast_ari_endpoints_get_cb(), ast_ari_endpoints_list(), ast_ari_endpoints_list_by_tech(), ast_ari_endpoints_list_by_tech_cb(), ast_ari_endpoints_list_cb(), ast_ari_endpoints_refer_cb(), ast_ari_endpoints_refer_to_endpoint(), ast_ari_endpoints_refer_to_endpoint_cb(), ast_ari_endpoints_send_message_cb(), ast_ari_endpoints_send_message_to_endpoint(), ast_ari_endpoints_send_message_to_endpoint_cb(), ast_ari_events_user_event(), ast_ari_events_user_event_cb(), ast_ari_mailboxes_delete(), ast_ari_mailboxes_delete_cb(), ast_ari_mailboxes_get(), ast_ari_mailboxes_get_cb(), ast_ari_mailboxes_list(), ast_ari_mailboxes_list_cb(), ast_ari_mailboxes_update(), ast_ari_mailboxes_update_cb(), ast_ari_playbacks_control(), ast_ari_playbacks_control_cb(), ast_ari_playbacks_get(), ast_ari_playbacks_get_cb(), ast_ari_playbacks_stop(), ast_ari_playbacks_stop_cb(), ast_ari_recordings_cancel_cb(), ast_ari_recordings_copy_stored(), ast_ari_recordings_copy_stored_cb(), ast_ari_recordings_delete_stored(), ast_ari_recordings_delete_stored_cb(), ast_ari_recordings_get_live(), ast_ari_recordings_get_live_cb(), ast_ari_recordings_get_stored(), ast_ari_recordings_get_stored_cb(), ast_ari_recordings_get_stored_file(), ast_ari_recordings_get_stored_file_cb(), ast_ari_recordings_list_stored_cb(), ast_ari_recordings_mute_cb(), ast_ari_recordings_pause_cb(), ast_ari_recordings_stop_cb(), ast_ari_recordings_unmute_cb(), ast_ari_recordings_unpause_cb(), ast_ari_sounds_get(), ast_ari_sounds_get_cb(), ast_ari_sounds_list(), ast_ari_sounds_list_cb(), channel_state_invalid(), find_bridge(), find_channel_control(), and find_control().

263 {
264  RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
265  va_list ap;
266 
267  va_start(ap, message_fmt);
268  message = ast_json_vstringf(message_fmt, ap);
269  va_end(ap);
270  response->message = ast_json_pack("{s: o}",
271  "message", ast_json_ref(message));
272  response->response_code = response_code;
273  response->response_text = response_text;
274 }
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition: json.c:67
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
int response_code
Definition: ari.h:99
struct ast_json * ast_json_vstringf(const char *format, va_list args)
Create a JSON string, vprintf style.
Definition: json.c:303
const char * response_text
Definition: ari.h:103
struct ast_json * message
Definition: ari.h:94
Abstract JSON element (object, array, string, int, ...).
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
void ast_ari_response_ok ( struct ast_ari_response response,
struct ast_json message 
)

Fill in an OK (200) ast_ari_response.

Parameters
responseResponse to fill in.
messageJSON response. This reference is stolen, so just ast_json_ref if you need to keep a reference to it.

Definition at line 276 of file res_ari.c.

References ast_ari_response::message, ast_ari_response::response_code, and ast_ari_response::response_text.

Referenced by ast_ari_applications_filter(), ast_ari_applications_get(), ast_ari_applications_list(), ast_ari_applications_subscribe(), ast_ari_applications_unsubscribe(), ast_ari_asterisk_get_global_var(), ast_ari_asterisk_get_info(), ast_ari_asterisk_get_module(), ast_ari_asterisk_list_log_channels(), ast_ari_asterisk_list_modules(), ast_ari_asterisk_ping(), ast_ari_bridges_create(), ast_ari_bridges_create_with_id(), ast_ari_bridges_get(), ast_ari_bridges_list(), ast_ari_channels_create(), ast_ari_channels_get(), ast_ari_channels_get_channel_var(), ast_ari_channels_list(), ast_ari_channels_rtpstatistics(), ast_ari_device_states_get(), ast_ari_device_states_list(), ast_ari_endpoints_get(), ast_ari_endpoints_list(), ast_ari_endpoints_list_by_tech(), ast_ari_mailboxes_get(), ast_ari_mailboxes_list(), ast_ari_playbacks_get(), ast_ari_recordings_copy_stored(), ast_ari_recordings_get_live(), ast_ari_recordings_get_stored(), ast_ari_recordings_get_stored_file(), ast_ari_recordings_list_stored(), ast_ari_sounds_get(), and ast_ari_sounds_list().

278 {
279  response->message = message;
280  response->response_code = 200;
281  response->response_text = "OK";
282 }
int response_code
Definition: ari.h:99
const char * response_text
Definition: ari.h:103
struct ast_json * message
Definition: ari.h:94
static struct ast_ari_conf_user* authenticate_api_key ( const char *  api_key)
static

Authenticate a ?api_key=userid:password

Parameters
api_keyAPI key query parameter
Returns
User object for the authenticated user.
Return values
NULLif authentication failed.

Definition at line 820 of file res_ari.c.

References ast_ari_config_validate_user(), ast_strdup, copy(), ast_ari_conf_user::password, RAII_VAR, and ast_ari_conf_user::username.

Referenced by authenticate_user().

821 {
822  RAII_VAR(char *, copy, NULL, ast_free);
823  char *username;
824  char *password;
825 
826  password = copy = ast_strdup(api_key);
827  if (!copy) {
828  return NULL;
829  }
830 
831  username = strsep(&password, ":");
832  if (!password) {
833  ast_log(LOG_WARNING, "Invalid api_key\n");
834  return NULL;
835  }
836 
837  return ast_ari_config_validate_user(username, password);
838 }
static int copy(char *infile, char *outfile)
Utility function to copy a file.
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
struct ast_ari_conf_user * ast_ari_config_validate_user(const char *username, const char *password)
Validated a user's credentials.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
static struct ast_ari_conf_user* authenticate_user ( struct ast_variable get_params,
struct ast_variable headers 
)
static

Authenticate an HTTP request.

Parameters
get_paramsGET parameters of the request.
headersHTTP headers.
Returns
User object for the authenticated user.
Return values
NULLif authentication failed.

Definition at line 848 of file res_ari.c.

References ast_ari_config_validate_user(), ast_http_get_auth(), authenticate_api_key(), ast_variable::name, ast_variable::next, RAII_VAR, and ast_variable::value.

850 {
851  RAII_VAR(struct ast_http_auth *, http_auth, NULL, ao2_cleanup);
852  struct ast_variable *v;
853 
854  /* HTTP Basic authentication */
855  http_auth = ast_http_get_auth(headers);
856  if (http_auth) {
857  return ast_ari_config_validate_user(http_auth->userid,
858  http_auth->password);
859  }
860 
861  /* ?api_key authentication */
862  for (v = get_params; v; v = v->next) {
863  if (strcasecmp("api_key", v->name) == 0) {
864  return authenticate_api_key(v->value);
865  }
866  }
867 
868  return NULL;
869 }
struct ast_variable * next
Structure for variables, used for configurations and for channel variables.
static struct ast_ari_conf_user * authenticate_api_key(const char *api_key)
Authenticate a ?api_key=userid:password
Definition: res_ari.c:820
HTTP authentication information.
Definition: http.h:125
struct ast_http_auth * ast_http_get_auth(struct ast_variable *headers)
Get HTTP authentication information from headers.
Definition: http.c:1582
struct ast_ari_conf_user * ast_ari_config_validate_user(const char *username, const char *password)
Validated a user's credentials.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
static void handle_options ( struct stasis_rest_handlers handler,
struct ast_variable headers,
struct ast_ari_response response 
)
static

Handle OPTIONS request, mainly for CORS preflight requests.

Some browsers will send this prior to non-simple methods (i.e. DELETE). See http://www.w3.org/TR/cors/ for the spec. Especially section 6.2.

Definition at line 361 of file res_ari.c.

References ast_ari_response_alloc_failed(), ast_ari_response_no_content(), ast_get_http_method(), AST_HTTP_MAX_METHOD, ast_str_append(), ast_str_buffer(), ast_str_create, stasis_rest_handlers::callbacks, ast_ari_response::headers, ast_variable::name, ast_variable::next, RAII_VAR, and ast_variable::value.

364 {
365  struct ast_variable *header;
366  char const *acr_method = NULL;
367  char const *acr_headers = NULL;
368  char const *origin = NULL;
369 
370  RAII_VAR(struct ast_str *, allow, NULL, ast_free);
371  enum ast_http_method m;
372  int allowed = 0;
373 
374  /* Regular OPTIONS response */
375  add_allow_header(handler, response);
376  ast_ari_response_no_content(response);
377 
378  /* Parse CORS headers */
379  for (header = headers; header != NULL; header = header->next) {
380  if (strcmp(ACR_METHOD, header->name) == 0) {
381  acr_method = header->value;
382  } else if (strcmp(ACR_HEADERS, header->name) == 0) {
383  acr_headers = header->value;
384  } else if (strcmp("Origin", header->name) == 0) {
385  origin = header->value;
386  }
387  }
388 
389  /* CORS 6.2, #1 - "If the Origin header is not present terminate this
390  * set of steps."
391  */
392  if (origin == NULL) {
393  return;
394  }
395 
396  /* CORS 6.2, #2 - "If the value of the Origin header is not a
397  * case-sensitive match for any of the values in list of origins do not
398  * set any additional headers and terminate this set of steps.
399  *
400  * Always matching is acceptable since the list of origins can be
401  * unbounded.
402  *
403  * The Origin header can only contain a single origin as the user agent
404  * will not follow redirects."
405  */
406  if (!origin_allowed(origin)) {
407  ast_log(LOG_NOTICE, "Origin header '%s' does not match an allowed origin.\n", origin);
408  return;
409  }
410 
411  /* CORS 6.2, #3 - "If there is no Access-Control-Request-Method header
412  * or if parsing failed, do not set any additional headers and terminate
413  * this set of steps."
414  */
415  if (acr_method == NULL) {
416  return;
417  }
418 
419  /* CORS 6.2, #4 - "If there are no Access-Control-Request-Headers
420  * headers let header field-names be the empty list."
421  */
422  if (acr_headers == NULL) {
423  acr_headers = "";
424  }
425 
426  /* CORS 6.2, #5 - "If method is not a case-sensitive match for any of
427  * the values in list of methods do not set any additional headers and
428  * terminate this set of steps."
429  */
430  allow = ast_str_create(20);
431 
432  if (!allow) {
434  return;
435  }
436 
437  /* Go ahead and build the ACA_METHODS header at the same time */
438  for (m = 0; m < AST_HTTP_MAX_METHOD; ++m) {
439  if (handler->callbacks[m] != NULL) {
440  char const *m_str = ast_get_http_method(m);
441  if (strcmp(m_str, acr_method) == 0) {
442  allowed = 1;
443  }
444  ast_str_append(&allow, 0, ",%s", m_str);
445  }
446  }
447 
448  if (!allowed) {
449  return;
450  }
451 
452  /* CORS 6.2 #6 - "If any of the header field-names is not a ASCII
453  * case-insensitive match for any of the values in list of headers do
454  * not set any additional headers and terminate this set of steps.
455  *
456  * Note: Always matching is acceptable since the list of headers can be
457  * unbounded."
458  */
459 
460  /* CORS 6.2 #7 - "If the resource supports credentials add a single
461  * Access-Control-Allow-Origin header, with the value of the Origin
462  * header as value, and add a single Access-Control-Allow-Credentials
463  * header with the case-sensitive string "true" as value."
464  *
465  * Added by process_cors_request() earlier in the request.
466  */
467 
468  /* CORS 6.2 #8 - "Optionally add a single Access-Control-Max-Age
469  * header..."
470  */
471 
472  /* CORS 6.2 #9 - "Add one or more Access-Control-Allow-Methods headers
473  * consisting of (a subset of) the list of methods."
474  */
475  ast_str_append(&response->headers, 0, "%s: OPTIONS%s\r\n",
476  ACA_METHODS, ast_str_buffer(allow));
477 
478 
479  /* CORS 6.2, #10 - "Add one or more Access-Control-Allow-Headers headers
480  * consisting of (a subset of) the list of headers.
481  *
482  * Since the list of headers can be unbounded simply returning headers
483  * can be enough."
484  */
485  if (!ast_strlen_zero(acr_headers)) {
486  ast_str_append(&response->headers, 0, "%s: %s\r\n",
487  ACA_HEADERS, acr_headers);
488  }
489 }
struct ast_variable * next
struct ast_str * headers
Definition: ari.h:96
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
void ast_ari_response_alloc_failed(struct ast_ari_response *response)
Fill in response with a 500 message for allocation failures.
Definition: res_ari.c:298
Structure for variables, used for configurations and for channel variables.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
void ast_ari_response_no_content(struct ast_ari_response *response)
Fill in a No Content (204) ast_ari_response.
Definition: res_ari.c:284
Support for dynamic strings.
Definition: strings.h:623
const char * ast_get_http_method(enum ast_http_method method) attribute_pure
Return http method name string.
Definition: http.c:193
stasis_rest_callback callbacks[AST_HTTP_MAX_METHOD]
Definition: ari.h:80
ast_http_method
HTTP Request methods known by Asterisk.
Definition: http.h:58
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
static void process_cors_request ( struct ast_variable headers,
struct ast_ari_response response 
)
static

Handle CORS headers for simple requests.

See http://www.w3.org/TR/cors/ for the spec. Especially section 6.1.

Definition at line 753 of file res_ari.c.

References ast_str_append(), ast_ari_response::headers, ast_variable::name, ast_variable::next, and ast_variable::value.

755 {
756  char const *origin = NULL;
757  struct ast_variable *header;
758 
759  /* Parse CORS headers */
760  for (header = headers; header != NULL; header = header->next) {
761  if (strcmp("Origin", header->name) == 0) {
762  origin = header->value;
763  }
764  }
765 
766  /* CORS 6.1, #1 - "If the Origin header is not present terminate this
767  * set of steps."
768  */
769  if (origin == NULL) {
770  return;
771  }
772 
773  /* CORS 6.1, #2 - "If the value of the Origin header is not a
774  * case-sensitive match for any of the values in list of origins, do not
775  * set any additional headers and terminate this set of steps.
776  *
777  * Note: Always matching is acceptable since the list of origins can be
778  * unbounded."
779  */
780  if (!origin_allowed(origin)) {
781  ast_log(LOG_NOTICE, "Origin header '%s' does not match an allowed origin.\n", origin);
782  return;
783  }
784 
785  /* CORS 6.1, #3 - "If the resource supports credentials add a single
786  * Access-Control-Allow-Origin header, with the value of the Origin
787  * header as value, and add a single Access-Control-Allow-Credentials
788  * header with the case-sensitive string "true" as value.
789  *
790  * Otherwise, add a single Access-Control-Allow-Origin header, with
791  * either the value of the Origin header or the string "*" as value."
792  */
793  ast_str_append(&response->headers, 0,
794  "Access-Control-Allow-Origin: %s\r\n", origin);
795  ast_str_append(&response->headers, 0,
796  "Access-Control-Allow-Credentials: true\r\n");
797 
798  /* CORS 6.1, #4 - "If the list of exposed headers is not empty add one
799  * or more Access-Control-Expose-Headers headers, with as values the
800  * header field names given in the list of exposed headers."
801  *
802  * No exposed headers; skipping
803  */
804 }
struct ast_variable * next
struct ast_str * headers
Definition: ari.h:96
Structure for variables, used for configurations and for channel variables.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139

Variable Documentation

struct ast_json* oom_json
static

Pre-defined message for allocation failures.

Definition at line 172 of file res_ari.c.

Referenced by ast_ari_oom_json().

struct stasis_rest_handlers* root_handler
static

Handler for root RESTful resource.

Definition at line 169 of file res_ari.c.

ast_mutex_t root_handler_lock
static

Lock for root_handler

Definition at line 166 of file res_ari.c.