ari_websockets.c File Reference

WebSocket support for RESTful API's. More...

#include "asterisk.h"
#include "asterisk/ari.h"
#include "asterisk/astobj2.h"
#include "asterisk/http_websocket.h"
#include "internal.h"

Include dependency graph for ari_websockets.c:

Go to the source code of this file.

Data Structures

struct  ast_ari_websocket_session

Defines

#define VALIDATION_FAILED

Functions

void ari_handle_websocket (struct ast_websocket_server *ws_server, struct ast_tcptls_session_instance *ser, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
 Wrapper for invoking the websocket code for an incoming connection.
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.
static int null_validator (struct ast_json *json)
 Validator that always succeeds.
static void websocket_session_dtor (void *obj)


Detailed Description

WebSocket support for RESTful API's.

Author:
David M. Lee, II <dlee@digium.com>

Definition in file ari_websockets.c.


Define Documentation

#define VALIDATION_FAILED

Value:

"{"                  \
   "  \"error\": \"InvalidMessage\","     \
   "  \"message\": \"Message validation failed\""  \
   "}"

Definition at line 152 of file ari_websockets.c.

Referenced by ast_ari_websocket_session_write().


Function Documentation

void ari_handle_websocket ( struct ast_websocket_server ws_server,
struct ast_tcptls_session_instance ser,
const char *  uri,
enum ast_http_method  method,
struct ast_variable get_params,
struct ast_variable headers 
)

Wrapper for invoking the websocket code for an incoming connection.

Parameters:
ws_server WebSocket server to invoke.
ser HTTP session.
uri Requested URI.
method Requested HTTP method.
get_params Parsed query parameters.
headers Parsed HTTP headers.

Definition at line 188 of file ari_websockets.c.

References ast_websocket_uri_cb(), and ast_http_uri::data.

Referenced by ast_ari_invoke().

00192 {
00193    struct ast_http_uri fake_urih = {
00194       .data = ws_server,
00195    };
00196    ast_websocket_uri_cb(ser, &fake_urih, uri, method, get_params,
00197       headers);
00198 }

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 }

static int null_validator ( struct ast_json json  )  [static]

Validator that always succeeds.

Definition at line 50 of file ari_websockets.c.

Referenced by ast_ari_websocket_session_create().

00051 {
00052    return 1;
00053 }

static void websocket_session_dtor ( void *  obj  )  [static]

Definition at line 39 of file ari_websockets.c.

References ast_websocket_unref(), NULL, session, and ast_ari_websocket_session::ws_session.

Referenced by ast_ari_websocket_session_create().

00040 {
00041    struct ast_ari_websocket_session *session = obj;
00042 
00043    ast_websocket_unref(session->ws_session);
00044    session->ws_session = NULL;
00045 }


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