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_ari_response *response)
 Callback type for RESTful method handlers.

Functions

int ast_ari_add_handler (struct stasis_rest_handlers *handler)
void ast_ari_get_docs (const char *uri, struct ast_variable *headers, struct ast_ari_response *response)
void ast_ari_invoke (struct ast_tcptls_session_instance *ser, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers, struct ast_ari_response *response)
enum ast_json_encoding_format ast_ari_json_format (void)
 Configured encoding format for JSON output.
struct ast_jsonast_ari_oom_json (void)
 The stock message to return when out of memory.
int ast_ari_remove_handler (struct stasis_rest_handlers *handler)
void ast_ari_response_alloc_failed (struct ast_ari_response *response)
 Fill in response with a 500 message for allocation failures.
void ast_ari_response_created (struct ast_ari_response *response, const char *url, struct ast_json *message)
 Fill in a Created (201) ast_ari_response.
void ast_ari_response_error (struct ast_ari_response *response, int response_code, const char *response_text, const char *message_fmt,...)
 Fill in an error ast_ari_response.
void ast_ari_response_no_content (struct ast_ari_response *response)
 Fill in a No Content (204) ast_ari_response.
void ast_ari_response_ok (struct ast_ari_response *response, struct ast_json *message)
 Fill in an OK (200) ast_ari_response.
struct ast_ari_websocket_sessionast_ari_websocket_session_create (struct ast_websocket *ws_session, int(*validator)(struct ast_json *))
 Create an ARI WebSocket session.
struct ast_jsonast_ari_websocket_session_read (struct ast_ari_websocket_session *session)
 Read a message from an ARI WebSocket.
int ast_ari_websocket_session_write (struct ast_ari_websocket_session *session, struct ast_json *message)
 Send a message to an ARI WebSocket.


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@digium.com>

Definition in file ari.h.


Typedef Documentation

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_ari_response *response)

Callback type for RESTful method handlers.

Parameters:
ser TCP/TLS session object
get_params GET parameters from the HTTP request.
path_vars Path variables from any wildcard path segments.
headers HTTP headers from the HTTP requiest.
[out] response The RESTful response.

Definition at line 59 of file ari.h.


Function Documentation

int ast_ari_add_handler ( struct stasis_rest_handlers handler  ) 

Add a resource for REST handling.

Parameters:
handler Handler to add.
Returns:
0 on success.

non-zero on failure.

Definition at line 176 of file res_ari.c.

References ao2_alloc, ao2_cleanup, ao2_ref, ast_module_ref, lock, NULL, stasis_rest_handlers::num_children, RAII_VAR, and SCOPED_MUTEX.

Referenced by load_module(), and setup_invocation_test().

00177 {
00178    RAII_VAR(struct stasis_rest_handlers *, new_handler, NULL, ao2_cleanup);
00179    size_t old_size, new_size;
00180 
00181    SCOPED_MUTEX(lock, &root_handler_lock);
00182 
00183    old_size = sizeof(*new_handler) +
00184       root_handler->num_children * sizeof(handler);
00185    new_size = old_size + sizeof(handler);
00186 
00187    new_handler = ao2_alloc(new_size, NULL);
00188    if (!new_handler) {
00189       return -1;
00190    }
00191    memcpy(new_handler, root_handler, old_size);
00192    new_handler->children[new_handler->num_children++] = handler;
00193 
00194    ao2_cleanup(root_handler);
00195    ao2_ref(new_handler, +1);
00196    root_handler = new_handler;
00197    ast_module_ref(ast_module_info->self);
00198    return 0;
00199 }

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

Definition at line 571 of file res_ari.c.

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(), ast_json_error::column, errno, host, ast_json_error::line, LOG_ERROR, ast_variable::name, ast_variable::next, NULL, RAII_VAR, ast_json_error::source, ast_json_error::text, and ast_variable::value.

Referenced by ast_ari_callback(), and AST_TEST_DEFINE().

00573 {
00574    RAII_VAR(struct ast_str *, absolute_path_builder, NULL, ast_free);
00575    RAII_VAR(char *, absolute_api_dirname, NULL, ast_std_free);
00576    RAII_VAR(char *, absolute_filename, NULL, ast_std_free);
00577    struct ast_json *obj = NULL;
00578    struct ast_variable *host = NULL;
00579    struct ast_json_error error = {};
00580    struct stat file_stat;
00581 
00582    ast_debug(3, "%s(%s)\n", __func__, uri);
00583 
00584    absolute_path_builder = ast_str_create(80);
00585    if (absolute_path_builder == NULL) {
00586       ast_ari_response_alloc_failed(response);
00587       return;
00588    }
00589 
00590    /* absolute path to the rest-api directory */
00591    ast_str_append(&absolute_path_builder, 0, "%s", ast_config_AST_DATA_DIR);
00592    ast_str_append(&absolute_path_builder, 0, "/rest-api/");
00593    absolute_api_dirname = realpath(ast_str_buffer(absolute_path_builder), NULL);
00594    if (absolute_api_dirname == NULL) {
00595       ast_log(LOG_ERROR, "Error determining real directory for rest-api\n");
00596       ast_ari_response_error(
00597          response, 500, "Internal Server Error",
00598          "Cannot find rest-api directory");
00599       return;
00600    }
00601 
00602    /* absolute path to the requested file */
00603    ast_str_append(&absolute_path_builder, 0, "%s", uri);
00604    absolute_filename = realpath(ast_str_buffer(absolute_path_builder), NULL);
00605    if (absolute_filename == NULL) {
00606       switch (errno) {
00607       case ENAMETOOLONG:
00608       case ENOENT:
00609       case ENOTDIR:
00610          ast_ari_response_error(
00611             response, 404, "Not Found",
00612             "Resource not found");
00613          break;
00614       case EACCES:
00615          ast_ari_response_error(
00616             response, 403, "Forbidden",
00617             "Permission denied");
00618          break;
00619       default:
00620          ast_log(LOG_ERROR,
00621             "Error determining real path for uri '%s': %s\n",
00622             uri, strerror(errno));
00623          ast_ari_response_error(
00624             response, 500, "Internal Server Error",
00625             "Cannot find file");
00626          break;
00627       }
00628       return;
00629    }
00630 
00631    if (!ast_begins_with(absolute_filename, absolute_api_dirname)) {
00632       /* HACKERZ! */
00633       ast_log(LOG_ERROR,
00634          "Invalid attempt to access '%s' (not in %s)\n",
00635          absolute_filename, absolute_api_dirname);
00636       ast_ari_response_error(
00637          response, 404, "Not Found",
00638          "Resource not found");
00639       return;
00640    }
00641 
00642    if (stat(absolute_filename, &file_stat) == 0) {
00643       if (!(file_stat.st_mode & S_IFREG)) {
00644          /* Not a file */
00645          ast_ari_response_error(
00646             response, 403, "Forbidden",
00647             "Invalid access");
00648          return;
00649       }
00650    } else {
00651       /* Does not exist */
00652       ast_ari_response_error(
00653          response, 404, "Not Found",
00654          "Resource not found");
00655       return;
00656    }
00657 
00658    /* Load resource object from file */
00659    obj = ast_json_load_new_file(absolute_filename, &error);
00660    if (obj == NULL) {
00661       ast_log(LOG_ERROR, "Error parsing resource file: %s:%d(%d) %s\n",
00662          error.source, error.line, error.column, error.text);
00663       ast_ari_response_error(
00664          response, 500, "Internal Server Error",
00665          "Yikes! Cannot parse resource");
00666       return;
00667    }
00668 
00669    /* Update the basePath properly */
00670    if (ast_json_object_get(obj, "basePath") != NULL) {
00671       for (host = headers; host; host = host->next) {
00672          if (strcasecmp(host->name, "Host") == 0) {
00673             break;
00674          }
00675       }
00676       if (host != NULL) {
00677          ast_json_object_set(
00678             obj, "basePath",
00679             ast_json_stringf("http://%s/ari", host->value));
00680       } else {
00681          /* Without the host, we don't have the basePath */
00682          ast_json_object_del(obj, "basePath");
00683       }
00684    }
00685 
00686    ast_ari_response_ok(response, obj);
00687 }

void ast_ari_invoke ( struct ast_tcptls_session_instance ser,
const char *  uri,
enum ast_http_method  method,
struct ast_variable get_params,
struct ast_variable headers,
struct ast_ari_response response 
)

Definition at line 479 of file res_ari.c.

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

Referenced by ast_ari_callback(), and AST_TEST_DEFINE().

00483 {
00484    RAII_VAR(struct stasis_rest_handlers *, root, NULL, ao2_cleanup);
00485    struct stasis_rest_handlers *handler;
00486    RAII_VAR(struct ast_variable *, path_vars, NULL, ast_variables_destroy);
00487    char *path = ast_strdupa(uri);
00488    char *path_segment;
00489    stasis_rest_callback callback;
00490 
00491    root = handler = get_root_handler();
00492    ast_assert(root != NULL);
00493 
00494    while ((path_segment = strsep(&path, "/")) && (strlen(path_segment) > 0)) {
00495       struct stasis_rest_handlers *found_handler = NULL;
00496       int i;
00497       ast_uri_decode(path_segment, ast_uri_http_legacy);
00498       ast_debug(3, "Finding handler for %s\n", path_segment);
00499       for (i = 0; found_handler == NULL && i < handler->num_children; ++i) {
00500          struct stasis_rest_handlers *child = handler->children[i];
00501 
00502          ast_debug(3, "  Checking %s\n", child->path_segment);
00503          if (child->is_wildcard) {
00504             /* Record the path variable */
00505             struct ast_variable *path_var = ast_variable_new(child->path_segment, path_segment, __FILE__);
00506             path_var->next = path_vars;
00507             path_vars = path_var;
00508             found_handler = child;
00509          } else if (strcmp(child->path_segment, path_segment) == 0) {
00510             found_handler = child;
00511          }
00512       }
00513 
00514       if (found_handler == NULL) {
00515          /* resource not found */
00516          ast_debug(3, "  Handler not found\n");
00517          ast_ari_response_error(
00518             response, 404, "Not Found",
00519             "Resource not found");
00520          return;
00521       } else {
00522          ast_debug(3, "  Got it!\n");
00523          handler = found_handler;
00524       }
00525    }
00526 
00527    ast_assert(handler != NULL);
00528    if (method == AST_HTTP_OPTIONS) {
00529       handle_options(handler, headers, response);
00530       return;
00531    }
00532 
00533    if (method < 0 || method >= AST_HTTP_MAX_METHOD) {
00534       add_allow_header(handler, response);
00535       ast_ari_response_error(
00536          response, 405, "Method Not Allowed",
00537          "Invalid method");
00538       return;
00539    }
00540 
00541    if (handler->ws_server && method == AST_HTTP_GET) {
00542       /* WebSocket! */
00543       ari_handle_websocket(handler->ws_server, ser, uri, method,
00544          get_params, headers);
00545       /* Since the WebSocket code handles the connection, we shouldn't
00546        * do anything else; setting no_response */
00547       response->no_response = 1;
00548       return;
00549    }
00550 
00551    callback = handler->callbacks[method];
00552    if (callback == NULL) {
00553       add_allow_header(handler, response);
00554       ast_ari_response_error(
00555          response, 405, "Method Not Allowed",
00556          "Invalid method");
00557       return;
00558    }
00559 
00560    callback(ser, get_params, path_vars, headers, response);
00561    if (response->message == NULL && response->response_code == 0) {
00562       /* Really should not happen */
00563       ast_log(LOG_ERROR, "ARI %s %s not implemented\n",
00564          ast_get_http_method(method), uri);
00565       ast_ari_response_error(
00566          response, 501, "Not Implemented",
00567          "Method not implemented");
00568    }
00569 }

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

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

Referenced by ast_ari_websocket_session_write().

00774 {
00775    RAII_VAR(struct ast_ari_conf *, cfg, NULL, ao2_cleanup);
00776    cfg = ast_ari_config_get();
00777    return cfg->general->format;
00778 }

struct ast_json* ast_ari_oom_json ( void   )  [read]

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

Referenced by ast_ari_websocket_events_event_websocket(), and session_register_app().

00172 {
00173    return oom_json;
00174 }

int ast_ari_remove_handler ( struct stasis_rest_handlers handler  ) 

Remove a resource for REST handling.

Parameters:
handler Handler to add.
Returns:
0 on success.

non-zero on failure.

Definition at line 201 of file res_ari.c.

References ao2_alloc, ao2_cleanup, ao2_ref, ast_assert, ast_module_unref, ast_mutex_lock, ast_mutex_unlock, stasis_rest_handlers::children, NULL, stasis_rest_handlers::num_children, and RAII_VAR.

Referenced by tear_down_invocation_test(), and unload_module().

00202 {
00203    RAII_VAR(struct stasis_rest_handlers *, new_handler, NULL, ao2_cleanup);
00204    size_t size, i, j;
00205 
00206    ast_assert(root_handler != NULL);
00207 
00208    ast_mutex_lock(&root_handler_lock);
00209    size = sizeof(*new_handler) +
00210       root_handler->num_children * sizeof(handler);
00211 
00212    new_handler = ao2_alloc(size, NULL);
00213    if (!new_handler) {
00214       return -1;
00215    }
00216    memcpy(new_handler, root_handler, sizeof(*new_handler));
00217 
00218    for (i = 0, j = 0; i < root_handler->num_children; ++i) {
00219       if (root_handler->children[i] == handler) {
00220          ast_module_unref(ast_module_info->self);
00221          continue;
00222       }
00223       new_handler->children[j++] = root_handler->children[i];
00224    }
00225    new_handler->num_children = j;
00226 
00227    ao2_cleanup(root_handler);
00228    ao2_ref(new_handler, +1);
00229    root_handler = new_handler;
00230    ast_mutex_unlock(&root_handler_lock);
00231    return 0;
00232 }

void ast_ari_response_alloc_failed ( struct ast_ari_response response  ) 

Fill in response with a 500 message for allocation failures.

Parameters:
response Response to fill in.

Definition at line 287 of file res_ari.c.

References ast_json_ref(), ast_ari_response::message, 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_get_global_var(), ast_ari_asterisk_get_global_var_cb(), ast_ari_asterisk_get_info(), ast_ari_asterisk_get_info_cb(), ast_ari_asterisk_set_global_var_cb(), 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_get_channel_var(), ast_ari_channels_get_channel_var_cb(), ast_ari_channels_hangup_cb(), ast_ari_channels_list(), ast_ari_channels_mute_cb(), ast_ari_channels_play_cb(), ast_ari_channels_play_with_id_cb(), ast_ari_channels_record_cb(), ast_ari_channels_redirect_cb(), ast_ari_channels_send_dtmf_cb(), ast_ari_channels_set_channel_var_cb(), ast_ari_channels_snoop_channel_cb(), ast_ari_channels_snoop_channel_with_id_cb(), ast_ari_channels_start_moh_cb(), ast_ari_channels_unmute_cb(), ast_ari_device_states_update_cb(), ast_ari_endpoints_get(), ast_ari_endpoints_list(), ast_ari_endpoints_list_by_tech(), ast_ari_events_event_websocket_ws_cb(), ast_ari_events_user_event_cb(), ast_ari_get_docs(), ast_ari_mailboxes_update_cb(), ast_ari_playbacks_control_cb(), ast_ari_recordings_copy_stored_cb(), ast_ari_recordings_list_stored(), ast_ari_sounds_list_cb(), control_list_create(), handle_options(), json_to_ast_variables(), and send_message().

00288 {
00289    response->message = ast_json_ref(oom_json);
00290    response->response_code = 500;
00291    response->response_text = "Internal Server Error";
00292 }

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:
response Response to fill in.
url URL to the created resource.
message JSON response. This reference is stolen, so just ast_json_ref if you need to keep a reference to it.

Definition at line 294 of file res_ari.c.

References ast_str_append(), ast_ari_response::headers, ast_ari_response::message, ast_ari_response::response_code, and ast_ari_response::response_text.

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

00296 {
00297    response->message = message;
00298    response->response_code = 201;
00299    response->response_text = "Created";
00300    ast_str_append(&response->headers, 0, "Location: %s\r\n", url);
00301 }

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:
response Response to fill in.
response_code HTTP response code.
response_text Text corresponding to the HTTP response code.
message_fmt Error message format string.

Definition at line 255 of file res_ari.c.

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_found(), 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_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_get_global_var(), ast_ari_asterisk_get_global_var_cb(), ast_ari_asterisk_get_info_cb(), ast_ari_asterisk_set_global_var(), ast_ari_asterisk_set_global_var_cb(), ast_ari_bridges_add_channel_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(), 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_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_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(), ast_ari_channels_list_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_send_dtmf(), ast_ari_channels_send_dtmf_cb(), ast_ari_channels_set_channel_var(), ast_ari_channels_set_channel_var_cb(), ast_ari_channels_snoop_channel_cb(), ast_ari_channels_snoop_channel_with_id_cb(), ast_ari_channels_start_moh_cb(), ast_ari_channels_start_silence_cb(), ast_ari_channels_stop_moh_cb(), ast_ari_channels_stop_silence_cb(), ast_ari_channels_unhold_cb(), ast_ari_channels_unmute(), ast_ari_channels_unmute_cb(), ast_ari_device_states_delete(), ast_ari_device_states_delete_cb(), ast_ari_device_states_get(), ast_ari_device_states_get_cb(), ast_ari_device_states_list(), ast_ari_device_states_list_cb(), ast_ari_device_states_update(), ast_ari_device_states_update_cb(), ast_ari_endpoints_get(), ast_ari_endpoints_get_cb(), ast_ari_endpoints_list(), ast_ari_endpoints_list_by_tech(), ast_ari_endpoints_list_by_tech_cb(), ast_ari_endpoints_list_cb(), ast_ari_endpoints_send_message_cb(), ast_ari_endpoints_send_message_to_endpoint(), ast_ari_endpoints_send_message_to_endpoint_cb(), ast_ari_events_event_websocket_ws_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_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(), check_add_remove_channel(), control_list_create(), control_recording(), find_bridge(), find_channel_control(), find_control(), json_to_ast_variables(), remove_trailing_slash(), and send_message().

00259 {
00260    RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
00261    va_list ap;
00262 
00263    va_start(ap, message_fmt);
00264    message = ast_json_vstringf(message_fmt, ap);
00265    va_end(ap);
00266    response->message = ast_json_pack("{s: o}",
00267                  "message", ast_json_ref(message));
00268    response->response_code = response_code;
00269    response->response_text = response_text;
00270 }

void ast_ari_response_no_content ( struct ast_ari_response response  ) 

void ast_ari_response_ok ( struct ast_ari_response response,
struct ast_json message 
)

struct ast_ari_websocket_session* ast_ari_websocket_session_create ( struct ast_websocket ws_session,
int(*)(struct ast_json *)  validator 
) [read]

Create an ARI WebSocket session.

If NULL is given for the validator function, no validation will be performed.

Parameters:
ws_session Underlying WebSocket session.
validator Function to validate outgoing messages.
Returns:
New ARI WebSocket session.

NULL on error.

Definition at line 55 of file ari_websockets.c.

References ao2_alloc, ao2_cleanup, ao2_ref, ast_ari_config_get(), ast_log, ast_websocket_set_nonblock(), ast_websocket_set_timeout(), config, errno, LOG_ERROR, LOG_WARNING, NULL, null_validator(), RAII_VAR, session, ast_ari_websocket_session::validator, and websocket_session_dtor().

Referenced by ast_ari_events_event_websocket_ws_cb().

00057 {
00058    RAII_VAR(struct ast_ari_websocket_session *, session, NULL, ao2_cleanup);
00059    RAII_VAR(struct ast_ari_conf *, config, ast_ari_config_get(), ao2_cleanup);
00060 
00061    if (ws_session == NULL) {
00062       return NULL;
00063    }
00064 
00065    if (config == NULL || config->general == NULL) {
00066       return NULL;
00067    }
00068 
00069    if (validator == NULL) {
00070       validator = null_validator;
00071    }
00072 
00073    if (ast_websocket_set_nonblock(ws_session) != 0) {
00074       ast_log(LOG_ERROR,
00075          "ARI web socket failed to set nonblock; closing: %s\n",
00076          strerror(errno));
00077       return NULL;
00078    }
00079 
00080    if (ast_websocket_set_timeout(ws_session, config->general->write_timeout)) {
00081       ast_log(LOG_WARNING, "Failed to set write timeout %d on ARI web socket\n",
00082          config->general->write_timeout);
00083    }
00084 
00085    session = ao2_alloc(sizeof(*session), websocket_session_dtor);
00086    if (!session) {
00087       return NULL;
00088    }
00089 
00090    ao2_ref(ws_session, +1);
00091    session->ws_session = ws_session;
00092    session->validator = validator;
00093 
00094    ao2_ref(session, +1);
00095    return session;
00096 }

struct ast_json* ast_ari_websocket_session_read ( struct ast_ari_websocket_session session  )  [read]

Read a message from an ARI WebSocket.

Parameters:
session Session to read from.
Returns:
Message received.

NULL if WebSocket could not be read.

Definition at line 98 of file ari_websockets.c.

References ast_debug, ast_json_load_buf(), ast_json_ref(), ast_json_unref(), ast_log, ast_wait_for_input(), ast_websocket_fd(), AST_WEBSOCKET_OPCODE_CLOSE, AST_WEBSOCKET_OPCODE_TEXT, ast_websocket_read(), errno, LOG_WARNING, NULL, RAII_VAR, and ast_ari_websocket_session::ws_session.

Referenced by ast_ari_websocket_events_event_websocket().

00100 {
00101    RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
00102 
00103    if (ast_websocket_fd(session->ws_session) < 0) {
00104       return NULL;
00105    }
00106 
00107    while (!message) {
00108       int res;
00109       char *payload;
00110       uint64_t payload_len;
00111       enum ast_websocket_opcode opcode;
00112       int fragmented;
00113 
00114       res = ast_wait_for_input(
00115          ast_websocket_fd(session->ws_session), -1);
00116 
00117       if (res <= 0) {
00118          ast_log(LOG_WARNING, "WebSocket poll error: %s\n",
00119             strerror(errno));
00120          return NULL;
00121       }
00122 
00123       res = ast_websocket_read(session->ws_session, &payload,
00124          &payload_len, &opcode, &fragmented);
00125 
00126       if (res != 0) {
00127          ast_log(LOG_WARNING, "WebSocket read error: %s\n",
00128             strerror(errno));
00129          return NULL;
00130       }
00131 
00132       switch (opcode) {
00133       case AST_WEBSOCKET_OPCODE_CLOSE:
00134          ast_debug(1, "WebSocket closed\n");
00135          return NULL;
00136       case AST_WEBSOCKET_OPCODE_TEXT:
00137          message = ast_json_load_buf(payload, payload_len, NULL);
00138          if (message == NULL) {
00139             ast_log(LOG_WARNING,
00140                "WebSocket input failed to parse\n");
00141          }
00142          break;
00143       default:
00144          /* Ignore all other message types */
00145          break;
00146       }
00147    }
00148 
00149    return ast_json_ref(message);
00150 }

int ast_ari_websocket_session_write ( struct ast_ari_websocket_session session,
struct ast_json message 
)

Send a message to an ARI WebSocket.

Parameters:
session Session to write to.
message Message to send.
Returns:
0 on success.

Non-zero on error.

Definition at line 158 of file ari_websockets.c.

References ast_ari_json_format(), ast_debug, ast_json_dump_string_format(), ast_json_free(), ast_log, AST_WEBSOCKET_OPCODE_TEXT, ast_websocket_write(), LOG_ERROR, LOG_NOTICE, NULL, RAII_VAR, str, VALIDATION_FAILED, ast_ari_websocket_session::validator, and ast_ari_websocket_session::ws_session.

Referenced by app_handler(), ast_ari_websocket_events_event_websocket(), and session_register_app().

00160 {
00161    RAII_VAR(char *, str, NULL, ast_json_free);
00162 
00163 #ifdef AST_DEVMODE
00164    if (!session->validator(message)) {
00165       ast_log(LOG_ERROR, "Outgoing message failed validation\n");
00166       return ast_websocket_write(session->ws_session,
00167          AST_WEBSOCKET_OPCODE_TEXT, VALIDATION_FAILED,
00168          strlen(VALIDATION_FAILED));
00169    }
00170 #endif
00171 
00172    str = ast_json_dump_string_format(message, ast_ari_json_format());
00173 
00174    if (str == NULL) {
00175       ast_log(LOG_ERROR, "Failed to encode JSON object\n");
00176       return -1;
00177    }
00178 
00179    ast_debug(3, "Examining ARI event: \n%s\n", str);
00180    if (ast_websocket_write(session->ws_session,
00181             AST_WEBSOCKET_OPCODE_TEXT, str,  strlen(str))) {
00182       ast_log(LOG_NOTICE, "Problem occurred during websocket write, websocket closed\n");
00183       return -1;
00184    }
00185    return 0;
00186 }


Generated on Thu Apr 16 06:28:52 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6