Asterisk - The Open Source Telephony Project GIT-master-754dea3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
Data Structures | Typedefs | Enumerations | Functions
ari.h File Reference

Asterisk RESTful API hooks. More...

#include "asterisk/http.h"
#include "asterisk/json.h"
Include dependency graph for ari.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ast_ari_response
 
struct  stasis_rest_handlers
 Handler for a single RESTful path segment. More...
 

Typedefs

typedef 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. More...
 

Enumerations

enum  ast_ari_invoke_result { ARI_INVOKE_RESULT_SUCCESS = 0 , ARI_INVOKE_RESULT_ERROR_CONTINUE = -1 , ARI_INVOKE_RESULT_ERROR_CLOSE = -2 }
 
enum  ast_ari_invoke_source { ARI_INVOKE_SOURCE_REST = 0 , ARI_INVOKE_SOURCE_WEBSOCKET , ARI_INVOKE_SOURCE_TEST }
 

Functions

int ast_ari_add_handler (struct stasis_rest_handlers *handler)
 
void ast_ari_get_docs (const char *uri, const char *prefix, struct ast_variable *headers, struct ast_ari_response *response)
 
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)
 
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...
 

Detailed Description

Asterisk RESTful API hooks.

This header file is used mostly as glue code between generated declarations and res_ari.c.

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

Definition in file ari.h.

Typedef Documentation

◆ stasis_rest_callback

typedef 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.

Parameters
serTCP/TLS session object (Maybe NULL if not available).
get_paramsGET parameters from the HTTP request.
path_varsPath variables from any wildcard path segments.
headersHTTP headers from the HTTP requiest.
body
[out]responseThe RESTful response.

Definition at line 60 of file ari.h.

Enumeration Type Documentation

◆ ast_ari_invoke_result

Enumerator
ARI_INVOKE_RESULT_SUCCESS 
ARI_INVOKE_RESULT_ERROR_CONTINUE 
ARI_INVOKE_RESULT_ERROR_CLOSE 

Definition at line 137 of file ari.h.

137 {
141};
@ ARI_INVOKE_RESULT_SUCCESS
Definition: ari.h:138
@ ARI_INVOKE_RESULT_ERROR_CLOSE
Definition: ari.h:140
@ ARI_INVOKE_RESULT_ERROR_CONTINUE
Definition: ari.h:139

◆ ast_ari_invoke_source

Enumerator
ARI_INVOKE_SOURCE_REST 
ARI_INVOKE_SOURCE_WEBSOCKET 
ARI_INVOKE_SOURCE_TEST 

Definition at line 147 of file ari.h.

147 {
151};
@ ARI_INVOKE_SOURCE_REST
Definition: ari.h:148
@ ARI_INVOKE_SOURCE_TEST
Definition: ari.h:150
@ ARI_INVOKE_SOURCE_WEBSOCKET
Definition: ari.h:149

Function Documentation

◆ 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 239 of file res_ari.c.

240{
241 RAII_VAR(struct stasis_rest_handlers *, new_handler, NULL, ao2_cleanup);
242 size_t old_size, new_size;
243
245
246 old_size = sizeof(*new_handler) + root_handler->num_children * sizeof(handler);
247 new_size = old_size + sizeof(handler);
248
249 new_handler = ao2_alloc(new_size, NULL);
250 if (!new_handler) {
251 return -1;
252 }
253 memcpy(new_handler, root_handler, old_size);
254 new_handler->children[new_handler->num_children++] = handler;
255
257 ao2_ref(new_handler, +1);
258 root_handler = new_handler;
259 return 0;
260}
ast_mutex_t lock
Definition: app_sla.c:337
#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:593
static struct stasis_rest_handlers * root_handler
Definition: res_ari.c:213
static ast_mutex_t root_handler_lock
Definition: res_ari.c:210
#define NULL
Definition: resample.c:96
Handler for a single RESTful path segment.
Definition: ari.h:69
size_t num_children
Definition: ari.h:93
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
#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_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 833 of file res_ari.c.

835{
836 RAII_VAR(struct ast_str *, absolute_path_builder, NULL, ast_free);
837 RAII_VAR(char *, absolute_api_dirname, NULL, ast_std_free);
838 RAII_VAR(char *, absolute_filename, NULL, ast_std_free);
839 struct ast_json *obj = NULL;
840 struct ast_variable *host = NULL;
841 struct ast_json_error error = {};
842 struct stat file_stat;
843
844 ast_debug(3, "%s(%s)\n", __func__, uri);
845
846 absolute_path_builder = ast_str_create(80);
847 if (absolute_path_builder == NULL) {
849 return;
850 }
851
852 /* absolute path to the rest-api directory */
853 ast_str_append(&absolute_path_builder, 0, "%s", ast_config_AST_DATA_DIR);
854 ast_str_append(&absolute_path_builder, 0, "/rest-api/");
855 absolute_api_dirname = realpath(ast_str_buffer(absolute_path_builder), NULL);
856 if (absolute_api_dirname == NULL) {
857 ast_log(LOG_ERROR, "Error determining real directory for rest-api\n");
859 response, 500, "Internal Server Error",
860 "Cannot find rest-api directory");
861 return;
862 }
863
864 /* absolute path to the requested file */
865 ast_str_append(&absolute_path_builder, 0, "%s", uri);
866 absolute_filename = realpath(ast_str_buffer(absolute_path_builder), NULL);
867 if (absolute_filename == NULL) {
868 switch (errno) {
869 case ENAMETOOLONG:
870 case ENOENT:
871 case ENOTDIR:
873 response, 404, "Not Found",
874 "Resource not found");
875 break;
876 case EACCES:
878 response, 403, "Forbidden",
879 "Permission denied");
880 break;
881 default:
883 "Error determining real path for uri '%s': %s\n",
884 uri, strerror(errno));
886 response, 500, "Internal Server Error",
887 "Cannot find file");
888 break;
889 }
890 return;
891 }
892
893 if (!ast_begins_with(absolute_filename, absolute_api_dirname)) {
894 /* HACKERZ! */
896 "Invalid attempt to access '%s' (not in %s)\n",
897 absolute_filename, absolute_api_dirname);
899 response, 404, "Not Found",
900 "Resource not found");
901 return;
902 }
903
904 if (stat(absolute_filename, &file_stat) == 0) {
905 if (!(file_stat.st_mode & S_IFREG)) {
906 /* Not a file */
908 response, 403, "Forbidden",
909 "Invalid access");
910 return;
911 }
912 } else {
913 /* Does not exist */
915 response, 404, "Not Found",
916 "Resource not found");
917 return;
918 }
919
920 /* Load resource object from file */
921 obj = ast_json_load_new_file(absolute_filename, &error);
922 if (obj == NULL) {
923 ast_log(LOG_ERROR, "Error parsing resource file: %s:%d(%d) %s\n",
924 error.source, error.line, error.column, error.text);
926 response, 500, "Internal Server Error",
927 "Yikes! Cannot parse resource");
928 return;
929 }
930
931 /* Update the basePath properly */
932 if (ast_json_object_get(obj, "basePath") != NULL) {
933 for (host = headers; host; host = host->next) {
934 if (strcasecmp(host->name, "Host") == 0) {
935 break;
936 }
937 }
938 if (host != NULL) {
939 if (prefix != NULL && strlen(prefix) > 0) {
941 obj, "basePath",
942 ast_json_stringf("http://%s%s/ari", host->value,prefix));
943 } else {
945 obj, "basePath",
946 ast_json_stringf("http://%s/ari", host->value));
947 }
948 } else {
949 /* Without the host, we don't have the basePath */
950 ast_json_object_del(obj, "basePath");
951 }
952 }
953
954 ast_ari_response_ok(response, obj);
955}
void ast_std_free(void *ptr)
Definition: astmm.c:1734
#define ast_free(a)
Definition: astmm.h:180
#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_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:407
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
int errno
const char * ast_config_AST_DATA_DIR
Definition: options.c:158
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:319
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:336
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:358
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
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
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
JSON parsing error information.
Definition: json.h:887
Abstract JSON element (object, array, string, int, ...).
Support for dynamic strings.
Definition: strings.h:623
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
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_invoke(), and AST_TEST_DEFINE().

◆ ast_ari_invoke()

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 
)

Definition at line 635 of file res_ari.c.

640{
643 struct stasis_rest_handlers *wildcard_handler = NULL;
644 RAII_VAR(struct ast_variable *, path_vars, NULL, ast_variables_destroy);
647
648 char *path = ast_strdupa(uri);
649 char *path_segment = NULL;
650 stasis_rest_callback callback;
651 SCOPE_ENTER(3, "Request: %s %s, path:%s\n", ast_get_http_method(method), uri, path);
652
653
654 if (!conf || !conf->general) {
655 if (ser && source == ARI_INVOKE_SOURCE_REST) {
657 }
658 ast_ari_response_error(response, 500, "Server Error", "URI handler config missing");
660 response->response_code, response->response_text);
661 }
662
663 user = authenticate_user(get_params, headers);
664
665 if (!user && source == ARI_INVOKE_SOURCE_REST) {
666 /* Per RFC 2617, section 1.2: The 401 (Unauthorized) response
667 * message is used by an origin server to challenge the
668 * authorization of a user agent. This response MUST include a
669 * WWW-Authenticate header field containing at least one
670 * challenge applicable to the requested resource.
671 */
672 ast_ari_response_error(response, 401, "Unauthorized", "Authentication required");
673
674 /* Section 1.2:
675 * realm = "realm" "=" realm-value
676 * realm-value = quoted-string
677 * Section 2:
678 * challenge = "Basic" realm
679 */
680 ast_str_append(&response->headers, 0,
681 "WWW-Authenticate: Basic realm=\"%s\"\r\n",
682 conf->general->auth_realm);
684 response->response_code, response->response_text);
685 } else if (!ast_fully_booted) {
686 ast_ari_response_error(response, 503, "Service Unavailable", "Asterisk not booted");
688 response->response_code, response->response_text);
689 } else if (user && user->read_only && method != AST_HTTP_GET && method != AST_HTTP_OPTIONS) {
690 ast_ari_response_error(response, 403, "Forbidden", "Write access denied");
692 response->response_code, response->response_text);
693 } else if (ast_ends_with(uri, "/")) {
694 remove_trailing_slash(uri, response);
696 response->response_code, response->response_text);
697 } else if (ast_begins_with(uri, "api-docs/")) {
698 /* Serving up API docs */
699 if (method != AST_HTTP_GET) {
700 ast_ari_response_error(response, 405, "Method Not Allowed", "Unsupported method");
701 } else {
702 if (urih) {
703 /* Skip the api-docs prefix */
704 ast_ari_get_docs(strchr(uri, '/') + 1, urih->prefix, headers, response);
705 } else {
706 /*
707 * If we were invoked without a urih, we're probably
708 * being called from the websocket so just use the
709 * default prefix. It's filled in by ast_http_uri_link().
710 */
711 ast_ari_get_docs(strchr(uri, '/') + 1, http_uri.prefix, headers, response);
712 }
713 }
715 response->response_code, response->response_text);
716 }
717
718 root = handler = get_root_handler();
719 ast_assert(root != NULL);
720
721 while ((path_segment = strsep(&path, "/")) && (strlen(path_segment) > 0)) {
722 struct stasis_rest_handlers *found_handler = NULL;
723 int i;
724 SCOPE_ENTER(4, "Finding handler for path segment %s\n", path_segment);
725
727
728 for (i = 0; found_handler == NULL && i < handler->num_children; ++i) {
729 struct stasis_rest_handlers *child = handler->children[i];
730 SCOPE_ENTER(5, "Checking handler path segment %s\n", child->path_segment);
731
732 if (child->is_wildcard) {
733 /* Record the path variable */
734 struct ast_variable *path_var = ast_variable_new(child->path_segment, path_segment, __FILE__);
735 path_var->next = path_vars;
736 path_vars = path_var;
737 wildcard_handler = child;
738 ast_trace(-1, " Checking %s %s: Matched wildcard.\n", handler->path_segment, child->path_segment);
739
740 } else if (strcmp(child->path_segment, path_segment) == 0) {
741 found_handler = child;
742 ast_trace(-1, " Checking %s %s: Explicit match with %s\n", handler->path_segment, child->path_segment, path_segment);
743 } else {
744 ast_trace(-1, " Checking %s %s: Didn't match %s\n", handler->path_segment, child->path_segment, path_segment);
745 }
746 SCOPE_EXIT("Done checking %s\n", child->path_segment);
747 }
748
749 if (!found_handler && wildcard_handler) {
750 ast_trace(-1, " No explicit handler found for %s. Using wildcard %s.\n",
751 path_segment, wildcard_handler->path_segment);
752 found_handler = wildcard_handler;
753 wildcard_handler = NULL;
754 }
755
756 if (found_handler == NULL) {
757 /* resource not found */
759 response, 404, "Not Found",
760 "Resource not found");
761 SCOPE_EXIT_EXPR(break, "Handler not found for %s\n", path_segment);
762 } else {
763 handler = found_handler;
764 }
765 SCOPE_EXIT("Done checking %s\n", path_segment);
766 }
767
768 if (handler == NULL || response->response_code == 404) {
769 /* resource not found */
771 response->response_code, response->response_text, uri);
772 }
773
775 if (method == AST_HTTP_OPTIONS) {
776 handle_options(handler, headers, response);
778 }
779
780 if (method < 0 || method >= AST_HTTP_MAX_METHOD) {
781 add_allow_header(handler, response);
783 response, 405, "Method Not Allowed",
784 "Invalid method");
786 response->response_code, response->response_text);
787 }
788
789 if (handler->is_websocket && method == AST_HTTP_GET) {
790 if (source == ARI_INVOKE_SOURCE_WEBSOCKET) {
792 response, 400, "Bad request",
793 "Can't upgrade to websocket from a websocket");
795 response->response_code, response->response_text);
796 }
797 /* WebSocket! */
798 ast_trace(-1, "Handling websocket %s\n", uri);
800 get_params, headers);
801 /* Since the WebSocket code handles the connection, we shouldn't
802 * do anything else; setting no_response */
803 response->no_response = 1;
805 }
806
807 callback = handler->callbacks[method];
808 if (callback == NULL) {
809 add_allow_header(handler, response);
811 response, 405, "Method Not Allowed",
812 "Invalid method");
814 response->response_code, response->response_text);
815 }
816
817 ast_trace(-1, "Running callback: %s\n", uri);
818 callback(ser, get_params, path_vars, headers, body, response);
819 if (response->message == NULL && response->response_code == 0) {
820 /* Really should not happen */
821 ast_log(LOG_ERROR, "ARI %s %s not implemented\n",
824 response, 501, "Not Implemented",
825 "Method not implemented");
827 response->response_code, response->response_text);
828 }
829 SCOPE_EXIT_RTN_VALUE(ARI_INVOKE_RESULT_SUCCESS, "Response: %d : %s\n",
830 response->response_code, response->response_text);
831}
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_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.
char * strsep(char **str, const char *delims)
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
#define SCOPE_ENTER(level,...)
#define SCOPE_EXIT_EXPR(__expr,...)
#define SCOPE_EXIT(...)
#define ast_trace(level,...)
@ AST_HTTP_GET
Definition: http.h:60
@ AST_HTTP_MAX_METHOD
Definition: http.h:66
@ AST_HTTP_OPTIONS
Definition: http.h:65
const char * ast_get_http_method(enum ast_http_method method) attribute_pure
Return http method name string.
Definition: http.c:193
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:853
#define ast_variable_new(name, value, filename)
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: extconf.c:1262
#define ast_fully_booted
Definition: options.h:117
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:609
static void add_allow_header(struct stasis_rest_handlers *handler, struct ast_ari_response *response)
Definition: res_ari.c:375
static struct ast_http_uri http_uri
Definition: res_ari.c:224
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:421
void ast_ari_get_docs(const char *uri, const char *prefix, struct ast_variable *headers, struct ast_ari_response *response)
Definition: res_ari.c:833
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:586
static struct stasis_rest_handlers * get_root_handler(void)
Definition: res_ari.c:298
const char * method
Definition: res_pjsip.c:1279
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
Per-user configuration options.
Definition: internal.h:96
All configuration options for ARI.
Definition: internal.h:54
struct ast_str * headers
Definition: ari.h:105
struct ast_json * message
Definition: ari.h:103
int response_code
Definition: ari.h:108
const char * response_text
Definition: ari.h:112
unsigned int no_response
Definition: ari.h:114
const char * prefix
Definition: http.h:106
All configuration options for http media cache.
struct conf_general_options * general
const char * path_segment
Definition: ari.h:71
structure to hold users read from users.conf
#define ast_assert(a)
Definition: utils.h:739
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(), ARI_INVOKE_RESULT_ERROR_CLOSE, ARI_INVOKE_RESULT_ERROR_CONTINUE, ARI_INVOKE_RESULT_SUCCESS, ARI_INVOKE_SOURCE_REST, ARI_INVOKE_SOURCE_WEBSOCKET, ast_ari_config_get(), ast_ari_get_docs(), ast_ari_response_error(), ast_assert, ast_begins_with(), ast_ends_with(), ast_fully_booted, ast_get_http_method(), AST_HTTP_GET, AST_HTTP_MAX_METHOD, AST_HTTP_OPTIONS, ast_http_request_close_on_completion(), ast_log, ast_str_append(), ast_strdupa, ast_trace, ast_uri_decode(), ast_uri_http_legacy, ast_variable_new, ast_variables_destroy(), authenticate_user(), conf::general, get_root_handler(), handle_options(), handler(), ast_ari_response::headers, http_uri, 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, ast_http_uri::prefix, RAII_VAR, remove_trailing_slash(), ast_ari_response::response_code, ast_ari_response::response_text, SCOPE_ENTER, SCOPE_EXIT, SCOPE_EXIT_EXPR, SCOPE_EXIT_RTN_VALUE, and strsep().

Referenced by ari_websocket_process_request(), 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 1015 of file res_ari.c.

1016{
1017 RAII_VAR(struct ast_ari_conf *, cfg, NULL, ao2_cleanup);
1018 cfg = ast_ari_config_get();
1019 return cfg->general->format;
1020}

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

Referenced by ari_ws_session_write(), and ast_ari_callback().

◆ 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 234 of file res_ari.c.

235{
236 return oom_json;
237}
static struct ast_json * oom_json
Definition: res_ari.c:216

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 262 of file res_ari.c.

263{
264 struct stasis_rest_handlers *new_handler;
265 size_t size;
266 size_t i;
267 size_t j;
268
270
272 size = sizeof(*new_handler) + root_handler->num_children * sizeof(handler);
273
274 new_handler = ao2_alloc(size, NULL);
275 if (!new_handler) {
277 return -1;
278 }
279
280 /* Create replacement root_handler less the handler to remove. */
281 memcpy(new_handler, root_handler, sizeof(*new_handler));
282 for (i = 0, j = 0; i < root_handler->num_children; ++i) {
283 if (root_handler->children[i] == handler) {
284 continue;
285 }
286 new_handler->children[j++] = root_handler->children[i];
287 }
288 new_handler->num_children = j;
289
290 /* Replace the old root_handler with the new. */
292 root_handler = new_handler;
293
295 return 0;
296}
#define ast_mutex_unlock(a)
Definition: lock.h:194
#define ast_mutex_lock(a)
Definition: lock.h:193
struct stasis_rest_handlers * children[]
Definition: ari.h:95

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 351 of file res_ari.c.

352{
353 response->message = ast_json_null();
354 response->response_code = 202;
355 response->response_text = "Accepted";
356}
struct ast_json * ast_json_null(void)
Get the JSON null value.
Definition: json.c:248

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 358 of file res_ari.c.

359{
360 response->message = ast_json_ref(oom_json);
361 response->response_code = 500;
362 response->response_text = "Internal Server Error";
363}
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_transfer_progress_cb(), ast_ari_channels_unmute_cb(), ast_ari_device_states_update_cb(), ast_ari_endpoints_get(), ast_ari_endpoints_list(), ast_ari_endpoints_list_by_tech(), ast_ari_events_user_event_cb(), ast_ari_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(), parse_app_args(), 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 365 of file res_ari.c.

367{
369 response->message = message;
370 response->response_code = 201;
371 response->response_text = "Created";
372 ast_str_append(&response->headers, 0, "Location: /%s%s\r\n", root->path_segment, url);
373}
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 319 of file res_ari.c.

323{
325 va_list ap;
326
327 va_start(ap, message_fmt);
328 message = ast_json_vstringf(message_fmt, ap);
329 va_end(ap);
330 response->message = ast_json_pack("{s: o}",
331 "message", ast_json_ref(message));
332 response->response_code = response_code;
333 response->response_text = response_text;
334}
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
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_transfer_progress(), ast_ari_channels_transfer_progress_cb(), ast_ari_channels_unhold_cb(), ast_ari_channels_unmute(), ast_ari_channels_unmute_cb(), ast_ari_device_states_delete(), ast_ari_device_states_delete_cb(), ast_ari_device_states_get(), ast_ari_device_states_get_cb(), ast_ari_device_states_list(), ast_ari_device_states_list_cb(), ast_ari_device_states_update(), ast_ari_device_states_update_cb(), ast_ari_endpoints_get(), ast_ari_endpoints_get_cb(), ast_ari_endpoints_list(), ast_ari_endpoints_list_by_tech(), ast_ari_endpoints_list_by_tech_cb(), ast_ari_endpoints_list_cb(), ast_ari_endpoints_refer_cb(), ast_ari_endpoints_refer_to_endpoint(), ast_ari_endpoints_refer_to_endpoint_cb(), ast_ari_endpoints_send_message_cb(), ast_ari_endpoints_send_message_to_endpoint(), ast_ari_endpoints_send_message_to_endpoint_cb(), ast_ari_events_user_event(), ast_ari_events_user_event_cb(), ast_ari_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(), parse_app_args(), 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 344 of file res_ari.c.

345{
346 response->message = ast_json_null();
347 response->response_code = 204;
348 response->response_text = "No Content";
349}

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_transfer_progress(), 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 336 of file res_ari.c.

338{
339 response->message = message;
340 response->response_code = 200;
341 response->response_text = "OK";
342}

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().