122#define WS_TIMER_FDNO (AST_EXTENDED_FDS + 1)
123#define WS_WEBSOCKET_FDNO (AST_EXTENDED_FDS + 2)
125#define MEDIA_WEBSOCKET_OPTIMAL_FRAME_SIZE "MEDIA_WEBSOCKET_OPTIMAL_FRAME_SIZE"
126#define MEDIA_WEBSOCKET_CONNECTION_ID "MEDIA_WEBSOCKET_CONNECTION_ID"
127#define INCOMING_CONNECTION_ID "INCOMING"
129#define ANSWER_CHANNEL "ANSWER"
130#define HANGUP_CHANNEL "HANGUP"
131#define START_MEDIA_BUFFERING "START_MEDIA_BUFFERING"
132#define STOP_MEDIA_BUFFERING "STOP_MEDIA_BUFFERING"
133#define MARK_MEDIA "MARK_MEDIA"
134#define FLUSH_MEDIA "FLUSH_MEDIA"
135#define GET_DRIVER_STATUS "GET_STATUS"
136#define REPORT_QUEUE_DRAINED "REPORT_QUEUE_DRAINED"
137#define PAUSE_MEDIA "PAUSE_MEDIA"
138#define CONTINUE_MEDIA "CONTINUE_MEDIA"
139#define SET_MEDIA_DIRECTION "SET_MEDIA_DIRECTION"
141#define QUEUE_LENGTH_MAX 1000
142#define QUEUE_LENGTH_XOFF_LEVEL 900
143#define QUEUE_LENGTH_XON_LEVEL 800
144#define MAX_TEXT_MESSAGE_LEN MIN(128, (AST_WEBSOCKET_MAX_RX_PAYLOAD_SIZE - 1))
158#define websocket_request_hangup(_instance, _cause, _tech) \
159 _websocket_request_hangup(_instance, _cause, _tech, __LINE__, __FUNCTION__)
163 .description =
"Media over WebSocket Channel Driver",
200 char *payload =
NULL;
217#define _create_event_MEDIA_XON(_instance) _create_event_nodata(_instance, "MEDIA_XON");
218#define _create_event_MEDIA_XOFF(_instance) _create_event_nodata(_instance, "MEDIA_XOFF");
219#define _create_event_QUEUE_DRAINED(_instance) _create_event_nodata(_instance, "QUEUE_DRAINED");
228 char *payload =
NULL;
232 "event",
"MEDIA_START",
248 ast_asprintf(&payload,
"%s %s:%s %s:%s %s:%s %s:%s %s:%d %s:%d",
270 char *payload =
NULL;
273 "event",
"MEDIA_BUFFERING_COMPLETED",
275 "correlation_id",
S_OR(
id,
"")
284 "MEDIA_BUFFERING_COMPLETED",
300 char *payload =
NULL;
303 "event",
"MEDIA_MARK_PROCESSED",
305 "correlation_id",
S_OR(
id,
"")
314 "MEDIA_MARK_PROCESSED",
330 char *payload =
NULL;
357 char *payload =
NULL;
376 ast_asprintf(&payload,
"%s channel_id:%s queue_length:%d xon_level:%d xoff_level:%d queue_full:%s bulk_media:%s media_paused:%s",
398 char *payload =
NULL;
399 char *error_text =
NULL;
403 va_start(ap, format);
406 if (res < 0 || !error_text) {
414 "error_text", error_text);
422 ast_asprintf(&payload,
"%s channel_id:%s error_text:%s",
434#define create_event(_instance, _event, ...) \
435 _create_event_ ## _event(_instance, ##__VA_ARGS__)
441#define send_event(_instance, _event, ...) \
444 char *_payload = _create_event_ ## _event(_instance, ##__VA_ARGS__); \
445 if (_payload && _instance->websocket) { \
446 _res = ast_websocket_write_string(_instance->websocket, _payload); \
448 ast_log(LOG_ERROR, "%s: Unable to send event %s\n", \
449 ast_channel_name(instance->channel), _payload); \
451 ast_debug(3, "%s: Sent %s\n", \
452 ast_channel_name(instance->channel), _payload); \
454 ast_free(_payload); \
488 ast_debug(4,
"%s: WebSocket sending MEDIA_XON\n",
504 ast_debug(4,
"%s: WebSocket sending QUEUE_DRAINED\n",
608 ast_debug(4,
"%s: WebSocket read timer fired with no frame available. Returning NULL frame.\n",
617 char *buffer,
size_t len)
672 ast_debug(4,
"%s: Queued '%s' option frame\n",
678#define ERROR_ON_PASSTHROUGH_MODE_RTN(instance, command) \
680 if (instance->passthrough) { \
681 send_event(instance, ERROR, "%s not supported in passthrough mode", command); \
682 ast_debug(4, "%s: WebSocket in passthrough mode. Ignoring %s command.\n", \
683 ast_channel_name(instance->channel), command); \
688#define ERROR_ON_INVALID_MEDIA_DIRECTION_RTN(instance, command, direction) \
690 if (instance->media_direction == direction) { \
691 send_event(instance, ERROR, "%s not supported while media direction " \
692 "is '%s'", command, websocket_media_direction_map[direction]); \
693 ast_debug(4, "%s: WebSocket media direction is '%s'. Ignoring %s command.\n", \
694 ast_channel_name(instance->channel), websocket_media_direction_map[direction], command); \
712 const char *command =
NULL;
720 send_event(instance, ERROR,
"Unable to parse JSON command");
726 data = strchr(buffer,
' ');
761 ast_debug(4,
"%s: WebSocket %s '%s' with %d bytes in leftover_data.\n",
773 option =
create_event(instance, MEDIA_BUFFERING_COMPLETED,
id);
798 option =
create_event(instance, MEDIA_MARK_PROCESSED,
id);
849 send_event(instance, ERROR,
"%s only supports JSON format.\n", command);
855 send_event(instance, ERROR,
"%s requires a 'direction' parameter.\n", command);
864 if (!instance->
timer) {
876 if (!instance->
timer) {
888 if (instance->
timer) {
898 send_event(instance, ERROR,
"'%s' is not a valid direction for %s.\n",
912 char *payload, uint64_t payload_len)
916 if (payload_len == 0) {
923 ast_log(
LOG_WARNING,
"%s: WebSocket TEXT message of length %d exceeds maximum length of %d\n",
934 memcpy(command, payload, payload_len);
935 command[payload_len] =
'\0';
945 char *payload, uint64_t payload_len)
947 char *next_frame_ptr =
NULL;
948 size_t bytes_read = 0;
950 size_t bytes_left = 0;
956 ast_debug(4,
"%s: WebSocket queue is full. Ignoring incoming binary message.\n",
962 next_frame_ptr = payload;
982 size_t bytes_avail_to_copy =
MIN(bytes_needed_for_frame, payload_len);
988 memcpy(append_ptr, payload, bytes_avail_to_copy);
994 if (bytes_avail_to_copy < bytes_needed_for_frame) {
995 ast_debug(4,
"%s: Leftover data %d bytes but only %d new bytes available of %d needed. Appending and waiting for next message.\n",
1011 payload_len -= bytes_avail_to_copy;
1012 next_frame_ptr = payload + bytes_avail_to_copy;
1014 ast_debug(5,
"%s: --- BR: %4d FQ: %4d PL: %4d LOL: %3d P: %p NFP: %p OFF: %4d NPL: %4d BAC: %3d\n",
1018 (
int)(payload_len + bytes_avail_to_copy),
1022 (
int)(next_frame_ptr - payload),
1024 (
int)bytes_avail_to_copy
1035 bytes_left = payload_len;
1051 ast_debug(5,
"%s: +++ BR: %4d FQ: %4d PL: %4d LOL: %3d P: %p NFP: %p OFF: %4d BL: %4d\n",
1059 (
int)(next_frame_ptr - payload),
1062 memcpy(instance->
leftover_data, next_frame_ptr, bytes_left);
1071 uint64_t payload_len = 0;
1072 char *payload =
NULL;
1084 &opcode, &fragmented);
1087 ast_debug(3,
"%s: WebSocket read error\n",
1104 ast_debug(3,
"%s: WebSocket closed by remote\n",
1113 ast_debug(5,
"%s: WebSocket dropped frame (application media direction is 'in')\n",
1134 ast_debug(3,
"%s: WebSocket connection with %s established\n",
1138 IPPROTO_TCP, TCP_NODELAY, (
char *) &nodelay,
sizeof(nodelay)) < 0) {
1170 if (!instance || !instance->
channel) {
1173 ast_debug(3,
"%s:%s: Hangup requested from %s line %d. cause: %s(%d) tech_cause: %s(%d)",
1189 if (!instance || !instance->
websocket) {
1205 ast_log(
LOG_WARNING,
"%s: This WebSocket channel only supports AST_FRAME_VOICE frames\n",
1211 ast_log(
LOG_WARNING,
"%s: This WebSocket channel only supports the '%s' format, not '%s'\n",
1254 ast_debug(3,
"%s: WebSocket call requested to %s. cid: %s\n",
1285 if (instance->
timer) {
1360 instance->type = ws_type;
1363 if (!instance->client) {
1365 chan_name, instance->connection_id);
1379 instance->native_format = fmt;
1392 if (instance->native_codec->minimum_bytes <= 10) {
1393 instance->passthrough = 1;
1394 instance->optimal_frame_size = 0;
1396 instance->optimal_frame_size =
1397 (instance->native_codec->default_ms * instance->native_codec->minimum_bytes)
1398 / instance->native_codec->minimum_ms;
1399 instance->leftover_data =
ast_calloc(1, instance->optimal_frame_size);
1400 if (!instance->leftover_data) {
1406 "%s: WebSocket channel native format '%s' Sample rate: %d ptime: %dms minms: %u minbytes: %u passthrough: %d optimal_frame_size: %d\n",
1412 instance->passthrough,
1413 instance->optimal_frame_size);
1426 proxy->connection_id);
1429 ast_debug(3,
"%s: WebSocket instance created and linked\n", proxy->connection_id);
1438 if (!instance->
timer) {
1443 ast_debug(3,
"%s: WebSocket timer rate %d\n",
1457 char *pkt_size =
NULL;
1548 ast_debug(3,
"%s: WebSocket channel requested\n",
1552 ast_log(
LOG_ERROR,
"%s: A connection id is required for the 'WebSocket' channel\n",
1560 ast_log(
LOG_ERROR,
"%s: connection_id is required for the 'WebSocket' channel\n",
1569 requestor_name,
args.options);
1586 requestor_name,
args.connection_id);
1590 ast_debug(3,
"%s: Using format %s from %s\n",
1618 if (!instance->passthrough) {
1628 "%s: URI parameters are not allowed for 'WebSocket/INCOMING' channels\n",
1633 ast_debug(3,
"%s: Using URI parameters '%s'\n",
1637 ast_log(
LOG_ERROR,
"%s: Invalid URI parameters '%s' in WebSocket/%s dial string\n",
1639 args.connection_id);
1644 comma = instance->uri_params;
1652 while ((comma = strchr(comma,
','))) {
1655 ast_debug(3,
"%s: Using final URI '%s'\n", requestor_name, instance->uri_params);
1662 ast_log(
LOG_WARNING,
"%s: 'f/control message format' dialstring parameter value missing or invalid. "
1663 "Defaulting to 'plain-text'\n",
1667 }
else if (global_cfg) {
1668 instance->control_msg_format = global_cfg->control_msg_format;
1672 requestor, 0,
"WebSocket/%s/%p",
args.connection_id, instance);
1680 ast_debug(3,
"%s: WebSocket channel %s allocated for connection %s\n",
1682 instance->connection_id);
1684 instance->channel =
ao2_bump(chan);
1713 ast_debug(3,
"%s: WebSocket channel created to %s\n",
1738 ast_debug(3,
"%s: WebSocket call hangup. cid: %s\n",
1779 const char *connection_id =
NULL;
1782 ast_debug(3,
"WebSocket established\n");
1784 for (v = upgrade_headers; v; v = v->
next) {
1787 for (v = get_params; v; v = v->
next) {
1852 int destroy_get_params = (get_params ==
NULL);
1856 ast_debug(2,
"URI: %s Starting\n", uri);
1870 ast_http_error(ser, 404,
"Not found",
"WebSocket instance not found");
1877 if (instance->websocket) {
1880 ast_http_error(ser, 409,
"Conflict",
"Another websocket connection exists for this connection id");
1891 for (v = get_params; v; v = v->
next) {
1901 get_params, headers);
1902 if (destroy_get_params) {
1913 .description =
"Media over Websocket",
1934 "control_mesage_format. Must be 'plain-text' or 'json'\n",
1954 sizeof(*cfg),
NULL);
1967 ast_debug(1,
"control_msg_format: %s\n",
1975 ast_debug(2,
"Initializing Websocket Client Configuration\n");
1983 "chan_websocket.conf,criteria=type=global,single_object=yes,explicit_name=global");
1986 ast_log(
LOG_ERROR,
"Failed to register chan_websocket global object with sorcery\n");
2022 ast_debug(2,
"Reloading chan_websocket configuration\n");
2052 instance_proxy_sort_fn, instance_proxy_cmp_fn);
2055 "Failed to allocate the chan_websocket instance registry\n");
2085 .
requires =
"res_http_websocket,res_websocket_client",
Asterisk main include file. File version handling, generic pbx functions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define ast_strdup(str)
A wrapper for strdup()
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_vasprintf(ret, fmt, ap)
A wrapper for vasprintf()
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
#define ast_calloc(num, len)
A wrapper for calloc()
#define ao2_weakproxy_set_object(weakproxy, obj, flags)
Associate weakproxy with obj.
int ao2_weakproxy_subscribe(void *weakproxy, ao2_weakproxy_notification_cb cb, void *data, int flags)
Request notification when weakproxy points to NULL.
@ AO2_ALLOC_OPT_LOCK_RWLOCK
#define AO2_STRING_FIELD_CMP_FN(stype, field)
Creates a compare function for a structure string field.
#define ao2_unlink(container, obj)
Remove an object from a container.
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
#define AO2_STRING_FIELD_SORT_FN(stype, field)
Creates a sort function for a structure string field.
#define ao2_weakproxy_find(c, arg, flags, tag)
Perform an ao2_find on a container with ao2_weakproxy objects, returning the real object.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
#define ao2_weakproxy_alloc(data_size, destructor_fn)
Allocate an ao2_weakproxy object.
#define AO2_STRING_FIELD_HASH_FN(stype, field)
Creates a hash function for a structure string field.
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
#define ao2_alloc(data_size, destructor_fn)
#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.
@ AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE
Replace objects with duplicate keys in container.
Internal Asterisk hangup causes.
#define AST_CAUSE_FAILURE
#define AST_CAUSE_NETWORK_OUT_OF_ORDER
#define AST_CAUSE_NO_ROUTE_DESTINATION
#define ERROR_ON_PASSTHROUGH_MODE_RTN(instance, command)
static void _websocket_request_hangup(struct websocket_pvt *instance, int ast_cause, enum ast_websocket_status_code tech_cause, int line, const char *function)
#define QUEUE_LENGTH_XON_LEVEL
#define send_event(_instance, _event,...)
Use this macro to create and send events passing in any event-specific parameters.
static int incoming_ws_http_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
static void instance_proxy_cb(void *weakproxy, void *data)
static struct ast_frame * dequeue_frame(struct websocket_pvt *instance)
static void * global_alloc(const char *name)
static const char * control_msg_format_to_str(enum webchan_control_msg_format value)
static int validate_uri_parameters(const char *uri_params)
static int webchan_write(struct ast_channel *ast, struct ast_frame *f)
Function called when we should write a frame to the channel.
static char * _create_event_MEDIA_BUFFERING_COMPLETED(struct websocket_pvt *instance, const char *id)
static const char * msg_format_map[]
static int webchan_hangup(struct ast_channel *ast)
static struct ast_channel_tech websocket_tech
static struct ast_frame * webchan_read(struct ast_channel *ast)
#define websocket_request_hangup(_instance, _cause, _tech)
#define MEDIA_WEBSOCKET_CONNECTION_ID
#define WS_WEBSOCKET_FDNO
static char * _create_event_MEDIA_MARK_PROCESSED(struct websocket_pvt *instance, const char *id)
static int read_from_ws_and_queue(struct websocket_pvt *instance)
webchan_control_msg_format
@ WEBCHAN_CONTROL_MSG_FORMAT_JSON
@ WEBCHAN_CONTROL_MSG_FORMAT_PLAIN
@ WEBCHAN_CONTROL_MSG_FORMAT_INVALID
static int handle_command(struct websocket_pvt *instance, char *buffer)
static int global_control_message_format_from_str(const struct aco_option *opt, struct ast_variable *var, void *obj)
static int webchan_send_dtmf_text(struct ast_channel *ast, char digit, unsigned int duration)
static struct ast_http_uri http_uri
static int reload_module(void)
#define GET_DRIVER_STATUS
static int set_channel_variables(struct websocket_pvt *instance)
@ WEBCHAN_MEDIA_DIRECTION_BOTH
@ WEBCHAN_MEDIA_DIRECTION_OUT
@ WEBCHAN_MEDIA_DIRECTION_IN
static int process_text_message(struct websocket_pvt *instance, char *payload, uint64_t payload_len)
static void websocket_destructor(void *data)
static int queue_frame_from_buffer(struct websocket_pvt *instance, char *buffer, size_t len)
static struct ast_sorcery * sorcery
#define ERROR_ON_INVALID_MEDIA_DIRECTION_RTN(instance, command, direction)
#define START_MEDIA_BUFFERING
static int set_channel_timer(struct websocket_pvt *instance)
static char * _create_event_STATUS(struct websocket_pvt *instance)
static char * _create_event_DTMF_END(struct websocket_pvt *instance, const char digit)
#define QUEUE_LENGTH_XOFF_LEVEL
static const struct ast_app_option websocket_options[128]
#define create_event(_instance, _event,...)
Use this macro to create events passing in any event-specific parameters.
static struct ao2_container * instances
static char * _create_event_ERROR(struct websocket_pvt *instance, const char *format,...)
#define MEDIA_WEBSOCKET_OPTIMAL_FRAME_SIZE
#define INCOMING_CONNECTION_ID
static struct websocket_pvt * websocket_new(const char *chan_name, const char *connection_id, struct ast_format *fmt)
#define REPORT_QUEUE_DRAINED
#define STOP_MEDIA_BUFFERING
static int load_module(void)
Function called when our module is loaded.
static const char * websocket_media_direction_map[]
static int webchan_call(struct ast_channel *ast, const char *dest, int timeout)
static enum webchan_control_msg_format control_msg_format_from_str(const char *value)
static int process_binary_message(struct websocket_pvt *instance, char *payload, uint64_t payload_len)
static struct ast_websocket_server * ast_ws_server
#define SET_MEDIA_DIRECTION
static char * _create_event_MEDIA_START(struct websocket_pvt *instance)
static int unload_module(void)
Function called when our module is unloaded.
static int global_control_message_format_to_str(const void *obj, const intptr_t *args, char **buf)
#define MAX_TEXT_MESSAGE_LEN
static void incoming_ws_established_cb(struct ast_websocket *ast_ws_session, struct ast_variable *get_params, struct ast_variable *upgrade_headers)
static int websocket_handoff_to_channel(struct websocket_pvt *instance)
static struct ast_channel * webchan_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
static char * _create_event_nodata(struct websocket_pvt *instance, char *event)
static int load_config(void)
static int global_apply(const struct ast_sorcery *sorcery, void *obj)
static int queue_option_frame(struct websocket_pvt *instance, char *buffer)
@ OPT_ARG_WS_MEDIA_DIRECTION
@ OPT_ARG_WS_NO_AUTO_ANSWER
General Asterisk PBX channel definitions.
const char * ast_channel_name(const struct ast_channel *chan)
int ast_channel_tech_hangupcause(const struct ast_channel *chan)
void * ast_channel_tech_pvt(const struct ast_channel *chan)
void ast_channel_tech_hangupcause_set(struct ast_channel *chan, int value)
struct varshead * ast_channel_varshead(struct ast_channel *chan)
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
int ast_channel_fdno(const struct ast_channel *chan)
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
const char * ast_channel_uniqueid(const struct ast_channel *chan)
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
#define ast_channel_unref(c)
Decrease channel reference count.
const char * ast_cause2str(int cause) attribute_pure
Gives the string form of a given cause code.
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
@ AST_FLAG_DISABLE_DEVSTATE_CACHE
void ast_channel_internal_fd_clear(struct ast_channel *chan, int which)
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
#define ast_channel_unlock(chan)
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
@ OPT_NOOP_T
Type for a default handler that should do nothing.
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static int uuid(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
ast_http_method
HTTP Request methods known by Asterisk.
void ast_http_uri_unlink(struct ast_http_uri *urihandler)
Unregister a URI handler.
void ast_http_error(struct ast_tcptls_session_instance *ser, int status, const char *title, const char *text)
Send HTTP error message and close socket.
int ast_http_uri_link(struct ast_http_uri *urihandler)
Register a URI handler.
Support for WebSocket connections within the Asterisk HTTP server and client WebSocket connections to...
int AST_OPTIONAL_API_NAME() ast_websocket_write(struct ast_websocket *session, enum ast_websocket_opcode opcode, char *payload, uint64_t payload_size)
Construct and transmit a WebSocket frame.
ast_websocket_status_code
Websocket Status Codes from RFC-6455.
@ AST_WEBSOCKET_STATUS_UNSUPPORTED_DATA
@ AST_WEBSOCKET_STATUS_NORMAL
@ AST_WEBSOCKET_STATUS_GOING_AWAY
@ AST_WEBSOCKET_STATUS_INTERNAL_ERROR
int AST_OPTIONAL_API_NAME() ast_websocket_server_add_protocol2(struct ast_websocket_server *server, struct ast_websocket_protocol *protocol)
Add a sub-protocol handler to the given server.
int AST_OPTIONAL_API_NAME() ast_websocket_write_string(struct ast_websocket *ws, const char *buf)
Construct and transmit a WebSocket frame containing string data.
struct ast_sockaddr *AST_OPTIONAL_API_NAME() ast_websocket_remote_address(struct ast_websocket *session)
Get the remote address for a WebSocket connected session.
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)
Callback suitable for use with a ast_http_uri.
ast_websocket_result
Result code for a websocket client.
int AST_OPTIONAL_API_NAME() ast_websocket_fd(struct ast_websocket *session)
Get the file descriptor for a WebSocket session.
ast_websocket_opcode
WebSocket operation codes.
@ AST_WEBSOCKET_OPCODE_PING
@ AST_WEBSOCKET_OPCODE_PONG
@ AST_WEBSOCKET_OPCODE_BINARY
@ AST_WEBSOCKET_OPCODE_CLOSE
@ AST_WEBSOCKET_OPCODE_TEXT
const char *AST_OPTIONAL_API_NAME() ast_websocket_status_to_str(enum ast_websocket_status_code code)
Convert a websocket status code to a string.
ast_websocket_type
WebSocket connection/configuration types.
struct ast_websocket_protocol *AST_OPTIONAL_API_NAME() ast_websocket_sub_protocol_alloc(const char *name)
Allocate a websocket sub-protocol instance.
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)
Read a WebSocket frame and handle it.
int AST_OPTIONAL_API_NAME() ast_websocket_close(struct ast_websocket *session, uint16_t reason)
Close a WebSocket session by sending a message with the CLOSE opcode and an optional code.
struct ast_websocket_server *AST_OPTIONAL_API_NAME() ast_websocket_server_create(void)
Creates a ast_websocket_server.
void AST_OPTIONAL_API_NAME() ast_websocket_unref(struct ast_websocket *session)
Decrease the reference count for a WebSocket session.
const char *AST_OPTIONAL_API_NAME() ast_websocket_result_to_str(enum ast_websocket_result result)
Convert a websocket result code to a string.
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the 'nonstandard' argument separation process for an application.
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
const char * ast_variable_find_in_list(const struct ast_variable *list, const char *variable)
Gets the value of a variable from a variable list by name.
#define ast_variable_new(name, value, filename)
#define ast_variable_list_append(head, new_var)
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Asterisk internal frame definitions.
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
void ast_frame_free(struct ast_frame *frame, int cache)
Frees a frame or list of frames.
#define AST_FRAME_SET_BUFFER(fr, _base, _ofs, _datalen)
struct ast_frame ast_null_frame
#define ast_debug(level,...)
Log a DEBUG message.
Asterisk JSON abstraction layer.
#define ast_json_object_string_get(object, key)
Get a string field from a JSON object.
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
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.
struct ast_json * ast_json_channel_vars(struct varshead *channelvars)
Construct a JSON object from a ast_var_t list.
char * ast_json_dump_string_format(struct ast_json *root, enum ast_json_encoding_format format)
Encode a JSON value to a string.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
#define AST_LIST_LOCK(head)
Locks a list.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
Asterisk locking-related definitions:
#define SCOPED_AO2WRLOCK(varname, obj)
scoped lock specialization for ao2 write locks.
#define SCOPED_LOCK(varname, lock, lockfunc, unlockfunc)
Scoped Locks.
Asterisk module definitions.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODPRI_CHANNEL_DRIVER
@ AST_MODULE_SUPPORT_CORE
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_MODULE_LOAD_SUCCESS
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Core PBX routines and definitions.
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
Sorcery Data Access Layer API.
#define ast_sorcery_unref(sorcery)
Decrease the reference count of a sorcery structure.
#define ast_sorcery_object_field_register_nodoc(sorcery, type, name, default_val, opt_type, flags,...)
Register a field within an object without documentation.
#define ast_sorcery_register_cust(object, option, def_value)
Register a custom field within an object.
void ast_sorcery_load(const struct ast_sorcery *sorcery)
Inform any wizards to load persistent objects.
void * ast_sorcery_retrieve_by_id(const struct ast_sorcery *sorcery, const char *type, const char *id)
Retrieve an object using its unique identifier.
#define ast_sorcery_object_register(sorcery, type, alloc, transform, apply)
Register an object type.
void ast_sorcery_reload(const struct ast_sorcery *sorcery)
Inform any wizards to reload persistent objects.
void * ast_sorcery_generic_alloc(size_t size, ao2_destructor_fn destructor)
Allocate a generic sorcery capable object.
#define ast_sorcery_apply_default(sorcery, type, name, data)
#define ast_sorcery_open()
Open a new sorcery structure.
int ast_strings_equal(const char *str1, const char *str2)
Compare strings for equality checking for NULL.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
static force_inline int attribute_pure ast_strlen_zero(const char *s)
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
char * ast_strsep(char **s, const char sep, uint32_t flags)
Act like strsep but ignore separators inside quotes.
Structure to pass both assignedid values to channel drivers.
Structure to describe a channel "technology", ie a channel driver See for examples:
struct ast_format_cap * capabilities
Main Channel structure associated with a channel.
Represents a media codec within Asterisk.
unsigned int default_ms
Default length of media carried (in milliseconds) in a frame.
int(* samples_count)(struct ast_frame *frame)
Retrieve the number of samples in a frame.
Structure used to handle boolean flags.
struct ast_format * format
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
enum ast_frame_type frametype
union ast_frame::@235 data
Definition of a URI handler.
ast_http_callback callback
JSON parsing error information.
Abstract JSON element (object, array, string, int, ...).
Socket address structure.
Full structure for sorcery.
describes a server instance
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
A websocket protocol implementation.
ast_websocket_callback session_established
Callback called when a new session is established. Mandatory.
Structure for a WebSocket server.
Structure definition for session.
char connection_id[0]
The name of the module owning this sorcery instance.
enum webchan_control_msg_format control_msg_format
struct ast_format * native_format
struct ast_channel * channel
int bulk_media_in_progress
enum webchan_control_msg_format control_msg_format
struct websocket_pvt::@141 frame_queue
enum ast_websocket_type type
pthread_t outbound_read_thread
struct ast_codec * native_codec
struct ast_websocket_client * client
struct ast_websocket * websocket
static struct aco_type global
Timing source management.
void ast_timer_close(struct ast_timer *handle)
Close an opened timing handle.
int ast_timer_ack(const struct ast_timer *handle, unsigned int quantity)
Acknowledge a timer event.
int ast_timer_set_rate(const struct ast_timer *handle, unsigned int rate)
Set the timing tick rate.
enum ast_timer_event ast_timer_get_event(const struct ast_timer *handle)
Retrieve timing event.
struct ast_timer * ast_timer_open(void)
Open a timer.
@ AST_TIMING_EVENT_EXPIRED
int ast_timer_fd(const struct ast_timer *handle)
Get a poll()-able file descriptor for a timer.
Support for translation of data formats. translate.c.
#define ast_test_flag(p, flag)
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
#define ARRAY_IN_BOUNDS(v, a)
Checks to see if value is within the bounds of the given array.
#define ast_set_flag(p, flag)
int ast_uri_verify_encoded(const char *string)
Verify if a string is valid as a URI component.
Universally unique identifier support.
char * ast_uuid_generate_str(char *buf, size_t size)
Generate a UUID string.
void ast_websocket_client_add_uri_params(struct ast_websocket_client *wc, const char *uri_params)
Add additional parameters to the URI.
struct ast_websocket_client * ast_websocket_client_retrieve_by_id(const char *id)
Retrieve a websocket client object by ID.
struct ast_websocket * ast_websocket_client_connect(struct ast_websocket_client *wc, void *lock_obj, const char *display_name, enum ast_websocket_result *result)
Connect to a websocket server using the configured authentication, retry and TLS options.