162 return cfg && cfg->general && cfg->general->enabled;
182 size_t old_size, new_size;
187 new_size = old_size +
sizeof(
handler);
194 new_handler->children[new_handler->num_children++] =
handler;
221 memcpy(new_handler,
root_handler,
sizeof(*new_handler));
261 const char *response_text,
262 const char *message_fmt, ...)
267 va_start(ap, message_fmt);
334 char *allowed =
ast_strdupa(cfg->general->allowed_origins);
342 if (!strcmp(
current, origin)) {
350#define ACR_METHOD "Access-Control-Request-Method"
351#define ACR_HEADERS "Access-Control-Request-Headers"
352#define ACA_METHODS "Access-Control-Allow-Methods"
353#define ACA_HEADERS "Access-Control-Allow-Headers"
366 char const *acr_method =
NULL;
367 char const *acr_headers =
NULL;
368 char const *origin =
NULL;
384 }
else if (strcmp(
"Origin",
header->
name) == 0) {
392 if (origin ==
NULL) {
407 ast_log(
LOG_NOTICE,
"Origin header '%s' does not match an allowed origin.\n", origin);
415 if (acr_method ==
NULL) {
422 if (acr_headers ==
NULL) {
441 if (strcmp(m_str, acr_method) == 0) {
507 ast_debug(3,
"Finding handler for %s\n", path);
516 for (i = 0; found_handler ==
NULL && i <
handler->num_children; ++i) {
522 path_var->
next = path_vars;
523 path_vars = path_var;
524 wildcard_handler = child;
527 }
else if (strcmp(child->
path_segment, path_segment) == 0) {
528 found_handler = child;
535 if (!found_handler && wildcard_handler) {
536 ast_debug(3,
" No explicit handler found for %s. Using wildcard %s.\n",
538 found_handler = wildcard_handler;
539 wildcard_handler =
NULL;
542 if (found_handler ==
NULL) {
544 ast_debug(3,
" Handler not found for %s\n", path_segment);
546 response, 404,
"Not Found",
547 "Resource not found");
563 response, 405,
"Method Not Allowed",
571 get_params, headers);
579 if (callback ==
NULL) {
582 response, 405,
"Method Not Allowed",
587 callback(ser, get_params, path_vars, headers, body, response);
593 response, 501,
"Not Implemented",
594 "Method not implemented");
607 struct stat file_stat;
612 if (absolute_path_builder ==
NULL) {
621 if (absolute_api_dirname ==
NULL) {
624 response, 500,
"Internal Server Error",
625 "Cannot find rest-api directory");
632 if (absolute_filename ==
NULL) {
638 response, 404,
"Not Found",
639 "Resource not found");
643 response, 403,
"Forbidden",
644 "Permission denied");
648 "Error determining real path for uri '%s': %s\n",
649 uri, strerror(
errno));
651 response, 500,
"Internal Server Error",
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");
669 if (stat(absolute_filename, &file_stat) == 0) {
670 if (!(file_stat.st_mode & S_IFREG)) {
673 response, 403,
"Forbidden",
680 response, 404,
"Not Found",
681 "Resource not found");
691 response, 500,
"Internal Server Error",
692 "Yikes! Cannot parse resource");
698 for (host = headers; host; host = host->
next) {
699 if (strcasecmp(host->
name,
"Host") == 0) {
726 slashless[strlen(slashless) - 1] =
'\0';
745 "ARI URLs do not end with a slash. Try /ari/%s", slashless);
756 char const *origin =
NULL;
769 if (origin ==
NULL) {
781 ast_log(
LOG_NOTICE,
"Origin header '%s' does not match an allowed origin.\n", origin);
794 "Access-Control-Allow-Origin: %s\r\n", origin);
796 "Access-Control-Allow-Credentials: true\r\n");
810 return cfg->general->format;
858 http_auth->password);
862 for (v = get_params; v; v = v->
next) {
863 if (strcasecmp(
"api_key", v->
name) == 0) {
902 if (!response_body) {
919 ast_http_error(ser, 500,
"Server Error",
"URI handler config missing");
934 "Request Entity Too Large",
935 "Request body too large");
940 "Internal Server Error",
945 "Bad Request",
"Error parsing request body");
968 if (get_params ==
NULL) {
969 get_params = post_vars;
970 }
else if (get_params && post_vars) {
973 while (last_var->
next) {
974 last_var = last_var->
next;
980 get_params = post_vars;
999 if (!
buf || (body && !
str)) {
1004 goto request_failed;
1040 "WWW-Authenticate: Basic realm=\"%s\"\r\n",
1083 "Content-type: application/json\r\n");
1095 ast_verbose(
"<--- Sending ARI response to %s --->\n%d %s\n%s%s\n\n",
1103 response.
fd != -1 ? response.
fd : 0, 0);
1105 response_body =
NULL;
1108 if (response.
fd >= 0) {
1116 .description =
"Asterisk RESTful API",
1160 "{s: s}",
"error",
"Allocation failed");
1212 .optional_modules =
"res_http_websocket",
1213 .
requires =
"http,res_stasis",
static int copy(char *infile, char *outfile)
Utility function to copy a file.
Asterisk RESTful API hooks.
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.
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.
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)
void ast_verbose(const char *fmt,...)
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.
char * strsep(char **str, const char *delims)
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)
int ast_ari_cli_register(void)
Register CLI commands for ARI.
void ast_ari_cli_unregister(void)
Unregister CLI commands for ARI.
struct ast_ari_conf * ast_ari_config_get(void)
Get the current ARI configuration.
int ast_ari_config_reload(void)
Reload the ARI configuration.
int ast_ari_config_init(void)
Initialize the ARI configuration.
struct ast_ari_conf_user * ast_ari_config_validate_user(const char *username, const char *password)
Validated a user's credentials.
void ast_ari_config_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)
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 ast_ari_conf_user * authenticate_api_key(const char *api_key)
Authenticate a ?api_key=userid:password
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_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)
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)
static struct ast_ari_conf_user * authenticate_user(struct ast_variable *get_params, struct ast_variable *headers)
Authenticate an HTTP request.
int ast_ari_add_handler(struct stasis_rest_handlers *handler)
static struct stasis_rest_handlers * get_root_handler(void)
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.
Per-user configuration options.
char password[ARI_PASSWORD_LEN]
All configuration options for ARI.
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
All configuration options for http media cache.
struct conf_general_options * general
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