Fri Feb 10 06:35:12 2012

Asterisk developer's documentation


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/cli.h"
#include "asterisk/astobj2.h"

Include dependency graph for cel.c:

Go to the source code of this file.

Data Structures

struct  channel_find_data

Defines

#define CEL_DEFAULT_EVENTS   0
 Track no events by default.
#define CEL_ENABLED_DEFAULT   0
 CEL is off by default.
#define CEL_MAX_EVENT_IDS   64
 Maximum possible CEL event IDs.
#define NUM_APP_BUCKETS   97
 Number of buckets for the appset container.

Functions

static int app_cmp (void *obj, void *arg, int flags)
static int app_hash (const void *obj, const int flags)
unsigned int ast_cel_check_enabled (void)
 Check to see if CEL is enabled.
void ast_cel_check_retire_linkedid (struct ast_channel *chan)
 Check and potentially retire a Linked ID.
int ast_cel_engine_init (void)
int ast_cel_engine_reload (void)
static void ast_cel_engine_term (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.
const char * ast_cel_get_ama_flag_name (enum ast_cel_ama_flag flag)
 Convert AMA flag to printable string.
const char * ast_cel_get_type_name (enum ast_cel_event_type type)
 Get the name of a CEL event type.
int ast_cel_report_event (struct ast_channel *chan, enum ast_cel_event_type event_type, const char *userdefevname, const char *extra, struct ast_channel *peer2)
 Report a channel event.
enum ast_cel_event_type ast_cel_str_to_event_type (const char *name)
 Get the event type from a string.
static int ast_cel_track_event (enum ast_cel_event_type et)
static int do_reload (void)
static char * handle_cli_status (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int linkedid_match (void *obj, void *arg, void *data, int flags)
static void parse_apps (const char *val)
static void parse_events (const char *val)
static int print_app (void *obj, void *arg, int flags)
static void print_cel_sub (const struct ast_event *event, void *data)

Variables

static struct ao2_containerappset
 Container of Asterisk application names.
static const char *const cel_ama_flags [AST_CEL_AMA_FLAG_TOTAL]
 Map of ast_cel_ama_flags to strings.
static char cel_dateformat [256]
 Configured date format for event timestamps.
static unsigned char cel_enabled
static const char *const cel_event_types [CEL_MAX_EVENT_IDS]
 Map of ast_cel_event_type to strings.
static struct ast_cli_entry cli_status = AST_CLI_DEFINE(handle_cli_status, "Display the CEL status")
static int64_t eventset
 which events we want to track
static ast_mutex_t reload_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 }


Detailed Description

Channel Event Logging API.

Author:
Steve Murphy <murf@digium.com>

Russell Bryant <russell@digium.com>

Todo:
Do thorough testing of all transfer methods to ensure that BLINDTRANSFER, ATTENDEDTRANSFER, BRIDGE_START, and BRIDGE_END events are all reported as expected.

Definition in file cel.c.


Define Documentation

#define CEL_DEFAULT_EVENTS   0

Track no events by default.

Definition at line 68 of file cel.c.

Referenced by do_reload().

#define CEL_ENABLED_DEFAULT   0

CEL is off by default.

Definition at line 50 of file cel.c.

Referenced by do_reload().

#define CEL_MAX_EVENT_IDS   64

Maximum possible CEL event IDs.

Note:
This limit is currently imposed by the eventset definition

Definition at line 63 of file cel.c.

#define NUM_APP_BUCKETS   97

Number of buckets for the appset container.

Definition at line 73 of file cel.c.

Referenced by ast_cel_engine_init().


Function Documentation

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

Definition at line 641 of file cel.c.

References app1, app2, CMP_MATCH, and CMP_STOP.

Referenced by ast_cel_engine_init().

00642 {
00643    const char *app1 = obj, *app2 = arg;
00644 
00645    return !strcasecmp(app1, app2) ? CMP_MATCH | CMP_STOP : 0;
00646 }

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

Definition at line 636 of file cel.c.

References ast_str_case_hash().

Referenced by ast_cel_engine_init().

00637 {
00638    return ast_str_case_hash((const char *) obj);
00639 }

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 131 of file cel.c.

00132 {
00133    return cel_enabled;
00134 }

void ast_cel_check_retire_linkedid ( struct ast_channel chan  ) 

Check and potentially retire a Linked ID.

Parameters:
chan channel that is being destroyed or its linkedid is changing
Since:
1.8
If at least one CEL backend is looking for CEL_LINKEDID_END events, this function will check if the given channel is the last active channel with that linkedid, and if it is, emit a CEL_LINKEDID_END event.

Returns:
nothing

Definition at line 382 of file cel.c.

References AST_CEL_LINKEDID_END, ast_cel_report_event(), ast_cel_track_event(), ast_channel_callback(), ast_channel_linkedid(), ast_channel_unref, ast_strlen_zero(), channel_find_data::chan, channel_find_data::linkedid, and linkedid_match().

Referenced by ast_channel_change_linkedid(), and ast_channel_destructor().

00383 {
00384    const char *linkedid = ast_channel_linkedid(chan);
00385    struct channel_find_data find_dat;
00386 
00387    /* make sure we need to do all this work */
00388 
00389    if (!ast_strlen_zero(linkedid) && ast_cel_track_event(AST_CEL_LINKEDID_END)) {
00390       struct ast_channel *tmp = NULL;
00391       find_dat.chan = chan;
00392       find_dat.linkedid = linkedid;
00393       if ((tmp = ast_channel_callback(linkedid_match, NULL, &find_dat, 0))) {
00394          tmp = ast_channel_unref(tmp);
00395       } else {
00396          ast_cel_report_event(chan, AST_CEL_LINKEDID_END, NULL, NULL, NULL);
00397       }
00398    }
00399 }

int ast_cel_engine_init ( void   ) 

Provided by cel.c

Definition at line 656 of file cel.c.

References ao2_container_alloc, ao2_ref, app_cmp(), app_hash(), ast_cel_engine_term(), ast_cli_register(), ast_register_atexit(), do_reload(), and NUM_APP_BUCKETS.

Referenced by main().

00657 {
00658    if (!(appset = ao2_container_alloc(NUM_APP_BUCKETS, app_hash, app_cmp))) {
00659       return -1;
00660    }
00661 
00662    if (do_reload()) {
00663       ao2_ref(appset, -1);
00664       appset = NULL;
00665       return -1;
00666    }
00667 
00668    if (ast_cli_register(&cli_status)) {
00669       ao2_ref(appset, -1);
00670       appset = NULL;
00671       return -1;
00672    }
00673 
00674    ast_register_atexit(ast_cel_engine_term);
00675 
00676    return 0;
00677 }

int ast_cel_engine_reload ( void   ) 

Provided by cel.c

Definition at line 679 of file cel.c.

References do_reload().

00680 {
00681    return do_reload();
00682 }

static void ast_cel_engine_term ( void   )  [static]

Definition at line 648 of file cel.c.

References ao2_ref.

Referenced by ast_cel_engine_init().

00649 {
00650    if (appset) {
00651       ao2_ref(appset, -1);
00652       appset = NULL;
00653    }
00654 }

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 401 of file cel.c.

References ast_cel_event_record::account_code, ast_cel_event_record::amaflag, ast_channel::amaflags, ast_party_caller::ani, ast_channel::appl, 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_name_set(), ast_channel_unref, ast_copy_string(), ast_dummy_channel_alloc(), AST_LIST_INSERT_HEAD, ast_localtime(), ast_strdup, ast_strftime(), ast_strlen_zero(), ast_var_assign(), ast_channel::caller, 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_channel::context, ast_channel::data, ast_channel::dialed, ast_cel_event_record::event_name, ast_cel_event_record::event_time, ast_cel_event_record::event_type, ast_channel::exten, 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, ast_party_dialed::number, ast_party_id::number, ast_cel_event_record::peer, ast_cel_event_record::peer_account, ast_channel::redirecting, 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, ast_channel::varshead, and ast_cel_event_record::version.

00402 {
00403    struct varshead *headp;
00404    struct ast_var_t *newvariable;
00405    const char *mixed_name;
00406    char timebuf[30];
00407    struct ast_channel *tchan;
00408    struct ast_cel_event_record record = {
00409       .version = AST_CEL_EVENT_RECORD_VERSION,
00410    };
00411 
00412    /* do not call ast_channel_alloc because this is not really a real channel */
00413    if (!(tchan = ast_dummy_channel_alloc())) {
00414       return NULL;
00415    }
00416 
00417    headp = &tchan->varshead;
00418 
00419    /* first, get the variables from the event */
00420    if (ast_cel_fill_record(event, &record)) {
00421       ast_channel_unref(tchan);
00422       return NULL;
00423    }
00424 
00425    /* next, fill the channel with their data */
00426    mixed_name = (record.event_type == AST_CEL_USER_DEFINED)
00427       ? record.user_defined_name : record.event_name;
00428    if ((newvariable = ast_var_assign("eventtype", mixed_name))) {
00429       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
00430    }
00431 
00432    if (ast_strlen_zero(cel_dateformat)) {
00433       snprintf(timebuf, sizeof(timebuf), "%ld.%06ld", (long) record.event_time.tv_sec,
00434             (long) record.event_time.tv_usec);
00435    } else {
00436       struct ast_tm tm;
00437       ast_localtime(&record.event_time, &tm, NULL);
00438       ast_strftime(timebuf, sizeof(timebuf), cel_dateformat, &tm);
00439    }
00440 
00441    if ((newvariable = ast_var_assign("eventtime", timebuf))) {
00442       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
00443    }
00444 
00445    if ((newvariable = ast_var_assign("eventenum", record.event_name))) {
00446       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
00447    }
00448    if ((newvariable = ast_var_assign("userdeftype", record.user_defined_name))) {
00449       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
00450    }
00451    if ((newvariable = ast_var_assign("eventextra", record.extra))) {
00452       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
00453    }
00454 
00455    tchan->caller.id.name.valid = 1;
00456    tchan->caller.id.name.str = ast_strdup(record.caller_id_name);
00457    tchan->caller.id.number.valid = 1;
00458    tchan->caller.id.number.str = ast_strdup(record.caller_id_num);
00459    tchan->caller.ani.number.valid = 1;
00460    tchan->caller.ani.number.str = ast_strdup(record.caller_id_ani);
00461    tchan->redirecting.from.number.valid = 1;
00462    tchan->redirecting.from.number.str = ast_strdup(record.caller_id_rdnis);
00463    tchan->dialed.number.str = ast_strdup(record.caller_id_dnid);
00464 
00465    ast_copy_string(tchan->exten, record.extension, sizeof(tchan->exten));
00466    ast_copy_string(tchan->context, record.context, sizeof(tchan->context));
00467    ast_channel_name_set(tchan, record.channel_name);
00468    ast_channel_uniqueid_set(tchan, record.unique_id);
00469    ast_channel_linkedid_set(tchan, record.linked_id);
00470    ast_channel_accountcode_set(tchan, record.account_code);
00471    ast_channel_peeraccount_set(tchan, record.peer_account);
00472    ast_channel_userfield_set(tchan, record.user_field);
00473 
00474    if ((newvariable = ast_var_assign("BRIDGEPEER", record.peer))) {
00475       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
00476    }
00477 
00478    tchan->appl = ast_strdup(record.application_name);
00479    tchan->data = ast_strdup(record.application_data);
00480    tchan->amaflags = record.amaflag;
00481 
00482    return tchan;
00483 }

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 593 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_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().

00594 {
00595    if (r->version != AST_CEL_EVENT_RECORD_VERSION) {
00596       ast_log(LOG_ERROR, "Module ABI mismatch for ast_cel_event_record.  "
00597             "Please ensure all modules were compiled for "
00598             "this version of Asterisk.\n");
00599       return -1;
00600    }
00601 
00602    r->event_type = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_EVENT_TYPE);
00603 
00604    r->event_time.tv_sec = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_EVENT_TIME);
00605    r->event_time.tv_usec = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_EVENT_TIME_USEC);
00606 
00607    r->event_name = ast_cel_get_type_name(r->event_type);
00608    if (r->event_type == AST_CEL_USER_DEFINED) {
00609       r->user_defined_name = ast_event_get_ie_str(e, AST_EVENT_IE_CEL_USEREVENT_NAME);
00610    } else {
00611       r->user_defined_name = "";
00612    }
00613 
00614    r->caller_id_name   = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDNAME), "");
00615    r->caller_id_num    = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDNUM), "");
00616    r->caller_id_ani    = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDANI), "");
00617    r->caller_id_rdnis  = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDRDNIS), "");
00618    r->caller_id_dnid   = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDDNID), "");
00619    r->extension        = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_EXTEN), "");
00620    r->context          = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CONTEXT), "");
00621    r->channel_name     = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CHANNAME), "");
00622    r->application_name = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_APPNAME), "");
00623    r->application_data = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_APPDATA), "");
00624    r->account_code     = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_ACCTCODE), "");
00625    r->peer_account     = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_ACCTCODE), "");
00626    r->unique_id        = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_UNIQUEID), "");
00627    r->linked_id        = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_LINKEDID), "");
00628    r->amaflag          = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_AMAFLAGS);
00629    r->user_field       = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_USERFIELD), "");
00630    r->peer             = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_PEER), "");
00631    r->extra            = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_EXTRA), "");
00632 
00633    return 0;
00634 }

const char* ast_cel_get_ama_flag_name ( enum ast_cel_ama_flag  flag  ) 

Convert AMA flag to printable string.

Parameters:
[in] flag the flag to convert to a string
Since:
1.8
Returns:
the string representation of the flag

Definition at line 351 of file cel.c.

References ARRAY_LEN, ast_log(), LOG_WARNING, and S_OR.

00352 {
00353    if (flag < 0 || flag >= ARRAY_LEN(cel_ama_flags)) {
00354       ast_log(LOG_WARNING, "Invalid AMA flag: %d\n", flag);
00355       return "Unknown";
00356    }
00357 
00358    return S_OR(cel_ama_flags[flag], "Unknown");
00359 }

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 346 of file cel.c.

References S_OR.

Referenced by ast_cel_fill_record(), and handle_cli_status().

00347 {
00348    return S_OR(cel_event_types[type], "Unknown");
00349 }

int ast_cel_report_event ( struct ast_channel chan,
enum ast_cel_event_type  event_type,
const char *  userdefevname,
const char *  extra,
struct ast_channel peer2 
)

Report a channel event.

Parameters:
chan This argument is required. This is the primary channel associated with this channel event.
event_type This is the type of call event being reported.
userdefevname This is an optional custom name for the call event.
extra This is an optional opaque field that will go into the "CEL_EXTRA" information element of the call event.
peer2 All CEL events contain a "peer name" information element. The first place the code will look to get a peer name is from the bridged channel to chan. If chan has no bridged channel and peer2 is specified, then the name of peer2 will go into the "peer name" field. If neither are available, the peer name field will be blank.
Since:
1.8
Precondition:
chan and peer2 are both unlocked
Return values:
0 success
non-zero failure

Definition at line 485 of file cel.c.

References ast_channel::amaflags, ast_party_caller::ani, ao2_find, ao2_ref, app, ast_channel::appl, ast_bridged_channel(), AST_CEL_APP_END, AST_CEL_APP_START, ast_cel_track_event(), ast_channel_accountcode(), ast_channel_linkedid(), ast_channel_lock, ast_channel_name(), ast_channel_peeraccount(), ast_channel_ref, ast_channel_uniqueid(), ast_channel_unlock, ast_channel_unref, ast_channel_userfield(), AST_EVENT_CEL, ast_event_destroy(), 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_event_queue(), ast_mutex_lock, ast_mutex_unlock, ast_strdupa, ast_tvnow(), ast_channel::caller, ast_channel::context, ast_channel::data, ast_channel::dialed, ast_channel::exten, ast_party_redirecting::from, ast_party_caller::id, ast_party_id::name, ast_party_dialed::number, ast_party_id::number, OBJ_POINTER, ast_channel::redirecting, reload_lock, S_COR, S_OR, ast_party_dialed::str, ast_party_number::str, ast_party_name::str, ast_party_number::valid, and ast_party_name::valid.

Referenced by __ast_channel_alloc_ap(), __ast_read(), analog_attempt_transfer(), ast_bridge_call(), ast_cel_check_retire_linkedid(), ast_channel_destructor(), ast_do_masquerade(), ast_do_pickup(), ast_hangup(), ast_raw_answer(), builtin_atxfer(), builtin_blindtransfer(), celgenuserevent_exec(), do_forward(), handle_request_refer(), local_attended_transfer(), manage_parked_call(), park_call_full(), parked_call_exec(), pbx_exec(), and wait_for_answer().

00487 {
00488    struct timeval eventtime;
00489    struct ast_event *ev;
00490    const char *peername = "";
00491    struct ast_channel *peer;
00492 
00493    ast_channel_lock(chan);
00494    peer = ast_bridged_channel(chan);
00495    if (peer) {
00496       ast_channel_ref(peer);
00497    }
00498    ast_channel_unlock(chan);
00499 
00500    /* Make sure a reload is not occurring while we're checking to see if this
00501     * is an event that we care about.  We could lose an important event in this
00502     * process otherwise. */
00503    ast_mutex_lock(&reload_lock);
00504 
00505    if (!cel_enabled || !ast_cel_track_event(event_type)) {
00506       ast_mutex_unlock(&reload_lock);
00507       if (peer) {
00508          ast_channel_unref(peer);
00509       }
00510       return 0;
00511    }
00512 
00513    if (event_type == AST_CEL_APP_START || event_type == AST_CEL_APP_END) {
00514       char *app;
00515       if (!(app = ao2_find(appset, (char *) chan->appl, OBJ_POINTER))) {
00516          ast_mutex_unlock(&reload_lock);
00517          if (peer) {
00518             ast_channel_unref(peer);
00519          }
00520          return 0;
00521       }
00522       ao2_ref(app, -1);
00523    }
00524 
00525    ast_mutex_unlock(&reload_lock);
00526 
00527    if (peer) {
00528       ast_channel_lock(peer);
00529       peername = ast_strdupa(ast_channel_name(peer));
00530       ast_channel_unlock(peer);
00531    } else if (peer2) {
00532       ast_channel_lock(peer2);
00533       peername = ast_strdupa(ast_channel_name(peer2));
00534       ast_channel_unlock(peer2);
00535    }
00536 
00537    if (!userdefevname) {
00538       userdefevname = "";
00539    }
00540 
00541    if (!extra) {
00542       extra = "";
00543    }
00544 
00545    eventtime = ast_tvnow();
00546 
00547    ast_channel_lock(chan);
00548 
00549    ev = ast_event_new(AST_EVENT_CEL,
00550       AST_EVENT_IE_CEL_EVENT_TYPE, AST_EVENT_IE_PLTYPE_UINT, event_type,
00551       AST_EVENT_IE_CEL_EVENT_TIME, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_sec,
00552       AST_EVENT_IE_CEL_EVENT_TIME_USEC, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_usec,
00553       AST_EVENT_IE_CEL_USEREVENT_NAME, AST_EVENT_IE_PLTYPE_STR, userdefevname,
00554       AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_PLTYPE_STR,
00555          S_COR(chan->caller.id.name.valid, chan->caller.id.name.str, ""),
00556       AST_EVENT_IE_CEL_CIDNUM, AST_EVENT_IE_PLTYPE_STR,
00557          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, ""),
00558       AST_EVENT_IE_CEL_CIDANI, AST_EVENT_IE_PLTYPE_STR,
00559          S_COR(chan->caller.ani.number.valid, chan->caller.ani.number.str, ""),
00560       AST_EVENT_IE_CEL_CIDRDNIS, AST_EVENT_IE_PLTYPE_STR,
00561          S_COR(chan->redirecting.from.number.valid, chan->redirecting.from.number.str, ""),
00562       AST_EVENT_IE_CEL_CIDDNID, AST_EVENT_IE_PLTYPE_STR,
00563          S_OR(chan->dialed.number.str, ""),
00564       AST_EVENT_IE_CEL_EXTEN, AST_EVENT_IE_PLTYPE_STR, chan->exten,
00565       AST_EVENT_IE_CEL_CONTEXT, AST_EVENT_IE_PLTYPE_STR, chan->context,
00566       AST_EVENT_IE_CEL_CHANNAME, AST_EVENT_IE_PLTYPE_STR, ast_channel_name(chan),
00567       AST_EVENT_IE_CEL_APPNAME, AST_EVENT_IE_PLTYPE_STR, S_OR(chan->appl, ""),
00568       AST_EVENT_IE_CEL_APPDATA, AST_EVENT_IE_PLTYPE_STR, S_OR(chan->data, ""),
00569       AST_EVENT_IE_CEL_AMAFLAGS, AST_EVENT_IE_PLTYPE_UINT, chan->amaflags,
00570       AST_EVENT_IE_CEL_ACCTCODE, AST_EVENT_IE_PLTYPE_STR, ast_channel_accountcode(chan),
00571       AST_EVENT_IE_CEL_PEERACCT, AST_EVENT_IE_PLTYPE_STR, ast_channel_peeraccount(chan),
00572       AST_EVENT_IE_CEL_UNIQUEID, AST_EVENT_IE_PLTYPE_STR, ast_channel_uniqueid(chan),
00573       AST_EVENT_IE_CEL_LINKEDID, AST_EVENT_IE_PLTYPE_STR, ast_channel_linkedid(chan),
00574       AST_EVENT_IE_CEL_USERFIELD, AST_EVENT_IE_PLTYPE_STR, ast_channel_userfield(chan),
00575       AST_EVENT_IE_CEL_EXTRA, AST_EVENT_IE_PLTYPE_STR, extra,
00576       AST_EVENT_IE_CEL_PEER, AST_EVENT_IE_PLTYPE_STR, peername,
00577       AST_EVENT_IE_END);
00578 
00579    ast_channel_unlock(chan);
00580 
00581    if (peer) {
00582       peer = ast_channel_unref(peer);
00583    }
00584 
00585    if (ev && ast_event_queue(ev)) {
00586       ast_event_destroy(ev);
00587       return -1;
00588    }
00589 
00590    return 0;
00591 }

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 209 of file cel.c.

References ARRAY_LEN.

Referenced by parse_events().

00210 {
00211    unsigned int i;
00212 
00213    for (i = 0; i < ARRAY_LEN(cel_event_types); i++) {
00214       if (!cel_event_types[i]) {
00215          continue;
00216       }
00217 
00218       if (!strcasecmp(name, cel_event_types[i])) {
00219          return i;
00220       }
00221    }
00222 
00223    return -1;
00224 }

static int ast_cel_track_event ( enum ast_cel_event_type  et  )  [static]

Definition at line 226 of file cel.c.

Referenced by ast_cel_check_retire_linkedid(), ast_cel_report_event(), and parse_apps().

00227 {
00228    return (eventset & ((int64_t) 1 << et));
00229 }

static int do_reload ( void   )  [static]

Definition at line 289 of file cel.c.

References ao2_callback, ast_config_destroy(), ast_config_load2(), ast_copy_string(), ast_mutex_lock, ast_mutex_unlock, ast_true(), ast_variable_retrieve(), ast_verb, CEL_DEFAULT_EVENTS, CEL_ENABLED_DEFAULT, config, CONFIG_STATUS_FILEMISSING, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, parse_apps(), parse_events(), and reload_lock.

00290 {
00291    struct ast_config *config;
00292    const char *enabled_value;
00293    const char *val;
00294    int res = 0;
00295    struct ast_flags config_flags = { 0, };
00296    const char *s;
00297 
00298    ast_mutex_lock(&reload_lock);
00299 
00300    /* Reset all settings before reloading configuration */
00301    cel_enabled = CEL_ENABLED_DEFAULT;
00302    eventset = CEL_DEFAULT_EVENTS;
00303    *cel_dateformat = '\0';
00304    ao2_callback(appset, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);
00305 
00306    config = ast_config_load2("cel.conf", "cel", config_flags);
00307 
00308    if (config == CONFIG_STATUS_FILEMISSING) {
00309       config = NULL;
00310       goto return_cleanup;
00311    }
00312 
00313    if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) {
00314       cel_enabled = ast_true(enabled_value);
00315    }
00316 
00317    if (!cel_enabled) {
00318       goto return_cleanup;
00319    }
00320 
00321    /* get the date format for logging */
00322    if ((s = ast_variable_retrieve(config, "general", "dateformat"))) {
00323       ast_copy_string(cel_dateformat, s, sizeof(cel_dateformat));
00324    }
00325 
00326    if ((val = ast_variable_retrieve(config, "general", "events"))) {
00327       parse_events(val);
00328    }
00329 
00330    if ((val = ast_variable_retrieve(config, "general", "apps"))) {
00331       parse_apps(val);
00332    }
00333 
00334 return_cleanup:
00335    ast_verb(3, "CEL logging %sabled.\n", cel_enabled ? "en" : "dis");
00336 
00337    ast_mutex_unlock(&reload_lock);
00338 
00339    if (config) {
00340       ast_config_destroy(config);
00341    }
00342 
00343    return res;
00344 }

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

Definition at line 153 of file cel.c.

References ao2_callback, ast_cli_args::argc, ast_cel_get_type_name(), ast_cli(), AST_EVENT_CEL, AST_EVENT_IE_EVENTTYPE, ast_event_report_subs(), AST_EVENT_SUB, ast_event_sub_append_ie_uint(), ast_event_sub_destroy(), ast_event_subscribe_new(), CLI_FAILURE, CLI_GENERATE, CLI_HANDLER, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, name, OBJ_NODATA, print_app(), print_cel_sub(), sub, and ast_cli_entry::usage.

00154 {
00155    unsigned int i;
00156    struct ast_event_sub *sub;
00157 
00158    switch (cmd) {
00159    case CLI_INIT:
00160       e->command = "cel show status";
00161       e->usage =
00162          "Usage: cel show status\n"
00163          "       Displays the Channel Event Logging system status.\n";
00164       return NULL;
00165    case CLI_GENERATE:
00166       return NULL;
00167    case CLI_HANDLER:
00168       break;
00169    }
00170 
00171    if (a->argc > 3) {
00172       return CLI_SHOWUSAGE;
00173    }
00174 
00175    ast_cli(a->fd, "CEL Logging: %s\n", cel_enabled ? "Enabled" : "Disabled");
00176 
00177    if (!cel_enabled) {
00178       return CLI_SUCCESS;
00179    }
00180 
00181    for (i = 0; i < (sizeof(eventset) * 8); i++) {
00182       const char *name;
00183 
00184       if (!(eventset & ((int64_t) 1 << i))) {
00185          continue;
00186       }
00187 
00188       name = ast_cel_get_type_name(i);
00189       if (strcasecmp(name, "Unknown")) {
00190          ast_cli(a->fd, "CEL Tracking Event: %s\n", name);
00191       }
00192    }
00193 
00194    ao2_callback(appset, OBJ_NODATA, print_app, a);
00195 
00196    if (!(sub = ast_event_subscribe_new(AST_EVENT_SUB, print_cel_sub, a))) {
00197       return CLI_FAILURE;
00198    }
00199    ast_event_sub_append_ie_uint(sub, AST_EVENT_IE_EVENTTYPE, AST_EVENT_CEL);
00200    ast_event_report_subs(sub);
00201    ast_event_sub_destroy(sub);
00202    sub = NULL;
00203 
00204    return CLI_SUCCESS;
00205 }

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

Definition at line 369 of file cel.c.

References ast_channel_linkedid(), ast_channel_lock, ast_channel_unlock, channel_find_data::chan, CMP_MATCH, CMP_STOP, and channel_find_data::linkedid.

Referenced by ast_cel_check_retire_linkedid().

00370 {
00371    struct ast_channel *c = obj;
00372    struct channel_find_data *find_dat = data;
00373    int res;
00374 
00375    ast_channel_lock(c);
00376    res = (c != find_dat->chan && ast_channel_linkedid(c) && !strcmp(find_dat->linkedid, ast_channel_linkedid(c)));
00377    ast_channel_unlock(c);
00378 
00379    return res ? CMP_MATCH | CMP_STOP : 0;
00380 }

static void parse_apps ( const char *  val  )  [static]

Definition at line 258 of file cel.c.

References ao2_alloc, ao2_link, ao2_ref, app, AST_CEL_APP_END, AST_CEL_APP_START, ast_cel_track_event(), ast_log(), ast_strdupa, ast_strip(), ast_strlen_zero(), LOG_WARNING, and strsep().

Referenced by do_reload().

00259 {
00260    char *apps = ast_strdupa(val);
00261    char *cur_app;
00262 
00263    if (!ast_cel_track_event(AST_CEL_APP_START) && !ast_cel_track_event(AST_CEL_APP_END)) {
00264       ast_log(LOG_WARNING, "An apps= config line, but not tracking APP events\n");
00265       return;
00266    }
00267 
00268    while ((cur_app = strsep(&apps, ","))) {
00269       char *app;
00270 
00271       cur_app = ast_strip(cur_app);
00272       if (ast_strlen_zero(cur_app)) {
00273          continue;
00274       }
00275 
00276       if (!(app = ao2_alloc(strlen(cur_app) + 1, NULL))) {
00277          continue;
00278       }
00279       strcpy(app, cur_app);
00280 
00281       ao2_link(appset, app);
00282       ao2_ref(app, -1);
00283       app = NULL;
00284    }
00285 }

static void parse_events ( const char *  val  )  [static]

Definition at line 231 of file cel.c.

References ast_cel_str_to_event_type(), ast_log(), ast_strdupa, ast_strip(), ast_strlen_zero(), events, LOG_WARNING, and strsep().

Referenced by do_reload().

00232 {
00233    char *events = ast_strdupa(val);
00234    char *cur_event;
00235 
00236    while ((cur_event = strsep(&events, ","))) {
00237       enum ast_cel_event_type event_type;
00238 
00239       cur_event = ast_strip(cur_event);
00240       if (ast_strlen_zero(cur_event)) {
00241          continue;
00242       }
00243 
00244       event_type = ast_cel_str_to_event_type(cur_event);
00245 
00246       if (event_type == 0) {
00247          /* All events */
00248          eventset = (int64_t) -1;
00249       } else if (event_type == -1) {
00250          ast_log(LOG_WARNING, "Unknown event name '%s'\n",
00251                cur_event);
00252       } else {
00253          eventset |= ((int64_t) 1 << event_type);
00254       }
00255    }
00256 }

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

Definition at line 136 of file cel.c.

References ast_cli(), and ast_cli_args::fd.

Referenced by handle_cli_status().

00137 {
00138    struct ast_cli_args *a = arg;
00139 
00140    ast_cli(a->fd, "CEL Tracking Application: %s\n", (const char *) obj);
00141 
00142    return 0;
00143 }

static void print_cel_sub ( const struct ast_event event,
void *  data 
) [static]

Definition at line 145 of file cel.c.

References ast_cli(), ast_event_get_ie_str(), AST_EVENT_IE_DESCRIPTION, and ast_cli_args::fd.

Referenced by handle_cli_status().

00146 {
00147    struct ast_cli_args *a = data;
00148 
00149    ast_cli(a->fd, "CEL Event Subscriber: %s\n",
00150          ast_event_get_ie_str(event, AST_EVENT_IE_DESCRIPTION));
00151 }


Variable Documentation

struct ao2_container* appset [static]

Container of Asterisk application names.

The apps in this container are the applications that were specified in the configuration as applications that CEL events should be generated for when they start and end on a channel.

Definition at line 82 of file cel.c.

const char* const cel_ama_flags[AST_CEL_AMA_FLAG_TOTAL] [static]

Map of ast_cel_ama_flags to strings.

Definition at line 124 of file cel.c.

char cel_dateformat[256] [static]

Configured date format for event timestamps.

Definition at line 87 of file cel.c.

unsigned char cel_enabled [static]

Is the CEL subsystem enabled ?

Definition at line 47 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 92 of file cel.c.

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

Definition at line 207 of file cel.c.

int64_t eventset [static]

which events we want to track

Note:
bit field, up to 64 events

Definition at line 57 of file cel.c.

ast_mutex_t reload_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static]

Definition at line 287 of file cel.c.

Referenced by ast_cel_report_event(), and do_reload().


Generated on Fri Feb 10 06:35:12 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6