Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Functions
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 "asterisk/stasis_app.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
 

Macros

#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. More...
 
struct ast_ari_websocket_sessionast_ari_websocket_session_create (struct ast_websocket *ws_session, int(*validator)(struct ast_json *))
 Create an ARI WebSocket session. More...
 
struct ast_sockaddrast_ari_websocket_session_get_remote_addr (struct ast_ari_websocket_session *session)
 Get the remote address from an ARI WebSocket. More...
 
const char * ast_ari_websocket_session_id (const struct ast_ari_websocket_session *session)
 Get the Session ID for an ARI WebSocket. More...
 
struct ast_jsonast_ari_websocket_session_read (struct ast_ari_websocket_session *session)
 Read a message from an ARI WebSocket. More...
 
int ast_ari_websocket_session_write (struct ast_ari_websocket_session *session, struct ast_json *message)
 Send a message to an ARI WebSocket. More...
 
static int null_validator (struct ast_json *json)
 Validator that always succeeds. More...
 
static void websocket_session_dtor (void *obj)
 

Detailed Description

WebSocket support for RESTful API's.

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

Definition in file ari_websockets.c.

Macro Definition Documentation

◆ VALIDATION_FAILED

#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

◆ ari_handle_websocket()

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_serverWebSocket server to invoke.
serHTTP session.
uriRequested URI.
methodRequested HTTP method.
get_paramsParsed query parameters.
headersParsed HTTP headers.

Definition at line 191 of file ari_websockets.c.

References ast_websocket_uri_cb(), and ast_http_uri::data.

Referenced by ast_ari_invoke().

195 {
196  struct ast_http_uri fake_urih = {
197  .data = ws_server,
198  };
199  ast_websocket_uri_cb(ser, &fake_urih, uri, method, get_params,
200  headers);
201 }
const char * method
Definition: res_pjsip.c:4335
int AST_OPTIONAL_API_NAME() ast_websocket_uri_cb(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_vars, struct ast_variable *headers)
Definition of a URI handler.
Definition: http.h:100
const char * uri
Definition: http.h:103
void * data
Definition: http.h:114

◆ ast_ari_websocket_session_create()

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

Create an ARI WebSocket session.

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

Parameters
ws_sessionUnderlying WebSocket session.
validatorFunction to validate outgoing messages.
Returns
New ARI WebSocket session.
NULL on error.

Definition at line 54 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, websocket_session_dtor(), and ast_ari_websocket_session::ws_session.

Referenced by ast_ari_events_event_websocket_ws_established_cb().

56 {
59 
60  if (ws_session == NULL) {
61  return NULL;
62  }
63 
64  if (config == NULL || config->general == NULL) {
65  return NULL;
66  }
67 
68  if (validator == NULL) {
69  validator = null_validator;
70  }
71 
72  if (ast_websocket_set_nonblock(ws_session) != 0) {
74  "ARI web socket failed to set nonblock; closing: %s\n",
75  strerror(errno));
76  return NULL;
77  }
78 
79  if (ast_websocket_set_timeout(ws_session, config->general->write_timeout)) {
80  ast_log(LOG_WARNING, "Failed to set write timeout %d on ARI web socket\n",
81  config->general->write_timeout);
82  }
83 
85  if (!session) {
86  return NULL;
87  }
88 
89  ao2_ref(ws_session, +1);
90  session->ws_session = ws_session;
91  session->validator = validator;
92 
93  ao2_ref(session, +1);
94  return session;
95 }
char * config
Definition: conf2ael.c:66
struct ast_ari_conf * ast_ari_config_get(void)
Get the current ARI configuration.
#define LOG_WARNING
Definition: logger.h:274
All configuration options for ARI.
Definition: internal.h:54
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
static int null_validator(struct ast_json *json)
Validator that always succeeds.
#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:911
static struct ast_mansession session
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define LOG_ERROR
Definition: logger.h:285
int errno
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
int AST_OPTIONAL_API_NAME() ast_websocket_set_timeout(struct ast_websocket *session, int timeout)
static void websocket_session_dtor(void *obj)
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
int AST_OPTIONAL_API_NAME() ast_websocket_set_nonblock(struct ast_websocket *session)

◆ ast_ari_websocket_session_get_remote_addr()

struct ast_sockaddr* ast_ari_websocket_session_get_remote_addr ( struct ast_ari_websocket_session session)

Get the remote address from an ARI WebSocket.

Parameters
sessionSession to write to.
Returns
ast_sockaddr (does not have to be freed)

Definition at line 185 of file ari_websockets.c.

References ast_websocket_remote_address(), and ast_ari_websocket_session::ws_session.

Referenced by ast_ari_websocket_session_write(), and stasis_app_message_handler().

187 {
188  return ast_websocket_remote_address(session->ws_session);
189 }
struct ast_sockaddr *AST_OPTIONAL_API_NAME() ast_websocket_remote_address(struct ast_websocket *session)
struct ast_websocket * ws_session

◆ ast_ari_websocket_session_id()

const char* ast_ari_websocket_session_id ( const struct ast_ari_websocket_session session)

Get the Session ID for an ARI WebSocket.

Parameters
sessionSession to query.
Returns
Session ID.
NULL on error.

Definition at line 203 of file ari_websockets.c.

References ast_websocket_session_id(), and ast_ari_websocket_session::ws_session.

Referenced by ast_ari_websocket_events_event_websocket_established().

205 {
206  return ast_websocket_session_id(session->ws_session);
207 }
const char *AST_OPTIONAL_API_NAME() ast_websocket_session_id(struct ast_websocket *session)
struct ast_websocket * ws_session

◆ ast_ari_websocket_session_read()

struct ast_json* ast_ari_websocket_session_read ( struct ast_ari_websocket_session session)

Read a message from an ARI WebSocket.

Parameters
sessionSession to read from.
Returns
Message received.
NULL if WebSocket could not be read.

Definition at line 97 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_established().

99 {
101 
102  if (ast_websocket_fd(session->ws_session) < 0) {
103  return NULL;
104  }
105 
106  while (!message) {
107  int res;
108  char *payload;
109  uint64_t payload_len;
110  enum ast_websocket_opcode opcode;
111  int fragmented;
112 
113  res = ast_wait_for_input(
114  ast_websocket_fd(session->ws_session), -1);
115 
116  if (res <= 0) {
117  ast_log(LOG_WARNING, "WebSocket poll error: %s\n",
118  strerror(errno));
119  return NULL;
120  }
121 
122  res = ast_websocket_read(session->ws_session, &payload,
123  &payload_len, &opcode, &fragmented);
124 
125  if (res != 0) {
126  ast_log(LOG_WARNING, "WebSocket read error: %s\n",
127  strerror(errno));
128  return NULL;
129  }
130 
131  switch (opcode) {
133  ast_debug(1, "WebSocket closed\n");
134  return NULL;
136  message = ast_json_load_buf(payload, payload_len, NULL);
137  if (message == NULL) {
139  "WebSocket input failed to parse\n");
140  }
141 
142  break;
143  default:
144  /* Ignore all other message types */
145  break;
146  }
147  }
148 
149  return ast_json_ref(message);
150 }
int AST_OPTIONAL_API_NAME() ast_websocket_read(struct ast_websocket *session, char **payload, uint64_t *payload_len, enum ast_websocket_opcode *opcode, int *fragmented)
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition: json.c:67
struct ast_json * ast_json_load_buf(const char *buffer, size_t buflen, struct ast_json_error *error)
Parse buffer with known length into a JSON object or array.
Definition: json.c:564
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
#define LOG_WARNING
Definition: logger.h:274
#define NULL
Definition: resample.c:96
int AST_OPTIONAL_API_NAME() ast_websocket_fd(struct ast_websocket *session)
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#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:911
struct ast_websocket * ws_session
int errno
Abstract JSON element (object, array, string, int, ...).
int ast_wait_for_input(int fd, int ms)
Definition: main/utils.c:1519
ast_websocket_opcode
WebSocket operation codes.

◆ ast_ari_websocket_session_write()

int ast_ari_websocket_session_write ( struct ast_ari_websocket_session session,
struct ast_json message 
)

Send a message to an ARI WebSocket.

Parameters
sessionSession to write to.
messageMessage 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_ari_websocket_session_get_remote_addr(), ast_json_dump_string_format(), ast_json_free(), ast_log, ast_sockaddr_stringify(), ast_websocket_write_string(), LOG_ERROR, LOG_NOTICE, NULL, RAII_VAR, str, VALIDATION_FAILED, ast_ari_websocket_session::validator, and ast_ari_websocket_session::ws_session.

Referenced by event_session_update_websocket(), and stasis_app_message_handler().

160 {
161  RAII_VAR(char *, str, NULL, ast_json_free);
162 
163 #ifdef AST_DEVMODE
164  if (!session->validator(message)) {
165  ast_log(LOG_ERROR, "Outgoing message failed validation\n");
167  }
168 #endif
169 
171 
172  if (str == NULL) {
173  ast_log(LOG_ERROR, "Failed to encode JSON object\n");
174  return -1;
175  }
176 
177  if (ast_websocket_write_string(session->ws_session, str)) {
178  ast_log(LOG_NOTICE, "Problem occurred during websocket write to %s, websocket closed\n",
180  return -1;
181  }
182  return 0;
183 }
enum ast_json_encoding_format ast_ari_json_format(void)
Configured encoding format for JSON output.
Definition: res_ari.c:806
int(* validator)(struct ast_json *)
void ast_json_free(void *p)
Asterisk&#39;s custom JSON allocator. Exposed for use by unit tests.
Definition: json.c:52
struct ast_sockaddr * ast_ari_websocket_session_get_remote_addr(struct ast_ari_websocket_session *session)
Get the remote address from an ARI WebSocket.
int AST_OPTIONAL_API_NAME() ast_websocket_write_string(struct ast_websocket *ws, const char *buf)
const char * str
Definition: app_jack.c:147
#define NULL
Definition: resample.c:96
#define ast_log
Definition: astobj2.c:42
#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:911
#define VALIDATION_FAILED
struct ast_websocket * ws_session
char * ast_json_dump_string_format(struct ast_json *root, enum ast_json_encoding_format format)
Encode a JSON value to a string.
Definition: json.c:463
#define LOG_ERROR
Definition: logger.h:285
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
#define LOG_NOTICE
Definition: logger.h:263

◆ null_validator()

static int null_validator ( struct ast_json json)
static

Validator that always succeeds.

Definition at line 49 of file ari_websockets.c.

Referenced by ast_ari_websocket_session_create().

50 {
51  return 1;
52 }

◆ websocket_session_dtor()

static void websocket_session_dtor ( void *  obj)
static

Definition at line 38 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().

39 {
40  struct ast_ari_websocket_session *session = obj;
41 
43  session->ws_session = NULL;
44 }
#define NULL
Definition: resample.c:96
static struct ast_mansession session
struct ast_websocket * ws_session
void AST_OPTIONAL_API_NAME() ast_websocket_unref(struct ast_websocket *session)