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

Internal API's for websockets. More...

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

Go to the source code of this file.

Data Structures

struct  ari_ws_session
 

Functions

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. More...
 
int ari_websocket_load_module (void)
 
int ari_websocket_process_request (struct ari_ws_session *ast_ws_session, const char *remote_addr, struct ast_variable *upgrade_headers, const char *app_name, struct ast_json *msg)
 
void ari_websocket_send_event (struct ari_ws_session *ari_ws_session, const char *app_name, struct ast_json *message, int debug_app)
 Callback handler for Stasis application messages. More...
 
int ari_websocket_unload_module (void)
 

Detailed Description

Internal API's for websockets.

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

Definition in file ari_websockets.h.

Function Documentation

◆ ari_handle_websocket()

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.

Parameters
ws_serverWebSocket server to invoke.
serHTTP session.
uriRequested URI.
methodRequested HTTP method.
get_paramsParsed query parameters.
headersParsed HTTP headers.

Definition at line 221 of file ari_websockets.c.

225{
226 struct ast_http_uri fake_urih = {
228 };
229
230 ast_websocket_uri_cb(ser, &fake_urih, uri, method, get_params,
231 headers);
232}
struct ast_websocket_server * ast_ws_server
int 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)
Callback suitable for use with a ast_http_uri.
const char * method
Definition: res_pjsip.c:1279
Definition of a URI handler.
Definition: http.h:102
const char * uri
Definition: http.h:105
void * data
Definition: http.h:116

References ast_websocket_uri_cb(), ast_ws_server, ast_http_uri::data, method, and ast_http_uri::uri.

Referenced by ast_ari_invoke().

◆ ari_websocket_load_module()

int ari_websocket_load_module ( void  )

Definition at line 722 of file ari_websockets.c.

723{
724 int res = 0;
725 struct ast_websocket_protocol *protocol;
726
728 ARI_WS_SESSION_NUM_BUCKETS, ari_ws_session_hash_fn,
729 NULL, ari_ws_session_cmp_fn);
732 "Failed to allocate the local registry for websocket applications\n");
734 }
735
737 if (!ast_ws_server) {
740 }
741
742 protocol = ast_websocket_sub_protocol_alloc("ari");
743 if (!protocol) {
748 }
752
754}
static int websocket_attempted_cb(struct ast_tcptls_session_instance *ser, struct ast_variable *get_params, struct ast_variable *headers, const char *session_id)
static struct ao2_container * ari_ws_session_registry
Local registry for created event_session objects.
static void websocket_established_cb(struct ast_websocket *ast_ws_session, struct ast_variable *get_params, struct ast_variable *upgrade_headers)
static void ari_ws_session_registry_dtor(void)
#define ARI_WS_SESSION_NUM_BUCKETS
#define ast_log
Definition: astobj2.c:42
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
struct ast_websocket_protocol * ast_websocket_sub_protocol_alloc(const char *name)
Allocate a websocket sub-protocol instance.
int ast_websocket_server_add_protocol2(struct ast_websocket_server *server, struct ast_websocket_protocol *protocol)
Add a sub-protocol handler to the given server.
struct ast_websocket_server * ast_websocket_server_create(void)
Creates a ast_websocket_server.
#define LOG_WARNING
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define NULL
Definition: resample.c:96
A websocket protocol implementation.
ast_websocket_callback session_established
Callback called when a new session is established. Mandatory.
ast_websocket_pre_callback session_attempted
Callback called when a new session is attempted. Optional.

References AO2_ALLOC_OPT_LOCK_MUTEX, ao2_container_alloc_hash, ao2_ref, ARI_WS_SESSION_NUM_BUCKETS, ari_ws_session_registry, ari_ws_session_registry_dtor(), ast_log, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_websocket_server_add_protocol2(), ast_websocket_server_create(), ast_websocket_sub_protocol_alloc(), ast_ws_server, LOG_WARNING, NULL, ast_websocket_protocol::session_attempted, ast_websocket_protocol::session_established, websocket_attempted_cb(), and websocket_established_cb().

Referenced by load_module().

◆ ari_websocket_process_request()

int ari_websocket_process_request ( struct ari_ws_session ast_ws_session,
const char *  remote_addr,
struct ast_variable upgrade_headers,
const char *  app_name,
struct ast_json msg 
)

Definition at line 261 of file ari_websocket_requests.c.

264{
265 int debug_app = stasis_app_get_debug_by_name(app_name);
267 struct ast_ari_response response = { .fd = -1, 0 };
268
269 SCOPE_ENTER(3, "%s: New WebSocket Msg\n", remote_addr);
270
271 if (TRACE_ATLEAST(3) || debug_app) {
272 char *str = ast_json_dump_string_format(request_msg, AST_JSON_PRETTY);
273 /* If we can't allocate a string, we can't respond to the client either. */
274 if (!str) {
275 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR, "%s: Failed to dump JSON request\n",
276 remote_addr);
277 }
278 ast_verbose("<--- Received ARI message from %s --->\n%s\n",
279 remote_addr, str);
281 }
282
284 parse_rest_request_msg, remote_addr, request_msg, &response, debug_app);
285
286 if (!request || response.response_code != 200) {
288 remote_addr, app_name, request, &response, debug_app);
289 SCOPE_EXIT_RTN_VALUE(0, "%s: Done with message\n", remote_addr);
290 }
291
292 /*
293 * We don't actually use the headers in the response
294 * but we have to allocate it because ast_ari_invoke
295 * and the resource handlers expect it.
296 */
297 response.headers = ast_str_create(80);
298 if (!response.headers) {
299 /* If we can't allocate a string, we can't respond to the client either. */
300 SCOPE_EXIT_LOG_RTN_VALUE(-1, LOG_ERROR, "%s: Failed allocate headers string\n",
301 remote_addr);
302 }
303
305 NULL, request->uri, request->method, request->query_strings,
306 upgrade_headers, request->body, &response);
307
308 ast_free(response.headers);
309
310 if (response.no_response) {
311 SCOPE_EXIT_RTN_VALUE(0, "No response needed\n");
312 }
313
315 remote_addr, app_name, request, &response, debug_app);
316
317 SCOPE_EXIT_RTN_VALUE(0, "%s: Done with message\n", remote_addr);
318}
const char * str
Definition: app_jack.c:150
@ ARI_INVOKE_SOURCE_WEBSOCKET
Definition: ari.h:149
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: res_ari.c:635
static struct rest_request_msg * parse_rest_request_msg(const char *remote_addr, struct ast_json *request_msg, struct ast_ari_response *response, int debug_app)
static void request_destroy(struct rest_request_msg *request)
static void send_rest_response(struct ari_ws_session *ari_ws_session, const char *remote_addr, const char *app_name, struct rest_request_msg *request, struct ast_ari_response *response, int debug_app)
#define ast_free(a)
Definition: astmm.h:180
static int request(void *obj)
Definition: chan_pjsip.c:2605
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2206
#define TRACE_ATLEAST(level)
#define SCOPE_EXIT_RTN_VALUE(__return_value,...)
#define SCOPE_EXIT_LOG_RTN_VALUE(__value, __log_level,...)
#define SCOPE_CALL_WITH_RESULT(level, __var, __funcname,...)
#define SCOPE_ENTER(level,...)
#define SCOPE_CALL(level, __funcname,...)
#define LOG_ERROR
void ast_json_free(void *p)
Asterisk's custom JSON allocator. Exposed for use by unit tests.
Definition: json.c:52
@ AST_JSON_PRETTY
Definition: json.h:795
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:484
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
int stasis_app_get_debug_by_name(const char *app_name)
Get debug status of an application.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
struct ast_str * headers
Definition: ari.h:105
int response_code
Definition: ari.h:108
unsigned int no_response
Definition: ari.h:114
#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 app_name(), ARI_INVOKE_SOURCE_WEBSOCKET, ast_ari_invoke(), ast_free, ast_json_dump_string_format(), ast_json_free(), AST_JSON_PRETTY, ast_str_create, ast_verbose(), ast_ari_response::fd, ast_ari_response::headers, LOG_ERROR, ast_ari_response::no_response, NULL, parse_rest_request_msg(), RAII_VAR, request(), request_destroy(), ast_ari_response::response_code, SCOPE_CALL, SCOPE_CALL_WITH_RESULT, SCOPE_ENTER, SCOPE_EXIT_LOG_RTN_VALUE, SCOPE_EXIT_RTN_VALUE, send_rest_response(), stasis_app_get_debug_by_name(), str, and TRACE_ATLEAST.

Referenced by websocket_established_cb().

◆ ari_websocket_send_event()

void ari_websocket_send_event ( struct ari_ws_session ari_ws_session,
const char *  app_name,
struct ast_json message,
int  debug_app 
)

Callback handler for Stasis application messages.

Definition at line 244 of file ari_websockets.c.

246{
247 char *remote_addr = ast_sockaddr_stringify(
249 const char *msg_type, *msg_application, *msg_timestamp, *msg_ast_id;
250 SCOPE_ENTER(4, "%s: Dispatching message from Stasis app '%s'\n", remote_addr, app_name);
251
253
255
256 msg_type = S_OR(ast_json_string_get(ast_json_object_get(message, "type")), "");
257 msg_application = S_OR(
258 ast_json_string_get(ast_json_object_get(message, "application")), "");
259
260 /* If we've been replaced, remove the application from our local
261 websocket_apps container */
262 if (strcmp(msg_type, "ApplicationReplaced") == 0 &&
263 strcmp(msg_application, app_name) == 0) {
264 ao2_find(ari_ws_session->websocket_apps, msg_application,
266 }
267
274 "%s: Failed to dispatch '%s' message from Stasis app '%s'; could not update message\n",
275 remote_addr, msg_type, msg_application);
276 }
277 }
278
279 msg_ast_id = S_OR(
280 ast_json_string_get(ast_json_object_get(message, "asterisk_id")), "");
281 if (ast_strlen_zero(msg_ast_id)) {
282 char eid[20];
283
284 if (ast_json_object_set(message, "asterisk_id",
288 "%s: Failed to dispatch '%s' message from Stasis app '%s'; could not update message\n",
289 remote_addr, msg_type, msg_application);
290 }
291 }
292
293 /* Now, we need to determine our state to see how we will handle the message */
297 "%s: Failed to dispatch '%s' message from Stasis app '%s'; could not update message\n",
298 remote_addr, msg_type, msg_application);
299 }
300
301 if (!ari_ws_session) {
302 /* If the websocket is NULL, the message goes to the queue */
305 }
307 "%s: Queued '%s' message for Stasis app '%s'; websocket is not ready\n",
308 remote_addr,
309 msg_type,
310 msg_application);
312
313 if (TRACE_ATLEAST(4) || debug_app) {
315
316 ast_verbose("<--- Sending ARI event to %s --->\n%s\n",
317 remote_addr,
318 str);
320 }
321
323 }
324
326 SCOPE_EXIT("%s: Dispatched '%s' message from Stasis app '%s'\n",
327 remote_addr, msg_type, app_name);
328}
static int ari_ws_session_write(struct ari_ws_session *ari_ws_session, struct ast_json *message)
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
#define ao2_unlock(a)
Definition: astobj2.h:729
#define ao2_lock(a)
Definition: astobj2.h:717
@ OBJ_NODATA
Definition: astobj2.h:1044
@ OBJ_UNLINK
Definition: astobj2.h:1039
#define SCOPE_EXIT(...)
#define SCOPE_EXIT_LOG_RTN(__log_level,...)
struct ast_sockaddr * ast_websocket_remote_address(struct ast_websocket *session)
Get the remote address for a WebSocket connected session.
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
Definition: json.c:278
struct ast_json * ast_json_timeval(const struct timeval tv, const char *zone)
Construct a timeval as JSON.
Definition: json.c:670
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
Definition: json.c:67
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
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:283
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
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:256
static struct timeval msg_timestamp(void *msg, enum smdi_message_type type)
Definition: res_smdi.c:366
int stasis_app_event_allowed(const char *app_name, struct ast_json *event)
Check if the given event should be filtered.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
struct ari_ws_session::@424 message_queue
struct ao2_container * websocket_apps
struct ast_websocket * ast_ws_session
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
#define ast_assert(a)
Definition: utils.h:739
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: utils.c:2839
struct ast_eid ast_eid_default
Global EID.
Definition: options.c:93
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:256

References ao2_find, ao2_lock, ao2_unlock, app_name(), ari_ws_session_write(), ast_assert, ast_eid_default, ast_eid_to_str(), ast_json_dump_string_format(), ast_json_free(), ast_json_object_get(), ast_json_object_set(), AST_JSON_PRETTY, ast_json_ref(), ast_json_string_create(), ast_json_string_get(), ast_json_timeval(), ast_log, ast_sockaddr_stringify(), ast_strlen_zero(), ast_tvnow(), AST_VECTOR_APPEND, ast_verbose(), ast_websocket_remote_address(), ari_ws_session::ast_ws_session, LOG_WARNING, ari_ws_session::message_queue, msg_timestamp(), NULL, OBJ_NODATA, OBJ_UNLINK, S_OR, SCOPE_ENTER, SCOPE_EXIT, SCOPE_EXIT_LOG_RTN, stasis_app_event_allowed(), str, TRACE_ATLEAST, and ari_ws_session::websocket_apps.

Referenced by ari_ws_session_read(), send_rest_response(), and stasis_app_message_handler().

◆ ari_websocket_unload_module()

int ari_websocket_unload_module ( void  )

Definition at line 711 of file ari_websockets.c.

712{
716 return 0;
717}
#define ao2_cleanup(obj)
Definition: astobj2.h:1934

References ao2_cleanup, ari_ws_session_registry_dtor(), ast_ws_server, and NULL.

Referenced by unload_module().