99 return general && general->enabled;
119 .description =
"Asterisk RESTful API",
135 size_t old_size, new_size;
140 new_size = old_size +
sizeof(
handler);
147 new_handler->children[new_handler->num_children++] =
handler;
174 memcpy(new_handler,
root_handler,
sizeof(*new_handler));
214 const char *response_text,
215 const char *message_fmt, ...)
220 va_start(ap, message_fmt);
287 char *allowed =
ast_strdupa(general ? general->allowed_origins :
"");
295 if (!strcmp(
current, origin)) {
303#define ACR_METHOD "Access-Control-Request-Method"
304#define ACR_HEADERS "Access-Control-Request-Headers"
305#define ACA_METHODS "Access-Control-Allow-Methods"
306#define ACA_HEADERS "Access-Control-Allow-Headers"
319 char const *acr_method =
NULL;
320 char const *acr_headers =
NULL;
321 char const *origin =
NULL;
337 }
else if (strcmp(
"Origin",
header->
name) == 0) {
345 if (origin ==
NULL) {
360 ast_log(
LOG_NOTICE,
"Origin header '%s' does not match an allowed origin.\n", origin);
368 if (acr_method ==
NULL) {
375 if (acr_headers ==
NULL) {
394 if (strcmp(m_str, acr_method) == 0) {
489 http_auth->password);
493 for (v = get_params; v; v = v->
next) {
494 if (strcasecmp(
"api_key", v->
name) == 0) {
506 slashless[strlen(slashless) - 1] =
'\0';
525 "ARI URLs do not end with a slash. Try /ari/%s", slashless);
574 "WWW-Authenticate: Basic realm=\"%s\"\r\n",
575 general->auth_realm);
621 for (i = 0; found_handler ==
NULL && i <
handler->num_children; ++i) {
628 path_var->
next = path_vars;
629 path_vars = path_var;
630 wildcard_handler = child;
633 }
else if (strcmp(child->
path_segment, path_segment) == 0) {
634 found_handler = child;
642 if (!found_handler && wildcard_handler) {
643 ast_trace(-1,
" No explicit handler found for %s. Using wildcard %s.\n",
645 found_handler = wildcard_handler;
646 wildcard_handler =
NULL;
649 if (found_handler ==
NULL) {
652 response, 404,
"Not Found",
653 "Resource not found");
658 SCOPE_EXIT(
"Done checking %s\n", path_segment);
676 response, 405,
"Method Not Allowed",
685 response, 400,
"Bad request",
686 "Can't upgrade to websocket from a websocket");
691 ast_trace(-1,
"Handling websocket %s\n", uri);
693 get_params, headers);
704 response, 405,
"Method Not Allowed",
710 ast_trace(-1,
"Running callback: %s\n", uri);
711 callback(ser, get_params, path_vars, headers, body, response);
717 response, 501,
"Not Implemented",
718 "Method not implemented");
735 struct stat file_stat;
740 if (absolute_path_builder ==
NULL) {
749 if (absolute_api_dirname ==
NULL) {
752 response, 500,
"Internal Server Error",
753 "Cannot find rest-api directory");
760 if (absolute_filename ==
NULL) {
766 response, 404,
"Not Found",
767 "Resource not found");
771 response, 403,
"Forbidden",
772 "Permission denied");
776 "Error determining real path for uri '%s': %s\n",
777 uri, strerror(
errno));
779 response, 500,
"Internal Server Error",
789 "Invalid attempt to access '%s' (not in %s)\n",
790 absolute_filename, absolute_api_dirname);
792 response, 404,
"Not Found",
793 "Resource not found");
797 if (stat(absolute_filename, &file_stat) == 0) {
798 if (!(file_stat.st_mode & S_IFREG)) {
801 response, 403,
"Forbidden",
808 response, 404,
"Not Found",
809 "Resource not found");
819 response, 500,
"Internal Server Error",
820 "Yikes! Cannot parse resource");
826 for (host = headers; host; host = host->
next) {
827 if (strcasecmp(host->
name,
"Host") == 0) {
858 char const *origin =
NULL;
871 if (origin ==
NULL) {
883 ast_log(
LOG_NOTICE,
"Origin header '%s' does not match an allowed origin.\n", origin);
896 "Access-Control-Allow-Origin: %s\r\n", origin);
898 "Access-Control-Allow-Credentials: true\r\n");
946 if (!response_body) {
971 "Request Entity Too Large",
972 "Request body too large");
977 "Internal Server Error",
982 "Bad Request",
"Error parsing request body");
990 ast_trace(-1,
"Checking body for vars\n");
1002 goto request_failed;
1006 if (get_params ==
NULL) {
1007 ast_trace(-1,
"No get_params, using post_vars if any\n");
1008 get_params = post_vars;
1009 }
else if (get_params && post_vars) {
1012 ast_trace(-1,
"Has get_params and post_vars. Merging\n");
1013 while (last_var->
next) {
1014 last_var = last_var->
next;
1020 get_params = post_vars;
1040 if (!
buf || (body && !
str)) {
1045 goto request_failed;
1064 urih, uri,
method, get_params, headers, body, &response);
1089 "Content-type: application/json\r\n");
1101 ast_verbose(
"<--- Sending ARI response to %s --->\n%d %s\n%s%s\n\n",
1109 response.
fd != -1 ? response.
fd : 0, 0);
1111 response_body =
NULL;
1114 if (response.
fd >= 0) {
1159 "{s: s}",
"error",
"Allocation failed");
1211 int is_now_enabled = 0;
1217 if (was_enabled && !is_now_enabled) {
1220 }
else if (!was_enabled && is_now_enabled) {
1233 .
requires =
"http,res_stasis,res_http_websocket,res_websocket_client",
static int copy(char *infile, char *outfile)
Utility function to copy a file.
Asterisk RESTful API hooks.
@ ARI_INVOKE_SOURCE_WEBSOCKET
@ ARI_INVOKE_RESULT_SUCCESS
@ ARI_INVOKE_RESULT_ERROR_CLOSE
@ ARI_INVOKE_RESULT_ERROR_CONTINUE
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.
int ari_websocket_load_module(int is_enabled)
int ari_websocket_unload_module(void)
void ari_handle_websocket(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.
Internal API's for websockets.
char * strsep(char **str, const char *delims)
Asterisk main include file. File version handling, generic pbx functions.
void ast_std_free(void *ptr)
#define ast_strdup(str)
A wrapper for strdup()
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define ao2_alloc(data_size, destructor_fn)
static struct ast_channel * callback(struct ast_channelstorage_instance *driver, ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags)
void ast_verbose(const char *fmt,...)
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
#define SCOPE_CALL_WITH_RESULT(level, __var, __funcname,...)
#define SCOPE_ENTER(level,...)
#define SCOPE_EXIT_EXPR(__expr,...)
#define ast_trace(level,...)
static char prefix[MAX_PREFIX]
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.
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...
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.
ast_http_method
HTTP Request methods known by Asterisk.
void ast_http_uri_unlink(struct ast_http_uri *urihandler)
Unregister a URI handler.
struct ast_http_auth * ast_http_get_auth(struct ast_variable *headers)
Get HTTP authentication information from headers.
const char * ast_get_http_method(enum ast_http_method method) attribute_pure
Return http method name string.
void ast_http_request_close_on_completion(struct ast_tcptls_session_instance *ser)
Request the HTTP connection be closed after this HTTP request.
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.
int ast_http_uri_link(struct ast_http_uri *urihandler)
Register a URI handler.
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.
#define ast_variable_new(name, value, filename)
struct ast_variable * ast_variables_dup(struct ast_variable *var)
Duplicate variable list.
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
#define ast_debug(level,...)
Log a DEBUG message.
Internal API's for res_ari.
struct ast_json * ast_json_null(void)
Get the JSON null value.
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
void ast_json_free(void *p)
Asterisk's custom JSON allocator. Exposed for use by unit tests.
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
struct ast_json * ast_json_vstringf(const char *format, va_list args)
Create a JSON string, vprintf style.
struct ast_json * ast_json_stringf(const char *format,...)
Create a JSON string, printf style.
int ast_json_object_del(struct ast_json *object, const char *key)
Delete a field from a JSON object.
ast_json_encoding_format
Encoding format type.
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
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.
int ast_json_object_set(struct ast_json *object, const char *key, struct ast_json *value)
Set a field in a JSON object.
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
char * ast_json_dump_string_format(struct ast_json *root, enum ast_json_encoding_format format)
Encode a JSON value to a string.
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.
int ast_json_is_null(const struct ast_json *value)
Check if value is JSON null.
#define ast_mutex_init(pmutex)
#define ast_mutex_unlock(a)
#define SCOPED_MUTEX(varname, lock)
scoped lock specialization for mutexes
#define ast_mutex_destroy(a)
#define ast_mutex_lock(a)
Asterisk module definitions.
@ AST_MODFLAG_GLOBAL_SYMBOLS
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODULE_SUPPORT_CORE
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_MODULE_LOAD_SUCCESS
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Asterisk file paths, configured in asterisk.conf.
const char * ast_config_AST_DATA_DIR
const char * app_name(struct ast_app *app)
void ari_cli_unregister(void)
Unregister CLI commands for ARI.
int ari_cli_register(void)
Register CLI commands for ARI.
int ari_conf_load(enum ari_conf_load_flags flags)
(Re)load the ARI configuration
struct ari_conf_general * ari_conf_get_general(void)
struct ari_conf_user * ari_conf_validate_user(const char *username, const char *password)
Validated a user's credentials.
void ari_conf_destroy(void)
Destroy the ARI configuration.
static void remove_trailing_slash(const char *uri, struct ast_ari_response *response)
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)
Callback for the root URI.
static struct stasis_rest_handlers * root_handler_create(void)
enum ast_json_encoding_format ast_ari_json_format(void)
Configured encoding format for JSON output.
static struct stasis_rest_handlers * root_handler
static ast_mutex_t root_handler_lock
static int is_enabled(void)
Helper function to check if module is enabled.
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.
int ast_ari_remove_handler(struct stasis_rest_handlers *handler)
static void add_allow_header(struct stasis_rest_handlers *handler, struct ast_ari_response *response)
static struct ari_conf_user * authenticate_user(struct ast_variable *get_params, struct ast_variable *headers)
Authenticate an HTTP request.
static struct ast_http_uri http_uri
static int reload_module(void)
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.
void ast_ari_response_ok(struct ast_ari_response *response, struct ast_json *message)
Fill in an OK (200) ast_ari_response.
static int origin_allowed(const char *origin)
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.
void ast_ari_response_accepted(struct ast_ari_response *response)
Fill in a Accepted (202) ast_ari_response.
struct ast_json * ast_ari_oom_json(void)
The stock message to return when out of memory.
static void process_cors_request(struct ast_variable *headers, struct ast_ari_response *response)
Handle CORS headers for simple requests.
void ast_ari_response_alloc_failed(struct ast_ari_response *response)
Fill in response with a 500 message for allocation failures.
void ast_ari_response_no_content(struct ast_ari_response *response)
Fill in a No Content (204) ast_ari_response.
static int load_module(void)
void ast_ari_get_docs(const char *uri, const char *prefix, struct ast_variable *headers, struct ast_ari_response *response)
static struct ast_json * oom_json
static int unload_module(void)
int ast_ari_add_handler(struct stasis_rest_handlers *handler)
enum ast_ari_invoke_result ast_ari_invoke(struct ast_tcptls_session_instance *ser, enum ast_ari_invoke_source source, const struct ast_http_uri *urih, 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)
static struct stasis_rest_handlers * get_root_handler(void)
static struct ari_conf_user * authenticate_api_key(const char *api_key)
Authenticate a ?api_key=userid:password
Stasis Application API. See Stasis Application API for detailed documentation.
int stasis_app_get_debug_by_name(const char *app_name)
Get debug status of an application.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
static int force_inline attribute_pure ast_ends_with(const char *str, const char *suffix)
Checks whether a string ends with another.
static force_inline int attribute_pure ast_strlen_zero(const char *s)
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Checks whether a string begins with another.
Global configuration options for ARI.
Per-user configuration options.
const ast_string_field password
struct ast_json * message
const char * response_text
HTTP authentication information.
Definition of a URI handler.
ast_http_callback callback
JSON parsing error information.
Abstract JSON element (object, array, string, int, ...).
Structure for mutex and tracking information.
Support for dynamic strings.
describes a server instance
struct ast_sockaddr remote_address
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
Handler for a single RESTful path segment.
const char * path_segment
struct stasis_rest_handlers * children[]
structure to hold users read from users.conf
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)
int error(const char *format,...)
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
void ast_uri_decode(char *s, struct ast_flags spec)
Decode URI, URN, URL (overwrite string)
const struct ast_flags ast_uri_http_legacy