cel.c File Reference

Channel Event Logging API. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/cel.h"
#include "asterisk/logger.h"
#include "asterisk/linkedlists.h"
#include "asterisk/utils.h"
#include "asterisk/config.h"
#include "asterisk/config_options.h"
#include "asterisk/cli.h"
#include "asterisk/astobj2.h"
#include "asterisk/stasis_message_router.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/stasis_bridges.h"
#include "asterisk/bridge.h"
#include "asterisk/parking.h"
#include "asterisk/pickup.h"
#include "asterisk/core_local.h"

Include dependency graph for cel.c:

Go to the source code of this file.

Data Structures

struct  cel_backend
struct  cel_config
 A container that holds all config-related information. More...
struct  cel_linkedid

Defines

#define BACKEND_BUCKETS   13
#define CEL_MAX_EVENT_IDS   64
 Maximum possible CEL event IDs.
#define NUM_APP_BUCKETS   97
 Number of buckets for the appset container.
#define NUM_DIALSTATUS_BUCKETS   251
 Number of buckets for the dialstatus container.

Typedefs

typedef void(* cel_channel_snapshot_monitor )(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
 Typedef for callbacks that get called on channel snapshot updates.

Functions

static AO2_GLOBAL_OBJ_STATIC (cel_configs)
static AO2_GLOBAL_OBJ_STATIC (cel_linkedids)
static AO2_GLOBAL_OBJ_STATIC (cel_dialstatus_store)
static AO2_GLOBAL_OBJ_STATIC (cel_backends)
static int apps_handler (const struct aco_option *opt, struct ast_variable *var, void *obj)
int ast_cel_backend_register (const char *name, ast_cel_backend_cb backend_callback)
 Register a CEL backend.
int ast_cel_backend_unregister (const char *name)
 Unregister a CEL backend.
unsigned int ast_cel_check_enabled (void)
 Check to see if CEL is enabled.
struct ast_eventast_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.
int ast_cel_engine_init (void)
int ast_cel_engine_reload (void)
struct ast_channelast_cel_fabricate_channel_from_event (const struct ast_event *event)
 Create a fake channel from data in a CEL event.
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.
void * ast_cel_general_config_alloc (void)
 Allocate a CEL configuration object.
struct ast_cel_general_configast_cel_get_config (void)
 Obtain the current CEL configuration.
const char * ast_cel_get_type_name (enum ast_cel_event_type type)
 Get the name of a CEL event type.
void ast_cel_publish_event (struct ast_channel *chan, enum ast_cel_event_type event_type, struct ast_json *blob)
 Publish a CEL event.
void ast_cel_set_config (struct ast_cel_general_config *config)
 Set the current CEL configuration.
enum ast_cel_event_type ast_cel_str_to_event_type (const char *name)
 Get the event type from a string.
struct stasis_topicast_cel_topic (void)
 Get the CEL topic.
static int ast_cel_track_event (enum ast_cel_event_type et)
static void cel_attended_transfer_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
static int cel_backend_cmp (void *obj, void *arg, int flags)
 Comparator function for cel_backend.
static int cel_backend_hash (const void *obj, int flags)
 Hashing function for cel_backend.
static int cel_backend_send_cb (void *obj, void *arg, int flags)
static void cel_blind_transfer_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void cel_bridge_enter_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void cel_bridge_leave_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void cel_channel_app_change (struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
static void cel_channel_linkedid_change (struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
static void cel_channel_state_change (struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
 Handle channel state changes.
static void * cel_config_alloc (void)
static void cel_config_dtor (void *obj)
 Destructor for cel_config.
static void cel_dial_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void cel_engine_cleanup (void)
static int cel_filter_channel_snapshot (struct ast_channel_snapshot *snapshot)
static void cel_general_config_dtor (void *obj)
 Destructor for cel_config.
static struct ast_strcel_generate_peer_str (struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *chan)
static void cel_generic_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
struct stasis_message_typecel_generic_type (void)
static int cel_linkedid_ref (const char *linkedid)
static void cel_local_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void cel_parking_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
static void cel_pickup_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
static int cel_pre_apply_config (void)
static int cel_report_event (struct ast_channel_snapshot *snapshot, enum ast_cel_event_type event_type, const char *userdefevname, struct ast_json *extra, const char *peer_str)
static void cel_snapshot_update_cb (void *data, struct stasis_subscription *sub, struct stasis_message *message)
static int cel_track_app (const char *const_app)
static void check_retire_linkedid (struct ast_channel_snapshot *snapshot)
 CONFIG_INFO_CORE ("cel", cel_cfg_info, cel_configs, cel_config_alloc,.files=ACO_FILES(&cel_conf),.pre_apply_config=cel_pre_apply_config,)
static int create_routes (void)
 Create the Stasis message router and routes for CEL.
static int create_subscriptions (void)
 Create the Stasis subscriptions for CEL.
static void destroy_routes (void)
static void destroy_subscriptions (void)
static int dialstatus_cmp (void *obj, void *arg, int flags)
 Comparator function for dialstatus container.
static int dialstatus_hash (const void *obj, int flags)
 Hashing function for dialstatus container.
static int events_handler (const struct aco_option *opt, struct ast_variable *var, void *obj)
static const char * get_blob_variable (struct ast_multi_channel_blob *blob, const char *varname)
static const char * get_caller_uniqueid (struct ast_multi_channel_blob *blob)
static struct
ast_multi_channel_blob
get_dialstatus_blob (const char *uniqueid)
static char * handle_cli_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int is_valid_dialstatus (struct ast_multi_channel_blob *blob)
static int lid_cmp (void *obj, void *arg, int flags)
static int lid_hash (const void *obj, const int flags)
static void save_dialstatus (struct ast_multi_channel_blob *blob)
 STASIS_MESSAGE_TYPE_DEFN (cel_generic_type)

Variables

static struct stasis_topiccel_aggregation_topic
static struct stasis_forwardcel_bridge_forwarder
static struct stasis_forwardcel_cel_forwarder
static struct stasis_forwardcel_channel_forwarder
cel_channel_snapshot_monitor cel_channel_monitors []
static struct aco_file cel_conf
 The config file to be processed for the module.
static const char *const cel_event_types [CEL_MAX_EVENT_IDS]
 Map of ast_cel_event_type to strings.
static struct stasis_forwardcel_parking_forwarder
static struct
stasis_message_router
cel_state_router
static struct stasis_topiccel_topic
static struct ast_cli_entry cli_status = AST_CLI_DEFINE(handle_cli_status, "Display the CEL status")
static struct ast_datastore_info fabricated_channel_datastore
static struct aco_type general_option
 An aco_type structure to link the "general" category to the ast_cel_general_config type.
static struct aco_typegeneral_options [] = ACO_TYPES(&general_option)


Detailed Description

Channel Event Logging API.

Author:
Steve Murphy <murf@digium.com>

Russell Bryant <russell@digium.com>

Definition in file cel.c.


Define Documentation

#define BACKEND_BUCKETS   13

The number of buckets into which backend names will be hashed

Definition at line 142 of file cel.c.

Referenced by ast_cel_engine_init().

#define CEL_MAX_EVENT_IDS   64

Maximum possible CEL event IDs.

Note:
This limit is currently imposed by the eventset definition

Definition at line 151 of file cel.c.

#define NUM_APP_BUCKETS   97

Number of buckets for the appset container.

Definition at line 156 of file cel.c.

Referenced by ast_cel_engine_init(), and ast_cel_general_config_alloc().

#define NUM_DIALSTATUS_BUCKETS   251

Number of buckets for the dialstatus container.

Definition at line 161 of file cel.c.

Referenced by ast_cel_engine_init().


Typedef Documentation

typedef void(* cel_channel_snapshot_monitor)(struct ast_channel_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)

Typedef for callbacks that get called on channel snapshot updates.

Definition at line 957 of file cel.c.


Function Documentation

static AO2_GLOBAL_OBJ_STATIC ( cel_configs   )  [static]

static AO2_GLOBAL_OBJ_STATIC ( cel_linkedids   )  [static]

Container of channel references to a linkedid for CEL purposes.

static AO2_GLOBAL_OBJ_STATIC ( cel_dialstatus_store   )  [static]

Container for dial end multichannel blobs for holding on to dial statuses

static AO2_GLOBAL_OBJ_STATIC ( cel_backends   )  [static]

Container for CEL backend information

static int apps_handler ( const struct aco_option opt,
struct ast_variable var,
void *  obj 
) [static]

Definition at line 576 of file cel.c.

References ast_cel_general_config::apps, ast_str_container_add(), ast_str_to_lower(), ast_strdupa, ast_strip(), ast_strlen_zero, strsep(), and ast_variable::value.

Referenced by ast_cel_engine_init().

00577 {
00578    struct ast_cel_general_config *cfg = obj;
00579    char *apps = ast_strdupa(var->value);
00580    char *cur_app;
00581 
00582    while ((cur_app = strsep(&apps, ","))) {
00583       cur_app = ast_strip(cur_app);
00584       if (ast_strlen_zero(cur_app)) {
00585          continue;
00586       }
00587 
00588       cur_app = ast_str_to_lower(cur_app);
00589       ast_str_container_add(cfg->apps, cur_app);
00590    }
00591 
00592    return 0;
00593 }

int ast_cel_backend_register ( const char *  name,
ast_cel_backend_cb  backend_callback 
)

Register a CEL backend.

Parameters:
name Name of backend to register
backend_callback Callback to register
Return values:
zero on success
non-zero on failure
Since:
12

Definition at line 1873 of file cel.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_cleanup, ao2_global_obj_ref, ao2_link, ao2_ref, ast_strlen_zero, cel_backend::callback, cel_backend::name, NULL, and RAII_VAR.

Referenced by load_config(), load_module(), my_load_module(), and test_cel_init_cb().

01874 {
01875    RAII_VAR(struct ao2_container *, backends, ao2_global_obj_ref(cel_backends), ao2_cleanup);
01876    struct cel_backend *backend;
01877 
01878    if (!backends || ast_strlen_zero(name) || !backend_callback) {
01879       return -1;
01880    }
01881 
01882    /* The backend object is immutable so it doesn't need a lock of its own. */
01883    backend = ao2_alloc_options(sizeof(*backend) + 1 + strlen(name), NULL,
01884       AO2_ALLOC_OPT_LOCK_NOLOCK);
01885    if (!backend) {
01886       return -1;
01887    }
01888    strcpy(backend->name, name);/* Safe */
01889    backend->callback = backend_callback;
01890 
01891    ao2_link(backends, backend);
01892    ao2_ref(backend, -1);
01893    return 0;
01894 }

int ast_cel_backend_unregister ( const char *  name  ) 

Unregister a CEL backend.

Parameters:
name Name of backend to unregister
Return values:
zero on success
non-zero on failure
Since:
12

Definition at line 1861 of file cel.c.

References ao2_find, ao2_global_obj_ref, ao2_ref, OBJ_NODATA, OBJ_SEARCH_KEY, and OBJ_UNLINK.

Referenced by cel_verify_and_cleanup_cb(), load_config(), my_unload_module(), tds_unload_module(), and unload_module().

01862 {
01863    struct ao2_container *backends = ao2_global_obj_ref(cel_backends);
01864 
01865    if (backends) {
01866       ao2_find(backends, name, OBJ_SEARCH_KEY | OBJ_NODATA | OBJ_UNLINK);
01867       ao2_ref(backends, -1);
01868    }
01869 
01870    return 0;
01871 }

unsigned int ast_cel_check_enabled ( void   ) 

Check to see if CEL is enabled.

Since:
1.8
Return values:
zero not enabled
non-zero enabled

Definition at line 447 of file cel.c.

References ao2_cleanup, ao2_global_obj_ref, ast_cel_general_config::enable, enabled, and cel_config::general.

Referenced by ast_cel_engine_init(), ast_cel_engine_reload(), ast_cel_set_config(), and handle_cli_status().

00448 {
00449    unsigned int enabled;
00450    struct cel_config *cfg = ao2_global_obj_ref(cel_configs);
00451 
00452    enabled = (!cfg || !cfg->general) ? 0 : cfg->general->enable;
00453    ao2_cleanup(cfg);
00454    return enabled;
00455 }

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_str 
) [read]

Allocate and populate a CEL event structure.

Parameters:
snapshot An ast_channel_snapshot of the primary channel associated with this channel event.
event_type The type of call event being reported.
userdefevname Custom name for the call event. (optional)
extra An event-specific opaque JSON blob to be rendered and placed in the "CEL_EXTRA" information element of the call event. (optional)
peer_str A list of comma-separated peer channel names. (optional)
Since:
12
Return values:
The created ast_event structure
NULL on failure

Definition at line 621 of file cel.c.

References ast_channel_snapshot::accountcode, ast_channel_snapshot::amaflags, ast_channel_snapshot::appl, AST_EVENT_CEL, AST_EVENT_IE_CEL_ACCTCODE, AST_EVENT_IE_CEL_AMAFLAGS, AST_EVENT_IE_CEL_APPDATA, AST_EVENT_IE_CEL_APPNAME, AST_EVENT_IE_CEL_CHANNAME, AST_EVENT_IE_CEL_CIDANI, AST_EVENT_IE_CEL_CIDDNID, AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_CEL_CIDNUM, AST_EVENT_IE_CEL_CIDRDNIS, AST_EVENT_IE_CEL_CONTEXT, AST_EVENT_IE_CEL_EVENT_TIME, AST_EVENT_IE_CEL_EVENT_TIME_USEC, AST_EVENT_IE_CEL_EVENT_TYPE, AST_EVENT_IE_CEL_EXTEN, AST_EVENT_IE_CEL_EXTRA, AST_EVENT_IE_CEL_LINKEDID, AST_EVENT_IE_CEL_PEER, AST_EVENT_IE_CEL_PEERACCT, AST_EVENT_IE_CEL_UNIQUEID, AST_EVENT_IE_CEL_USEREVENT_NAME, AST_EVENT_IE_CEL_USERFIELD, AST_EVENT_IE_END, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_IE_PLTYPE_UINT, ast_event_new(), ast_json_dump_string, ast_json_free(), ast_tvnow(), ast_channel_snapshot::caller_ani, ast_channel_snapshot::caller_dnid, ast_channel_snapshot::caller_name, ast_channel_snapshot::caller_number, ast_channel_snapshot::caller_rdnis, ast_channel_snapshot::context, ast_channel_snapshot::data, ast_channel_snapshot::exten, ast_channel_snapshot::linkedid, ast_channel_snapshot::name, NULL, ast_channel_snapshot::peeraccount, RAII_VAR, S_OR, ast_channel_snapshot::uniqueid, and ast_channel_snapshot::userfield.

Referenced by append_expected_event_snapshot(), and cel_report_event().

00624 {
00625    struct timeval eventtime = ast_tvnow();
00626    RAII_VAR(char *, extra_txt, NULL, ast_json_free);
00627    if (extra) {
00628       extra_txt = ast_json_dump_string(extra);
00629    }
00630    return ast_event_new(AST_EVENT_CEL,
00631       AST_EVENT_IE_CEL_EVENT_TYPE, AST_EVENT_IE_PLTYPE_UINT, event_type,
00632       AST_EVENT_IE_CEL_EVENT_TIME, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_sec,
00633       AST_EVENT_IE_CEL_EVENT_TIME_USEC, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_usec,
00634       AST_EVENT_IE_CEL_USEREVENT_NAME, AST_EVENT_IE_PLTYPE_STR, S_OR(userdefevname, ""),
00635       AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_PLTYPE_STR, snapshot->caller_name,
00636       AST_EVENT_IE_CEL_CIDNUM, AST_EVENT_IE_PLTYPE_STR, snapshot->caller_number,
00637       AST_EVENT_IE_CEL_CIDANI, AST_EVENT_IE_PLTYPE_STR, snapshot->caller_ani,
00638       AST_EVENT_IE_CEL_CIDRDNIS, AST_EVENT_IE_PLTYPE_STR, snapshot->caller_rdnis,
00639       AST_EVENT_IE_CEL_CIDDNID, AST_EVENT_IE_PLTYPE_STR, snapshot->caller_dnid,
00640       AST_EVENT_IE_CEL_EXTEN, AST_EVENT_IE_PLTYPE_STR, snapshot->exten,
00641       AST_EVENT_IE_CEL_CONTEXT, AST_EVENT_IE_PLTYPE_STR, snapshot->context,
00642       AST_EVENT_IE_CEL_CHANNAME, AST_EVENT_IE_PLTYPE_STR, snapshot->name,
00643       AST_EVENT_IE_CEL_APPNAME, AST_EVENT_IE_PLTYPE_STR, snapshot->appl,
00644       AST_EVENT_IE_CEL_APPDATA, AST_EVENT_IE_PLTYPE_STR, snapshot->data,
00645       AST_EVENT_IE_CEL_AMAFLAGS, AST_EVENT_IE_PLTYPE_UINT, snapshot->amaflags,
00646       AST_EVENT_IE_CEL_ACCTCODE, AST_EVENT_IE_PLTYPE_STR, snapshot->accountcode,
00647       AST_EVENT_IE_CEL_PEERACCT, AST_EVENT_IE_PLTYPE_STR, snapshot->peeraccount,
00648       AST_EVENT_IE_CEL_UNIQUEID, AST_EVENT_IE_PLTYPE_STR, snapshot->uniqueid,
00649       AST_EVENT_IE_CEL_LINKEDID, AST_EVENT_IE_PLTYPE_STR, snapshot->linkedid,
00650       AST_EVENT_IE_CEL_USERFIELD, AST_EVENT_IE_PLTYPE_STR, snapshot->userfield,
00651       AST_EVENT_IE_CEL_EXTRA, AST_EVENT_IE_PLTYPE_STR, S_OR(extra_txt, ""),
00652       AST_EVENT_IE_CEL_PEER, AST_EVENT_IE_PLTYPE_STR, S_OR(peer, ""),
00653       AST_EVENT_IE_END);
00654 }

int ast_cel_engine_init ( void   ) 

Provided by cel.c

Definition at line 1696 of file cel.c.

References ACO_EXACT, aco_info_init(), aco_option_register, aco_option_register_custom, aco_process_config(), aco_set_defaults(), ao2_cleanup, ao2_container_alloc, ao2_global_obj_replace_unref, ao2_ref, apps_handler(), ast_cel_check_enabled(), ast_cli_register(), ast_log, ast_register_cleanup(), BACKEND_BUCKETS, cel_backend_cmp(), cel_backend_hash(), cel_config_alloc(), cel_engine_cleanup(), cel_generic_type(), container, create_routes(), create_subscriptions(), date_format, dialstatus_cmp(), dialstatus_hash(), events_handler(), FLDSET, cel_config::general, lid_cmp(), lid_hash(), LOG_NOTICE, NUM_APP_BUCKETS, NUM_DIALSTATUS_BUCKETS, OPT_BOOL_T, OPT_STRINGFIELD_T, STASIS_MESSAGE_TYPE_INIT, and STRFLDSET.

Referenced by main().

01697 {
01698    struct ao2_container *container;
01699 
01700    container = ao2_container_alloc(NUM_APP_BUCKETS, lid_hash, lid_cmp);
01701    ao2_global_obj_replace_unref(cel_linkedids, container);
01702    ao2_cleanup(container);
01703    if (!container) {
01704       cel_engine_cleanup();
01705       return -1;
01706    }
01707 
01708    container = ao2_container_alloc(NUM_DIALSTATUS_BUCKETS,
01709       dialstatus_hash, dialstatus_cmp);
01710    ao2_global_obj_replace_unref(cel_dialstatus_store, container);
01711    ao2_cleanup(container);
01712    if (!container) {
01713       cel_engine_cleanup();
01714       return -1;
01715    }
01716 
01717    if (STASIS_MESSAGE_TYPE_INIT(cel_generic_type)) {
01718       cel_engine_cleanup();
01719       return -1;
01720    }
01721 
01722    if (ast_cli_register(&cli_status)) {
01723       cel_engine_cleanup();
01724       return -1;
01725    }
01726 
01727    container = ao2_container_alloc(BACKEND_BUCKETS, cel_backend_hash, cel_backend_cmp);
01728    ao2_global_obj_replace_unref(cel_backends, container);
01729    ao2_cleanup(container);
01730    if (!container) {
01731       cel_engine_cleanup();
01732       return -1;
01733    }
01734 
01735    if (aco_info_init(&cel_cfg_info)) {
01736       cel_engine_cleanup();
01737       return -1;
01738    }
01739 
01740    aco_option_register(&cel_cfg_info, "enable", ACO_EXACT, general_options, "no", OPT_BOOL_T, 1, FLDSET(struct ast_cel_general_config, enable));
01741    aco_option_register(&cel_cfg_info, "dateformat", ACO_EXACT, general_options, "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_cel_general_config, date_format));
01742    aco_option_register_custom(&cel_cfg_info, "apps", ACO_EXACT, general_options, "", apps_handler, 0);
01743    aco_option_register_custom(&cel_cfg_info, "events", ACO_EXACT, general_options, "", events_handler, 0);
01744 
01745    if (aco_process_config(&cel_cfg_info, 0)) {
01746       struct cel_config *cel_cfg = cel_config_alloc();
01747 
01748       if (!cel_cfg) {
01749          cel_engine_cleanup();
01750          return -1;
01751       }
01752 
01753       /* We couldn't process the configuration so create a default config. */
01754       if (!aco_set_defaults(&general_option, "general", cel_cfg->general)) {
01755          ast_log(LOG_NOTICE, "Failed to process CEL configuration; using defaults\n");
01756          ao2_global_obj_replace_unref(cel_configs, cel_cfg);
01757       }
01758       ao2_ref(cel_cfg, -1);
01759    }
01760 
01761    if (create_subscriptions()) {
01762       cel_engine_cleanup();
01763       return -1;
01764    }
01765 
01766    if (ast_cel_check_enabled() && create_routes()) {
01767       cel_engine_cleanup();
01768       return -1;
01769    }
01770 
01771    ast_register_cleanup(cel_engine_cleanup);
01772    return 0;
01773 }

int ast_cel_engine_reload ( void   ) 

Provided by cel.c

Definition at line 1775 of file cel.c.

References aco_process_config(), ACO_PROCESS_ERROR, ast_cel_check_enabled(), ast_verb, create_routes(), destroy_routes(), and is_enabled().

01776 {
01777    unsigned int was_enabled = ast_cel_check_enabled();
01778    unsigned int is_enabled;
01779 
01780    if (aco_process_config(&cel_cfg_info, 1) == ACO_PROCESS_ERROR) {
01781       return -1;
01782    }
01783 
01784    is_enabled = ast_cel_check_enabled();
01785 
01786    if (!was_enabled && is_enabled) {
01787       if (create_routes()) {
01788          return -1;
01789       }
01790    } else if (was_enabled && !is_enabled) {
01791       destroy_routes();
01792    }
01793 
01794    ast_verb(3, "CEL logging %sabled.\n", is_enabled ? "en" : "dis");
01795 
01796    return 0;
01797 }

struct ast_channel* ast_cel_fabricate_channel_from_event ( const struct ast_event event  )  [read]

Create a fake channel from data in a CEL event.

Note:
This function creates a fake channel containing the serialized channel data in the given cel event. It should be released with ast_channel_unref() but could be released with ast_channel_release().
Parameters:
event the CEL event
Since:
1.8
Returns:
a channel with the data filled in, or NULL on error
Todo:
This function is very expensive, especially given that some CEL backends use it on every CEL event. This function really needs to go away at some point.

Definition at line 754 of file cel.c.

References ast_cel_event_record::account_code, ast_cel_event_record::amaflag, ast_party_caller::ani, ao2_cleanup, ao2_global_obj_ref, ast_cel_event_record::application_data, ast_cel_event_record::application_name, AST_CEL_EVENT_RECORD_VERSION, ast_cel_fill_record(), AST_CEL_USER_DEFINED, ast_channel_amaflags_set(), ast_channel_appl_set(), ast_channel_caller(), ast_channel_context_set(), ast_channel_data_set(), ast_channel_datastore_add(), ast_channel_dialed(), ast_channel_exten_set(), ast_channel_internal_set_fake_ids(), ast_channel_name_set(), ast_channel_redirecting(), ast_channel_unref, ast_channel_varshead(), ast_datastore_alloc, ast_datastore_free(), ast_dummy_channel_alloc(), AST_LIST_INSERT_HEAD, ast_localtime(), ast_malloc, ast_strdup, ast_strftime(), ast_strlen_zero, ast_var_assign(), ast_cel_event_record::caller_id_ani, ast_cel_event_record::caller_id_dnid, ast_cel_event_record::caller_id_name, ast_cel_event_record::caller_id_num, ast_cel_event_record::caller_id_rdnis, ast_cel_event_record::channel_name, ast_cel_event_record::context, ast_datastore::data, ast_cel_event_record::event_name, ast_cel_event_record::event_time, ast_cel_event_record::event_type, ast_cel_event_record::extension, ast_cel_event_record::extra, ast_party_redirecting::from, ast_party_caller::id, ast_cel_event_record::linked_id, ast_party_id::name, NULL, ast_party_dialed::number, ast_party_id::number, ast_cel_event_record::peer, ast_cel_event_record::peer_account, RAII_VAR, ast_party_dialed::str, ast_party_number::str, ast_party_name::str, ast_cel_event_record::unique_id, ast_cel_event_record::user_defined_name, ast_cel_event_record::user_field, ast_party_number::valid, ast_party_name::valid, and ast_cel_event_record::version.

Referenced by custom_log(), and write_cel().

00755 {
00756    struct varshead *headp;
00757    struct ast_var_t *newvariable;
00758    const char *mixed_name;
00759    char timebuf[30];
00760    struct ast_channel *tchan;
00761    struct ast_cel_event_record record = {
00762       .version = AST_CEL_EVENT_RECORD_VERSION,
00763    };
00764    struct ast_datastore *datastore;
00765    char *app_data;
00766    RAII_VAR(struct cel_config *, cfg, ao2_global_obj_ref(cel_configs), ao2_cleanup);
00767 
00768    if (!cfg || !cfg->general) {
00769       return NULL;
00770    }
00771 
00772    /* do not call ast_channel_alloc because this is not really a real channel */
00773    if (!(tchan = ast_dummy_channel_alloc())) {
00774       return NULL;
00775    }
00776 
00777    headp = ast_channel_varshead(tchan);
00778 
00779    /* first, get the variables from the event */
00780    if (ast_cel_fill_record(event, &record)) {
00781       ast_channel_unref(tchan);
00782       return NULL;
00783    }
00784 
00785    /* next, fill the channel with their data */
00786    mixed_name = (record.event_type == AST_CEL_USER_DEFINED)
00787       ? record.user_defined_name : record.event_name;
00788    if ((newvariable = ast_var_assign("eventtype", mixed_name))) {
00789       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
00790    }
00791 
00792    if (ast_strlen_zero(cfg->general->date_format)) {
00793       snprintf(timebuf, sizeof(timebuf), "%ld.%06ld", (long) record.event_time.tv_sec,
00794             (long) record.event_time.tv_usec);
00795    } else {
00796       struct ast_tm tm;
00797       ast_localtime(&record.event_time, &tm, NULL);
00798       ast_strftime(timebuf, sizeof(timebuf), cfg->general->date_format, &tm);
00799    }
00800 
00801    if ((newvariable = ast_var_assign("eventtime", timebuf))) {
00802       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
00803    }
00804 
00805    if ((newvariable = ast_var_assign("eventenum", record.event_name))) {
00806       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
00807    }
00808    if ((newvariable = ast_var_assign("userdeftype", record.user_defined_name))) {
00809       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
00810    }
00811    if ((newvariable = ast_var_assign("eventextra", record.extra))) {
00812       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
00813    }
00814 
00815    ast_channel_caller(tchan)->id.name.valid = 1;
00816    ast_channel_caller(tchan)->id.name.str = ast_strdup(record.caller_id_name);
00817    ast_channel_caller(tchan)->id.number.valid = 1;
00818    ast_channel_caller(tchan)->id.number.str = ast_strdup(record.caller_id_num);
00819    ast_channel_caller(tchan)->ani.number.valid = 1;
00820    ast_channel_caller(tchan)->ani.number.str = ast_strdup(record.caller_id_ani);
00821    ast_channel_redirecting(tchan)->from.number.valid = 1;
00822    ast_channel_redirecting(tchan)->from.number.str = ast_strdup(record.caller_id_rdnis);
00823    ast_channel_dialed(tchan)->number.str = ast_strdup(record.caller_id_dnid);
00824 
00825    ast_channel_exten_set(tchan, record.extension);
00826    ast_channel_context_set(tchan, record.context);
00827    ast_channel_name_set(tchan, record.channel_name);
00828    ast_channel_internal_set_fake_ids(tchan, record.unique_id, record.linked_id);
00829    ast_channel_accountcode_set(tchan, record.account_code);
00830    ast_channel_peeraccount_set(tchan, record.peer_account);
00831    ast_channel_userfield_set(tchan, record.user_field);
00832 
00833    if ((newvariable = ast_var_assign("BRIDGEPEER", record.peer))) {
00834       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
00835    }
00836 
00837    ast_channel_amaflags_set(tchan, record.amaflag);
00838 
00839    /* We need to store an 'application name' and 'application
00840     * data' on the channel for logging purposes, but the channel
00841     * structure only provides a place to store pointers, and it
00842     * expects these pointers to be pointing to data that does not
00843     * need to be freed. This means that the channel's destructor
00844     * does not attempt to free any storage that these pointers
00845     * point to. However, we can't provide data in that form directly for
00846     * these structure members. In order to ensure that these data
00847     * elements have a lifetime that matches the channel's
00848     * lifetime, we'll put them in a datastore attached to the
00849     * channel, and set's the channel's pointers to point into the
00850     * datastore.  The datastore will then be automatically destroyed
00851     * when the channel is destroyed.
00852     */
00853 
00854    if (!(datastore = ast_datastore_alloc(&fabricated_channel_datastore, NULL))) {
00855       ast_channel_unref(tchan);
00856       return NULL;
00857    }
00858 
00859    if (!(app_data = ast_malloc(strlen(record.application_name) + strlen(record.application_data) + 2))) {
00860       ast_datastore_free(datastore);
00861       ast_channel_unref(tchan);
00862       return NULL;
00863    }
00864 
00865    ast_channel_appl_set(tchan, strcpy(app_data, record.application_name));
00866    ast_channel_data_set(tchan, strcpy(app_data + strlen(record.application_name) + 1,
00867       record.application_data));
00868 
00869    datastore->data = app_data;
00870    ast_channel_datastore_add(tchan, datastore);
00871 
00872    return tchan;
00873 }

int ast_cel_fill_record ( const struct ast_event event,
struct ast_cel_event_record r 
)

Fill in an ast_cel_event_record from a CEL event.

Parameters:
[in] event the CEL event
[out] r the ast_cel_event_record to fill in
Since:
1.8
Return values:
0 success
non-zero failure

Definition at line 913 of file cel.c.

References ast_cel_event_record::account_code, ast_cel_event_record::amaflag, ast_cel_event_record::application_data, ast_cel_event_record::application_name, AST_CEL_EVENT_RECORD_VERSION, ast_cel_get_type_name(), AST_CEL_USER_DEFINED, ast_event_get_ie_str(), ast_event_get_ie_uint(), AST_EVENT_IE_CEL_ACCTCODE, AST_EVENT_IE_CEL_AMAFLAGS, AST_EVENT_IE_CEL_APPDATA, AST_EVENT_IE_CEL_APPNAME, AST_EVENT_IE_CEL_CHANNAME, AST_EVENT_IE_CEL_CIDANI, AST_EVENT_IE_CEL_CIDDNID, AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_CEL_CIDNUM, AST_EVENT_IE_CEL_CIDRDNIS, AST_EVENT_IE_CEL_CONTEXT, AST_EVENT_IE_CEL_EVENT_TIME, AST_EVENT_IE_CEL_EVENT_TIME_USEC, AST_EVENT_IE_CEL_EVENT_TYPE, AST_EVENT_IE_CEL_EXTEN, AST_EVENT_IE_CEL_EXTRA, AST_EVENT_IE_CEL_LINKEDID, AST_EVENT_IE_CEL_PEER, AST_EVENT_IE_CEL_PEERACCT, AST_EVENT_IE_CEL_UNIQUEID, AST_EVENT_IE_CEL_USEREVENT_NAME, AST_EVENT_IE_CEL_USERFIELD, ast_log, ast_cel_event_record::caller_id_ani, ast_cel_event_record::caller_id_dnid, ast_cel_event_record::caller_id_name, ast_cel_event_record::caller_id_num, ast_cel_event_record::caller_id_rdnis, ast_cel_event_record::channel_name, ast_cel_event_record::context, ast_cel_event_record::event_name, ast_cel_event_record::event_time, ast_cel_event_record::event_type, ast_cel_event_record::extension, ast_cel_event_record::extra, ast_cel_event_record::linked_id, LOG_ERROR, ast_cel_event_record::peer, ast_cel_event_record::peer_account, S_OR, ast_cel_event_record::unique_id, ast_cel_event_record::user_defined_name, ast_cel_event_record::user_field, and ast_cel_event_record::version.

Referenced by ast_cel_fabricate_channel_from_event(), manager_log(), odbc_log(), pgsql_log(), radius_log(), and tds_log().

00914 {
00915    if (r->version != AST_CEL_EVENT_RECORD_VERSION) {
00916       ast_log(LOG_ERROR, "Module ABI mismatch for ast_cel_event_record.  "
00917             "Please ensure all modules were compiled for "
00918             "this version of Asterisk.\n");
00919       return -1;
00920    }
00921 
00922    r->event_type = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_EVENT_TYPE);
00923 
00924    r->event_time.tv_sec = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_EVENT_TIME);
00925    r->event_time.tv_usec = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_EVENT_TIME_USEC);
00926 
00927    r->event_name = ast_cel_get_type_name(r->event_type);
00928    if (r->event_type == AST_CEL_USER_DEFINED) {
00929       r->user_defined_name = ast_event_get_ie_str(e, AST_EVENT_IE_CEL_USEREVENT_NAME);
00930    } else {
00931       r->user_defined_name = "";
00932    }
00933 
00934    r->caller_id_name   = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDNAME), "");
00935    r->caller_id_num    = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDNUM), "");
00936    r->caller_id_ani    = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDANI), "");
00937    r->caller_id_rdnis  = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDRDNIS), "");
00938    r->caller_id_dnid   = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDDNID), "");
00939    r->extension        = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_EXTEN), "");
00940    r->context          = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CONTEXT), "");
00941    r->channel_name     = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CHANNAME), "");
00942    r->application_name = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_APPNAME), "");
00943    r->application_data = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_APPDATA), "");
00944    r->account_code     = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_ACCTCODE), "");
00945    r->peer_account     = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_PEERACCT), "");
00946    r->unique_id        = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_UNIQUEID), "");
00947    r->linked_id        = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_LINKEDID), "");
00948    r->amaflag          = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_AMAFLAGS);
00949    r->user_field       = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_USERFIELD), "");
00950    r->peer             = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_PEER), "");
00951    r->extra            = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_EXTRA), "");
00952 
00953    return 0;
00954 }

void* ast_cel_general_config_alloc ( void   ) 

Allocate a CEL configuration object.

Return values:
NULL on error
The new CEL configuration object

Definition at line 182 of file cel.c.

References ao2_alloc, ao2_cleanup, ao2_ref, ast_str_container_alloc, ast_string_field_init, cel_general_config_dtor(), NULL, NUM_APP_BUCKETS, and RAII_VAR.

Referenced by cel_config_alloc(), and load_module().

00183 {
00184    RAII_VAR(struct ast_cel_general_config *, cfg, NULL, ao2_cleanup);
00185 
00186    if (!(cfg = ao2_alloc(sizeof(*cfg), cel_general_config_dtor))) {
00187       return NULL;
00188    }
00189 
00190    if (ast_string_field_init(cfg, 64)) {
00191       return NULL;
00192    }
00193 
00194    if (!(cfg->apps = ast_str_container_alloc(NUM_APP_BUCKETS))) {
00195       return NULL;
00196    }
00197 
00198    ao2_ref(cfg, +1);
00199    return cfg;
00200 }

struct ast_cel_general_config* ast_cel_get_config ( void   )  [read]

Obtain the current CEL configuration.

Since:
12 The configuration is a ref counted object. The caller of this function must decrement the ref count when finished with the configuration.
Return values:
NULL on error
The current CEL configuration

Definition at line 1823 of file cel.c.

References ao2_cleanup, ao2_global_obj_ref, ao2_ref, NULL, and RAII_VAR.

Referenced by test_cel_init_cb().

01824 {
01825    RAII_VAR(struct cel_config *, mod_cfg, ao2_global_obj_ref(cel_configs), ao2_cleanup);
01826 
01827    if (!mod_cfg || !mod_cfg->general) {
01828       return NULL;
01829    }
01830 
01831    ao2_ref(mod_cfg->general, +1);
01832    return mod_cfg->general;
01833 }

const char* ast_cel_get_type_name ( enum ast_cel_event_type  type  ) 

Get the name of a CEL event type.

Parameters:
type the type to get the name of
Since:
1.8
Returns:
the string representation of the type

Definition at line 595 of file cel.c.

References S_OR.

Referenced by ast_cel_fill_record(), cel_generic_cb(), dump_event(), and handle_cli_status().

00596 {
00597    return S_OR(cel_event_types[type], "Unknown");
00598 }

void ast_cel_publish_event ( struct ast_channel chan,
enum ast_cel_event_type  event_type,
struct ast_json blob 
)

Publish a CEL event.

Since:
12
Parameters:
chan This is the primary channel associated with this channel event.
event_type This is the type of call event being reported.
blob This contains any additional parameters that need to be conveyed for this event.

Definition at line 1799 of file cel.c.

References ao2_cleanup, ast_cel_topic(), ast_channel_blob_create_from_cache(), ast_channel_uniqueid(), ast_json_pack(), ast_json_unref(), cel_generic_type(), and stasis_publish().

Referenced by celgenuserevent_exec().

01802 {
01803    struct ast_json *cel_blob;
01804    struct stasis_message *message;
01805 
01806    cel_blob = ast_json_pack("{s: i, s: O}",
01807       "event_type", event_type,
01808       "event_details", blob);
01809 
01810    message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(chan), cel_generic_type(), cel_blob);
01811    if (message) {
01812       stasis_publish(ast_cel_topic(), message);
01813    }
01814    ao2_cleanup(message);
01815    ast_json_unref(cel_blob);
01816 }

void ast_cel_set_config ( struct ast_cel_general_config config  ) 

Set the current CEL configuration.

Since:
12
Parameters:
config The new CEL configuration

Definition at line 1835 of file cel.c.

References ao2_bump, ao2_cleanup, ao2_global_obj_ref, ao2_ref, ast_cel_check_enabled(), create_routes(), destroy_routes(), cel_config::general, and is_enabled().

Referenced by cel_verify_and_cleanup_cb(), and test_cel_init_cb().

01836 {
01837    int was_enabled;
01838    int is_enabled;
01839    struct ast_cel_general_config *cleanup_config;
01840    struct cel_config *mod_cfg = ao2_global_obj_ref(cel_configs);
01841 
01842    if (mod_cfg) {
01843       was_enabled = ast_cel_check_enabled();
01844 
01845       cleanup_config = mod_cfg->general;
01846       ao2_bump(config);
01847       mod_cfg->general = config;
01848       ao2_cleanup(cleanup_config);
01849 
01850       is_enabled = ast_cel_check_enabled();
01851       if (!was_enabled && is_enabled) {
01852          create_routes();
01853       } else if (was_enabled && !is_enabled) {
01854          destroy_routes();
01855       }
01856 
01857       ao2_ref(mod_cfg, -1);
01858    }
01859 }

enum ast_cel_event_type ast_cel_str_to_event_type ( const char *  name  ) 

Get the event type from a string.

Parameters:
name the event type name as a string
Since:
1.8
Returns:
the ast_cel_event_type given by the string

Definition at line 522 of file cel.c.

References ARRAY_LEN, AST_CEL_INVALID_VALUE, ast_log, and LOG_ERROR.

Referenced by events_handler().

00523 {
00524    unsigned int i;
00525 
00526    for (i = 0; i < ARRAY_LEN(cel_event_types); i++) {
00527       if (cel_event_types[i] && !strcasecmp(name, cel_event_types[i])) {
00528          return i;
00529       }
00530    }
00531 
00532    ast_log(LOG_ERROR, "Unknown event name '%s'\n", name);
00533    return AST_CEL_INVALID_VALUE;
00534 }

struct stasis_topic* ast_cel_topic ( void   )  [read]

Get the CEL topic.

Return values:
The CEL topic
NULL if not allocated

Definition at line 1818 of file cel.c.

Referenced by ast_cel_publish_event(), and create_subscriptions().

01819 {
01820    return cel_topic;
01821 }

static int ast_cel_track_event ( enum ast_cel_event_type  et  )  [static]

Definition at line 536 of file cel.c.

References ao2_cleanup, ao2_global_obj_ref, and RAII_VAR.

Referenced by cel_channel_linkedid_change(), cel_channel_state_change(), and cel_report_event().

00537 {
00538    RAII_VAR(struct cel_config *, cfg, ao2_global_obj_ref(cel_configs), ao2_cleanup);
00539 
00540    if (!cfg || !cfg->general) {
00541       return 0;
00542    }
00543 
00544    return (cfg->general->events & ((int64_t) 1 << et));
00545 }

static void cel_attended_transfer_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
) [static]

Definition at line 1378 of file cel.c.

References ast_attended_transfer_message::app, AST_ATTENDED_TRANSFER_DEST_APP, AST_ATTENDED_TRANSFER_DEST_BRIDGE_MERGE, AST_ATTENDED_TRANSFER_DEST_FAIL, AST_ATTENDED_TRANSFER_DEST_LINK, AST_ATTENDED_TRANSFER_DEST_LOCAL_APP, AST_ATTENDED_TRANSFER_DEST_THREEWAY, AST_CEL_ATTENDEDTRANSFER, ast_json_pack(), ast_json_unref(), ast_bridge_channel_snapshot_pair::bridge_snapshot, cel_report_event(), ast_bridge_channel_snapshot_pair::channel_snapshot, ast_attended_transfer_message::dest, ast_attended_transfer_message::dest_type, ast_channel_snapshot::name, NULL, stasis_message_data(), ast_attended_transfer_message::target, ast_attended_transfer_message::to_transfer_target, ast_attended_transfer_message::to_transferee, ast_attended_transfer_message::transferee, ast_channel_snapshot::uniqueid, and ast_bridge_snapshot::uniqueid.

Referenced by create_routes().

01381 {
01382    struct ast_attended_transfer_message *xfer = stasis_message_data(message);
01383    struct ast_json *extra = NULL;
01384    struct ast_bridge_snapshot *bridge1, *bridge2;
01385    struct ast_channel_snapshot *channel1, *channel2;
01386 
01387    /* Make sure bridge1 is always non-NULL */
01388    if (!xfer->to_transferee.bridge_snapshot) {
01389       bridge1 = xfer->to_transfer_target.bridge_snapshot;
01390       bridge2 = xfer->to_transferee.bridge_snapshot;
01391       channel1 = xfer->to_transfer_target.channel_snapshot;
01392       channel2 = xfer->to_transferee.channel_snapshot;
01393    } else {
01394       bridge1 = xfer->to_transferee.bridge_snapshot;
01395       bridge2 = xfer->to_transfer_target.bridge_snapshot;
01396       channel1 = xfer->to_transferee.channel_snapshot;
01397       channel2 = xfer->to_transfer_target.channel_snapshot;
01398    }
01399 
01400    switch (xfer->dest_type) {
01401    case AST_ATTENDED_TRANSFER_DEST_FAIL:
01402       return;
01403       /* handle these three the same */
01404    case AST_ATTENDED_TRANSFER_DEST_BRIDGE_MERGE:
01405    case AST_ATTENDED_TRANSFER_DEST_LINK:
01406    case AST_ATTENDED_TRANSFER_DEST_THREEWAY:
01407       extra = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: s, s: s}",
01408          "bridge1_id", bridge1->uniqueid,
01409          "channel2_name", channel2->name,
01410          "channel2_uniqueid", channel2->uniqueid,
01411          "bridge2_id", bridge2->uniqueid,
01412          "transferee_channel_name", xfer->transferee ? xfer->transferee->name : "N/A",
01413          "transferee_channel_uniqueid", xfer->transferee ? xfer->transferee->uniqueid : "N/A",
01414          "transfer_target_channel_name", xfer->target ? xfer->target->name : "N/A",
01415          "transfer_target_channel_uniqueid", xfer->target ? xfer->target->uniqueid : "N/A");
01416       if (!extra) {
01417          return;
01418       }
01419       break;
01420    case AST_ATTENDED_TRANSFER_DEST_APP:
01421    case AST_ATTENDED_TRANSFER_DEST_LOCAL_APP:
01422       extra = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: s, s: s}",
01423          "bridge1_id", bridge1->uniqueid,
01424          "channel2_name", channel2->name,
01425          "channel2_uniqueid", channel2->uniqueid,
01426          "app", xfer->dest.app,
01427          "transferee_channel_name", xfer->transferee ? xfer->transferee->name : "N/A",
01428          "transferee_channel_uniqueid", xfer->transferee ? xfer->transferee->uniqueid : "N/A",
01429          "transfer_target_channel_name", xfer->target ? xfer->target->name : "N/A",
01430          "transfer_target_channel_uniqueid", xfer->target ? xfer->target->uniqueid : "N/A");
01431       if (!extra) {
01432          return;
01433       }
01434       break;
01435    }
01436    cel_report_event(channel1, AST_CEL_ATTENDEDTRANSFER, NULL, extra, NULL);
01437    ast_json_unref(extra);
01438 }

static int cel_backend_cmp ( void *  obj,
void *  arg,
int  flags 
) [static]

Comparator function for cel_backend.

Definition at line 336 of file cel.c.

References CMP_MATCH, cel_backend::name, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, and OBJ_SEARCH_PARTIAL_KEY.

Referenced by ast_cel_engine_init().

00337 {
00338    const struct cel_backend *object_left = obj;
00339    const struct cel_backend *object_right = arg;
00340    const char *right_key = arg;
00341    int cmp;
00342 
00343    switch (flags & OBJ_SEARCH_MASK) {
00344    case OBJ_SEARCH_OBJECT:
00345       right_key = object_right->name;
00346       /* Fall through */
00347    case OBJ_SEARCH_KEY:
00348       cmp = strcmp(object_left->name, right_key);
00349       break;
00350    case OBJ_SEARCH_PARTIAL_KEY:
00351       /*
00352        * We could also use a partial key struct containing a length
00353        * so strlen() does not get called for every comparison instead.
00354        */
00355       cmp = strncmp(object_left->name, right_key, strlen(right_key));
00356       break;
00357    default:
00358       /*
00359        * What arg points to is specific to this traversal callback
00360        * and has no special meaning to astobj2.
00361        */
00362       cmp = 0;
00363       break;
00364    }
00365    if (cmp) {
00366       return 0;
00367    }
00368    /*
00369     * At this point the traversal callback is identical to a sorted
00370     * container.
00371     */
00372    return CMP_MATCH;
00373 }

static int cel_backend_hash ( const void *  obj,
int  flags 
) [static]

Hashing function for cel_backend.

Definition at line 313 of file cel.c.

References ast_assert, ast_str_hash(), cel_backend::name, name, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, and OBJ_SEARCH_OBJECT.

Referenced by ast_cel_engine_init().

00314 {
00315    const struct cel_backend *backend;
00316    const char *name;
00317 
00318    switch (flags & OBJ_SEARCH_MASK) {
00319    case OBJ_SEARCH_OBJECT:
00320       backend = obj;
00321       name = backend->name;
00322       break;
00323    case OBJ_SEARCH_KEY:
00324       name = obj;
00325       break;
00326    default:
00327       /* Hash can only work on something with a full key. */
00328       ast_assert(0);
00329       return 0;
00330    }
00331 
00332    return ast_str_hash(name);
00333 }

static int cel_backend_send_cb ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 656 of file cel.c.

References cel_backend::callback.

Referenced by cel_report_event().

00657 {
00658    struct cel_backend *backend = obj;
00659 
00660    backend->callback(arg);
00661    return 0;
00662 }

static void cel_blind_transfer_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
) [static]

Definition at line 1353 of file cel.c.

References AST_BRIDGE_TRANSFER_SUCCESS, AST_CEL_BLINDTRANSFER, ast_json_pack(), ast_json_unref(), ast_blind_transfer_message::bridge, cel_report_event(), ast_blind_transfer_message::context, ast_blind_transfer_message::exten, ast_channel_snapshot::name, NULL, ast_blind_transfer_message::result, stasis_message_data(), ast_blind_transfer_message::transferee, ast_blind_transfer_message::transferer, ast_channel_snapshot::uniqueid, and ast_bridge_snapshot::uniqueid.

Referenced by create_routes().

01356 {
01357    struct ast_blind_transfer_message *transfer_msg = stasis_message_data(message);
01358    struct ast_channel_snapshot *chan_snapshot = transfer_msg->transferer;
01359    struct ast_bridge_snapshot *bridge_snapshot = transfer_msg->bridge;
01360    struct ast_json *extra;
01361 
01362    if (transfer_msg->result != AST_BRIDGE_TRANSFER_SUCCESS) {
01363       return;
01364    }
01365 
01366    extra = ast_json_pack("{s: s, s: s, s: s, s: s, s: s}",
01367       "extension", transfer_msg->exten,
01368       "context", transfer_msg->context,
01369       "bridge_id", bridge_snapshot->uniqueid,
01370       "transferee_channel_name", transfer_msg->transferee ? transfer_msg->transferee->name : "N/A",
01371       "transferee_channel_uniqueid", transfer_msg->transferee ? transfer_msg->transferee->uniqueid  : "N/A");
01372    if (extra) {
01373       cel_report_event(chan_snapshot, AST_CEL_BLINDTRANSFER, NULL, extra, NULL);
01374       ast_json_unref(extra);
01375    }
01376 }

static void cel_bridge_enter_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
) [static]

Definition at line 1152 of file cel.c.

References AST_CEL_BRIDGE_ENTER, ast_free, ast_json_pack(), ast_json_unref(), ast_str_buffer(), ast_bridge_blob::blob, ast_bridge_blob::bridge, cel_filter_channel_snapshot(), cel_generate_peer_str(), cel_report_event(), ast_bridge_blob::channel, NULL, RAII_VAR, stasis_message_data(), ast_bridge_snapshot::technology, and ast_bridge_snapshot::uniqueid.

Referenced by create_routes().

01155 {
01156    struct ast_bridge_blob *blob = stasis_message_data(message);
01157    struct ast_bridge_snapshot *snapshot = blob->bridge;
01158    struct ast_channel_snapshot *chan_snapshot = blob->channel;
01159    RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref);
01160    RAII_VAR(struct ast_str *, peer_str, NULL, ast_free);
01161 
01162    if (cel_filter_channel_snapshot(chan_snapshot)) {
01163       return;
01164    }
01165 
01166    extra = ast_json_pack("{s: s, s: s}",
01167       "bridge_id", snapshot->uniqueid,
01168       "bridge_technology", snapshot->technology);
01169    if (!extra) {
01170       return;
01171    }
01172 
01173    peer_str = cel_generate_peer_str(snapshot, chan_snapshot);
01174    if (!peer_str) {
01175       return;
01176    }
01177 
01178    cel_report_event(chan_snapshot, AST_CEL_BRIDGE_ENTER, NULL, extra, ast_str_buffer(peer_str));
01179 }

static void cel_bridge_leave_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
) [static]

Definition at line 1181 of file cel.c.

References AST_CEL_BRIDGE_EXIT, ast_free, ast_json_pack(), ast_json_unref(), ast_str_buffer(), ast_bridge_blob::blob, ast_bridge_blob::bridge, cel_filter_channel_snapshot(), cel_generate_peer_str(), cel_report_event(), ast_bridge_blob::channel, NULL, RAII_VAR, stasis_message_data(), ast_bridge_snapshot::technology, and ast_bridge_snapshot::uniqueid.

Referenced by create_routes().

01184 {
01185    struct ast_bridge_blob *blob = stasis_message_data(message);
01186    struct ast_bridge_snapshot *snapshot = blob->bridge;
01187    struct ast_channel_snapshot *chan_snapshot = blob->channel;
01188    RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref);
01189    RAII_VAR(struct ast_str *, peer_str, NULL, ast_free);
01190 
01191    if (cel_filter_channel_snapshot(chan_snapshot)) {
01192       return;
01193    }
01194 
01195    extra = ast_json_pack("{s: s, s: s}",
01196       "bridge_id", snapshot->uniqueid,
01197       "bridge_technology", snapshot->technology);
01198    if (!extra) {
01199       return;
01200    }
01201 
01202    peer_str = cel_generate_peer_str(snapshot, chan_snapshot);
01203    if (!peer_str) {
01204       return;
01205    }
01206 
01207    cel_report_event(chan_snapshot, AST_CEL_BRIDGE_EXIT, NULL, extra, ast_str_buffer(peer_str));
01208 }

static void cel_channel_app_change ( struct ast_channel_snapshot old_snapshot,
struct ast_channel_snapshot new_snapshot 
) [static]

Definition at line 1053 of file cel.c.

References ast_channel_snapshot::appl, AST_CEL_APP_END, AST_CEL_APP_START, ast_strlen_zero, cel_report_event(), and NULL.

01056 {
01057    if (new_snapshot && old_snapshot
01058       && !strcmp(old_snapshot->appl, new_snapshot->appl)) {
01059       return;
01060    }
01061 
01062    /* old snapshot has an application, end it */
01063    if (old_snapshot && !ast_strlen_zero(old_snapshot->appl)) {
01064       cel_report_event(old_snapshot, AST_CEL_APP_END, NULL, NULL, NULL);
01065    }
01066 
01067    /* new snapshot has an application, start it */
01068    if (new_snapshot && !ast_strlen_zero(new_snapshot->appl)) {
01069       cel_report_event(new_snapshot, AST_CEL_APP_START, NULL, NULL, NULL);
01070    }
01071 }

static void cel_channel_linkedid_change ( struct ast_channel_snapshot old_snapshot,
struct ast_channel_snapshot new_snapshot 
) [static]

Definition at line 1035 of file cel.c.

References ast_assert, AST_CEL_LINKEDID_END, ast_cel_track_event(), ast_strlen_zero, cel_linkedid_ref(), check_retire_linkedid(), and ast_channel_snapshot::linkedid.

01038 {
01039    if (!old_snapshot || !new_snapshot) {
01040       return;
01041    }
01042 
01043    ast_assert(!ast_strlen_zero(new_snapshot->linkedid));
01044    ast_assert(!ast_strlen_zero(old_snapshot->linkedid));
01045 
01046    if (ast_cel_track_event(AST_CEL_LINKEDID_END)
01047       && strcmp(old_snapshot->linkedid, new_snapshot->linkedid)) {
01048       cel_linkedid_ref(new_snapshot->linkedid);
01049       check_retire_linkedid(old_snapshot);
01050    }
01051 }

static void cel_channel_state_change ( struct ast_channel_snapshot old_snapshot,
struct ast_channel_snapshot new_snapshot 
) [static]

Handle channel state changes.

Definition at line 989 of file cel.c.

References ao2_cleanup, AST_CEL_ANSWER, AST_CEL_CHANNEL_END, AST_CEL_CHANNEL_START, AST_CEL_HANGUP, AST_CEL_LINKEDID_END, ast_cel_track_event(), AST_FLAG_DEAD, ast_json_pack(), ast_json_unref(), AST_STATE_UP, ast_strlen_zero, ast_test_flag, ast_multi_channel_blob::blob, cel_report_event(), check_retire_linkedid(), ast_channel_snapshot::flags, get_blob_variable(), get_dialstatus_blob(), ast_channel_snapshot::hangupcause, ast_channel_snapshot::hangupsource, NULL, ast_channel_snapshot::state, and ast_channel_snapshot::uniqueid.

00992 {
00993    int is_hungup, was_hungup;
00994 
00995    if (!new_snapshot) {
00996       cel_report_event(old_snapshot, AST_CEL_CHANNEL_END, NULL, NULL, NULL);
00997       if (ast_cel_track_event(AST_CEL_LINKEDID_END)) {
00998          check_retire_linkedid(old_snapshot);
00999       }
01000       return;
01001    }
01002 
01003    if (!old_snapshot) {
01004       cel_report_event(new_snapshot, AST_CEL_CHANNEL_START, NULL, NULL, NULL);
01005       return;
01006    }
01007 
01008    was_hungup = ast_test_flag(&old_snapshot->flags, AST_FLAG_DEAD) ? 1 : 0;
01009    is_hungup = ast_test_flag(&new_snapshot->flags, AST_FLAG_DEAD) ? 1 : 0;
01010 
01011    if (!was_hungup && is_hungup) {
01012       struct ast_json *extra;
01013       struct ast_multi_channel_blob *blob = get_dialstatus_blob(new_snapshot->uniqueid);
01014       const char *dialstatus = "";
01015 
01016       if (blob && !ast_strlen_zero(get_blob_variable(blob, "dialstatus"))) {
01017          dialstatus = get_blob_variable(blob, "dialstatus");
01018       }
01019       extra = ast_json_pack("{s: i, s: s, s: s}",
01020          "hangupcause", new_snapshot->hangupcause,
01021          "hangupsource", new_snapshot->hangupsource,
01022          "dialstatus", dialstatus);
01023       cel_report_event(new_snapshot, AST_CEL_HANGUP, NULL, extra, NULL);
01024       ast_json_unref(extra);
01025       ao2_cleanup(blob);
01026       return;
01027    }
01028 
01029    if (old_snapshot->state != new_snapshot->state && new_snapshot->state == AST_STATE_UP) {
01030       cel_report_event(new_snapshot, AST_CEL_ANSWER, NULL, NULL, NULL);
01031       return;
01032    }
01033 }

static void* cel_config_alloc ( void   )  [static]

Definition at line 218 of file cel.c.

References ao2_alloc, ao2_cleanup, ao2_ref, ast_cel_general_config_alloc(), cel_config_dtor(), NULL, and RAII_VAR.

Referenced by ast_cel_engine_init().

00219 {
00220    RAII_VAR(struct cel_config *, cfg, NULL, ao2_cleanup);
00221 
00222    if (!(cfg = ao2_alloc(sizeof(*cfg), cel_config_dtor))) {
00223       return NULL;
00224    }
00225 
00226    if (!(cfg->general = ast_cel_general_config_alloc())) {
00227       return NULL;
00228    }
00229 
00230    ao2_ref(cfg, +1);
00231    return cfg;
00232 }

static void cel_config_dtor ( void *  obj  )  [static]

Destructor for cel_config.

Definition at line 211 of file cel.c.

References ao2_cleanup, cel_config::general, and NULL.

Referenced by cel_config_alloc().

00212 {
00213    struct cel_config *cfg = obj;
00214    ao2_cleanup(cfg->general);
00215    cfg->general = NULL;
00216 }

static void cel_dial_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
) [static]

Definition at line 1298 of file cel.c.

References AST_CEL_FORWARD, ast_json_pack(), ast_json_unref(), ast_multi_channel_blob_get_channel(), ast_strlen_zero, ast_multi_channel_blob::blob, cel_filter_channel_snapshot(), cel_report_event(), get_blob_variable(), get_caller_uniqueid(), is_valid_dialstatus(), NULL, save_dialstatus(), and stasis_message_data().

Referenced by create_routes().

01300 {
01301    struct ast_multi_channel_blob *blob = stasis_message_data(message);
01302 
01303    if (cel_filter_channel_snapshot(ast_multi_channel_blob_get_channel(blob, "caller"))) {
01304       return;
01305    }
01306 
01307    if (!get_caller_uniqueid(blob)) {
01308       return;
01309    }
01310 
01311    if (!ast_strlen_zero(get_blob_variable(blob, "forward"))) {
01312       struct ast_channel_snapshot *caller = ast_multi_channel_blob_get_channel(blob, "caller");
01313       struct ast_json *extra;
01314 
01315       if (!caller) {
01316          return;
01317       }
01318 
01319       extra = ast_json_pack("{s: s}", "forward", get_blob_variable(blob, "forward"));
01320       if (extra) {
01321          cel_report_event(caller, AST_CEL_FORWARD, NULL, extra, NULL);
01322          ast_json_unref(extra);
01323       }
01324    }
01325 
01326    if (is_valid_dialstatus(blob)) {
01327       save_dialstatus(blob);
01328    }
01329 }

static void cel_engine_cleanup ( void   )  [static]

Definition at line 1507 of file cel.c.

References aco_info_destroy(), ao2_global_obj_release, ast_cli_unregister(), cel_generic_type(), destroy_routes(), destroy_subscriptions(), and STASIS_MESSAGE_TYPE_CLEANUP.

Referenced by ast_cel_engine_init().

01508 {
01509    destroy_routes();
01510    destroy_subscriptions();
01511    STASIS_MESSAGE_TYPE_CLEANUP(cel_generic_type);
01512 
01513    ast_cli_unregister(&cli_status);
01514    aco_info_destroy(&cel_cfg_info);
01515    ao2_global_obj_release(cel_configs);
01516    ao2_global_obj_release(cel_dialstatus_store);
01517    ao2_global_obj_release(cel_linkedids);
01518    ao2_global_obj_release(cel_backends);
01519 }

static int cel_filter_channel_snapshot ( struct ast_channel_snapshot snapshot  )  [static]

Definition at line 1084 of file cel.c.

References AST_CHAN_TP_INTERNAL, and ast_channel_snapshot::tech_properties.

Referenced by cel_bridge_enter_cb(), cel_bridge_leave_cb(), cel_dial_cb(), and cel_snapshot_update_cb().

01085 {
01086    if (!snapshot) {
01087       return 0;
01088    }
01089    return snapshot->tech_properties & AST_CHAN_TP_INTERNAL;
01090 }

static void cel_general_config_dtor ( void *  obj  )  [static]

Destructor for cel_config.

Definition at line 174 of file cel.c.

References ao2_cleanup, ast_cel_general_config::apps, ast_string_field_free_memory, and NULL.

Referenced by ast_cel_general_config_alloc().

00175 {
00176    struct ast_cel_general_config *cfg = obj;
00177    ast_string_field_free_memory(cfg);
00178    ao2_cleanup(cfg->apps);
00179    cfg->apps = NULL;
00180 }

static struct ast_str* cel_generate_peer_str ( struct ast_bridge_snapshot bridge,
struct ast_channel_snapshot chan 
) [static, read]

Definition at line 1114 of file cel.c.

References ao2_cleanup, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ast_channel_snapshot_get_latest(), ast_str_append(), ast_str_create(), ast_str_truncate(), ast_bridge_snapshot::channels, ast_channel_snapshot::name, NULL, and ast_channel_snapshot::uniqueid.

Referenced by cel_bridge_enter_cb(), and cel_bridge_leave_cb().

01117 {
01118    struct ast_str *peer_str = ast_str_create(32);
01119    struct ao2_iterator i;
01120    char *current_chan = NULL;
01121 
01122    if (!peer_str) {
01123       return NULL;
01124    }
01125 
01126    for (i = ao2_iterator_init(bridge->channels, 0);
01127       (current_chan = ao2_iterator_next(&i));
01128       ao2_cleanup(current_chan)) {
01129       struct ast_channel_snapshot *current_snapshot;
01130 
01131       /* Don't add the channel for which this message is being generated */
01132       if (!strcmp(current_chan, chan->uniqueid)) {
01133          continue;
01134       }
01135 
01136       current_snapshot = ast_channel_snapshot_get_latest(current_chan);
01137       if (!current_snapshot) {
01138          continue;
01139       }
01140 
01141       ast_str_append(&peer_str, 0, "%s,", current_snapshot->name);
01142       ao2_cleanup(current_snapshot);
01143    }
01144    ao2_iterator_destroy(&i);
01145 
01146    /* Rip off the trailing comma */
01147    ast_str_truncate(peer_str, -1);
01148 
01149    return peer_str;
01150 }

static void cel_generic_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
) [static]

Definition at line 1331 of file cel.c.

References ast_cel_get_type_name(), AST_CEL_USER_DEFINED, ast_json_integer_get(), ast_json_object_get(), ast_json_string_get(), ast_log, ast_channel_blob::blob, cel_report_event(), LOG_ERROR, NULL, ast_channel_blob::snapshot, and stasis_message_data().

Referenced by create_routes().

01334 {
01335    struct ast_channel_blob *obj = stasis_message_data(message);
01336    int event_type = ast_json_integer_get(ast_json_object_get(obj->blob, "event_type"));
01337    struct ast_json *event_details = ast_json_object_get(obj->blob, "event_details");
01338 
01339    switch (event_type) {
01340    case AST_CEL_USER_DEFINED:
01341       {
01342          const char *event = ast_json_string_get(ast_json_object_get(event_details, "event"));
01343          struct ast_json *extra = ast_json_object_get(event_details, "extra");
01344          cel_report_event(obj->snapshot, event_type, event, extra, NULL);
01345          break;
01346       }
01347    default:
01348       ast_log(LOG_ERROR, "Unhandled %s event blob\n", ast_cel_get_type_name(event_type));
01349       break;
01350    }
01351 }

struct stasis_message_type* cel_generic_type ( void   )  [read]

static int cel_linkedid_ref ( const char *  linkedid  )  [static]

Definition at line 875 of file cel.c.

References AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_cleanup, ao2_find, ao2_global_obj_ref, ao2_link, ao2_lock, ao2_ref, ao2_unlock, ast_log, ast_strlen_zero, cel_linkedid::count, cel_linkedid::id, LOG_ERROR, NULL, OBJ_SEARCH_KEY, and RAII_VAR.

Referenced by cel_channel_linkedid_change(), and cel_report_event().

00876 {
00877    RAII_VAR(struct ao2_container *, linkedids, ao2_global_obj_ref(cel_linkedids), ao2_cleanup);
00878    struct cel_linkedid *lid;
00879 
00880    if (ast_strlen_zero(linkedid)) {
00881       ast_log(LOG_ERROR, "The linkedid should never be empty\n");
00882       return -1;
00883    }
00884    if (!linkedids) {
00885       /* The CEL module is shutdown.  Abort. */
00886       return -1;
00887    }
00888 
00889    ao2_lock(linkedids);
00890    lid = ao2_find(linkedids, (void *) linkedid, OBJ_SEARCH_KEY);
00891    if (!lid) {
00892       /*
00893        * Changes to the lid->count member are protected by the
00894        * container lock so the lid object does not need its own lock.
00895        */
00896       lid = ao2_alloc_options(sizeof(*lid) + strlen(linkedid) + 1, NULL,
00897          AO2_ALLOC_OPT_LOCK_NOLOCK);
00898       if (!lid) {
00899          ao2_unlock(linkedids);
00900          return -1;
00901       }
00902       strcpy(lid->id, linkedid);/* Safe */
00903 
00904       ao2_link(linkedids, lid);
00905    }
00906    ++lid->count;
00907    ao2_unlock(linkedids);
00908    ao2_ref(lid, -1);
00909 
00910    return 0;
00911 }

static void cel_local_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
) [static]

Definition at line 1464 of file cel.c.

References AST_CEL_LOCAL_OPTIMIZE, ast_json_pack(), ast_json_unref(), ast_multi_channel_blob_get_channel(), cel_report_event(), ast_channel_snapshot::name, NULL, stasis_message_data(), and ast_channel_snapshot::uniqueid.

Referenced by create_routes().

01467 {
01468    struct ast_multi_channel_blob *obj = stasis_message_data(message);
01469    struct ast_channel_snapshot *localone = ast_multi_channel_blob_get_channel(obj, "1");
01470    struct ast_channel_snapshot *localtwo = ast_multi_channel_blob_get_channel(obj, "2");
01471    struct ast_json *extra;
01472 
01473    if (!localone || !localtwo) {
01474       return;
01475    }
01476 
01477    extra = ast_json_pack("{s: s, s: s}",
01478       "local_two", localtwo->name,
01479       "local_two_uniqueid", localtwo->uniqueid);
01480    if (!extra) {
01481       return;
01482    }
01483 
01484    cel_report_event(localone, AST_CEL_LOCAL_OPTIMIZE, NULL, extra, NULL);
01485    ast_json_unref(extra);
01486 }

static void cel_parking_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
) [static]

Definition at line 1210 of file cel.c.

References AST_CEL_PARK_END, AST_CEL_PARK_START, ast_json_pack(), ast_json_unref(), cel_report_event(), ast_parked_call_payload::event_type, ast_channel_snapshot::name, NULL, PARKED_CALL, PARKED_CALL_FAILED, PARKED_CALL_GIVEUP, PARKED_CALL_SWAP, PARKED_CALL_TIMEOUT, PARKED_CALL_UNPARKED, ast_parked_call_payload::parkee, ast_parked_call_payload::parker_dial_string, ast_parked_call_payload::parkinglot, RAII_VAR, ast_parked_call_payload::retriever, and stasis_message_data().

Referenced by create_routes().

01213 {
01214    struct ast_parked_call_payload *parked_payload = stasis_message_data(message);
01215    RAII_VAR(struct ast_json *, extra, NULL, ast_json_unref);
01216    const char *reason = NULL;
01217 
01218    switch (parked_payload->event_type) {
01219    case PARKED_CALL:
01220       extra = ast_json_pack("{s: s, s: s}",
01221          "parker_dial_string", parked_payload->parker_dial_string,
01222          "parking_lot", parked_payload->parkinglot);
01223       if (extra) {
01224          cel_report_event(parked_payload->parkee, AST_CEL_PARK_START, NULL, extra, NULL);
01225       }
01226       return;
01227    case PARKED_CALL_TIMEOUT:
01228       reason = "ParkedCallTimeOut";
01229       break;
01230    case PARKED_CALL_GIVEUP:
01231       reason = "ParkedCallGiveUp";
01232       break;
01233    case PARKED_CALL_UNPARKED:
01234       reason = "ParkedCallUnparked";
01235       break;
01236    case PARKED_CALL_FAILED:
01237       reason = "ParkedCallFailed";
01238       break;
01239    case PARKED_CALL_SWAP:
01240       reason = "ParkedCallSwap";
01241       break;
01242    }
01243 
01244    if (parked_payload->retriever) {
01245       extra = ast_json_pack("{s: s, s: s}",
01246          "reason", reason,
01247          "retriever", parked_payload->retriever->name);
01248    } else {
01249       extra = ast_json_pack("{s: s}", "reason", reason);
01250    }
01251 
01252    if (extra) {
01253       cel_report_event(parked_payload->parkee, AST_CEL_PARK_END, NULL, extra, NULL);
01254    }
01255 }

static void cel_pickup_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
) [static]

Definition at line 1440 of file cel.c.

References AST_CEL_PICKUP, ast_json_pack(), ast_json_unref(), ast_multi_channel_blob_get_channel(), cel_report_event(), ast_channel_snapshot::name, NULL, stasis_message_data(), and ast_channel_snapshot::uniqueid.

Referenced by create_routes().

01443 {
01444    struct ast_multi_channel_blob *obj = stasis_message_data(message);
01445    struct ast_channel_snapshot *channel = ast_multi_channel_blob_get_channel(obj, "channel");
01446    struct ast_channel_snapshot *target = ast_multi_channel_blob_get_channel(obj, "target");
01447    struct ast_json *extra;
01448 
01449    if (!channel || !target) {
01450       return;
01451    }
01452 
01453    extra = ast_json_pack("{s: s, s: s}",
01454       "pickup_channel", channel->name,
01455       "pickup_channel_uniqueid", channel->uniqueid);
01456    if (!extra) {
01457       return;
01458    }
01459 
01460    cel_report_event(target, AST_CEL_PICKUP, NULL, extra, NULL);
01461    ast_json_unref(extra);
01462 }

static int cel_pre_apply_config ( void   )  [static]

Definition at line 257 of file cel.c.

References aco_pending_config(), ao2_container_count(), ast_cel_general_config::apps, AST_CEL_APP_END, AST_CEL_APP_START, ast_log, ast_cel_general_config::events, cel_config::general, and LOG_ERROR.

00258 {
00259    struct cel_config *cfg = aco_pending_config(&cel_cfg_info);
00260 
00261    if (!cfg->general) {
00262       return -1;
00263    }
00264 
00265    if (!ao2_container_count(cfg->general->apps)) {
00266       return 0;
00267    }
00268 
00269    if (cfg->general->events & ((int64_t) 1 << AST_CEL_APP_START)) {
00270       return 0;
00271    }
00272 
00273    if (cfg->general->events & ((int64_t) 1 << AST_CEL_APP_END)) {
00274       return 0;
00275    }
00276 
00277    ast_log(LOG_ERROR, "Applications are listed to be tracked, but APP events are not tracked\n");
00278    return -1;
00279 }

static int cel_report_event ( struct ast_channel_snapshot snapshot,
enum ast_cel_event_type  event_type,
const char *  userdefevname,
struct ast_json extra,
const char *  peer_str 
) [static]

Definition at line 664 of file cel.c.

References ao2_callback, ao2_cleanup, ao2_global_obj_ref, ast_channel_snapshot::appl, AST_CEL_APP_END, AST_CEL_APP_START, AST_CEL_CHANNEL_START, ast_cel_create_event(), AST_CEL_LINKEDID_END, ast_cel_track_event(), ast_event_destroy(), cel_backend_send_cb(), cel_linkedid_ref(), cel_track_app(), ast_channel_snapshot::linkedid, OBJ_MULTIPLE, OBJ_NODATA, and RAII_VAR.

Referenced by cel_attended_transfer_cb(), cel_blind_transfer_cb(), cel_bridge_enter_cb(), cel_bridge_leave_cb(), cel_channel_app_change(), cel_channel_state_change(), cel_dial_cb(), cel_generic_cb(), cel_local_cb(), cel_parking_cb(), cel_pickup_cb(), and check_retire_linkedid().

00667 {
00668    struct ast_event *ev;
00669    RAII_VAR(struct cel_config *, cfg, ao2_global_obj_ref(cel_configs), ao2_cleanup);
00670    RAII_VAR(struct ao2_container *, backends, ao2_global_obj_ref(cel_backends), ao2_cleanup);
00671 
00672    if (!cfg || !cfg->general || !cfg->general->enable || !backends) {
00673       return 0;
00674    }
00675 
00676    /* Record the linkedid of new channels if we are tracking LINKEDID_END even if we aren't
00677     * reporting on CHANNEL_START so we can track when to send LINKEDID_END */
00678    if (event_type == AST_CEL_CHANNEL_START
00679       && ast_cel_track_event(AST_CEL_LINKEDID_END)) {
00680       if (cel_linkedid_ref(snapshot->linkedid)) {
00681          return -1;
00682       }
00683    }
00684 
00685    if (!ast_cel_track_event(event_type)) {
00686       return 0;
00687    }
00688 
00689    if ((event_type == AST_CEL_APP_START || event_type == AST_CEL_APP_END)
00690       && !cel_track_app(snapshot->appl)) {
00691       return 0;
00692    }
00693 
00694    ev = ast_cel_create_event(snapshot, event_type, userdefevname, extra, peer_str);
00695    if (!ev) {
00696       return -1;
00697    }
00698 
00699    /* Distribute event to backends */
00700    ao2_callback(backends, OBJ_MULTIPLE | OBJ_NODATA, cel_backend_send_cb, ev);
00701    ast_event_destroy(ev);
00702 
00703    return 0;
00704 }

static void cel_snapshot_update_cb ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
) [static]

Definition at line 1092 of file cel.c.

References ARRAY_LEN, ast_channel_snapshot_type(), cel_filter_channel_snapshot(), stasis_cache_update::new_snapshot, stasis_cache_update::old_snapshot, stasis_message_data(), stasis_cache_update::type, and update().

Referenced by create_routes().

01094 {
01095    struct stasis_cache_update *update = stasis_message_data(message);
01096    if (ast_channel_snapshot_type() == update->type) {
01097       struct ast_channel_snapshot *old_snapshot;
01098       struct ast_channel_snapshot *new_snapshot;
01099       size_t i;
01100 
01101       old_snapshot = stasis_message_data(update->old_snapshot);
01102       new_snapshot = stasis_message_data(update->new_snapshot);
01103 
01104       if (cel_filter_channel_snapshot(old_snapshot) || cel_filter_channel_snapshot(new_snapshot)) {
01105          return;
01106       }
01107 
01108       for (i = 0; i < ARRAY_LEN(cel_channel_monitors); ++i) {
01109          cel_channel_monitors[i](old_snapshot, new_snapshot);
01110       }
01111    }
01112 }

static int cel_track_app ( const char *  const_app  )  [static]

Definition at line 600 of file cel.c.

References ao2_cleanup, ao2_find, ao2_global_obj_ref, app, ast_str_to_lower(), ast_strdupa, NULL, OBJ_SEARCH_KEY, and RAII_VAR.

Referenced by cel_report_event().

00601 {
00602    RAII_VAR(struct cel_config *, cfg, ao2_global_obj_ref(cel_configs), ao2_cleanup);
00603    RAII_VAR(char *, app, NULL, ao2_cleanup);
00604    char *app_lower;
00605 
00606    if (!cfg || !cfg->general) {
00607       return 0;
00608    }
00609 
00610    app_lower = ast_str_to_lower(ast_strdupa(const_app));
00611    app = ao2_find(cfg->general->apps, app_lower, OBJ_SEARCH_KEY);
00612    if (!app) {
00613       return 0;
00614    }
00615 
00616    return 1;
00617 }

static void check_retire_linkedid ( struct ast_channel_snapshot snapshot  )  [static]

Definition at line 708 of file cel.c.

References ao2_cleanup, ao2_find, ao2_global_obj_ref, ao2_lock, ao2_ref, ao2_unlink, ao2_unlock, AST_CEL_LINKEDID_END, ast_log, ast_strlen_zero, cel_report_event(), cel_linkedid::count, ast_channel_snapshot::linkedid, LOG_ERROR, NULL, OBJ_SEARCH_KEY, and RAII_VAR.

Referenced by cel_channel_linkedid_change(), and cel_channel_state_change().

00709 {
00710    RAII_VAR(struct ao2_container *, linkedids, ao2_global_obj_ref(cel_linkedids), ao2_cleanup);
00711    struct cel_linkedid *lid;
00712 
00713    if (!linkedids || ast_strlen_zero(snapshot->linkedid)) {
00714       /* The CEL module is shutdown.  Abort. */
00715       return;
00716    }
00717 
00718    ao2_lock(linkedids);
00719 
00720    lid = ao2_find(linkedids, (void *) snapshot->linkedid, OBJ_SEARCH_KEY);
00721    if (!lid) {
00722       ao2_unlock(linkedids);
00723 
00724       /*
00725        * The user may have done a reload to start tracking linkedids
00726        * when a call was already in progress.  This is an unusual kind
00727        * of change to make after starting Asterisk.
00728        */
00729       ast_log(LOG_ERROR, "Something weird happened, couldn't find linkedid %s\n",
00730          snapshot->linkedid);
00731       return;
00732    }
00733 
00734    if (!--lid->count) {
00735       /* No channels use this linkedid anymore. */
00736       ao2_unlink(linkedids, lid);
00737       ao2_unlock(linkedids);
00738 
00739       cel_report_event(snapshot, AST_CEL_LINKEDID_END, NULL, NULL, NULL);
00740    } else {
00741       ao2_unlock(linkedids);
00742    }
00743    ao2_ref(lid, -1);
00744 }

CONFIG_INFO_CORE ( "cel"  ,
cel_cfg_info  ,
cel_configs  ,
cel_config_alloc  ,
files = ACO_FILES(&cel_conf),
pre_apply_config = cel_pre_apply_config 
)

static int create_routes ( void   )  [static]

Create the Stasis message router and routes for CEL.

Definition at line 1570 of file cel.c.

References ast_attended_transfer_type(), ast_blind_transfer_type(), ast_call_pickup_type(), ast_channel_dial_type(), ast_channel_entered_bridge_type(), ast_channel_left_bridge_type(), ast_local_optimization_end_type(), ast_log, AST_LOG_ERROR, ast_parked_call_type(), cel_attended_transfer_cb(), cel_blind_transfer_cb(), cel_bridge_enter_cb(), cel_bridge_leave_cb(), cel_dial_cb(), cel_generic_cb(), cel_generic_type(), cel_local_cb(), cel_parking_cb(), cel_pickup_cb(), cel_snapshot_update_cb(), NULL, stasis_cache_update_type(), stasis_message_router_add(), and stasis_message_router_create().

Referenced by ast_cel_engine_init(), ast_cel_engine_reload(), and ast_cel_set_config().

01571 {
01572    int ret = 0;
01573 
01574    cel_state_router = stasis_message_router_create(cel_aggregation_topic);
01575    if (!cel_state_router) {
01576       return -1;
01577    }
01578 
01579    ret |= stasis_message_router_add(cel_state_router,
01580       stasis_cache_update_type(),
01581       cel_snapshot_update_cb,
01582       NULL);
01583 
01584    ret |= stasis_message_router_add(cel_state_router,
01585       ast_channel_dial_type(),
01586       cel_dial_cb,
01587       NULL);
01588 
01589    ret |= stasis_message_router_add(cel_state_router,
01590       ast_channel_entered_bridge_type(),
01591       cel_bridge_enter_cb,
01592       NULL);
01593 
01594    ret |= stasis_message_router_add(cel_state_router,
01595       ast_channel_left_bridge_type(),
01596       cel_bridge_leave_cb,
01597       NULL);
01598 
01599    ret |= stasis_message_router_add(cel_state_router,
01600       ast_parked_call_type(),
01601       cel_parking_cb,
01602       NULL);
01603 
01604    ret |= stasis_message_router_add(cel_state_router,
01605       cel_generic_type(),
01606       cel_generic_cb,
01607       NULL);
01608 
01609    ret |= stasis_message_router_add(cel_state_router,
01610       ast_blind_transfer_type(),
01611       cel_blind_transfer_cb,
01612       NULL);
01613 
01614    ret |= stasis_message_router_add(cel_state_router,
01615       ast_attended_transfer_type(),
01616       cel_attended_transfer_cb,
01617       NULL);
01618 
01619    ret |= stasis_message_router_add(cel_state_router,
01620       ast_call_pickup_type(),
01621       cel_pickup_cb,
01622       NULL);
01623 
01624    ret |= stasis_message_router_add(cel_state_router,
01625       ast_local_optimization_end_type(),
01626       cel_local_cb,
01627       NULL);
01628 
01629    if (ret) {
01630       ast_log(AST_LOG_ERROR, "Failed to register for Stasis messages\n");
01631    }
01632 
01633    return ret;
01634 }

static int create_subscriptions ( void   )  [static]

Create the Stasis subscriptions for CEL.

Definition at line 1524 of file cel.c.

References ast_bridge_topic_all_cached(), ast_cel_topic(), ast_channel_topic_all_cached(), ast_parking_topic(), stasis_forward_all(), and stasis_topic_create().

01525 {
01526    cel_aggregation_topic = stasis_topic_create("cel_aggregation_topic");
01527    if (!cel_aggregation_topic) {
01528       return -1;
01529    }
01530 
01531    cel_topic = stasis_topic_create("cel_topic");
01532    if (!cel_topic) {
01533       return -1;
01534    }
01535 
01536    cel_channel_forwarder = stasis_forward_all(
01537       ast_channel_topic_all_cached(),
01538       cel_aggregation_topic);
01539    if (!cel_channel_forwarder) {
01540       return -1;
01541    }
01542 
01543    cel_bridge_forwarder = stasis_forward_all(
01544       ast_bridge_topic_all_cached(),
01545       cel_aggregation_topic);
01546    if (!cel_bridge_forwarder) {
01547       return -1;
01548    }
01549 
01550    cel_parking_forwarder = stasis_forward_all(
01551       ast_parking_topic(),
01552       cel_aggregation_topic);
01553    if (!cel_parking_forwarder) {
01554       return -1;
01555    }
01556 
01557    cel_cel_forwarder = stasis_forward_all(
01558       ast_cel_topic(),
01559       cel_aggregation_topic);
01560    if (!cel_cel_forwarder) {
01561       return -1;
01562    }
01563 
01564    return 0;
01565 }

static void destroy_routes ( void   )  [static]

static void destroy_subscriptions ( void   )  [static]

static int dialstatus_cmp ( void *  obj,
void *  arg,
int  flags 
) [static]

Comparator function for dialstatus container.

Definition at line 408 of file cel.c.

References CMP_MATCH, get_caller_uniqueid(), OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, and OBJ_SEARCH_PARTIAL_KEY.

Referenced by ast_cel_engine_init().

00409 {
00410    struct ast_multi_channel_blob *object_left = obj;
00411    struct ast_multi_channel_blob *object_right = arg;
00412    const char *right_key = arg;
00413    int cmp;
00414 
00415    switch (flags & OBJ_SEARCH_MASK) {
00416    case OBJ_SEARCH_OBJECT:
00417       right_key = get_caller_uniqueid(object_right);
00418       /* Fall through */
00419    case OBJ_SEARCH_KEY:
00420       cmp = strcmp(get_caller_uniqueid(object_left), right_key);
00421       break;
00422    case OBJ_SEARCH_PARTIAL_KEY:
00423       /*
00424        * We could also use a partial key struct containing a length
00425        * so strlen() does not get called for every comparison instead.
00426        */
00427       cmp = strncmp(get_caller_uniqueid(object_left), right_key, strlen(right_key));
00428       break;
00429    default:
00430       /*
00431        * What arg points to is specific to this traversal callback
00432        * and has no special meaning to astobj2.
00433        */
00434       cmp = 0;
00435       break;
00436    }
00437    if (cmp) {
00438       return 0;
00439    }
00440    /*
00441     * At this point the traversal callback is identical to a sorted
00442     * container.
00443     */
00444    return CMP_MATCH;
00445 }

static int dialstatus_hash ( const void *  obj,
int  flags 
) [static]

Hashing function for dialstatus container.

Definition at line 386 of file cel.c.

References ast_assert, ast_str_hash(), ast_multi_channel_blob::blob, get_caller_uniqueid(), OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, and OBJ_SEARCH_OBJECT.

Referenced by ast_cel_engine_init().

00387 {
00388    struct ast_multi_channel_blob *blob;
00389    const char *key;
00390 
00391    switch (flags & OBJ_SEARCH_MASK) {
00392    case OBJ_SEARCH_KEY:
00393       key = obj;
00394       break;
00395    case OBJ_SEARCH_OBJECT:
00396       blob = (void *) obj;
00397       key = get_caller_uniqueid(blob);
00398       break;
00399    default:
00400       /* Hash can only work on something with a full key. */
00401       ast_assert(0);
00402       return 0;
00403    }
00404    return ast_str_hash(key);
00405 }

static int events_handler ( const struct aco_option opt,
struct ast_variable var,
void *  obj 
) [static]

Definition at line 547 of file cel.c.

References AST_CEL_ALL, AST_CEL_INVALID_VALUE, ast_cel_str_to_event_type(), ast_strdupa, ast_strip(), ast_strlen_zero, ast_cel_general_config::events, events, strsep(), and ast_variable::value.

Referenced by ast_cel_engine_init().

00548 {
00549    struct ast_cel_general_config *cfg = obj;
00550    char *events = ast_strdupa(var->value);
00551    char *cur_event;
00552 
00553    while ((cur_event = strsep(&events, ","))) {
00554       enum ast_cel_event_type event_type;
00555 
00556       cur_event = ast_strip(cur_event);
00557       if (ast_strlen_zero(cur_event)) {
00558          continue;
00559       }
00560 
00561       event_type = ast_cel_str_to_event_type(cur_event);
00562 
00563       if (event_type == AST_CEL_ALL) {
00564          /* All events */
00565          cfg->events = (int64_t) -1;
00566       } else if (event_type == AST_CEL_INVALID_VALUE) {
00567          return -1;
00568       } else {
00569          cfg->events |= ((int64_t) 1 << event_type);
00570       }
00571    }
00572 
00573    return 0;
00574 }

static const char* get_blob_variable ( struct ast_multi_channel_blob blob,
const char *  varname 
) [static]

Definition at line 973 of file cel.c.

References ast_json_object_get(), ast_json_string_get(), ast_multi_channel_blob_get_json(), and NULL.

Referenced by cel_channel_state_change(), cel_dial_cb(), and is_valid_dialstatus().

00974 {
00975    struct ast_json *json = ast_multi_channel_blob_get_json(blob);
00976    if (!json) {
00977       return NULL;
00978    }
00979 
00980    json = ast_json_object_get(json, varname);
00981    if (!json) {
00982       return NULL;
00983    }
00984 
00985    return ast_json_string_get(json);
00986 }

static const char* get_caller_uniqueid ( struct ast_multi_channel_blob blob  )  [static]

Definition at line 375 of file cel.c.

References ast_multi_channel_blob_get_channel(), NULL, and ast_channel_snapshot::uniqueid.

Referenced by cel_dial_cb(), dialstatus_cmp(), and dialstatus_hash().

00376 {
00377    struct ast_channel_snapshot *caller = ast_multi_channel_blob_get_channel(blob, "caller");
00378    if (!caller) {
00379       return NULL;
00380    }
00381 
00382    return caller->uniqueid;
00383 }

static struct ast_multi_channel_blob* get_dialstatus_blob ( const char *  uniqueid  )  [static, read]

Definition at line 961 of file cel.c.

References ao2_find, ao2_global_obj_ref, ao2_ref, ast_multi_channel_blob::blob, NULL, OBJ_SEARCH_KEY, and OBJ_UNLINK.

Referenced by cel_channel_state_change().

00962 {
00963    struct ao2_container *dial_statuses = ao2_global_obj_ref(cel_dialstatus_store);
00964    struct ast_multi_channel_blob *blob = NULL;
00965 
00966    if (dial_statuses) {
00967       blob = ao2_find(dial_statuses, uniqueid, OBJ_SEARCH_KEY | OBJ_UNLINK);
00968       ao2_ref(dial_statuses, -1);
00969    }
00970    return blob;
00971 }

static char* handle_cli_status ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 457 of file cel.c.

References ao2_cleanup, ao2_global_obj_ref, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, app, ast_cli_args::argc, ast_cel_check_enabled(), ast_cel_get_type_name(), ast_cli(), CLI_GENERATE, CLI_HANDLER, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, cel_backend::name, name, NULL, RAII_VAR, and ast_cli_entry::usage.

00458 {
00459    unsigned int i;
00460    RAII_VAR(struct cel_config *, cfg, ao2_global_obj_ref(cel_configs), ao2_cleanup);
00461    RAII_VAR(struct ao2_container *, backends, ao2_global_obj_ref(cel_backends), ao2_cleanup);
00462    struct ao2_iterator iter;
00463    char *app;
00464 
00465    switch (cmd) {
00466    case CLI_INIT:
00467       e->command = "cel show status";
00468       e->usage =
00469          "Usage: cel show status\n"
00470          "       Displays the Channel Event Logging system status.\n";
00471       return NULL;
00472    case CLI_GENERATE:
00473       return NULL;
00474    case CLI_HANDLER:
00475       break;
00476    }
00477 
00478    if (a->argc > 3) {
00479       return CLI_SHOWUSAGE;
00480    }
00481 
00482    ast_cli(a->fd, "CEL Logging: %s\n", ast_cel_check_enabled() ? "Enabled" : "Disabled");
00483 
00484    if (!cfg || !cfg->general || !cfg->general->enable) {
00485       return CLI_SUCCESS;
00486    }
00487 
00488    for (i = 0; i < (sizeof(cfg->general->events) * 8); i++) {
00489       const char *name;
00490 
00491       if (!(cfg->general->events & ((int64_t) 1 << i))) {
00492          continue;
00493       }
00494 
00495       name = ast_cel_get_type_name(i);
00496       if (strcasecmp(name, "Unknown")) {
00497          ast_cli(a->fd, "CEL Tracking Event: %s\n", name);
00498       }
00499    }
00500 
00501    iter = ao2_iterator_init(cfg->general->apps, 0);
00502    for (; (app = ao2_iterator_next(&iter)); ao2_ref(app, -1)) {
00503       ast_cli(a->fd, "CEL Tracking Application: %s\n", app);
00504    }
00505    ao2_iterator_destroy(&iter);
00506 
00507    if (backends) {
00508       struct cel_backend *backend;
00509 
00510       iter = ao2_iterator_init(backends, 0);
00511       for (; (backend = ao2_iterator_next(&iter)); ao2_ref(backend, -1)) {
00512          ast_cli(a->fd, "CEL Event Subscriber: %s\n", backend->name);
00513       }
00514       ao2_iterator_destroy(&iter);
00515    }
00516 
00517    return CLI_SUCCESS;
00518 }

static int is_valid_dialstatus ( struct ast_multi_channel_blob blob  )  [static]

Definition at line 1269 of file cel.c.

References ast_strlen_zero, and get_blob_variable().

Referenced by cel_dial_cb().

01270 {
01271    const char *dialstatus = get_blob_variable(blob, "dialstatus");
01272    int res = 0;
01273 
01274    if (ast_strlen_zero(dialstatus)) {
01275       res = 0;
01276    } else if (!strcasecmp(dialstatus, "CHANUNAVAIL")) {
01277       res = 1;
01278    } else if (!strcasecmp(dialstatus, "CONGESTION")) {
01279       res = 1;
01280    } else if (!strcasecmp(dialstatus, "NOANSWER")) {
01281       res = 1;
01282    } else if (!strcasecmp(dialstatus, "BUSY")) {
01283       res = 1;
01284    } else if (!strcasecmp(dialstatus, "ANSWER")) {
01285       res = 1;
01286    } else if (!strcasecmp(dialstatus, "CANCEL")) {
01287       res = 1;
01288    } else if (!strcasecmp(dialstatus, "DONTCALL")) {
01289       res = 1;
01290    } else if (!strcasecmp(dialstatus, "TORTURE")) {
01291       res = 1;
01292    } else if (!strcasecmp(dialstatus, "INVALIDARGS")) {
01293       res = 1;
01294    }
01295    return res;
01296 }

static int lid_cmp ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 1657 of file cel.c.

References CMP_MATCH, cel_linkedid::id, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, OBJ_SEARCH_OBJECT, and OBJ_SEARCH_PARTIAL_KEY.

Referenced by ast_cel_engine_init().

01658 {
01659    const struct cel_linkedid *object_left = obj;
01660    const struct cel_linkedid *object_right = arg;
01661    const char *right_key = arg;
01662    int cmp;
01663 
01664    switch (flags & OBJ_SEARCH_MASK) {
01665    case OBJ_SEARCH_OBJECT:
01666       right_key = object_right->id;
01667       /* Fall through */
01668    case OBJ_SEARCH_KEY:
01669       cmp = strcmp(object_left->id, right_key);
01670       break;
01671    case OBJ_SEARCH_PARTIAL_KEY:
01672       /*
01673        * We could also use a partial key struct containing a length
01674        * so strlen() does not get called for every comparison instead.
01675        */
01676       cmp = strncmp(object_left->id, right_key, strlen(right_key));
01677       break;
01678    default:
01679       /*
01680        * What arg points to is specific to this traversal callback
01681        * and has no special meaning to astobj2.
01682        */
01683       cmp = 0;
01684       break;
01685    }
01686    if (cmp) {
01687       return 0;
01688    }
01689    /*
01690     * At this point the traversal callback is identical to a sorted
01691     * container.
01692     */
01693    return CMP_MATCH;
01694 }

static int lid_hash ( const void *  obj,
const int  flags 
) [static]

Definition at line 1636 of file cel.c.

References ast_assert, ast_str_hash(), cel_linkedid::id, OBJ_SEARCH_KEY, OBJ_SEARCH_MASK, and OBJ_SEARCH_OBJECT.

Referenced by ast_cel_engine_init().

01637 {
01638    const struct cel_linkedid *lid;
01639    const char *key;
01640 
01641    switch (flags & OBJ_SEARCH_MASK) {
01642    case OBJ_SEARCH_KEY:
01643       key = obj;
01644       break;
01645    case OBJ_SEARCH_OBJECT:
01646       lid = obj;
01647       key = lid->id;
01648       break;
01649    default:
01650       /* Hash can only work on something with a full key. */
01651       ast_assert(0);
01652       return 0;
01653    }
01654    return ast_str_hash(key);
01655 }

static void save_dialstatus ( struct ast_multi_channel_blob blob  )  [static]

Definition at line 1257 of file cel.c.

References ao2_global_obj_ref, ao2_link, ao2_ref, ast_assert, and NULL.

Referenced by cel_dial_cb().

01258 {
01259    struct ao2_container *dial_statuses = ao2_global_obj_ref(cel_dialstatus_store);
01260 
01261    ast_assert(blob != NULL);
01262 
01263    if (dial_statuses) {
01264       ao2_link(dial_statuses, blob);
01265       ao2_ref(dial_statuses, -1);
01266    }
01267 }

STASIS_MESSAGE_TYPE_DEFN ( cel_generic_type   ) 


Variable Documentation

Aggregation topic for all topics CEL needs to know about

Definition at line 121 of file cel.c.

Subscription for forwarding the channel caching topic

Definition at line 127 of file cel.c.

Subscription for forwarding the CEL-specific topic

Definition at line 133 of file cel.c.

Subscription for forwarding the channel caching topic

Definition at line 124 of file cel.c.

Initial value:

Definition at line 1078 of file cel.c.

struct aco_file cel_conf [static]

Initial value:

 {
   .filename = "cel.conf",                  
   .types = ACO_TYPES(&general_option),     
   .skip_category = "(^manager$|^radius$)", 
}
The config file to be processed for the module.

Definition at line 244 of file cel.c.

const char* const cel_event_types[CEL_MAX_EVENT_IDS] [static]

Map of ast_cel_event_type to strings.

Definition at line 286 of file cel.c.

Subscription for forwarding the parking topic

Definition at line 130 of file cel.c.

Message router for state that CEL needs to know about

Definition at line 115 of file cel.c.

struct stasis_topic* cel_topic [static]

Topic for CEL-specific messages

Definition at line 118 of file cel.c.

struct ast_cli_entry cli_status = AST_CLI_DEFINE(handle_cli_status, "Display the CEL status") [static]

Definition at line 520 of file cel.c.

Referenced by dnsmgr_init(), and dnsmgr_shutdown().

Initial value:

 {
   .type = "CEL fabricated channel",
   .destroy = ast_free_ptr,
}

Definition at line 749 of file cel.c.

struct aco_type general_option [static]

An aco_type structure to link the "general" category to the ast_cel_general_config type.

Definition at line 235 of file cel.c.

struct aco_type* general_options[] = ACO_TYPES(&general_option) [static]

Definition at line 281 of file cel.c.


Generated on Thu Apr 16 06:29:27 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6