Asterisk - The Open Source Telephony Project GIT-master-67613d1
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>
Include dependency graph for res_ari.c:

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. More...
 
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. More...
 
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. More...
 
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 = AST_BUILDOPT_SUM, .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.

Macro Definition Documentation

◆ ACA_HEADERS

#define ACA_HEADERS   "Access-Control-Allow-Headers"

Definition at line 353 of file res_ari.c.

◆ ACA_METHODS

#define ACA_METHODS   "Access-Control-Allow-Methods"

Definition at line 352 of file res_ari.c.

◆ ACR_HEADERS

#define ACR_HEADERS   "Access-Control-Request-Headers"

Definition at line 351 of file res_ari.c.

◆ ACR_METHOD

#define ACR_METHOD   "Access-Control-Request-Method"

Definition at line 350 of file res_ari.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1214 of file res_ari.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1214 of file res_ari.c.

◆ add_allow_header()

static void add_allow_header ( struct stasis_rest_handlers handler,
struct ast_ari_response response 
)
static

Definition at line 315 of file res_ari.c.

317{
318 enum ast_http_method m;
319 ast_str_append(&response->headers, 0,
320 "Allow: OPTIONS");
321 for (m = 0; m < AST_HTTP_MAX_METHOD; ++m) {
322 if (handler->callbacks[m] != NULL) {
323 ast_str_append(&response->headers, 0,
324 ",%s", ast_get_http_method(m));
325 }
326 }
327 ast_str_append(&response->headers, 0, "\r\n");
328}
ast_http_method
HTTP Request methods known by Asterisk.
Definition: http.h:58
@ AST_HTTP_MAX_METHOD
Definition: http.h:66
const char * ast_get_http_method(enum ast_http_method method) attribute_pure
Return http method name string.
Definition: http.c:193
#define NULL
Definition: resample.c: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
struct ast_str * headers
Definition: ari.h:96
static void handler(const char *name, int response_code, struct ast_variable *get_params, struct ast_variable *path_vars, struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
Definition: test_ari.c:59

References ast_get_http_method(), AST_HTTP_MAX_METHOD, ast_str_append(), handler(), ast_ari_response::headers, and NULL.

Referenced by ast_ari_invoke(), and handle_options().

◆ ast_ari_add_handler()

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.

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
197 ao2_ref(new_handler, +1);
198 root_handler = new_handler;
199 return 0;
200}
ast_mutex_t lock
Definition: app_sla.c:331
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
#define SCOPED_MUTEX(varname, lock)
scoped lock specialization for mutexes
Definition: lock.h:589
static struct stasis_rest_handlers * root_handler
Definition: res_ari.c:169
static ast_mutex_t root_handler_lock
Definition: res_ari.c:166
Handler for a single RESTful path segment.
Definition: ari.h:69
size_t num_children
Definition: ari.h:84
#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

References ao2_alloc, ao2_cleanup, ao2_ref, handler(), lock, NULL, stasis_rest_handlers::num_children, RAII_VAR, root_handler, root_handler_lock, and SCOPED_MUTEX.

Referenced by load_module(), and setup_invocation_test().

◆ ast_ari_callback()

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 
)
static

Definition at line 885 of file res_ari.c.

891{
893 RAII_VAR(struct ast_str *, response_body, ast_str_create(256), ast_free);
895 struct ast_ari_response response = { .fd = -1, 0 };
896 RAII_VAR(struct ast_variable *, post_vars, NULL, ast_variables_destroy);
897 struct ast_variable *var;
898 const char *app_name = NULL;
899 RAII_VAR(struct ast_json *, body, ast_json_null(), ast_json_unref);
900 int debug_app = 0;
901
902 if (!response_body) {
904 ast_http_error(ser, 500, "Server Error", "Out of memory");
905 return 0;
906 }
907
908 response.headers = ast_str_create(40);
909 if (!response.headers) {
911 ast_http_error(ser, 500, "Server Error", "Out of memory");
912 return 0;
913 }
914
916 if (!conf || !conf->general) {
917 ast_free(response.headers);
919 ast_http_error(ser, 500, "Server Error", "URI handler config missing");
920 return 0;
921 }
922
923 process_cors_request(headers, &response);
924
925 /* Process form data from a POST. It could be mixed with query
926 * parameters, which seems a bit odd. But it's allowed, so that's okay
927 * with us.
928 */
929 post_vars = ast_http_get_post_vars(ser, headers);
930 if (!post_vars) {
931 switch (errno) {
932 case EFBIG:
933 ast_ari_response_error(&response, 413,
934 "Request Entity Too Large",
935 "Request body too large");
936 goto request_failed;
937 case ENOMEM:
939 ast_ari_response_error(&response, 500,
940 "Internal Server Error",
941 "Out of memory");
942 goto request_failed;
943 case EIO:
944 ast_ari_response_error(&response, 400,
945 "Bad Request", "Error parsing request body");
946 goto request_failed;
947 }
948
949 /* Look for a JSON request entity only if there were no post_vars.
950 * If there were post_vars, then the request body would already have
951 * been consumed and can not be read again.
952 */
953 body = ast_http_get_json(ser, headers);
954 if (!body) {
955 switch (errno) {
956 case EFBIG:
957 ast_ari_response_error(&response, 413, "Request Entity Too Large", "Request body too large");
958 goto request_failed;
959 case ENOMEM:
960 ast_ari_response_error(&response, 500, "Internal Server Error", "Error processing request");
961 goto request_failed;
962 case EIO:
963 ast_ari_response_error(&response, 400, "Bad Request", "Error parsing request body");
964 goto request_failed;
965 }
966 }
967 }
968 if (get_params == NULL) {
969 get_params = post_vars;
970 } else if (get_params && post_vars) {
971 /* Has both post_vars and get_params */
972 struct ast_variable *last_var = post_vars;
973 while (last_var->next) {
974 last_var = last_var->next;
975 }
976 /* The duped get_params will get freed when post_vars gets
977 * ast_variables_destroyed.
978 */
979 last_var->next = ast_variables_dup(get_params);
980 get_params = post_vars;
981 }
982
983 /* At this point, get_params will contain post_vars (if any) */
984 app_name = ast_variable_find_in_list(get_params, "app");
985 if (!app_name) {
986 struct ast_json *app = ast_json_object_get(body, "app");
987
989 }
990
991 /* stasis_app_get_debug_by_name returns an "||" of the app's debug flag
992 * and the global debug flag.
993 */
995 if (debug_app) {
996 struct ast_str *buf = ast_str_create(512);
998
999 if (!buf || (body && !str)) {
1001 ast_ari_response_error(&response, 500, "Server Error", "Out of memory");
1003 ast_free(buf);
1004 goto request_failed;
1005 }
1006
1007 ast_str_append(&buf, 0, "<--- ARI request received from: %s --->\n",
1009 for (var = headers; var; var = var->next) {
1010 ast_str_append(&buf, 0, "%s: %s\n", var->name, var->value);
1011 }
1012 for (var = get_params; var; var = var->next) {
1013 ast_str_append(&buf, 0, "%s: %s\n", var->name, var->value);
1014 }
1015 ast_verbose("%sbody:\n%s\n\n", ast_str_buffer(buf), S_OR(str, ""));
1017 ast_free(buf);
1018 }
1019
1020 user = authenticate_user(get_params, headers);
1021 if (response.response_code > 0) {
1022 /* POST parameter processing error. Do nothing. */
1023 } else if (!user) {
1024 /* Per RFC 2617, section 1.2: The 401 (Unauthorized) response
1025 * message is used by an origin server to challenge the
1026 * authorization of a user agent. This response MUST include a
1027 * WWW-Authenticate header field containing at least one
1028 * challenge applicable to the requested resource.
1029 */
1030 ast_ari_response_error(&response, 401, "Unauthorized", "Authentication required");
1031
1032 /* Section 1.2:
1033 * realm = "realm" "=" realm-value
1034 * realm-value = quoted-string
1035 * Section 2:
1036 * challenge = "Basic" realm
1037 */
1038 ast_str_append(&response.headers, 0,
1039 "WWW-Authenticate: Basic realm=\"%s\"\r\n",
1040 conf->general->auth_realm);
1041 } else if (!ast_fully_booted) {
1043 ast_ari_response_error(&response, 503, "Service Unavailable", "Asterisk not booted");
1044 } else if (user->read_only && method != AST_HTTP_GET && method != AST_HTTP_OPTIONS) {
1045 ast_ari_response_error(&response, 403, "Forbidden", "Write access denied");
1046 } else if (ast_ends_with(uri, "/")) {
1047 remove_trailing_slash(uri, &response);
1048 } else if (ast_begins_with(uri, "api-docs/")) {
1049 /* Serving up API docs */
1050 if (method != AST_HTTP_GET) {
1051 ast_ari_response_error(&response, 405, "Method Not Allowed", "Unsupported method");
1052 } else {
1053 /* Skip the api-docs prefix */
1054 ast_ari_get_docs(strchr(uri, '/') + 1, urih->prefix, headers, &response);
1055 }
1056 } else {
1057 /* Other RESTful resources */
1058 ast_ari_invoke(ser, uri, method, get_params, headers, body,
1059 &response);
1060 }
1061
1062 if (response.no_response) {
1063 /* The handler indicates no further response is necessary.
1064 * Probably because it already handled it */
1065 ast_free(response.headers);
1066 return 0;
1067 }
1068
1069request_failed:
1070
1071 /* If you explicitly want to have no content, set message to
1072 * ast_json_null().
1073 */
1074 ast_assert(response.message != NULL);
1075 ast_assert(response.response_code > 0);
1076
1077 /* response.message could be NULL, in which case the empty response_body
1078 * is correct
1079 */
1080 if (response.message && !ast_json_is_null(response.message)) {
1081 ast_str_append(&response.headers, 0,
1082 "Content-type: application/json\r\n");
1083 if (ast_json_dump_str_format(response.message, &response_body,
1084 conf->general->format) != 0) {
1085 /* Error encoding response */
1086 response.response_code = 500;
1087 response.response_text = "Internal Server Error";
1088 ast_str_set(&response_body, 0, "%s", "");
1089 ast_str_set(&response.headers, 0, "%s", "");
1090 }
1091 }
1092
1093 if (debug_app) {
1094 ast_verbose("<--- Sending ARI response to %s --->\n%d %s\n%s%s\n\n",
1096 response.response_text, ast_str_buffer(response.headers),
1097 ast_str_buffer(response_body));
1098 }
1099
1100 ast_http_send(ser, method, response.response_code,
1101 response.response_text, response.headers, response_body,
1102 response.fd != -1 ? response.fd : 0, 0);
1103 /* ast_http_send takes ownership, so we don't have to free them */
1104 response_body = NULL;
1105
1106 ast_json_unref(response.message);
1107 if (response.fd >= 0) {
1108 close(response.fd);
1109 }
1110 return 0;
1111}
static const char app[]
Definition: app_adsiprog.c:56
const char * str
Definition: app_jack.c:147
#define var
Definition: ast_expr2f.c:605
#define ast_free(a)
Definition: astmm.h:180
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2206
void ast_http_send(struct ast_tcptls_session_instance *ser, enum ast_http_method method, int status_code, const char *status_title, struct ast_str *http_header, struct ast_str *out, int fd, unsigned int static_content)
Generic function for sending HTTP/1.1 response.
Definition: http.c:459
struct ast_variable * ast_http_get_post_vars(struct ast_tcptls_session_instance *ser, struct ast_variable *headers)
Get post variables from client Request Entity-Body, if content type is application/x-www-form-urlenco...
Definition: http.c:1356
struct ast_json * ast_http_get_json(struct ast_tcptls_session_instance *ser, struct ast_variable *headers)
Get JSON from client Request Entity-Body, if content type is application/json.
Definition: http.c:1317
@ AST_HTTP_GET
Definition: http.h:60
@ AST_HTTP_OPTIONS
Definition: http.h:65
void ast_http_request_close_on_completion(struct ast_tcptls_session_instance *ser)
Request the HTTP connection be closed after this HTTP request.
Definition: http.c:840
void ast_http_error(struct ast_tcptls_session_instance *ser, int status, const char *title, const char *text)
Send HTTP error message and close socket.
Definition: http.c:651
const char * ast_variable_find_in_list(const struct ast_variable *list, const char *variable)
Gets the value of a variable from a variable list by name.
Definition: main/config.c:919
struct ast_variable * ast_variables_dup(struct ast_variable *var)
Duplicate variable list.
Definition: main/config.c:543
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
struct ast_json * ast_json_null(void)
Get the JSON null value.
Definition: json.c:248
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
void ast_json_free(void *p)
Asterisk's custom JSON allocator. Exposed for use by unit tests.
Definition: json.c:52
int ast_json_dump_str_format(struct ast_json *root, struct ast_str **dst, enum ast_json_encoding_format format)
Encode a JSON value to an ast_str.
Definition: json.c:520
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:283
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:407
char * ast_json_dump_string_format(struct ast_json *root, enum ast_json_encoding_format format)
Encode a JSON value to a string.
Definition: json.c:484
int ast_json_is_null(const struct ast_json *value)
Check if value is JSON null.
Definition: json.c:273
int errno
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:256
#define ast_fully_booted
Definition: options.h:117
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
struct ast_ari_conf * ast_ari_config_get(void)
Get the current ARI configuration.
static void remove_trailing_slash(const char *uri, struct ast_ari_response *response)
Definition: res_ari.c:722
enum ast_json_encoding_format ast_ari_json_format(void)
Configured encoding format for JSON output.
Definition: res_ari.c:806
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.
Definition: res_ari.c:259
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)
Definition: res_ari.c:491
static void process_cors_request(struct ast_variable *headers, struct ast_ari_response *response)
Handle CORS headers for simple requests.
Definition: res_ari.c:753
void ast_ari_get_docs(const char *uri, const char *prefix, struct ast_variable *headers, struct ast_ari_response *response)
Definition: res_ari.c:598
static struct ast_ari_conf_user * authenticate_user(struct ast_variable *get_params, struct ast_variable *headers)
Authenticate an HTTP request.
Definition: res_ari.c:848
const char * method
Definition: res_pjsip.c:1279
int stasis_app_get_debug_by_name(const char *app_name)
Get debug status of an application.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
static int force_inline attribute_pure ast_ends_with(const char *str, const char *suffix)
Checks whether a string ends with another.
Definition: strings.h:116
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Checks whether a string begins with another.
Definition: strings.h:97
Per-user configuration options.
Definition: internal.h:96
All configuration options for ARI.
Definition: internal.h:54
struct ast_json * message
Definition: ari.h:94
int response_code
Definition: ari.h:99
const char * response_text
Definition: ari.h:103
unsigned int no_response
Definition: ari.h:105
const char * prefix
Definition: http.h:106
Abstract JSON element (object, array, string, int, ...).
Support for dynamic strings.
Definition: strings.h:623
struct ast_sockaddr remote_address
Definition: tcptls.h:152
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
All configuration options for http media cache.
struct conf_general_options * general
structure to hold users read from users.conf
#define ast_assert(a)
Definition: utils.h:739

References ao2_cleanup, app, app_name(), ast_ari_config_get(), ast_ari_get_docs(), ast_ari_invoke(), ast_ari_json_format(), ast_ari_response_error(), ast_assert, ast_begins_with(), ast_ends_with(), ast_free, ast_fully_booted, ast_http_error(), AST_HTTP_GET, ast_http_get_json(), ast_http_get_post_vars(), AST_HTTP_OPTIONS, ast_http_request_close_on_completion(), ast_http_send(), ast_json_dump_str_format(), ast_json_dump_string_format(), ast_json_free(), ast_json_is_null(), ast_json_null(), ast_json_object_get(), ast_json_string_get(), ast_json_unref(), ast_sockaddr_stringify(), ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_set(), ast_variable_find_in_list(), ast_variables_destroy(), ast_variables_dup(), ast_verbose(), authenticate_user(), buf, errno, ast_ari_response::fd, conf::general, ast_ari_response::headers, ast_ari_response::message, method, ast_variable::next, ast_ari_response::no_response, NULL, ast_http_uri::prefix, process_cors_request(), RAII_VAR, ast_tcptls_session_instance::remote_address, remove_trailing_slash(), ast_ari_response::response_code, ast_ari_response::response_text, S_OR, stasis_app_get_debug_by_name(), str, and var.

◆ ast_ari_get_docs()

void ast_ari_get_docs ( const char *  uri,
const char *  prefix,
struct ast_variable headers,
struct ast_ari_response response 
)

Definition at line 598 of file res_ari.c.

600{
601 RAII_VAR(struct ast_str *, absolute_path_builder, NULL, ast_free);
602 RAII_VAR(char *, absolute_api_dirname, NULL, ast_std_free);
603 RAII_VAR(char *, absolute_filename, NULL, ast_std_free);
604 struct ast_json *obj = NULL;
605 struct ast_variable *host = NULL;
606 struct ast_json_error error = {};
607 struct stat file_stat;
608
609 ast_debug(3, "%s(%s)\n", __func__, uri);
610
611 absolute_path_builder = ast_str_create(80);
612 if (absolute_path_builder == NULL) {
614 return;
615 }
616
617 /* absolute path to the rest-api directory */
618 ast_str_append(&absolute_path_builder, 0, "%s", ast_config_AST_DATA_DIR);
619 ast_str_append(&absolute_path_builder, 0, "/rest-api/");
620 absolute_api_dirname = realpath(ast_str_buffer(absolute_path_builder), NULL);
621 if (absolute_api_dirname == NULL) {
622 ast_log(LOG_ERROR, "Error determining real directory for rest-api\n");
624 response, 500, "Internal Server Error",
625 "Cannot find rest-api directory");
626 return;
627 }
628
629 /* absolute path to the requested file */
630 ast_str_append(&absolute_path_builder, 0, "%s", uri);
631 absolute_filename = realpath(ast_str_buffer(absolute_path_builder), NULL);
632 if (absolute_filename == NULL) {
633 switch (errno) {
634 case ENAMETOOLONG:
635 case ENOENT:
636 case ENOTDIR:
638 response, 404, "Not Found",
639 "Resource not found");
640 break;
641 case EACCES:
643 response, 403, "Forbidden",
644 "Permission denied");
645 break;
646 default:
648 "Error determining real path for uri '%s': %s\n",
649 uri, strerror(errno));
651 response, 500, "Internal Server Error",
652 "Cannot find file");
653 break;
654 }
655 return;
656 }
657
658 if (!ast_begins_with(absolute_filename, absolute_api_dirname)) {
659 /* HACKERZ! */
661 "Invalid attempt to access '%s' (not in %s)\n",
662 absolute_filename, absolute_api_dirname);
664 response, 404, "Not Found",
665 "Resource not found");
666 return;
667 }
668
669 if (stat(absolute_filename, &file_stat) == 0) {
670 if (!(file_stat.st_mode & S_IFREG)) {
671 /* Not a file */
673 response, 403, "Forbidden",
674 "Invalid access");
675 return;
676 }
677 } else {
678 /* Does not exist */
680 response, 404, "Not Found",
681 "Resource not found");
682 return;
683 }
684
685 /* Load resource object from file */
686 obj = ast_json_load_new_file(absolute_filename, &error);
687 if (obj == NULL) {
688 ast_log(LOG_ERROR, "Error parsing resource file: %s:%d(%d) %s\n",
689 error.source, error.line, error.column, error.text);
691 response, 500, "Internal Server Error",
692 "Yikes! Cannot parse resource");
693 return;
694 }
695
696 /* Update the basePath properly */
697 if (ast_json_object_get(obj, "basePath") != NULL) {
698 for (host = headers; host; host = host->next) {
699 if (strcasecmp(host->name, "Host") == 0) {
700 break;
701 }
702 }
703 if (host != NULL) {
704 if (prefix != NULL && strlen(prefix) > 0) {
706 obj, "basePath",
707 ast_json_stringf("http://%s%s/ari", host->value,prefix));
708 } else {
710 obj, "basePath",
711 ast_json_stringf("http://%s/ari", host->value));
712 }
713 } else {
714 /* Without the host, we don't have the basePath */
715 ast_json_object_del(obj, "basePath");
716 }
717 }
718
719 ast_ari_response_ok(response, obj);
720}
void ast_std_free(void *ptr)
Definition: astmm.c:1734
#define ast_log
Definition: astobj2.c:42
static char prefix[MAX_PREFIX]
Definition: http.c:144
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
struct ast_json * ast_json_stringf(const char *format,...)
Create a JSON string, printf style.
Definition: json.c:293
int ast_json_object_del(struct ast_json *object, const char *key)
Delete a field from a JSON object.
Definition: json.c:418
int ast_json_object_set(struct ast_json *object, const char *key, struct ast_json *value)
Set a field in a JSON object.
Definition: json.c:414
struct ast_json * ast_json_load_new_file(const char *path, struct ast_json_error *error)
Parse file at path into JSON object or array.
Definition: json.c:604
const char * ast_config_AST_DATA_DIR
Definition: options.c:158
void ast_ari_response_ok(struct ast_ari_response *response, struct ast_json *message)
Fill in an OK (200) ast_ari_response.
Definition: res_ari.c:276
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
JSON parsing error information.
Definition: json.h:887
int error(const char *format,...)
Definition: utils/frame.c:999

References ast_ari_response_alloc_failed(), ast_ari_response_error(), ast_ari_response_ok(), ast_begins_with(), ast_config_AST_DATA_DIR, ast_debug, ast_free, ast_json_load_new_file(), ast_json_object_del(), ast_json_object_get(), ast_json_object_set(), ast_json_stringf(), ast_log, ast_std_free(), ast_str_append(), ast_str_buffer(), ast_str_create, errno, error(), LOG_ERROR, ast_variable::name, ast_variable::next, NULL, prefix, RAII_VAR, and ast_variable::value.

Referenced by ast_ari_callback(), and AST_TEST_DEFINE().

◆ ast_ari_invoke()

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 
)

Definition at line 491 of file res_ari.c.

495{
498 struct stasis_rest_handlers *wildcard_handler = NULL;
499 RAII_VAR(struct ast_variable *, path_vars, NULL, ast_variables_destroy);
500 char *path = ast_strdupa(uri);
501 char *path_segment;
502 stasis_rest_callback callback;
503
504 root = handler = get_root_handler();
505 ast_assert(root != NULL);
506
507 ast_debug(3, "Finding handler for %s\n", path);
508
509 while ((path_segment = strsep(&path, "/")) && (strlen(path_segment) > 0)) {
510 struct stasis_rest_handlers *found_handler = NULL;
511 int i;
512
514 ast_debug(3, " Finding handler for %s\n", path_segment);
515
516 for (i = 0; found_handler == NULL && i < handler->num_children; ++i) {
517 struct stasis_rest_handlers *child = handler->children[i];
518
519 if (child->is_wildcard) {
520 /* Record the path variable */
521 struct ast_variable *path_var = ast_variable_new(child->path_segment, path_segment, __FILE__);
522 path_var->next = path_vars;
523 path_vars = path_var;
524 wildcard_handler = child;
525 ast_debug(3, " Checking %s %s: Matched wildcard.\n", handler->path_segment, child->path_segment);
526
527 } else if (strcmp(child->path_segment, path_segment) == 0) {
528 found_handler = child;
529 ast_debug(3, " Checking %s %s: Explicit match with %s\n", handler->path_segment, child->path_segment, path_segment);
530 } else {
531 ast_debug(3, " Checking %s %s: Didn't match %s\n", handler->path_segment, child->path_segment, path_segment);
532 }
533 }
534
535 if (!found_handler && wildcard_handler) {
536 ast_debug(3, " No explicit handler found for %s. Using wildcard %s.\n",
537 path_segment, wildcard_handler->path_segment);
538 found_handler = wildcard_handler;
539 wildcard_handler = NULL;
540 }
541
542 if (found_handler == NULL) {
543 /* resource not found */
544 ast_debug(3, " Handler not found for %s\n", path_segment);
546 response, 404, "Not Found",
547 "Resource not found");
548 return;
549 } else {
550 handler = found_handler;
551 }
552 }
553
555 if (method == AST_HTTP_OPTIONS) {
556 handle_options(handler, headers, response);
557 return;
558 }
559
560 if (method < 0 || method >= AST_HTTP_MAX_METHOD) {
561 add_allow_header(handler, response);
563 response, 405, "Method Not Allowed",
564 "Invalid method");
565 return;
566 }
567
568 if (handler->ws_server && method == AST_HTTP_GET) {
569 /* WebSocket! */
570 ari_handle_websocket(handler->ws_server, ser, uri, method,
571 get_params, headers);
572 /* Since the WebSocket code handles the connection, we shouldn't
573 * do anything else; setting no_response */
574 response->no_response = 1;
575 return;
576 }
577
578 callback = handler->callbacks[method];
579 if (callback == NULL) {
580 add_allow_header(handler, response);
582 response, 405, "Method Not Allowed",
583 "Invalid method");
584 return;
585 }
586
587 callback(ser, get_params, path_vars, headers, body, response);
588 if (response->message == NULL && response->response_code == 0) {
589 /* Really should not happen */
590 ast_log(LOG_ERROR, "ARI %s %s not implemented\n",
593 response, 501, "Not Implemented",
594 "Method not implemented");
595 }
596}
void(* stasis_rest_callback)(struct ast_tcptls_session_instance *ser, struct ast_variable *get_params, struct ast_variable *path_vars, struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
Callback type for RESTful method handlers.
Definition: ari.h:60
void ari_handle_websocket(struct ast_websocket_server *ws_server, struct ast_tcptls_session_instance *ser, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
Wrapper for invoking the websocket code for an incoming connection.
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
char * strsep(char **str, const char *delims)
#define ast_variable_new(name, value, filename)
static void add_allow_header(struct stasis_rest_handlers *handler, struct ast_ari_response *response)
Definition: res_ari.c:315
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.
Definition: res_ari.c:361
static struct stasis_rest_handlers * get_root_handler(void)
Definition: res_ari.c:238
const char * path_segment
Definition: ari.h:71
void ast_uri_decode(char *s, struct ast_flags spec)
Decode URI, URN, URL (overwrite string)
Definition: utils.c:762
const struct ast_flags ast_uri_http_legacy
Definition: utils.c:720

References add_allow_header(), ao2_cleanup, ari_handle_websocket(), ast_ari_response_error(), ast_assert, ast_debug, ast_get_http_method(), AST_HTTP_GET, AST_HTTP_MAX_METHOD, AST_HTTP_OPTIONS, ast_log, ast_strdupa, ast_uri_decode(), ast_uri_http_legacy, ast_variable_new, ast_variables_destroy(), get_root_handler(), handle_options(), handler(), stasis_rest_handlers::is_wildcard, LOG_ERROR, ast_ari_response::message, method, ast_variable::next, ast_ari_response::no_response, NULL, stasis_rest_handlers::path_segment, RAII_VAR, ast_ari_response::response_code, and strsep().

Referenced by ast_ari_callback(), and AST_TEST_DEFINE().

◆ ast_ari_json_format()

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.

807{
808 RAII_VAR(struct ast_ari_conf *, cfg, NULL, ao2_cleanup);
809 cfg = ast_ari_config_get();
810 return cfg->general->format;
811}

References ao2_cleanup, ast_ari_config_get(), NULL, and RAII_VAR.

Referenced by ast_ari_callback(), ast_ari_websocket_session_write(), and stasis_app_message_handler().

◆ ast_ari_oom_json()

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.

175{
176 return oom_json;
177}
static struct ast_json * oom_json
Definition: res_ari.c:172

References oom_json.

◆ ast_ari_remove_handler()

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.

203{
204 struct stasis_rest_handlers *new_handler;
205 size_t size;
206 size_t i;
207 size_t j;
208
210
212 size = sizeof(*new_handler) + root_handler->num_children * sizeof(handler);
213
214 new_handler = ao2_alloc(size, NULL);
215 if (!new_handler) {
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. */
232 root_handler = new_handler;
233
235 return 0;
236}
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_mutex_lock(a)
Definition: lock.h:189
struct stasis_rest_handlers * children[]
Definition: ari.h:86

References ao2_alloc, ao2_cleanup, ast_assert, ast_mutex_lock, ast_mutex_unlock, stasis_rest_handlers::children, handler(), NULL, stasis_rest_handlers::num_children, root_handler, and root_handler_lock.

Referenced by tear_down_invocation_test(), and unload_module().

◆ ast_ari_response_accepted()

void ast_ari_response_accepted ( struct ast_ari_response response)

Fill in a Accepted (202) ast_ari_response.

Definition at line 291 of file res_ari.c.

292{
293 response->message = ast_json_null();
294 response->response_code = 202;
295 response->response_text = "Accepted";
296}

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

Referenced by ast_ari_asterisk_reload_module().

◆ ast_ari_response_alloc_failed()

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.

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

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

Referenced by ari_bridges_play_helper(), ari_bridges_play_new(), ari_channels_handle_originate_with_id(), 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_event_websocket_ws_attempted_cb(), ast_ari_events_event_websocket_ws_established_cb(), ast_ari_events_user_event_cb(), ast_ari_get_docs(), 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(), control_list_create(), handle_options(), json_to_ast_variables(), return_sorcery_object(), send_message(), and send_refer().

◆ ast_ari_response_created()

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.

307{
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}
static char url[512]

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

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

◆ ast_ari_response_error()

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.

263{
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_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
struct ast_json * ast_json_vstringf(const char *format, va_list args)
Create a JSON string, vprintf style.
Definition: json.c:303

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

Referenced by ari_bridges_play_helper(), ari_bridges_play_new(), ari_channels_handle_originate_with_id(), ari_channels_handle_play(), ari_channels_handle_snoop_channel(), 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_callback(), 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_event_websocket_ws_attempted_cb(), ast_ari_events_event_websocket_ws_established_cb(), ast_ari_events_user_event(), ast_ari_events_user_event_cb(), ast_ari_get_docs(), ast_ari_invoke(), 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(), check_add_remove_channel(), control_list_create(), control_recording(), external_media_audiosocket_tcp(), find_bridge(), find_channel_control(), find_control(), json_to_ast_variables(), remove_trailing_slash(), send_message(), and send_refer().

◆ ast_ari_response_no_content()

void ast_ari_response_no_content ( struct ast_ari_response response)

Fill in a No Content (204) ast_ari_response.

Definition at line 284 of file res_ari.c.

285{
286 response->message = ast_json_null();
287 response->response_code = 204;
288 response->response_text = "No Content";
289}

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

Referenced by ast_ari_asterisk_add_log(), ast_ari_asterisk_delete_log(), ast_ari_asterisk_delete_object(), ast_ari_asterisk_load_module(), ast_ari_asterisk_reload_module(), ast_ari_asterisk_rotate_log(), ast_ari_asterisk_set_global_var(), ast_ari_asterisk_unload_module(), ast_ari_bridges_add_channel(), ast_ari_bridges_clear_video_source(), ast_ari_bridges_destroy(), ast_ari_bridges_remove_channel(), ast_ari_bridges_set_video_source(), ast_ari_bridges_start_moh(), ast_ari_bridges_stop_moh(), ast_ari_channels_answer(), ast_ari_channels_continue_in_dialplan(), ast_ari_channels_dial(), ast_ari_channels_hangup(), ast_ari_channels_hold(), ast_ari_channels_move(), ast_ari_channels_mute(), ast_ari_channels_redirect(), ast_ari_channels_ring(), ast_ari_channels_ring_stop(), ast_ari_channels_send_dtmf(), ast_ari_channels_set_channel_var(), ast_ari_channels_start_moh(), ast_ari_channels_start_silence(), ast_ari_channels_stop_moh(), ast_ari_channels_stop_silence(), ast_ari_channels_unhold(), ast_ari_channels_unmute(), ast_ari_device_states_delete(), ast_ari_device_states_update(), ast_ari_events_user_event(), ast_ari_mailboxes_delete(), ast_ari_mailboxes_update(), ast_ari_playbacks_control(), ast_ari_playbacks_stop(), ast_ari_recordings_delete_stored(), control_recording(), and handle_options().

◆ ast_ari_response_ok()

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.

278{
279 response->message = message;
280 response->response_code = 200;
281 response->response_text = "OK";
282}

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

Referenced by ari_channels_handle_originate_with_id(), ari_channels_handle_snoop_channel(), 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_get_docs(), 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(), ast_ari_sounds_list(), and return_sorcery_object().

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 1214 of file res_ari.c.

◆ authenticate_api_key()

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.

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
#define LOG_WARNING
struct ast_ari_conf_user * ast_ari_config_validate_user(const char *username, const char *password)
Validated a user's credentials.

References ast_ari_config_validate_user(), ast_free, ast_log, ast_strdup, copy(), LOG_WARNING, NULL, ast_ari_conf_user::password, RAII_VAR, strsep(), and ast_ari_conf_user::username.

Referenced by authenticate_user().

◆ authenticate_user()

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.

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_http_auth * ast_http_get_auth(struct ast_variable *headers)
Get HTTP authentication information from headers.
Definition: http.c:1582
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

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

Referenced by ast_ari_callback().

◆ get_root_handler()

static struct stasis_rest_handlers * get_root_handler ( void  )
static

Definition at line 238 of file res_ari.c.

239{
242 return root_handler;
243}

References ao2_ref, lock, root_handler, root_handler_lock, and SCOPED_MUTEX.

Referenced by ast_ari_invoke(), and ast_ari_response_created().

◆ handle_options()

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.

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);
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",
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}
#define LOG_NOTICE
#define ACA_HEADERS
Definition: res_ari.c:353
static int origin_allowed(const char *origin)
Definition: res_ari.c:330
#define ACA_METHODS
Definition: res_ari.c:352
#define ACR_HEADERS
Definition: res_ari.c:351
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
#define ACR_METHOD
Definition: res_ari.c:350
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
const ast_string_field value
const ast_string_field name
struct header * next

References ACA_HEADERS, ACA_METHODS, ACR_HEADERS, ACR_METHOD, add_allow_header(), ast_ari_response_alloc_failed(), ast_ari_response_no_content(), ast_free, ast_get_http_method(), AST_HTTP_MAX_METHOD, ast_log, ast_str_append(), ast_str_buffer(), ast_str_create, ast_strlen_zero(), handler(), ast_ari_response::headers, LOG_NOTICE, header::name, header::next, NULL, origin_allowed(), RAII_VAR, and header::value.

Referenced by ast_ari_invoke().

◆ is_enabled()

static int is_enabled ( void  )
static

Helper function to check if module is enabled.

Definition at line 159 of file res_ari.c.

160{
162 return cfg && cfg->general && cfg->general->enabled;
163}

References ao2_cleanup, ast_ari_config_get(), and RAII_VAR.

Referenced by ast_cel_set_config(), load_module(), reload_module(), and unload_module().

◆ load_module()

static int load_module ( void  )
static

Definition at line 1144 of file res_ari.c.

1145{
1147
1148 /* root_handler may have been built during a declined load */
1149 if (!root_handler) {
1151 }
1152 if (!root_handler) {
1154 }
1155
1156 /* oom_json may have been built during a declined load */
1157 if (!oom_json) {
1159 "{s: s}", "error", "Allocation failed");
1160 }
1161 if (!oom_json) {
1162 /* Ironic */
1163 unload_module();
1165 }
1166
1167 if (ast_ari_config_init() != 0) {
1168 unload_module();
1170 }
1171
1172 if (is_enabled()) {
1173 ast_debug(3, "ARI enabled\n");
1175 } else {
1176 ast_debug(3, "ARI disabled\n");
1177 }
1178
1179 if (ast_ari_cli_register() != 0) {
1180 unload_module();
1182 }
1183
1185}
int ast_http_uri_link(struct ast_http_uri *urihandler)
Register a URI handler.
Definition: http.c:676
#define ast_mutex_init(pmutex)
Definition: lock.h:186
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
int ast_ari_cli_register(void)
Register CLI commands for ARI.
Definition: res/ari/cli.c:431
int ast_ari_config_init(void)
Initialize the ARI configuration.
static struct stasis_rest_handlers * root_handler_create(void)
Definition: res_ari.c:245
static int is_enabled(void)
Helper function to check if module is enabled.
Definition: res_ari.c:159
static struct ast_http_uri http_uri
Definition: res_ari.c:1113
static int unload_module(void)
Definition: res_ari.c:1123

References ast_ari_cli_register(), ast_ari_config_init(), ast_debug, ast_http_uri_link(), ast_json_pack(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_mutex_init, http_uri, is_enabled(), oom_json, root_handler, root_handler_create(), root_handler_lock, and unload_module().

◆ origin_allowed()

static int origin_allowed ( const char *  origin)
static

Definition at line 330 of file res_ari.c.

331{
333
334 char *allowed = ast_strdupa(cfg->general->allowed_origins);
335 char *current;
336
337 while ((current = strsep(&allowed, ","))) {
338 if (!strcmp(current, "*")) {
339 return 1;
340 }
341
342 if (!strcmp(current, origin)) {
343 return 1;
344 }
345 }
346
347 return 0;
348}
size_t current
Definition: main/cli.c:113

References ao2_cleanup, ast_ari_config_get(), ast_strdupa, current, RAII_VAR, and strsep().

Referenced by handle_options(), and process_cors_request().

◆ process_cors_request()

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.

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}

References ast_log, ast_str_append(), ast_ari_response::headers, LOG_NOTICE, header::name, header::next, NULL, origin_allowed(), and header::value.

Referenced by ast_ari_callback().

◆ reload_module()

static int reload_module ( void  )
static

Definition at line 1187 of file res_ari.c.

1188{
1189 char was_enabled = is_enabled();
1190
1191 if (ast_ari_config_reload() != 0) {
1193 }
1194
1195 if (was_enabled && !is_enabled()) {
1196 ast_debug(3, "Disabling ARI\n");
1198 } else if (!was_enabled && is_enabled()) {
1199 ast_debug(3, "Enabling ARI\n");
1201 }
1202
1204}
void ast_http_uri_unlink(struct ast_http_uri *urihandler)
Unregister a URI handler.
Definition: http.c:708
int ast_ari_config_reload(void)
Reload the ARI configuration.

References ast_ari_config_reload(), ast_debug, ast_http_uri_link(), ast_http_uri_unlink(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, http_uri, and is_enabled().

◆ remove_trailing_slash()

static void remove_trailing_slash ( const char *  uri,
struct ast_ari_response response 
)
static

Definition at line 722 of file res_ari.c.

724{
725 char *slashless = ast_strdupa(uri);
726 slashless[strlen(slashless) - 1] = '\0';
727
728 /* While it's tempting to redirect the client to the slashless URL,
729 * that is problematic. A 302 Found is the most appropriate response,
730 * but most clients issue a GET on the location you give them,
731 * regardless of the method of the original request.
732 *
733 * While there are some ways around this, it gets into a lot of client
734 * specific behavior and corner cases in the HTTP standard. There's also
735 * very little practical benefit of redirecting; only GET and HEAD can
736 * be redirected automagically; all other requests "MUST NOT
737 * automatically redirect the request unless it can be confirmed by the
738 * user, since this might change the conditions under which the request
739 * was issued."
740 *
741 * Given all of that, a 404 with a nice message telling them what to do
742 * is probably our best bet.
743 */
744 ast_ari_response_error(response, 404, "Not Found",
745 "ARI URLs do not end with a slash. Try /ari/%s", slashless);
746}

References ast_ari_response_error(), and ast_strdupa.

Referenced by ast_ari_callback().

◆ root_handler_create()

static struct stasis_rest_handlers * root_handler_create ( void  )
static

Definition at line 245 of file res_ari.c.

246{
248
249 handler = ao2_alloc(sizeof(*handler), NULL);
250 if (!handler) {
251 return NULL;
252 }
253 handler->path_segment = "ari";
254
255 ao2_ref(handler, +1);
256 return handler;
257}

References ao2_alloc, ao2_cleanup, ao2_ref, handler(), NULL, and RAII_VAR.

Referenced by load_module().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 1123 of file res_ari.c.

1124{
1126
1127 if (is_enabled()) {
1128 ast_debug(3, "Disabling ARI\n");
1130 }
1131
1133
1137
1139 oom_json = NULL;
1140
1141 return 0;
1142}
#define ast_mutex_destroy(a)
Definition: lock.h:188
void ast_ari_cli_unregister(void)
Unregister CLI commands for ARI.
Definition: res/ari/cli.c:435
void ast_ari_config_destroy(void)
Destroy the ARI configuration.

References ao2_cleanup, ast_ari_cli_unregister(), ast_ari_config_destroy(), ast_debug, ast_http_uri_unlink(), ast_json_unref(), ast_mutex_destroy, http_uri, is_enabled(), NULL, oom_json, root_handler, and root_handler_lock.

Referenced by load_module().

Variable Documentation

◆ __mod_info

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 = AST_BUILDOPT_SUM, .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

Definition at line 1214 of file res_ari.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1214 of file res_ari.c.

◆ http_uri

struct ast_http_uri http_uri
static

Definition at line 1113 of file res_ari.c.

Referenced by load_module(), reload_module(), and unload_module().

◆ oom_json

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(), ast_ari_response_alloc_failed(), load_module(), and unload_module().

◆ root_handler

struct stasis_rest_handlers* root_handler
static

Handler for root RESTful resource.

Definition at line 169 of file res_ari.c.

Referenced by ast_ari_add_handler(), ast_ari_remove_handler(), get_root_handler(), load_module(), and unload_module().

◆ root_handler_lock

ast_mutex_t root_handler_lock
static