53 #include "asterisk/stasis_message_router.h"
54 #include "asterisk/stasis_channels.h"
55 #include "asterisk/stasis_bridges.h"
142 #define BACKEND_BUCKETS 13
151 #define CEL_MAX_EVENT_IDS 64
156 #define NUM_APP_BUCKETS 97
161 #define NUM_DIALSTATUS_BUCKETS 251
185 ao2_cleanup(cfg->
apps);
221 ao2_cleanup(cfg->general);
225 static void *cel_config_alloc(
void)
245 .item_offset = offsetof(
struct cel_config, general),
247 .category =
"general",
257 static struct aco_type ignore_option = {
260 .category = (
const char*)ignore_categories,
267 .types =
ACO_TYPES(&general_option, &ignore_option),
270 static int cel_pre_apply_config(
void);
273 .files = ACO_FILES(&cel_conf),
274 .pre_apply_config = cel_pre_apply_config,
277 static int cel_pre_apply_config(
void)
297 ast_log(LOG_ERROR,
"Applications are listed to be tracked, but APP events are not tracked\n");
307 [AST_CEL_ALL] =
"ALL",
350 enabled = (!cfg || !cfg->general) ? 0 : cfg->general->
enable;
365 e->
command =
"cel show status";
367 "Usage: cel show status\n"
368 " Displays the Channel Event Logging system status.\n";
377 return CLI_SHOWUSAGE;
382 if (!cfg || !cfg->general || !cfg->general->
enable) {
386 for (i = 0; i < (
sizeof(cfg->general->
events) * 8); i++) {
389 if (!(cfg->general->
events & ((int64_t) 1 << i))) {
394 if (strcasecmp(name,
"Unknown")) {
395 ast_cli(a->fd,
"CEL Tracking Event: %s\n", name);
400 for (; (app = ao2_iterator_next(&iter));
ao2_ref(app, -1)) {
401 ast_cli(a->fd,
"CEL Tracking Application: %s\n", app);
409 for (; (backend = ao2_iterator_next(&iter));
ao2_ref(backend, -1)) {
410 ast_cli(a->fd,
"CEL Event Subscriber: %s\n", backend->
name);
418 static struct ast_cli_entry cli_status = AST_CLI_DEFINE(handle_cli_status,
"Display the CEL status");
424 for (i = 0; i < ARRAY_LEN(cel_event_types); i++) {
425 if (cel_event_types[i] && !strcasecmp(name, cel_event_types[i])) {
430 ast_log(LOG_ERROR,
"Unknown event name '%s'\n", name);
431 return AST_CEL_INVALID_VALUE;
438 if (!cfg || !cfg->general) {
442 return (cfg->general->
events & ((int64_t) 1 << et)) ? 1 : 0;
451 while ((cur_event = strsep(&events,
","))) {
455 if (ast_strlen_zero(cur_event)) {
461 if (event_type == AST_CEL_ALL) {
463 cfg->
events = (int64_t) -1;
464 }
else if (event_type == AST_CEL_INVALID_VALUE) {
467 cfg->
events |= ((int64_t) 1 << event_type);
480 while ((cur_app = strsep(&apps,
","))) {
482 if (ast_strlen_zero(cur_app)) {
495 return S_OR(cel_event_types[type],
"Unknown");
498 static int cel_track_app(
const char *const_app)
501 RAII_VAR(
char *, app, NULL, ao2_cleanup);
504 if (!cfg || !cfg->general) {
517 static int cel_linkedid_ref(
const char *linkedid);
521 struct ast_json *extra,
const char *peer)
526 userdefevname, extra, peer);
531 const char *userdefevname,
struct ast_json *extra,
const char *peer)
563 static int cel_backend_send_cb(
void *obj,
void *arg,
int flags)
573 const char *userdefevname,
struct ast_json *extra,
574 const char *peer_str)
580 if (!cfg || !cfg->general || !cfg->general->
enable || !
backends) {
593 if (!ast_cel_track_event(event_type)) {
616 static void check_retire_linkedid(
struct ast_channel_snapshot *snapshot,
const struct timeval *event_time)
621 if (!linkedids || ast_strlen_zero(snapshot->
peer->
linkedid)) {
630 ao2_unlock(linkedids);
637 ast_log(LOG_ERROR,
"Something weird happened, couldn't find linkedid %s\n",
645 ao2_unlock(linkedids);
649 ao2_unlock(linkedids);
658 .
type =
"CEL fabricated channel",
666 const char *mixed_name;
676 if (!cfg || !cfg->general) {
685 headp = ast_channel_varshead(tchan);
695 ? record.user_defined_name : record.event_name;
696 if ((newvariable = ast_var_assign(
"eventtype", mixed_name))) {
700 if (ast_strlen_zero(cfg->general->date_format)) {
701 snprintf(timebuf,
sizeof(timebuf),
"%ld.%06ld", (
long) record.event_time.tv_sec,
702 (
long) record.event_time.tv_usec);
706 ast_strftime(timebuf,
sizeof(timebuf), cfg->general->date_format, &tm);
709 if ((newvariable = ast_var_assign(
"eventtime", timebuf))) {
713 if ((newvariable = ast_var_assign(
"eventenum", record.event_name))) {
716 if ((newvariable = ast_var_assign(
"userdeftype", record.user_defined_name))) {
719 if ((newvariable = ast_var_assign(
"eventextra", record.extra))) {
733 ast_channel_exten_set(tchan, record.extension);
734 ast_channel_context_set(tchan, record.context);
735 ast_channel_name_set(tchan, record.channel_name);
737 ast_channel_accountcode_set(tchan, record.account_code);
738 ast_channel_peeraccount_set(tchan, record.peer_account);
739 ast_channel_userfield_set(tchan, record.user_field);
741 if ((newvariable = ast_var_assign(
"BRIDGEPEER", record.peer))) {
762 if (!(datastore = ast_datastore_alloc(&fabricated_channel_datastore, NULL))) {
767 if (!(app_data =
ast_malloc(strlen(record.application_name) + strlen(record.application_data) + 2))) {
773 ast_channel_appl_set(tchan, strcpy(app_data, record.application_name));
774 ast_channel_data_set(tchan, strcpy(app_data + strlen(record.application_name) + 1,
775 record.application_data));
777 datastore->
data = app_data;
783 static int cel_linkedid_ref(
const char *linkedid)
788 if (ast_strlen_zero(linkedid)) {
789 ast_log(LOG_ERROR,
"The linkedid should never be empty\n");
804 lid = ao2_alloc_options(
sizeof(*lid) + strlen(linkedid) + 1, NULL,
807 ao2_unlock(linkedids);
810 strcpy(lid->
id, linkedid);
815 ao2_unlock(linkedids);
824 ast_log(LOG_ERROR,
"Module ABI mismatch for ast_cel_event_record. "
825 "Please ensure all modules were compiled for "
826 "this version of Asterisk.\n");
839 r->user_defined_name =
"";
868 const struct timeval *event_time);
901 const struct timeval *event_time)
903 int is_hungup, was_hungup;
913 if (!was_hungup && is_hungup) {
920 "dialstatus", dialstatus ? dialstatus->
dialstatus :
"");
921 cel_report_event(new_snapshot,
AST_CEL_HANGUP, event_time, NULL, extra, NULL);
923 ao2_cleanup(dialstatus);
927 check_retire_linkedid(new_snapshot, event_time);
933 cel_report_event(new_snapshot,
AST_CEL_ANSWER, event_time, NULL, NULL, NULL);
938 static void cel_channel_linkedid_change(
941 const struct timeval *event_time)
947 ast_assert(!ast_strlen_zero(new_snapshot->
peer->
linkedid));
948 ast_assert(!ast_strlen_zero(old_snapshot->
peer->
linkedid));
953 check_retire_linkedid(old_snapshot, event_time);
957 static void cel_channel_app_change(
960 const struct timeval *event_time)
967 if (old_snapshot && !ast_strlen_zero(old_snapshot->
dialplan->
appl)) {
968 cel_report_event(old_snapshot,
AST_CEL_APP_END, event_time, NULL, NULL, NULL);
983 cel_channel_app_change,
985 cel_channel_linkedid_change,
1006 for (i = 0; i < ARRAY_LEN(cel_channel_monitors); ++i) {
1011 static struct ast_str *cel_generate_peer_str(
1017 char *current_chan = NULL;
1024 (current_chan = ao2_iterator_next(&i));
1025 ao2_cleanup(current_chan)) {
1034 if (!current_snapshot) {
1039 ao2_cleanup(current_snapshot);
1049 static void cel_bridge_enter_cb(
1059 if (cel_filter_channel_snapshot(chan_snapshot)) {
1070 peer_str = cel_generate_peer_str(snapshot, chan_snapshot);
1079 static void cel_bridge_leave_cb(
1089 if (cel_filter_channel_snapshot(chan_snapshot)) {
1100 peer_str = cel_generate_peer_str(snapshot, chan_snapshot);
1109 static void cel_parking_cb(
1115 const char *reason = NULL;
1127 case PARKED_CALL_TIMEOUT:
1128 reason =
"ParkedCallTimeOut";
1130 case PARKED_CALL_GIVEUP:
1131 reason =
"ParkedCallGiveUp";
1133 case PARKED_CALL_UNPARKED:
1134 reason =
"ParkedCallUnparked";
1136 case PARKED_CALL_FAILED:
1137 reason =
"ParkedCallFailed";
1139 case PARKED_CALL_SWAP:
1140 reason =
"ParkedCallSwap";
1146 "reason", reason ?:
"",
1161 const char *dialstatus_string = get_blob_variable(blob,
"dialstatus");
1163 size_t dialstatus_string_len;
1165 if (!dial_statuses || ast_strlen_zero(dialstatus_string)) {
1166 ao2_cleanup(dial_statuses);
1172 if (!strcasecmp(dialstatus_string,
"ANSWER") && strcasecmp(dialstatus->
dialstatus,
"ANSWER")) {
1186 dialstatus_string_len = strlen(dialstatus_string) + 1;
1187 dialstatus = ao2_alloc_options(
sizeof(*dialstatus) + dialstatus_string_len, NULL,
1197 ao2_link(dial_statuses, dialstatus);
1204 const char *dialstatus = get_blob_variable(blob,
"dialstatus");
1207 if (ast_strlen_zero(dialstatus)) {
1209 }
else if (!strcasecmp(dialstatus,
"CHANUNAVAIL")) {
1211 }
else if (!strcasecmp(dialstatus,
"CONGESTION")) {
1213 }
else if (!strcasecmp(dialstatus,
"NOANSWER")) {
1215 }
else if (!strcasecmp(dialstatus,
"BUSY")) {
1217 }
else if (!strcasecmp(dialstatus,
"ANSWER")) {
1219 }
else if (!strcasecmp(dialstatus,
"CANCEL")) {
1221 }
else if (!strcasecmp(dialstatus,
"DONTCALL")) {
1223 }
else if (!strcasecmp(dialstatus,
"TORTURE")) {
1225 }
else if (!strcasecmp(dialstatus,
"INVALIDARGS")) {
1238 if (!snapshot || cel_filter_channel_snapshot(snapshot)) {
1242 if (!ast_strlen_zero(get_blob_variable(blob,
"forward"))) {
1245 extra =
ast_json_pack(
"{s: s}",
"forward", get_blob_variable(blob,
"forward"));
1253 if (is_valid_dialstatus(blob)) {
1254 save_dialstatus(blob, snapshot);
1258 static void cel_generic_cb(
1266 switch (event_type) {
1272 event, extra, NULL);
1281 static void cel_blind_transfer_cb(
1295 "extension", transfer_msg->
exten,
1296 "context", transfer_msg->
context,
1297 "bridge_id", bridge_snapshot->
uniqueid,
1307 static void cel_attended_transfer_cb(
1330 case AST_ATTENDED_TRANSFER_DEST_FAIL:
1333 case AST_ATTENDED_TRANSFER_DEST_BRIDGE_MERGE:
1334 case AST_ATTENDED_TRANSFER_DEST_LINK:
1335 case AST_ATTENDED_TRANSFER_DEST_THREEWAY:
1336 extra =
ast_json_pack(
"{s: s, s: s, s: s, s: s, s: s, s: s, s: s, s: s}",
1338 "channel2_name", channel2->
base->
name,
1349 case AST_ATTENDED_TRANSFER_DEST_APP:
1350 case AST_ATTENDED_TRANSFER_DEST_LOCAL_APP:
1351 extra =
ast_json_pack(
"{s: s, s: s, s: s, s: s, s: s, s: s, s: s, s: s}",
1353 "channel2_name", channel2->
base->
name,
1355 "app", xfer->dest.
app,
1370 static void cel_pickup_cb(
1379 if (!channel || !target) {
1384 "pickup_channel", channel->
base->
name,
1395 static void cel_local_optimization_cb_helper(
1405 if (!localone || !localtwo) {
1420 static void cel_local_optimization_end_cb(
1430 static void cel_local_optimization_begin_cb(
1437 static void destroy_routes(
void)
1440 cel_state_router = NULL;
1445 ao2_cleanup(cel_aggregation_topic);
1446 cel_aggregation_topic = NULL;
1447 ao2_cleanup(cel_topic);
1450 cel_channel_forwarder = stasis_forward_cancel(cel_channel_forwarder);
1451 cel_bridge_forwarder = stasis_forward_cancel(cel_bridge_forwarder);
1452 cel_parking_forwarder = stasis_forward_cancel(cel_parking_forwarder);
1453 cel_cel_forwarder = stasis_forward_cancel(cel_cel_forwarder);
1456 static int unload_module(
void)
1478 if (!cel_aggregation_topic) {
1489 cel_aggregation_topic);
1490 if (!cel_channel_forwarder) {
1496 cel_aggregation_topic);
1497 if (!cel_bridge_forwarder) {
1503 cel_aggregation_topic);
1504 if (!cel_parking_forwarder) {
1510 cel_aggregation_topic);
1511 if (!cel_cel_forwarder) {
1525 cel_state_router = stasis_message_router_create(cel_aggregation_topic);
1526 if (!cel_state_router) {
1534 cel_snapshot_update_cb,
1543 ast_channel_entered_bridge_type(),
1544 cel_bridge_enter_cb,
1548 ast_channel_left_bridge_type(),
1549 cel_bridge_leave_cb,
1563 ast_blind_transfer_type(),
1564 cel_blind_transfer_cb,
1568 ast_attended_transfer_type(),
1569 cel_attended_transfer_cb,
1579 cel_local_optimization_end_cb,
1584 cel_local_optimization_begin_cb,
1588 ast_log(AST_LOG_ERROR,
"Failed to register for Stasis messages\n");
1597 static
int load_module(
void)
1604 ao2_cleanup(container);
1612 ao2_cleanup(container);
1626 cel_backend_hash_fn, NULL, cel_backend_cmp_fn);
1628 ao2_cleanup(container);
1643 struct cel_config *cel_cfg = cel_config_alloc();
1651 ast_log(LOG_NOTICE,
"Failed to process CEL configuration; using defaults\n");
1668 static int reload_module(
void)
1679 if (!was_enabled && is_enabled) {
1683 }
else if (was_enabled && !is_enabled) {
1687 ast_verb(3,
"CEL logging %sabled.\n", is_enabled ?
"en" :
"dis");
1700 "extra",
"extra",
S_OR(extra,
""));
1715 "event_type", event_type,
1722 ao2_cleanup(message);
1735 if (!mod_cfg || !mod_cfg->general) {
1739 ao2_ref(mod_cfg->general, +1);
1740 return mod_cfg->general;
1753 cleanup_config = mod_cfg->general;
1755 mod_cfg->general = config;
1756 ao2_cleanup(cleanup_config);
1759 if (!was_enabled && is_enabled) {
1761 }
else if (was_enabled && !is_enabled) {
1786 if (!
backends || ast_strlen_zero(name) || !backend_callback) {
1791 backend = ao2_alloc_options(
sizeof(*backend) + 1 + strlen(name), NULL,
1796 strcpy(backend->
name, name);
1797 backend->
callback = backend_callback;
1804 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER,
"CEL Engine",
1805 .support_level = AST_MODULE_SUPPORT_CORE,
1806 .load = load_module,
1807 .unload = unload_module,
1808 .reload = reload_module,
1810 .requires =
"extconfig",
enum ast_cel_event_type ast_cel_str_to_event_type(const char *name)
Get the event type from a string.
cel_channel_snapshot_monitor cel_channel_monitors[]
Handlers for channel snapshot changes.
the last channel with the given linkedid is retired
#define NUM_APP_BUCKETS
Number of buckets for the appset container.
const ast_string_field data
Helper struct for getting the fields out of a CEL event.
Channel Event CID name Used by: AST_EVENT_CEL Payload type: STR.
Channel Event app name Used by: AST_EVENT_CEL Payload type: STR.
struct ao2_container * channels
Main Channel structure associated with a channel.
Local proxy channel special access.
#define CEL_MAX_EVENT_IDS
Maximum possible CEL event IDs.
char * str
Subscriber phone number (Malloced)
struct ast_json * ast_json_ref(struct ast_json *value)
Increase refcount on value.
static void cel_config_dtor(void *obj)
Destructor for cel_config.
A container that holds all config-related information.
struct ast_channel_snapshot_base * base
static struct aco_file cel_conf
The config file to be processed for the module.
Channels with this particular technology are an implementation detail of Asterisk and should generall...
Asterisk main include file. File version handling, generic pbx functions.
AO2_STRING_FIELD_HASH_FN(transport_monitor, key)
Hashing function for struct transport_monitor.
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
char * str
Subscriber phone number (Malloced)
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
struct ast_event * ast_cel_create_event_with_time(struct ast_channel_snapshot *snapshot, enum ast_cel_event_type event_type, const struct timeval *event_time, const char *userdefevname, struct ast_json *extra, const char *peer)
Allocate and populate a CEL event structure.
int stasis_message_router_add(struct stasis_message_router *router, struct stasis_message_type *message_type, stasis_subscription_cb callback, void *data)
Add a route to a message router.
Message representing attended transfer.
struct ast_channel_snapshot * channel
#define aco_option_register_custom(info, name, matchtype, types, default_val, handler, flags)
Register a config option.
static struct aco_type general_option
An aco_type structure to link the "general" category to the ast_cel_general_config type...
Channel Event extra data Used by: AST_EVENT_CEL Payload type: STR.
const ast_string_field name
#define ast_channel_unref(c)
Decrease channel reference count.
Registered applications container.
static struct stasis_forward * cel_parking_forwarder
The arg parameter is a search key, but is not an object.
char exten[AST_MAX_EXTENSION]
int stasis_message_router_set_congestion_limits(struct stasis_message_router *router, long low_water, long high_water)
Set the high and low alert water marks of the stasis message router.
Message published during a blind transfer.
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
struct ast_party_name name
Subscriber name.
struct ast_party_id from
Who is redirecting the call (Sent to the party the call is redirected toward)
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
struct ast_channel_snapshot * snapshot
int ast_cli_unregister(struct ast_cli_entry *e)
Unregisters a command or an array of commands.
descriptor for a cli entry.
struct stasis_message_type * ast_parked_call_type(void)
accessor for the parked call stasis message type
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
#define AST_TASKPROCESSOR_HIGH_WATER_LEVEL
const ast_string_field rdnis
#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.
static struct stasis_topic * cel_aggregation_topic
void ast_json_free(void *p)
Asterisk's custom JSON allocator. Exposed for use by unit tests.
Structure that contains a snapshot of information about a bridge.
Channel Event channel name Used by: AST_EVENT_CEL Payload type: STR.
#define aco_option_register(info, name, matchtype, types, default_val, opt_type, flags,...)
Register a config option.
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
A local channel optimization occurred, this marks the end.
static void destroy_subscriptions(void)
Destroy the active Stasis subscriptions.
Structure for variables, used for configurations and for channel variables.
Channel Event UniqueID Used by: AST_EVENT_CEL Payload type: STR.
Channel Event context name Used by: AST_EVENT_CEL Payload type: STR.
Structure representing a snapshot of channel state.
Channel Event app args/data Used by: AST_EVENT_CEL Payload type: STR.
void * ast_cel_general_config_alloc(void)
Allocate a CEL configuration object.
Channel Event peeraccount Used by: AST_EVENT_CEL Payload type: STR.
Channel Event Time (micro-seconds) Used by: AST_EVENT_CEL Payload type: UINT.
Channel Event CID dnid Used by: AST_EVENT_CEL Payload type: STR.
#define ast_json_dump_string(root)
Encode a JSON value to a compact string.
#define ast_str_container_alloc(buckets)
Allocates a hash container for bare strings.
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Structure for a data store type.
AO2_STRING_FIELD_CMP_FN(transport_monitor, key)
Comparison function for struct transport_monitor.
struct ast_channel_snapshot * target
const ast_string_field accountcode
char * str
Subscriber name (Malloced)
const ast_string_field uniqueid
struct stasis_topic * ast_bridge_topic_all(void)
A topic which publishes the events for all bridges.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
enum aco_process_status aco_process_config(struct aco_info *info, int reload)
Process a config info via the options registered with an aco_info.
A local channel optimization has begun.
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
CONFIG_INFO_CORE("stasis", cfg_info, globals, stasis_config_alloc,.files=ACO_FILES(&stasis_conf),)
Register information about the configs being processed by this module.
struct ast_cel_general_config * ast_cel_get_config(void)
Obtain the current CEL configuration.
struct ast_event * ast_cel_create_event(struct ast_channel_snapshot *snapshot, enum ast_cel_event_type event_type, const char *userdefevname, struct ast_json *extra, const char *peer)
Allocate and populate a CEL event structure.
A parked call message payload.
#define ast_strdup(str)
A wrapper for strdup()
Structure for a data store object.
static const char *const cel_event_types[CEL_MAX_EVENT_IDS]
Map of ast_cel_event_type to strings.
static struct stasis_forward * cel_channel_forwarder
The representation of a single configuration file to be processed.
Structure representing a change of snapshot of channel state.
enum ast_parked_call_event_type event_type
void ast_free_ptr(void *ptr)
free() wrapper
#define ACO_TYPES(...)
A helper macro to ensure that aco_info types always have a sentinel.
struct ast_channel_snapshot_dialplan * dialplan
struct ast_bridge_channel_snapshot_pair to_transferee
void stasis_message_router_unsubscribe_and_join(struct stasis_message_router *router)
Unsubscribe the router from the upstream topic, blocking until the final message has been processed...
Channel Event Type Used by: AST_EVENT_CEL Payload type: UINT.
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...
the list of registered channel types
Blob of data associated with a channel.
char * ast_str_truncate(struct ast_str *buf, ssize_t len)
Truncates the enclosed string to the given length.
Channel Event Time (seconds) Used by: AST_EVENT_CEL Payload type: UINT.
#define ast_cli_register(e)
Registers a command or an array of commands.
Channel Event CID num Used by: AST_EVENT_CEL Payload type: STR.
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
struct ast_party_id id
Caller party ID.
struct ast_bridge_channel_snapshot_pair to_transfer_target
const ast_string_field context
Configuration File Parser.
Channel Event extension name Used by: AST_EVENT_CEL Payload type: STR.
struct ast_bridge_snapshot * bridge
struct stasis_topic * ast_channel_topic_all(void)
A topic which publishes the events for all channels.
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
void(* cel_channel_snapshot_monitor)(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot, const struct timeval *event_time)
Typedef for callbacks that get called on channel snapshot updates.
const ast_string_field technology
int aco_info_init(struct aco_info *info)
Initialize an aco_info structure.
struct ast_party_id ani
Automatic Number Identification (ANI)
struct ast_channel_snapshot * parkee
General Asterisk PBX channel definitions.
void(* ast_cel_backend_cb)(struct ast_event *event)
CEL backend callback.
void * aco_pending_config(struct aco_info *info)
Get pending config changes.
const ast_string_field appl
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_dummy_channel_alloc()
Create a fake channel structure.
struct ast_channel * ast_cel_fabricate_channel_from_event(const struct ast_event *event)
Create a fake channel from data in a CEL event.
struct ast_channel_snapshot * transferee
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.
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
unsigned int ast_cel_check_enabled(void)
Hashing function for cel_backend.
static struct stasis_forward * cel_bridge_forwarder
void ast_cel_publish_user_event(struct ast_channel *chan, const char *event, const char *extra)
Publish a CEL user event.
char uniqueid[AST_MAX_UNIQUEID]
uint32_t version
struct ABI version
const ast_string_field exten
struct ast_channel_snapshot_hangup * hangup
static struct stasis_rest_handlers events
REST handler for /api-docs/events.json.
Channel Event Userfield Used by: AST_EVENT_CEL Payload type: STR.
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
void ast_channel_amaflags_set(struct ast_channel *chan, enum ama_flags value)
A set of macros to manage forward-linked lists.
#define ast_malloc(len)
A wrapper for malloc()
struct ao2_container * container
struct ast_bridge_snapshot * bridge
static void cel_channel_state_change(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot, const struct timeval *event_time)
Handle channel state changes.
hangup terminates connection
struct stasis_topic * stasis_topic_create(const char *name)
Create a new topic.
Blob of data associated with a bridge.
Channel Event CID RDNIS field Used by: AST_EVENT_CEL Payload type: STR.
enum aco_category_op category_match
static force_inline char * ast_str_to_lower(char *str)
Convert a string to all lower-case.
Core PBX routines and definitions.
struct stasis_topic * ast_cel_topic(void)
Get the CEL topic.
Their was an error and no changes were applied.
void ast_cel_publish_event(struct ast_channel *chan, enum ast_cel_event_type event_type, struct ast_json *blob)
Publish a CEL event.
struct ast_channel_snapshot_caller * caller
enum ast_attended_transfer_dest_type dest_type
struct stasis_message_type * ast_local_optimization_end_type(void)
Message type for when a local channel optimization completes.
#define STASIS_MESSAGE_TYPE_DEFN(name,...)
Boiler-plate messaging macro for defining public message types.
Configuration option-handling.
struct stasis_message_type * ast_call_pickup_type(void)
accessor for call pickup message type
struct ast_channel_snapshot * transferer
#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.
Support for dynamic strings.
const ast_string_field dnid
Channel Event User Event Name Used by: AST_EVENT_CEL Payload type: STR.
#define ao2_unlink(container, obj)
Remove an object from a container.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
void aco_info_destroy(struct aco_info *info)
Destroy an initialized aco_info struct.
#define ao2_global_obj_release(holder)
Release the ao2 object held in the global holder.
Type for default option handler for bools (ast_true/ast_false)
void ast_cel_set_config(struct ast_cel_general_config *config)
Set the current CEL configuration.
static struct stasis_message_router * cel_state_router
static const char * ignore_categories[]
char context[AST_MAX_CONTEXT]
const ast_string_field userfield
struct ao2_container * apps
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
static int create_routes(void)
Create the Stasis message router and routes for CEL.
static struct stasis_topic * cel_topic
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
Channel Event Peer – for Things involving multiple channels, like BRIDGE Used by: AST_EVENT_CEL Payl...
Channel Event CID ANI field Used by: AST_EVENT_CEL Payload type: STR.
int aco_set_defaults(struct aco_type *type, const char *category, void *obj)
Set all default options of obj.
Module could not be loaded properly.
#define STRFLDSET(type,...)
Convert a struct and a list of stringfield fields to an argument list of field offsets.
Support for logging to various files, console and syslog Configuration in file logger.conf.
struct ast_channel_snapshot * new_snapshot
enum ast_channel_state state
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
const ast_string_field uniqueid
An API for managing task processing threads that can be shared across modules.
const ast_string_field parkinglot
Channel Event AMA flags Used by: AST_EVENT_CEL Payload type: UINT.
struct stasis_message_type * ast_channel_snapshot_type(void)
Message type for ast_channel_snapshot_update.
struct ast_channel_snapshot * old_snapshot
#define AST_CEL_EVENT_RECORD_VERSION
struct ABI version
struct stasis_message * ast_channel_blob_create_from_cache(const char *uniqueid, struct stasis_message_type *type, struct ast_json *blob)
Create a ast_channel_blob message, pulling channel state from the cache.
static int is_enabled(void)
Helper function to check if module is enabled.
uint32_t ast_event_get_ie_uint(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has an integer payload.
const ast_string_field ani
int ast_cel_backend_unregister(const char *name)
Unregister a CEL backend.
ast_cel_backend_cb callback
#define ao2_global_obj_replace_unref(holder, obj)
Replace an ao2 object in the global holder, throwing away any old object.
A structure to hold CEL global configuration options.
struct stasis_message_type * ast_local_optimization_begin_type(void)
Message type for when a local channel optimization begins.
struct stasis_topic * ast_parking_topic(void)
accessor for the parking stasis topic
Channel Event LinkedID Used by: AST_EVENT_CEL Payload type: STR.
void ast_event_destroy(struct ast_event *event)
Destroy an event.
#define NUM_DIALSTATUS_BUCKETS
Number of buckets for the dialstatus container.
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...
Standard Command Line Interface.
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
struct ast_event * ast_event_new(enum ast_event_type event_type,...)
Create a new event.
Type information about a category-level configurable object.
const ast_string_field number
static int enabled
Whether or not we are storing history.
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...
A ringing phone is answered.
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.
A multi channel blob data structure for multi_channel_blob stasis messages.
static AO2_GLOBAL_OBJ_STATIC(cel_backends)
struct ast_party_dialed::@206 number
Dialed/Called number.
const ast_string_field parker_dial_string
Abstract JSON element (object, array, string, int, ...).
Type for default option handler for stringfields.
a user-defined event, the event name field should be set
static struct stasis_forward * cel_cel_forwarder
ast_cel_event_type
CEL event types.
struct stasis_message_type * ast_channel_dial_type(void)
Message type for when a channel dials another channel.
int ast_cel_fill_record(const struct ast_event *e, struct ast_cel_event_record *r)
Fill in an ast_cel_event_record from a CEL event.
unsigned char valid
TRUE if the name information is valid/present.
struct ast_channel_snapshot * transferee
struct stasis_forward * stasis_forward_all(struct stasis_topic *from_topic, struct stasis_topic *to_topic)
Create a subscription which forwards all messages from one topic to another.
const char * ast_event_get_ie_str(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has a string payload.
struct ast_channel_snapshot_peer * peer
#define ASTERISK_GPL_KEY
The text the key() function should return.
struct ast_channel_snapshot * retriever
Asterisk module definitions.
intmax_t ast_json_integer_get(const struct ast_json *integer)
Get the value from a JSON integer.
int ast_cel_backend_register(const char *name, ast_cel_backend_cb backend_callback)
Register a CEL backend.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
a directed pickup was performed on this channel
unsigned char valid
TRUE if the number information is valid/present.
static void cel_general_config_dtor(void *obj)
Destructor for cel_config.
enum ast_transfer_result result
this call was forwarded somewhere else
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
static int create_subscriptions(void)
Create the Stasis subscriptions for CEL.
int ast_str_container_add(struct ao2_container *str_container, const char *add)
Adds a string to a string container allocated by ast_str_container_alloc.
const char * ast_cel_get_type_name(enum ast_cel_event_type type)
Get the name of a CEL event type.
Channel Event AccountCode Used by: AST_EVENT_CEL Payload type: STR.
const ast_string_field name
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
void ast_channel_internal_set_fake_ids(struct ast_channel *chan, const char *uniqueid, const char *linkedid)
Set uniqueid and linkedid string value only (not time)
struct ast_party_number number
Subscriber phone number.
#define ao2_link(container, obj)
Add an object to a container.