Asterisk - The Open Source Telephony Project GIT-master-c753fe4
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_close_per_call_websocket (char *app_id)
 Close a per-call outbound websocket connection. More...
 
char * ast_ari_create_per_call_websocket (const char *app_name, struct ast_channel *channel)
 Create a per-call outbound websocket connection. More...
 
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 132 of file res_ari.c.

133{
134 RAII_VAR(struct stasis_rest_handlers *, new_handler, NULL, ao2_cleanup);
135 size_t old_size, new_size;
136
138
139 old_size = sizeof(*new_handler) + root_handler->num_children * sizeof(handler);
140 new_size = old_size + sizeof(handler);
141
142 new_handler = ao2_alloc(new_size, NULL);
143 if (!new_handler) {
144 return -1;
145 }
146 memcpy(new_handler, root_handler, old_size);
147 new_handler->children[new_handler->num_children++] = handler;
148
150 ao2_ref(new_handler, +1);
151 root_handler = new_handler;
152 return 0;
153}
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:596
static struct stasis_rest_handlers * root_handler
Definition: res_ari.c:106
static ast_mutex_t root_handler_lock
Definition: res_ari.c:103
#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_close_per_call_websocket()

void ast_ari_close_per_call_websocket ( char *  app_name)

Close a per-call outbound websocket connection.

Parameters
app_idThe ephemeral application id returned by ast_ari_create_per_call_websocket().

This function should really only be called by app_stasis.

Note
This call will block until all messages for the channel have been sent or 5 seconds has elapsed. After that, the websocket will be closed.

Close a per-call outbound websocket connection.

Definition at line 1295 of file ari_websockets.c.

1296{
1297 struct ari_ws_session *session = NULL;
1298 pthread_t thread;
1299 struct timeval tv_start;
1300
1302 if (!session) {
1303 ast_debug(3, "%s: Per call websocket not found\n", app_name);
1305 return;
1306 }
1308
1309 /*
1310 * When stasis_app_exec() returns, the StasisEnd event for the
1311 * channel has been queued but since actually sending it is done
1312 * in a separate thread, it probably won't have been sent yet.
1313 * We need to wait for it to go out on the wire before we close the
1314 * websocket. ari_websocket_send_event will set a flag on the session
1315 * when a StasisEnd event is sent for the channel that originally
1316 * triggered the connection. We'll wait for that but we don't want
1317 * to wait forever so there's a fail-safe timeout in case a thread
1318 * got cancelled or we missed the StasisEnd event somehow.
1319 */
1320 ast_debug(3, "%s: Waiting for StasisEnd event to be sent RC: %d\n",
1321 session->session_id, (int)ao2_ref(session, 0));
1322
1323 tv_start = ast_tvnow();
1324 while (session->thread > 0 && !session->stasis_end_sent) {
1325 struct timeval tv_now = ast_tvnow();
1326 int64_t diff = ast_tvdiff_ms(tv_now, tv_start);
1327 ast_debug(3, "%s: Waiting for StasisEnd event %lu %d %ld\n",
1328 session->session_id, (unsigned long)session->thread,
1329 session->stasis_end_sent, diff);
1330 if (diff > STASIS_END_MAX_WAIT_MS) {
1331 break;
1332 }
1333 /* Sleep for 500ms before checking again. */
1334 usleep(500 * 1000);
1335 }
1336 ast_debug(3, "%s: StasisEnd event sent. Scheduling websocket close. RC: %d\n",
1337 session->session_id, (int)ao2_ref(session, 0));
1338
1339 /*
1340 * We can continue to send events like ChannelVarset and ChannelDestroyed
1341 * to the websocket after the StasisEnd event but those events won't be
1342 * generated until after the Stasis() dialplan app returns. We don't want
1343 * to hold up the dialplan while we wait so we'll create a thread that waits
1344 * a few seconds more before closing the websocket.
1345 *
1346 * We transferring ownership of the session to the thread.
1347 */
1350 ast_log(LOG_WARNING, "%s: Failed to create websocket close thread\n",
1351 session->session_id);
1353 }
1354 ast_debug(3, "%s: Scheduled websocket close RC: %d\n",
1355 session->session_id, (int)ao2_ref(session, 0));
1356
1357 return;
1358}
pthread_t thread
Definition: app_sla.c:335
static struct ari_ws_session * session_find_by_app(const char *app_name, unsigned int ws_type)
static void session_unref(struct ari_ws_session *session)
#define STASIS_END_MAX_WAIT_MS
static void * outbound_session_pc_close_thread(void *data)
static struct ast_mansession session
#define ast_free(a)
Definition: astmm.h:180
#define ast_log
Definition: astobj2.c:42
@ AST_WS_TYPE_CLIENT_PER_CALL
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_WARNING
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
#define ast_pthread_create_detached_background(a, b, c, d)
Definition: utils.h:597

References ao2_ref, app_name(), ast_debug, ast_free, ast_log, ast_pthread_create_detached_background, ast_tvdiff_ms(), ast_tvnow(), AST_WS_TYPE_CLIENT_PER_CALL, LOG_WARNING, NULL, outbound_session_pc_close_thread(), session, session_find_by_app(), session_unref(), STASIS_END_MAX_WAIT_MS, and thread.

Referenced by app_exec().

◆ ast_ari_create_per_call_websocket()

char * ast_ari_create_per_call_websocket ( const char *  app_name,
struct ast_channel chan 
)

Create a per-call outbound websocket connection.

Parameters
app_nameThe app name.
channelThe channel to create the websocket for.

This function should really only be called by app_stasis.

A "per_call" websocket configuration must already exist in ari.conf that has 'app_name' in its 'apps' parameter.

The channel uniqueid is used to create a unique app_id composed of "<app_name>-<channel_uniqueid>" which will be returned from this call. This ID will be used to register an ephemeral Stasis application and should be used as the app_name for the call to stasis_app_exec(). When stasis_app_exec() returns, ast_ari_close_per_call_websocket() must be called with the app_id to close the websocket.

The channel unique id is also used to detect when the StasisEnd event is sent for the channel. It's how ast_ari_close_per_call_websocket() knows that all messages for the channel have been sent and it's safe to close the websocket.

Return values
Theephemeral application id or NULL if one could not be created. This pointer will be freed by ast_ari_close_per_call_websocket(). Do not free it yourself.

Create a per-call outbound websocket connection.

Definition at line 1157 of file ari_websockets.c.

1159{
1162 RAII_VAR(char *, session_id, NULL, ast_free);
1163 RAII_VAR(char *, app_id, NULL, ast_free);
1164 enum ari_conf_owc_fields invalid_fields;
1165 const char *owc_id = NULL;
1166 char *app_id_rtn = NULL;
1167 struct timeval tv_start;
1168 int res = 0;
1169
1171 if (!owc) {
1172 ast_log(LOG_WARNING, "%s: Failed to find outbound websocket per-call config for app '%s'\n",
1173 ast_channel_name(chan), app_name);
1174 return NULL;
1175 }
1176 owc_id = ast_sorcery_object_get_id(owc);
1177 invalid_fields = ari_conf_owc_get_invalid_fields(owc_id);
1178
1179 if (invalid_fields) {
1180 ast_log(LOG_WARNING, "%s: Unable to create per-call websocket. Outbound websocket config is invalid\n",
1181 owc_id);
1182 return NULL;
1183 }
1184
1185 res = ast_asprintf(&session_id, "%s:%s", owc_id, ast_channel_name(chan));
1186 if (res < 0) {
1187 return NULL;
1188 }
1189 res = ast_asprintf(&app_id, "%s:%s", app_name, ast_channel_name(chan));
1190 if (res < 0) {
1191 ast_free(app_id);
1192 return NULL;
1193 }
1194
1195 session = session_create(NULL, app_id, owc->subscribe_all,
1196 session_id, owc, AST_WS_TYPE_CLIENT_PER_CALL);
1197 if (!session) {
1198 ast_log(LOG_WARNING, "%s: Failed to create websocket session\n", session_id);
1199 return NULL;
1200 }
1201
1202 session->channel_id = ast_strdup(ast_channel_uniqueid(chan));
1203 session->channel_name = ast_strdup(ast_channel_name(chan));
1204
1205 /*
1206 * We have to bump the session reference count here because
1207 * we need to check that the session is connected before we return.
1208 * If it didn't connect, then the thread will have cleaned up the
1209 * session while we're in the loop checking for the connection
1210 * which will result in a SEGV or FRACK.
1211 * RAII will clean up this bump.
1212 */
1214 ast_debug(2, "%s: Starting thread RC: %d\n", session->session_id,
1215 (int)ao2_ref(session, 0));
1216
1220 ast_log(LOG_WARNING, "%s: Failed to create thread.\n", session->session_id);
1221 return NULL;
1222 }
1223
1224 /*
1225 * We need to make sure the session connected and is processing
1226 * requests before we return but we don't want to block forever
1227 * in case the thread never starts or gets cancelled so we have
1228 * a fail-safe timeout.
1229 */
1230 tv_start = ast_tvnow();
1231 while (session->thread > 0 && !session->connected) {
1232 struct timeval tv_now = ast_tvnow();
1233 if (ast_tvdiff_ms(tv_now, tv_start) > PER_CALL_FAIL_SAFE_TIMEOUT(owc)) {
1234 break;
1235 }
1236 /* Sleep for 500ms before checking again. */
1237 usleep(500 * 1000);
1238 }
1239
1240 if (session->thread <= 0 || !session->connected) {
1241 ast_log(LOG_WARNING, "%s: Failed to create per call websocket thread\n",
1242 session_id);
1243 return NULL;
1244 }
1245
1246 ast_debug(3, "%s: Created per call websocket for app '%s'\n",
1247 session_id, app_id);
1248
1249 /*
1250 * We now need to prevent RAII from freeing the app_id.
1251 */
1252 app_id_rtn = app_id;
1253 app_id = NULL;
1254 return app_id_rtn;
1255}
static struct ari_ws_session * session_create(struct ast_tcptls_session_instance *ser, const char *apps, int subscribe_all, const char *session_id, struct ari_conf_outbound_websocket *ows, enum ast_websocket_type ws_type)
static void * outbound_session_handler_thread(void *obj)
static void session_cleanup(struct ari_ws_session *session)
#define PER_CALL_FAIL_SAFE_TIMEOUT(owc)
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
const char * ast_channel_name(const struct ast_channel *chan)
const char * ast_channel_uniqueid(const struct ast_channel *chan)
@ AST_WS_TYPE_CLIENT_PER_CALL_CONFIG
ari_conf_owc_fields
Definition: internal.h:96
struct ari_conf_outbound_websocket * ari_conf_get_owc_for_app(const char *app_name, unsigned int ws_type)
Get the outbound websocket configuration for a Stasis app.
enum ari_conf_owc_fields ari_conf_owc_get_invalid_fields(const char *id)
const char * ast_sorcery_object_get_id(const void *object)
Get the unique identifier of a sorcery object.
Definition: sorcery.c:2317

References ao2_bump, ao2_cleanup, ao2_ref, app_name(), ari_conf_get_owc_for_app(), ari_conf_owc_get_invalid_fields(), ast_asprintf, ast_channel_name(), ast_channel_uniqueid(), ast_debug, ast_free, ast_log, ast_pthread_create_detached_background, ast_sorcery_object_get_id(), ast_strdup, ast_tvdiff_ms(), ast_tvnow(), AST_WS_TYPE_CLIENT_PER_CALL, AST_WS_TYPE_CLIENT_PER_CALL_CONFIG, LOG_WARNING, NULL, outbound_session_handler_thread(), PER_CALL_FAIL_SAFE_TIMEOUT, RAII_VAR, session, session_cleanup(), session_create(), and session_unref().

Referenced by app_exec().

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

728{
729 RAII_VAR(struct ast_str *, absolute_path_builder, NULL, ast_free);
730 RAII_VAR(char *, absolute_api_dirname, NULL, ast_std_free);
731 RAII_VAR(char *, absolute_filename, NULL, ast_std_free);
732 struct ast_json *obj = NULL;
733 struct ast_variable *host = NULL;
734 struct ast_json_error error = {};
735 struct stat file_stat;
736
737 ast_debug(3, "%s(%s)\n", __func__, uri);
738
739 absolute_path_builder = ast_str_create(80);
740 if (absolute_path_builder == NULL) {
742 return;
743 }
744
745 /* absolute path to the rest-api directory */
746 ast_str_append(&absolute_path_builder, 0, "%s", ast_config_AST_DATA_DIR);
747 ast_str_append(&absolute_path_builder, 0, "/rest-api/");
748 absolute_api_dirname = realpath(ast_str_buffer(absolute_path_builder), NULL);
749 if (absolute_api_dirname == NULL) {
750 ast_log(LOG_ERROR, "Error determining real directory for rest-api\n");
752 response, 500, "Internal Server Error",
753 "Cannot find rest-api directory");
754 return;
755 }
756
757 /* absolute path to the requested file */
758 ast_str_append(&absolute_path_builder, 0, "%s", uri);
759 absolute_filename = realpath(ast_str_buffer(absolute_path_builder), NULL);
760 if (absolute_filename == NULL) {
761 switch (errno) {
762 case ENAMETOOLONG:
763 case ENOENT:
764 case ENOTDIR:
766 response, 404, "Not Found",
767 "Resource not found");
768 break;
769 case EACCES:
771 response, 403, "Forbidden",
772 "Permission denied");
773 break;
774 default:
776 "Error determining real path for uri '%s': %s\n",
777 uri, strerror(errno));
779 response, 500, "Internal Server Error",
780 "Cannot find file");
781 break;
782 }
783 return;
784 }
785
786 if (!ast_begins_with(absolute_filename, absolute_api_dirname)) {
787 /* HACKERZ! */
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");
794 return;
795 }
796
797 if (stat(absolute_filename, &file_stat) == 0) {
798 if (!(file_stat.st_mode & S_IFREG)) {
799 /* Not a file */
801 response, 403, "Forbidden",
802 "Invalid access");
803 return;
804 }
805 } else {
806 /* Does not exist */
808 response, 404, "Not Found",
809 "Resource not found");
810 return;
811 }
812
813 /* Load resource object from file */
814 obj = ast_json_load_new_file(absolute_filename, &error);
815 if (obj == NULL) {
816 ast_log(LOG_ERROR, "Error parsing resource file: %s:%d(%d) %s\n",
817 error.source, error.line, error.column, error.text);
819 response, 500, "Internal Server Error",
820 "Yikes! Cannot parse resource");
821 return;
822 }
823
824 /* Update the basePath properly */
825 if (ast_json_object_get(obj, "basePath") != NULL) {
826 for (host = headers; host; host = host->next) {
827 if (strcasecmp(host->name, "Host") == 0) {
828 break;
829 }
830 }
831 if (host != NULL) {
832 if (prefix != NULL && strlen(prefix) > 0) {
834 obj, "basePath",
835 ast_json_stringf("http://%s%s/ari", host->value,prefix));
836 } else {
838 obj, "basePath",
839 ast_json_stringf("http://%s/ari", host->value));
840 }
841 } else {
842 /* Without the host, we don't have the basePath */
843 ast_json_object_del(obj, "basePath");
844 }
845 }
846
847 ast_ari_response_ok(response, obj);
848}
void ast_std_free(void *ptr)
Definition: astmm.c:1734
static char prefix[MAX_PREFIX]
Definition: http.c:144
#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:159
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:212
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:229
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:251
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 528 of file res_ari.c.

533{
536 struct stasis_rest_handlers *wildcard_handler = NULL;
537 RAII_VAR(struct ast_variable *, path_vars, NULL, ast_variables_destroy);
540
541 char *path = ast_strdupa(uri);
542 char *path_segment = NULL;
544 SCOPE_ENTER(3, "Request: %s %s, path:%s\n", ast_get_http_method(method), uri, path);
545
546
547 if (!general) {
548 if (ser && source == ARI_INVOKE_SOURCE_REST) {
550 }
551 ast_ari_response_error(response, 500, "Server Error", "URI handler config missing");
553 response->response_code, response->response_text);
554 }
555
556 user = authenticate_user(get_params, headers);
557
558 if (!user && source == ARI_INVOKE_SOURCE_REST) {
559 /* Per RFC 2617, section 1.2: The 401 (Unauthorized) response
560 * message is used by an origin server to challenge the
561 * authorization of a user agent. This response MUST include a
562 * WWW-Authenticate header field containing at least one
563 * challenge applicable to the requested resource.
564 */
565 ast_ari_response_error(response, 401, "Unauthorized", "Authentication required");
566
567 /* Section 1.2:
568 * realm = "realm" "=" realm-value
569 * realm-value = quoted-string
570 * Section 2:
571 * challenge = "Basic" realm
572 */
573 ast_str_append(&response->headers, 0,
574 "WWW-Authenticate: Basic realm=\"%s\"\r\n",
575 general->auth_realm);
577 response->response_code, response->response_text);
578 } else if (!ast_fully_booted) {
579 ast_ari_response_error(response, 503, "Service Unavailable", "Asterisk not booted");
581 response->response_code, response->response_text);
582 } else if (user && user->read_only && method != AST_HTTP_GET && method != AST_HTTP_OPTIONS) {
583 ast_ari_response_error(response, 403, "Forbidden", "Write access denied");
585 response->response_code, response->response_text);
586 } else if (ast_ends_with(uri, "/")) {
587 remove_trailing_slash(uri, response);
589 response->response_code, response->response_text);
590 } else if (ast_begins_with(uri, "api-docs/")) {
591 /* Serving up API docs */
592 if (method != AST_HTTP_GET) {
593 ast_ari_response_error(response, 405, "Method Not Allowed", "Unsupported method");
594 } else {
595 if (urih) {
596 /* Skip the api-docs prefix */
597 ast_ari_get_docs(strchr(uri, '/') + 1, urih->prefix, headers, response);
598 } else {
599 /*
600 * If we were invoked without a urih, we're probably
601 * being called from the websocket so just use the
602 * default prefix. It's filled in by ast_http_uri_link().
603 */
604 ast_ari_get_docs(strchr(uri, '/') + 1, http_uri.prefix, headers, response);
605 }
606 }
608 response->response_code, response->response_text);
609 }
610
611 root = handler = get_root_handler();
612 ast_assert(root != NULL);
613
614 while ((path_segment = strsep(&path, "/")) && (strlen(path_segment) > 0)) {
615 struct stasis_rest_handlers *found_handler = NULL;
616 int i;
617 SCOPE_ENTER(4, "Finding handler for path segment %s\n", path_segment);
618
620
621 for (i = 0; found_handler == NULL && i < handler->num_children; ++i) {
622 struct stasis_rest_handlers *child = handler->children[i];
623 SCOPE_ENTER(5, "Checking handler path segment %s\n", child->path_segment);
624
625 if (child->is_wildcard) {
626 /* Record the path variable */
627 struct ast_variable *path_var = ast_variable_new(child->path_segment, path_segment, __FILE__);
628 path_var->next = path_vars;
629 path_vars = path_var;
630 wildcard_handler = child;
631 ast_trace(-1, " Checking %s %s: Matched wildcard.\n", handler->path_segment, child->path_segment);
632
633 } else if (strcmp(child->path_segment, path_segment) == 0) {
634 found_handler = child;
635 ast_trace(-1, " Checking %s %s: Explicit match with %s\n", handler->path_segment, child->path_segment, path_segment);
636 } else {
637 ast_trace(-1, " Checking %s %s: Didn't match %s\n", handler->path_segment, child->path_segment, path_segment);
638 }
639 SCOPE_EXIT("Done checking %s\n", child->path_segment);
640 }
641
642 if (!found_handler && wildcard_handler) {
643 ast_trace(-1, " No explicit handler found for %s. Using wildcard %s.\n",
644 path_segment, wildcard_handler->path_segment);
645 found_handler = wildcard_handler;
646 wildcard_handler = NULL;
647 }
648
649 if (found_handler == NULL) {
650 /* resource not found */
652 response, 404, "Not Found",
653 "Resource not found");
654 SCOPE_EXIT_EXPR(break, "Handler not found for %s\n", path_segment);
655 } else {
656 handler = found_handler;
657 }
658 SCOPE_EXIT("Done checking %s\n", path_segment);
659 }
660
661 if (handler == NULL || response->response_code == 404) {
662 /* resource not found */
664 response->response_code, response->response_text, uri);
665 }
666
668 if (method == AST_HTTP_OPTIONS) {
669 handle_options(handler, headers, response);
671 }
672
673 if (method < 0 || method >= AST_HTTP_MAX_METHOD) {
674 add_allow_header(handler, response);
676 response, 405, "Method Not Allowed",
677 "Invalid method");
679 response->response_code, response->response_text);
680 }
681
682 if (handler->is_websocket && method == AST_HTTP_GET) {
683 if (source == ARI_INVOKE_SOURCE_WEBSOCKET) {
685 response, 400, "Bad request",
686 "Can't upgrade to websocket from a websocket");
688 response->response_code, response->response_text);
689 }
690 /* WebSocket! */
691 ast_trace(-1, "Handling websocket %s\n", uri);
693 get_params, headers);
694 /* Since the WebSocket code handles the connection, we shouldn't
695 * do anything else; setting no_response */
696 response->no_response = 1;
698 }
699
700 callback = handler->callbacks[method];
701 if (callback == NULL) {
702 add_allow_header(handler, response);
704 response, 405, "Method Not Allowed",
705 "Invalid method");
707 response->response_code, response->response_text);
708 }
709
710 ast_trace(-1, "Running callback: %s\n", uri);
711 callback(ser, get_params, path_vars, headers, body, response);
712 if (response->message == NULL && response->response_code == 0) {
713 /* Really should not happen */
714 ast_log(LOG_ERROR, "ARI %s %s not implemented\n",
717 response, 501, "Not Implemented",
718 "Method not implemented");
720 response->response_code, response->response_text);
721 }
722 SCOPE_EXIT_RTN_VALUE(ARI_INVOKE_RESULT_SUCCESS, "Response: %d : %s\n",
723 response->response_code, response->response_text);
724}
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
static struct ast_channel * callback(struct ast_channelstorage_instance *driver, ao2_callback_data_fn *cb_fn, void *arg, void *data, int ao2_flags)
#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:118
struct ari_conf_general * ari_conf_get_general(void)
static void remove_trailing_slash(const char *uri, struct ast_ari_response *response)
Definition: res_ari.c:502
static void add_allow_header(struct stasis_rest_handlers *handler, struct ast_ari_response *response)
Definition: res_ari.c:268
static struct ari_conf_user * authenticate_user(struct ast_variable *get_params, struct ast_variable *headers)
Authenticate an HTTP request.
Definition: res_ari.c:479
static struct ast_http_uri http_uri
Definition: res_ari.c:117
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:314
void ast_ari_get_docs(const char *uri, const char *prefix, struct ast_variable *headers, struct ast_ari_response *response)
Definition: res_ari.c:726
static struct stasis_rest_handlers * get_root_handler(void)
Definition: res_ari.c:191
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
Global configuration options for ARI.
Definition: internal.h:57
Per-user configuration options.
Definition: internal.h:84
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
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_conf_get_general(), 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_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(), callback(), 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 908 of file res_ari.c.

909{
911 return general ? general->format : AST_JSON_COMPACT;
912}
@ AST_JSON_COMPACT
Definition: json.h:793

References ao2_cleanup, ari_conf_get_general(), AST_JSON_COMPACT, and RAII_VAR.

Referenced by ast_ari_callback(), and session_write().

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

128{
129 return oom_json;
130}
static struct ast_json * oom_json
Definition: res_ari.c:109

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

156{
157 struct stasis_rest_handlers *new_handler;
158 size_t size;
159 size_t i;
160 size_t j;
161
163
165 size = sizeof(*new_handler) + root_handler->num_children * sizeof(handler);
166
167 new_handler = ao2_alloc(size, NULL);
168 if (!new_handler) {
170 return -1;
171 }
172
173 /* Create replacement root_handler less the handler to remove. */
174 memcpy(new_handler, root_handler, sizeof(*new_handler));
175 for (i = 0, j = 0; i < root_handler->num_children; ++i) {
176 if (root_handler->children[i] == handler) {
177 continue;
178 }
179 new_handler->children[j++] = root_handler->children[i];
180 }
181 new_handler->num_children = j;
182
183 /* Replace the old root_handler with the new. */
185 root_handler = new_handler;
186
188 return 0;
189}
#define ast_mutex_unlock(a)
Definition: lock.h:197
#define ast_mutex_lock(a)
Definition: lock.h:196
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 244 of file res_ari.c.

245{
246 response->message = ast_json_null();
247 response->response_code = 202;
248 response->response_text = "Accepted";
249}
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 251 of file res_ari.c.

252{
253 response->message = ast_json_ref(oom_json);
254 response->response_code = 500;
255 response->response_text = "Internal Server Error";
256}
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(), 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 258 of file res_ari.c.

260{
262 response->message = message;
263 response->response_code = 201;
264 response->response_text = "Created";
265 ast_str_append(&response->headers, 0, "Location: /%s%s\r\n", root->path_segment, url);
266}
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 212 of file res_ari.c.

216{
218 va_list ap;
219
220 va_start(ap, message_fmt);
221 message = ast_json_vstringf(message_fmt, ap);
222 va_end(ap);
223 response->message = ast_json_pack("{s: o}",
224 "message", ast_json_ref(message));
225 response->response_code = response_code;
226 response->response_text = response_text;
227}
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(), 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 237 of file res_ari.c.

238{
239 response->message = ast_json_null();
240 response->response_code = 204;
241 response->response_text = "No Content";
242}

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

231{
232 response->message = message;
233 response->response_code = 200;
234 response->response_text = "OK";
235}

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