39 #include "asterisk/stasis_channels.h"
118 #define NUM_MULTI_CHANNEL_BLOB_BUCKETS 7
131 return channel_topic_all;
136 return ao2_bump(channel_cache_by_name);
143 static int channel_snapshot_hash_cb(
const void *obj,
const int flags)
153 key =
object->base->name;
166 static int channel_snapshot_cmp_cb(
void *obj,
void *arg,
int flags)
170 const char *right_key = arg;
175 right_key = object_right->
base->
name;
177 cmp = strcasecmp(object_left->
base->
name, right_key);
180 cmp = strncasecmp(object_left->
base->
name, right_key, strlen(right_key));
196 static int channel_snapshot_uniqueid_hash_cb(
const void *obj,
const int flags)
201 switch (flags & OBJ_SEARCH_MASK) {
206 key =
object->base->uniqueid;
219 static int channel_snapshot_uniqueid_cmp_cb(
void *obj,
void *arg,
int flags)
223 const char *right_key = arg;
226 switch (flags & OBJ_SEARCH_MASK) {
230 cmp = strcasecmp(object_left->
base->
uniqueid, right_key);
233 cmp = strncasecmp(object_left->
base->
uniqueid, right_key, strlen(right_key));
245 static void channel_snapshot_dtor(
void *obj)
249 ao2_cleanup(snapshot->
base);
250 ao2_cleanup(snapshot->
peer);
251 ao2_cleanup(snapshot->
caller);
253 ao2_cleanup(snapshot->
bridge);
255 ao2_cleanup(snapshot->
hangup);
260 static void channel_snapshot_base_dtor(
void *obj)
271 snapshot = ao2_alloc_options(
sizeof(*snapshot), channel_snapshot_base_dtor,
289 snapshot->
creationtime = ast_channel_creationtime(chan);
301 const char *
linkedid =
S_OR(ast_channel_linkedid(chan),
"");
302 const char *peeraccount =
S_OR(ast_channel_peeraccount(chan),
"");
303 size_t linkedid_len = strlen(linkedid) + 1;
304 size_t peeraccount_len = strlen(peeraccount) + 1;
312 strcpy(snapshot->
account, peeraccount);
319 static void channel_snapshot_caller_dtor(
void *obj)
330 snapshot = ao2_alloc_options(
sizeof(*snapshot), channel_snapshot_caller_dtor,
342 S_COR(ast_channel_caller(chan)->
id.
name.valid, ast_channel_caller(chan)->
id.
name.str,
""));
344 S_COR(ast_channel_caller(chan)->
id.
number.valid, ast_channel_caller(chan)->
id.
number.str,
""));
346 S_COR(ast_channel_caller(chan)->
id.subaddress.valid, ast_channel_caller(chan)->
id.subaddress.str,
""));
348 S_COR(ast_channel_caller(chan)->
ani.number.valid, ast_channel_caller(chan)->
ani.number.str,
""));
351 S_COR(ast_channel_redirecting(chan)->from.number.valid, ast_channel_redirecting(chan)->from.number.str,
""));
354 S_OR(ast_channel_dialed(chan)->
number.str,
""));
356 S_COR(ast_channel_dialed(chan)->subaddress.valid, ast_channel_dialed(chan)->subaddress.
str,
""));
365 const char *
name =
S_COR(ast_channel_connected(chan)->
id.name.valid, ast_channel_connected(chan)->
id.name.str,
"");
366 const char *
number =
S_COR(ast_channel_connected(chan)->
id.number.valid, ast_channel_connected(chan)->
id.number.str,
"");
367 size_t name_len = strlen(name) + 1;
368 size_t number_len = strlen(number) + 1;
376 strcpy(snapshot->
name, name);
385 const char *uniqueid =
"";
400 strcpy(snapshot->
id, uniqueid);
405 static void channel_snapshot_dialplan_dtor(
void *obj)
416 snapshot = ao2_alloc_options(
sizeof(*snapshot), channel_snapshot_dialplan_dtor,
427 if (ast_channel_appl(chan)) {
430 if (ast_channel_data(chan)) {
435 snapshot->
priority = ast_channel_priority(chan);
442 const char *hangupsource =
S_OR(ast_channel_hangupsource(chan),
"");
450 snapshot->
cause = ast_channel_hangupcause(chan);
451 strcpy(snapshot->
source, hangupsource);
466 snapshot = ao2_alloc_options(
sizeof(*snapshot), channel_snapshot_dtor,
481 snapshot->
base = channel_snapshot_base_create(chan);
482 if (!snapshot->
base) {
492 snapshot->
peer = channel_snapshot_peer_create(chan);
493 if (!snapshot->
peer) {
506 snapshot->
caller = channel_snapshot_caller_create(chan);
512 snapshot->
connected = channel_snapshot_connected_create(chan);
520 snapshot->
bridge = channel_snapshot_bridge_create(chan);
531 snapshot->
dialplan = channel_snapshot_dialplan_create(chan);
542 snapshot->
hangup = channel_snapshot_hangup_create(chan);
552 snapshot->
amaflags = ast_channel_amaflags(chan);
553 ast_copy_flags(&snapshot->
flags, ast_channel_flags(chan), 0xFFFFFFFF);
554 ast_set_flag(&snapshot->
softhangup_flags, ast_channel_softhangup_internal_flag(chan));
563 static void channel_snapshot_update_dtor(
void *obj)
575 update = ao2_alloc_options(
sizeof(*update), channel_snapshot_update_dtor,
600 static void channel_blob_dtor(
void *obj)
603 ao2_cleanup(
event->snapshot);
607 static void ast_channel_publish_dial_internal(
struct ast_channel *caller,
609 const char *dialstatus,
const char *forward)
620 ast_assert(peer != NULL);
623 "dialstatus",
S_OR(dialstatus,
""),
624 "forward",
S_OR(forward,
""),
625 "dialstring",
S_OR(dialstring,
""));
638 ast_channel_lock(caller);
639 if (ast_strlen_zero(dialstatus)) {
644 ast_channel_unlock(caller);
645 if (!caller_snapshot) {
653 ast_channel_lock(peer);
654 if (ast_strlen_zero(dialstatus)) {
659 ast_channel_unlock(peer);
660 if (!peer_snapshot) {
670 ast_channel_lock(forwarded);
672 ast_channel_unlock(forwarded);
673 if (!forwarded_snapshot) {
678 ao2_ref(forwarded_snapshot, -1);
684 publish_message_for_channel_topics(msg, caller ?: peer);
689 static void remove_dial_masquerade(
struct ast_channel *peer);
690 static void remove_dial_masquerade_caller(
struct ast_channel *caller);
691 static int set_dial_masquerade(
struct ast_channel *caller,
695 struct ast_channel *forwarded,
const char *dialstring,
const char *dialstatus,
698 ast_assert(peer != NULL);
712 for (;; ast_channel_unlock(caller), sched_yield()) {
713 ast_channel_lock(caller);
714 if (ast_channel_trylock(peer)) {
717 if (forwarded && ast_channel_trylock(forwarded)) {
718 ast_channel_unlock(peer);
724 if (ast_strlen_zero(dialstatus)) {
725 set_dial_masquerade(caller, peer, dialstring);
727 remove_dial_masquerade(peer);
731 ast_channel_publish_dial_internal(caller, peer, forwarded, dialstring, dialstatus,
736 ast_channel_unlock(forwarded);
738 ast_channel_unlock(peer);
739 remove_dial_masquerade_caller(caller);
740 ast_channel_unlock(caller);
745 const char *dialstring,
const char *dialstatus)
757 obj = ao2_alloc(
sizeof(*obj), channel_blob_dtor);
788 msg = create_channel_blob_message(snapshot, type, blob);
789 ao2_cleanup(snapshot);
804 msg = create_channel_blob_message(snapshot, type, blob);
805 ao2_cleanup(snapshot);
825 static int channel_role_cmp_cb(
void *obj,
void *arg,
int flags)
829 const char *right_key = arg;
832 switch (flags & OBJ_SEARCH_MASK) {
834 right_key = object_right->
role;
836 cmp = strcasecmp(object_left->
role, right_key);
839 cmp = strncasecmp(object_left->
role, right_key, strlen(right_key));
855 static int channel_role_hash_cb(
const void *obj,
const int flags)
860 switch (flags & OBJ_SEARCH_MASK) {
878 static void multi_channel_blob_dtor(
void *obj)
890 ast_assert(blob != NULL);
892 obj = ao2_alloc(
sizeof(*obj), multi_channel_blob_dtor);
898 NUM_MULTI_CHANNEL_BLOB_BUCKETS, channel_role_hash_cb, NULL, channel_role_cmp_cb);
910 ast_assert(!ast_strlen_zero(uniqueid));
917 ast_assert(!ast_strlen_zero(name));
931 update = channel_snapshot_update_create(chan);
948 ast_channel_snapshot_set(chan, NULL);
954 static void channel_role_snapshot_dtor(
void *obj)
958 ao2_cleanup(role_snapshot->
snapshot);
964 int role_len = strlen(role) + 1;
966 if (!obj || ast_strlen_zero(role) || !snapshot) {
970 role_snapshot = ao2_alloc_options(
sizeof(*role_snapshot) + role_len,
972 if (!role_snapshot) {
987 if (!obj || ast_strlen_zero(role)) {
992 if (!role_snapshot) {
1007 if (!obj || ast_strlen_zero(role)) {
1012 NUM_MULTI_CHANNEL_BLOB_BUCKETS,
1013 channel_snapshot_hash_cb, NULL, channel_snapshot_cmp_cb);
1014 if (!ret_container) {
1021 if (!it_role_snapshots) {
1026 while ((role_snapshot = ao2_iterator_next(it_role_snapshots))) {
1032 return ret_container;
1057 ast_set_flag(ast_channel_snapshot_segment_flags(chan), segment);
1073 update = channel_snapshot_update_create(chan);
1098 ao2_wrlock(channel_cache);
1102 ao2_unlock(channel_cache);
1105 ao2_wrlock(channel_cache_by_name);
1109 ao2_unlock(channel_cache_by_name);
1116 ast_clear_flag(ast_channel_snapshot_segment_flags(chan), AST_FLAGS_ALL);
1157 char *new_value = NULL;
1158 size_t new_value_size = 0;
1160 ast_assert(name != NULL);
1161 ast_assert(value != NULL);
1168 value, strlen(value));
1175 new_value = (
char *)value;
1184 value, strlen(value));
1186 ast_log(LOG_WARNING,
"%s: The contents of variable '%s' had invalid UTF-8 sequences which were replaced",
1187 ast_channel_name(chan), name);
1192 "value", new_value);
1194 ast_log(LOG_ERROR,
"Error creating message\n");
1210 struct ast_str *channel_event_string;
1212 const char *variable =
1229 "Uniqueid: none\r\n");
1231 if (!channel_event_string) {
1241 ast_free(channel_event_string);
1248 struct ast_str *channel_string;
1254 if (!channel_string) {
1262 ast_free(channel_string);
1268 struct ast_str *channel_string;
1275 if (!channel_string) {
1282 "Logintime: %ld\r\n",
1284 ast_free(channel_string);
1294 if (snapshot == NULL
1303 "{ s: s, s: s, s: s, s: s,"
1304 " s: o, s: o, s: s,"
1305 " s: o, s: o, s: s }",
1310 "protocol_id", snapshot->
base->protocol_id,
1339 ast_assert(old_snapshot != NULL);
1340 ast_assert(new_snapshot != NULL);
1360 ast_assert(old_snapshot != NULL);
1361 ast_assert(new_snapshot != NULL);
1370 ast_assert(old_snapshot != NULL);
1371 ast_assert(new_snapshot != NULL);
1376 static struct ast_json *channel_blob_to_json(
1407 if (!json_channel) {
1423 static struct ast_json *dtmf_end_to_json(
1430 const char *direction =
1440 if (strcasecmp(
"Received", direction) != 0) {
1445 if (!json_channel) {
1450 "type",
"ChannelDtmfReceived",
1454 "channel", json_channel);
1457 static struct ast_json *varset_to_json(
1461 return channel_blob_to_json(message,
"ChannelVarset", sanitize);
1464 static struct ast_json *hangup_request_to_json(
1468 return channel_blob_to_json(message,
"ChannelHangupRequest", sanitize);
1471 static struct ast_json *dial_to_json(
1477 const char *dialstatus =
1479 const char *forward =
1481 const char *dialstring =
1493 "dialstatus", dialstatus,
1495 "dialstring", dialstring);
1509 if (forwarded_json) {
1523 struct ast_str *channel_string;
1528 if (!channel_string) {
1534 ast_free(channel_string);
1542 return channel_blob_to_json(message,
"ChannelTalkingStarted", sanitize);
1547 struct ast_str *channel_string;
1553 if (!channel_string) {
1562 ast_free(channel_string);
1570 return channel_blob_to_json(message,
"ChannelTalkingFinished", sanitize);
1584 if (!json_channel) {
1589 "type",
"ChannelHold",
1591 "musicclass",
S_OR(musicclass,
"N/A"),
1592 "channel", json_channel);
1604 if (!json_channel) {
1609 "type",
"ChannelUnhold",
1611 "channel", json_channel);
1619 .to_json = dial_to_json,
1622 .to_ami = varset_to_ami,
1623 .to_json = varset_to_json,
1626 .to_json = hangup_request_to_json,
1631 .to_json = dtmf_end_to_json,
1634 .to_json = hold_to_json,
1637 .to_json = unhold_to_json,
1651 .to_ami = agent_login_to_ami,
1654 .to_ami = agent_logoff_to_ami,
1657 .to_ami = talking_start_to_ami,
1658 .to_json = talking_start_to_json,
1661 .to_ami = talking_stop_to_ami,
1662 .to_json = talking_stop_to_json,
1667 static void stasis_channels_cleanup(
void)
1669 ao2_cleanup(channel_topic_all);
1670 channel_topic_all = NULL;
1671 ao2_cleanup(channel_cache);
1672 channel_cache = NULL;
1673 ao2_cleanup(channel_cache_by_name);
1674 channel_cache_by_name = NULL;
1709 if (!channel_topic_all) {
1715 NULL, channel_snapshot_uniqueid_cmp_cb);
1716 if (!channel_cache) {
1722 NULL, channel_snapshot_cmp_cb);
1723 if (!channel_cache_by_name) {
1768 static
void dial_target_free(struct
dial_target *doomed)
1773 ast_free(doomed->dialstring);
1795 dial_target_free(cur);
1803 ao2_lock(masq_data);
1804 if (masq_data->
caller == chan) {
1805 dial_masquerade_datastore_cleanup(masq_data);
1808 if (cur->
peer == chan) {
1810 dial_target_free(cur);
1816 ao2_unlock(masq_data);
1819 static void dial_masquerade_datastore_dtor(
void *vdoomed)
1821 dial_masquerade_datastore_cleanup(vdoomed);
1829 dial_masquerade_datastore_dtor);
1841 static void dial_masquerade_datastore_destroy(
void *data)
1850 static void dial_masquerade_caller_datastore_destroy(
void *data)
1852 dial_masquerade_datastore_cleanup(data);
1864 ao2_lock(masq_data);
1865 if (!masq_data->
caller) {
1867 }
else if (masq_data->
caller == old_chan) {
1869 ast_debug(1,
"Caller channel %s being masqueraded out to %s (is_empty:%d)\n",
1870 ast_channel_name(new_chan), ast_channel_name(old_chan),
1873 ast_channel_publish_dial_internal(new_chan, cur->
peer, NULL,
1875 ast_channel_publish_dial_internal(old_chan, cur->
peer, NULL,
1878 dial_masquerade_datastore_cleanup(masq_data);
1882 if (cur->
peer == old_chan) {
1883 ast_debug(1,
"Peer channel %s being masqueraded out to %s\n",
1884 ast_channel_name(new_chan), ast_channel_name(old_chan));
1885 ast_channel_publish_dial_internal(masq_data->
caller, new_chan, NULL,
1887 ast_channel_publish_dial_internal(masq_data->
caller, old_chan, NULL,
1891 dial_target_free(cur);
1897 ao2_unlock(masq_data);
1900 datastore = dial_masquerade_datastore_find(old_chan);
1917 static void dial_masquerade_breakdown(
void *data,
struct ast_channel *old_chan,
struct ast_channel *new_chan)
1922 ao2_lock(masq_data);
1924 if (!masq_data->
caller) {
1925 ao2_unlock(masq_data);
1929 if (masq_data->
caller == new_chan) {
1934 ast_debug(1,
"Caller channel %s being masqueraded into by %s (is_empty:%d)\n",
1935 ast_channel_name(old_chan), ast_channel_name(new_chan),
1938 ast_channel_publish_dial_internal(old_chan, cur->
peer, NULL,
1940 ast_channel_publish_dial_internal(new_chan, cur->
peer, NULL,
1944 ao2_unlock(masq_data);
1953 if (cur->
peer == new_chan) {
1954 ast_debug(1,
"Peer channel %s being masqueraded into by %s\n",
1955 ast_channel_name(old_chan), ast_channel_name(new_chan));
1956 ast_channel_publish_dial_internal(masq_data->
caller, old_chan, NULL,
1958 ast_channel_publish_dial_internal(masq_data->
caller, new_chan, NULL,
1964 ao2_unlock(masq_data);
1968 .
type =
"stasis-chan-dial-masq",
1969 .destroy = dial_masquerade_datastore_destroy,
1970 .chan_fixup = dial_masquerade_fixup,
1971 .chan_breakdown = dial_masquerade_breakdown,
1975 .
type =
"stasis-chan-dial-masq",
1976 .destroy = dial_masquerade_caller_datastore_destroy,
1977 .chan_fixup = dial_masquerade_fixup,
1978 .chan_breakdown = dial_masquerade_breakdown,
2017 datastore = ast_datastore_alloc(!masq_data ? &dial_masquerade_caller_info : &dial_masquerade_info, NULL);
2023 masq_data = dial_masquerade_datastore_alloc();
2028 masq_data->
caller = chan;
2031 datastore->
data = masq_data;
2037 static int set_dial_masquerade(
struct ast_channel *caller,
struct ast_channel *peer,
const char *dialstring)
2044 datastore = dial_masquerade_datastore_find(caller);
2046 masq_data = dial_masquerade_datastore_add(caller, NULL);
2048 masq_data = datastore->
data;
2060 ast_assert(masq_data->
caller == caller);
2079 ao2_lock(masq_data);
2080 dial_masquerade_datastore_remove_chan(masq_data, peer);
2082 ao2_unlock(masq_data);
2084 datastore = dial_masquerade_datastore_find(peer);
2086 if (datastore->
data == masq_data) {
2099 dial_masquerade_datastore_remove_chan(datastore->
data, peer);
2105 if (dial_masquerade_datastore_add(peer, masq_data)) {
2111 dial_masquerade_datastore_remove_chan(masq_data, peer);
2116 static void remove_dial_masquerade(
struct ast_channel *peer)
2121 datastore = dial_masquerade_datastore_find(peer);
2126 masq_data = datastore->
data;
2128 dial_masquerade_datastore_remove_chan(masq_data, peer);
2135 static void remove_dial_masquerade_caller(
struct ast_channel *caller)
2140 datastore = dial_masquerade_datastore_find(caller);
2145 masq_data = datastore->
data;
2150 dial_masquerade_datastore_remove_chan(masq_data, caller);
struct stasis_message_type * ast_channel_hold_type(void)
Message type for when a channel is placed on hold.
struct ao2_container * ast_channel_cache_by_name(void)
Secondary channel cache, indexed by name.
struct stasis_message_type * ast_channel_talking_stop(void)
Message type for a channel stopping talking.
const ast_string_field data
Struct containing info for an AMI event to send out.
#define ast_string_field_init_extended(x, field)
Initialize an extended string field.
Main Channel structure associated with a channel.
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
struct ast_channel_snapshot_base * base
struct stasis_message_type * ast_channel_dtmf_end_type(void)
Message type for when DTMF ends on a channel.
Asterisk main include file. File version handling, generic pbx functions.
struct ast_flags feature_flags
const ast_string_field uniqueid
char * str
Subscriber phone number (Malloced)
struct stasis_message_type * ast_channel_unhold_type(void)
Message type for when a channel is removed from hold.
struct dial_masquerade_datastore::@404 dialed_peers
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
int ast_channel_snapshot_cep_equal(const struct ast_channel_snapshot *old_snapshot, const struct ast_channel_snapshot *new_snapshot)
Compares the context, exten and priority of two snapshots.
void ast_channel_snapshot_invalidate_segment(struct ast_channel *chan, enum ast_channel_snapshot_segment_invalidation segment)
Invalidate a channel snapshot segment from being reused.
const ast_string_field name
The arg parameter is a search key, but is not an object.
int(* channel_snapshot)(const struct ast_channel_snapshot *snapshot)
Callback which determines whether a channel should be sanitized from a message based on the channel's...
Support for translation of data formats. translate.c.
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
void ast_channel_publish_cached_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Publish a channel blob message using the latest snapshot from the cache.
void ast_channel_publish_dial(struct ast_channel *caller, struct ast_channel *peer, const char *dialstring, const char *dialstatus)
Publish in the ast_channel_topic or ast_channel_topic_all topics a stasis message for the channels in...
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
struct ast_channel_snapshot * snapshot
struct stasis_message_type * ast_channel_moh_start_type(void)
Message type for starting music on hold on a channel.
struct varshead * ast_channel_get_manager_vars(struct ast_channel *chan)
Gets the variables for a given channel, as specified by ast_channel_set_manager_vars().
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
AST_JSON_INT_T ast_json_int_t
Primarily used to cast when packing to an "I" type.
const ast_string_field rdnis
int ast_party_id_presentation(const struct ast_party_id *id)
Determine the overall presentation value for the given party.
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container, as described below.
Structure representing a snapshot of channel state.
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Assume that the ao2_container is already locked.
struct stasis_message_type * ast_channel_wink_type(void)
Message type for when a wink occurs on a channel.
Structure for a data store type.
ast_channel_state
ast_channel states
const ast_string_field accountcode
struct stasis_message_type * ast_channel_flash_type(void)
Message type for when a hook flash occurs on a channel.
#define AST_NUM_CHANNEL_BUCKETS
const ast_string_field uniqueid
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
Source contained fully valid UTF-8.
#define ast_strdup(str)
A wrapper for strdup()
Structure for a data store object.
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
struct stasis_message_type * ast_channel_varset_type(void)
Message type for when a variable is set on a channel.
struct stasis_message_type * ast_channel_chanspy_start_type(void)
Message type for when a channel starts spying on another channel.
Structure containing connected information for a channel snapshot.
int ast_json_is_null(const struct ast_json *value)
Check if value is JSON null.
Structure representing a change of snapshot of channel state.
const ast_string_field type
struct stasis_message_type * ast_channel_talking_start(void)
Message type for a channel starting talking.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
UTF-8 information and validation functions.
struct ast_channel_snapshot_dialplan * dialplan
struct ast_manager_event_blob * ast_manager_event_blob_create(int event_flags, const char *manager_event, const char *extra_fields_fmt,...)
Construct a ast_manager_event_blob.
Structure containing callbacks for Stasis message sanitization.
struct ast_channel_snapshot * ast_channel_snapshot_create(struct ast_channel *chan)
Generate a snapshot of the channel state. This is an ao2 object, so ao2_cleanup() to deallocate...
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
struct ast_json * ast_multi_channel_blob_get_json(struct ast_multi_channel_blob *obj)
Retrieve the JSON blob from a ast_multi_channel_blob. Returned ast_json is still owned by obj...
int ast_json_object_set(struct ast_json *object, const char *key, struct ast_json *value)
Set a field in a JSON object.
Blob of data associated with a channel.
int ast_channel_snapshot_caller_id_equal(const struct ast_channel_snapshot *old_snapshot, const struct ast_channel_snapshot *new_snapshot)
Compares the callerid info of two snapshots.
struct ast_json * ast_json_dialplan_cep_app(const char *context, const char *exten, int priority, const char *app_name, const char *app_data)
Construct a context/exten/priority/application/application_data as JSON.
struct ast_json * ast_json_null(void)
Get the JSON null value.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
struct ast_json * ast_json_channel_vars(struct varshead *channelvars)
Construct a JSON object from a ast_var_t list.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
const ast_string_field dialed_subaddr
ast_channel_snapshot_segment_invalidation
Channel snapshot invalidation flags, used to force generation of segments.
struct stasis_message_type * type
const ast_string_field context
struct stasis_topic * ast_channel_topic_all(void)
A topic which publishes the events for all channels.
struct ast_bridge * ast_channel_get_bridge(const struct ast_channel *chan)
Get the bridge associated with a channel.
struct varshead * ari_vars
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
struct ast_channel_snapshot * ast_channel_snapshot_get_latest_by_name(const char *name)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object...
Structure containing hangup information for a channel snapshot.
struct ast_json * ast_json_name_number(const char *name, const char *number)
Common JSON rendering functions for common 'objects'.
Asterisk JSON abstraction layer.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
const ast_string_field appl
struct ast_json * ast_json_string_create(const char *value)
Construct a JSON string from value.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
int ast_stasis_channels_init(void)
Initialize the stasis channel topic and message types.
#define ast_strdupa(s)
duplicate a string in memory from the stack
void ast_multi_channel_blob_add_channel(struct ast_multi_channel_blob *obj, const char *role, struct ast_channel_snapshot *snapshot)
Add a ast_channel_snapshot to a ast_multi_channel_blob object.
const struct timeval * stasis_message_timestamp(const struct stasis_message *msg)
Get the time when a message was created.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
#define ast_channel_cleanup(c)
Cleanup a channel reference.
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Structure containing dialplan information for a channel snapshot.
const ast_string_field subaddr
const ast_string_field exten
struct timeval creationtime
struct varshead * ast_channel_get_ari_vars(struct ast_channel *chan)
Gets the variables for a given channel, as specified by ast_channel_set_ari_vars().
struct ast_channel_snapshot_hangup * hangup
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
A set of macros to manage forward-linked lists.
struct stasis_message_type * ast_channel_agent_login_type(void)
Message type for agent login on a channel.
#define ast_debug(level,...)
Log a DEBUG message.
struct stasis_topic * stasis_topic_create(const char *name)
Create a new topic.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
struct stasis_message_type * ast_channel_agent_logoff_type(void)
Message type for agent logoff on a channel.
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Core PBX routines and definitions.
struct ast_json * ast_json_timeval(const struct timeval tv, const char *zone)
Construct a timeval as JSON.
struct ao2_container * ast_multi_channel_blob_get_channels(struct ast_multi_channel_blob *obj, const char *role)
Retrieve all channel snapshots associated with a specific role from a ast_multi_channel_blob.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
struct ast_channel_snapshot_caller * caller
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
struct ast_flags softhangup_flags
struct stasis_message_type * ast_channel_mixmonitor_start_type(void)
Message type for starting mixmonitor on a channel.
Structure that contains information about a bridge.
#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.
struct varshead * manager_vars
Support for dynamic strings.
struct stasis_message_type * ast_channel_mixmonitor_stop_type(void)
Message type for stopping mixmonitor on a channel.
const ast_string_field dnid
Structure containing peer information for a channel snapshot.
struct ast_channel_snapshot * snapshot
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
void ast_channel_publish_varset(struct ast_channel *chan, const char *name, const char *value)
Publish a ast_channel_publish_varset for a channel.
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
void ast_channel_publish_final_snapshot(struct ast_channel *chan)
Send the final channel snapshot for a channel, thus removing it from cache.
Structure containing caller information for a channel snapshot.
Structure containing base information for a channel snapshot.
struct stasis_message * ast_channel_blob_create(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Creates a ast_channel_blob message.
void ast_channel_publish_dial_forward(struct ast_channel *caller, struct ast_channel *peer, struct ast_channel *forwarded, const char *dialstring, const char *dialstatus, const char *forward)
Publish in the ast_channel_topic or ast_channel_topic_all topics a stasis message for the channels in...
const ast_string_field userfield
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
STASIS_MESSAGE_TYPE_DEFN(ast_channel_snapshot_type)
Define channel message types.
struct stasis_message_type * ast_channel_hangup_handler_type(void)
Message type for hangup handler related actions.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
#define ast_calloc(num, len)
A wrapper for calloc()
char * ast_escape_c_alloc(const char *s)
Escape standard 'C' sequences in the given string.
struct ast_channel_snapshot * new_snapshot
enum ast_channel_state state
struct stasis_message_type * ast_channel_snapshot_type(void)
Message type for ast_channel_snapshot_update.
struct ast_channel_snapshot * old_snapshot
struct stasis_message_type * ast_channel_dtmf_begin_type(void)
Message type for when DTMF begins on a channel.
struct stasis_message * ast_channel_blob_create_from_cache(const char *channel_id, struct stasis_message_type *type, struct ast_json *blob)
Create a ast_channel_blob message, pulling channel state from the cache.
const ast_string_field ani
struct ast_json * ast_json_object_create(void)
Create a new JSON object.
const ast_string_field language
The arg parameter is an object of the same type.
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
struct ao2_container * channel_snapshots
#define ast_channel_ref(c)
Increase channel reference count.
struct ast_channel_snapshot * ast_channel_snapshot_get_latest(const char *uniqueid)
Obtain the latest ast_channel_snapshot from the Stasis Message Bus API cache. This is an ao2 object...
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
const ast_string_field number
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
struct ast_channel_snapshot * ast_multi_channel_blob_get_channel(struct ast_multi_channel_blob *obj, const char *role)
Retrieve a channel snapshot associated with a specific role from a ast_multi_channel_blob.
struct ast_channel_snapshot_bridge * bridge
A multi channel blob data structure for multi_channel_blob stasis messages.
Abstract JSON element (object, array, string, int, ...).
int ast_channel_has_manager_vars(void)
Return whether or not any manager variables have been set.
struct stasis_message_type * ast_channel_dial_type(void)
Message type for when a channel dials another channel.
void ast_channel_publish_snapshot(struct ast_channel *chan)
Publish a ast_channel_snapshot for a channel.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
int ast_channel_snapshot_connected_line_equal(const struct ast_channel_snapshot *old_snapshot, const struct ast_channel_snapshot *new_snapshot)
Compares the connected line info of two snapshots.
enum ast_utf8_replace_result ast_utf8_replace_invalid_chars(char *dst, size_t *dst_size, const char *src, size_t src_len)
Copy a string safely replacing any invalid UTF-8 sequences.
Search option field mask.
void ast_channel_publish_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Publish a channel blob message.
struct ast_channel * caller
struct stasis_message_type * ast_channel_moh_stop_type(void)
Message type for stopping music on hold on a channel.
struct ast_json * ast_channel_snapshot_to_json(const struct ast_channel_snapshot *snapshot, const struct stasis_message_sanitizer *sanitize)
Build a JSON object from a ast_channel_snapshot.
struct ast_channel * peer
struct ast_channel_snapshot_peer * peer
struct stasis_message_type * ast_channel_hangup_request_type(void)
Message type for when a hangup is requested on a channel.
intmax_t ast_json_integer_get(const struct ast_json *integer)
Get the value from a JSON integer.
struct stasis_message_type * ast_channel_masquerade_type(void)
Message type for when a channel is being masqueraded.
struct stasis_message_type * ast_channel_fax_type(void)
Message type for a fax operation.
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
const char * ast_state2str(enum ast_channel_state state)
Gives the string form of a given channel state.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Structure containing bridge information for a channel snapshot.
struct ast_json * ast_json_copy(const struct ast_json *value)
Copy a JSON value, but not its children.
A channel snapshot wrapper object used in ast_multi_channel_blob objects.
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
struct ast_channel_snapshot_connected * connected
struct ast_multi_channel_blob * ast_multi_channel_blob_create(struct ast_json *blob)
Create a ast_multi_channel_blob suitable for a stasis_message.
struct stasis_message_type * ast_channel_chanspy_stop_type(void)
Message type for when a channel stops spying on another channel.
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
const ast_string_field name
struct dial_target::@403 list
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
struct stasis_message_type * ast_channel_mixmonitor_mute_type(void)
Message type for muting or unmuting mixmonitor on a channel.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
#define ao2_link(container, obj)
Add an object to a container.