Wed Oct 28 13:31:56 2009

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_MAX_EVENT_IDS   64
 Maximum possible CEL event IDs.

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 const int64_t CEL_DEFAULT_EVENTS = 0
 Track no events by default.
static unsigned char cel_enabled
static const unsigned char CEL_ENALBED_DEFAULT = 0
 CEL is off by default.
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 const int NUM_APP_BUCKETS = 97
 Number of buckets for the appset container.
static ast_mutex_t reload_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )


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_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.


Function Documentation

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

Definition at line 617 of file cel.c.

References app1, app2, CMP_MATCH, and CMP_STOP.

Referenced by ast_cel_engine_init().

00618 {
00619    const char *app1 = obj, *app2 = arg;
00620 
00621    return !strcasecmp(app1, app2) ? CMP_MATCH | CMP_STOP : 0;
00622 }

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

Definition at line 612 of file cel.c.

References ast_str_case_hash().

Referenced by ast_cel_engine_init().

00613 {
00614    return ast_str_case_hash((const char *) obj);
00615 }

unsigned int ast_cel_check_enabled ( void   ) 

Check to see if CEL is enabled.

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

Definition at line 130 of file cel.c.

00131 {
00132    return cel_enabled;
00133 }

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

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

Referenced by ast_channel_change_linkedid(), and ast_channel_destructor().

00377 {
00378    const char *linkedid = chan->linkedid;
00379    struct channel_find_data find_dat;
00380 
00381    /* make sure we need to do all this work */
00382 
00383    if (!ast_strlen_zero(linkedid) && ast_cel_track_event(AST_CEL_LINKEDID_END)) {
00384       struct ast_channel *tmp = NULL;
00385       find_dat.chan = chan;
00386       find_dat.linkedid = linkedid;
00387       if ((tmp = ast_channel_callback(linkedid_match, NULL, &find_dat, 0))) {
00388          tmp = ast_channel_unref(tmp);
00389       } else {
00390          ast_cel_report_event(chan, AST_CEL_LINKEDID_END, NULL, NULL, NULL);
00391       }
00392    }
00393 }

int ast_cel_engine_init ( void   ) 

Provided by cel.c

Definition at line 632 of file cel.c.

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

Referenced by main().

00633 {
00634    if (!(appset = ao2_container_alloc(NUM_APP_BUCKETS, app_hash, app_cmp))) {
00635       return -1;
00636    }
00637 
00638    if (do_reload()) {
00639       ao2_ref(appset, -1);
00640       appset = NULL;
00641       return -1;
00642    }
00643 
00644    if (ast_cli_register(&cli_status)) {
00645       ao2_ref(appset, -1);
00646       appset = NULL;
00647       return -1;
00648    }
00649 
00650    ast_register_atexit(ast_cel_engine_term);
00651 
00652    return 0;
00653 }

int ast_cel_engine_reload ( void   ) 

Provided by cel.c

Definition at line 655 of file cel.c.

References do_reload().

00656 {
00657    return do_reload();
00658 }

static void ast_cel_engine_term ( void   )  [static]

Definition at line 624 of file cel.c.

References ao2_ref.

Referenced by ast_cel_engine_init().

00625 {
00626    if (appset) {
00627       ao2_ref(appset, -1);
00628       appset = NULL;
00629    }
00630 }

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.

This function creates a fake channel containing the serialized channel data in the given cel event. It must be released with ast_channel_release.

Parameters:
event the CEL event
Since:
1.6.3
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 395 of file cel.c.

References ast_cel_event_record::account_code, accountcode, ast_cel_event_record::amaflag, ast_channel::amaflags, 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_channel_release(), ast_copy_string(), ast_dummy_channel_alloc(), AST_LIST_INSERT_HEAD, ast_localtime(), ast_strdup, ast_strftime(), ast_string_field_set, 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_channel::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_rdnis, ast_cel_event_record::context, ast_channel::context, ast_channel::data, ast_cel_event_record::event_name, ast_cel_event_record::event_time, ast_channel::exten, ast_cel_event_record::extension, ast_cel_event_record::extra, ast_cel_event_record::linked_id, name, pbx_builtin_setvar_helper(), ast_cel_event_record::peer, ast_cel_event_record::peer_account, ast_cel_event_record::unique_id, ast_cel_event_record::user_field, ast_channel::varshead, and ast_cel_event_record::version.

00396 {
00397    struct varshead *headp;
00398    struct ast_var_t *newvariable;
00399    char timebuf[30];
00400    struct ast_channel *tchan;
00401    struct ast_cel_event_record record = {
00402       .version = AST_CEL_EVENT_RECORD_VERSION,
00403    };
00404 
00405    /* do not call ast_channel_alloc because this is not really a real channel */
00406    if (!(tchan = ast_dummy_channel_alloc())) {
00407       return NULL;
00408    }
00409 
00410    headp = &tchan->varshead;
00411 
00412    /* first, get the variables from the event */
00413    if (ast_cel_fill_record(event, &record)) {
00414       ast_channel_release(tchan);
00415       return NULL;
00416    }
00417 
00418    /* next, fill the channel with their data */
00419    if ((newvariable = ast_var_assign("eventtype", record.event_name))) {
00420       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
00421    }
00422 
00423    if (ast_strlen_zero(cel_dateformat)) {
00424       snprintf(timebuf, sizeof(timebuf), "%ld.%06ld", record.event_time.tv_sec,
00425             (long) record.event_time.tv_usec);
00426    } else {
00427       struct ast_tm tm;
00428       ast_localtime(&record.event_time, &tm, NULL);
00429       ast_strftime(timebuf, sizeof(timebuf), cel_dateformat, &tm);
00430    }
00431 
00432    if ((newvariable = ast_var_assign("eventtime", timebuf))) {
00433       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
00434    }
00435 
00436    if ((newvariable = ast_var_assign("eventextra", record.extra))) {
00437       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
00438    }
00439 
00440    tchan->cid.cid_name = ast_strdup(record.caller_id_name);
00441    tchan->cid.cid_num = ast_strdup(record.caller_id_num);
00442    tchan->cid.cid_ani = ast_strdup(record.caller_id_ani);
00443    tchan->cid.cid_rdnis = ast_strdup(record.caller_id_rdnis);
00444    tchan->cid.cid_dnid = ast_strdup(record.caller_id_dnid);
00445 
00446    ast_copy_string(tchan->exten, record.extension, sizeof(tchan->exten));
00447    ast_copy_string(tchan->context, record.context, sizeof(tchan->context));
00448    ast_string_field_set(tchan, name, record.channel_name);
00449    ast_string_field_set(tchan, uniqueid, record.unique_id);
00450    ast_string_field_set(tchan, linkedid, record.linked_id);
00451    ast_string_field_set(tchan, accountcode, record.account_code);
00452    ast_string_field_set(tchan, peeraccount, record.peer_account);
00453    ast_string_field_set(tchan, userfield, record.user_field);
00454 
00455    pbx_builtin_setvar_helper(tchan, "BRIDGEPEER", record.peer);
00456 
00457    tchan->appl = ast_strdup(record.application_name);
00458    tchan->data = ast_strdup(record.application_data);
00459    tchan->amaflags = record.amaflag;
00460 
00461    return tchan;
00462 }

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.6.3
Return values:
0 success
non-zero failure

Definition at line 567 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().

00568 {
00569    if (r->version != AST_CEL_EVENT_RECORD_VERSION) {
00570       ast_log(LOG_ERROR, "Module ABI mismatch for ast_cel_event_record.  "
00571             "Please ensure all modules were compiled for "
00572             "this version of Asterisk.\n");
00573       return -1;
00574    }
00575 
00576    r->event_type = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_EVENT_TYPE);
00577 
00578    r->event_time.tv_sec = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_EVENT_TIME);
00579    r->event_time.tv_usec = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_EVENT_TIME_USEC);
00580 
00581    r->user_defined_name = "";
00582 
00583    if (r->event_type == AST_CEL_USER_DEFINED) {
00584       r->user_defined_name = ast_event_get_ie_str(e, AST_EVENT_IE_CEL_USEREVENT_NAME);
00585       r->event_name = r->user_defined_name;
00586    } else {
00587       r->event_name = ast_cel_get_type_name(r->event_type);
00588    }
00589 
00590    r->caller_id_name   = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDNAME), "");
00591    r->caller_id_num    = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDNUM), "");
00592    r->caller_id_ani    = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDANI), "");
00593    r->caller_id_rdnis  = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDRDNIS), "");
00594    r->caller_id_dnid   = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDDNID), "");
00595    r->extension        = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_EXTEN), "");
00596    r->context          = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CONTEXT), "");
00597    r->channel_name     = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CHANNAME), "");
00598    r->application_name = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_APPNAME), "");
00599    r->application_data = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_APPDATA), "");
00600    r->account_code     = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_ACCTCODE), "");
00601    r->peer_account     = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_ACCTCODE), "");
00602    r->unique_id        = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_UNIQUEID), "");
00603    r->linked_id        = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_LINKEDID), "");
00604    r->amaflag          = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_AMAFLAGS);
00605    r->user_field       = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_USERFIELD), "");
00606    r->peer             = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_PEER), "");
00607    r->extra            = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_EXTRA), "");
00608 
00609    return 0;
00610 }

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.6.3
Returns:
the string representation of the flag

Definition at line 350 of file cel.c.

References S_OR.

00351 {
00352    return S_OR(cel_ama_flags[flag], "Unknown");
00353 }

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.6.3
Returns:
the string representation of the type

Definition at line 345 of file cel.c.

References S_OR.

Referenced by ast_cel_fill_record(), and handle_cli_status().

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

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.6.3
Precondition:
chan and peer2 are both unlocked
Return values:
0 success
non-zero failure

Definition at line 464 of file cel.c.

References ast_channel::accountcode, ast_channel::amaflags, 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_lock, ast_channel_ref, ast_channel_unlock, ast_channel_unref, 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::cid, ast_callerid::cid_ani, ast_callerid::cid_dnid, ast_callerid::cid_name, ast_callerid::cid_num, ast_callerid::cid_rdnis, ast_channel::context, ast_channel::data, ast_channel::exten, ast_channel::linkedid, ast_channel::name, OBJ_POINTER, ast_channel::peeraccount, reload_lock, S_OR, ast_channel::uniqueid, and ast_channel::userfield.

Referenced by __analog_handle_event(), __ast_channel_alloc_ap(), __ast_read(), analog_attempt_transfer(), ast_bridge_call(), ast_cel_check_retire_linkedid(), ast_channel_destructor(), ast_do_masquerade(), ast_hangup(), ast_raw_answer(), builtin_atxfer(), builtin_blindtransfer(), celgenuserevent_exec(), do_forward(), handle_request_refer(), local_attended_transfer(), manage_parkinglot(), park_call_full(), park_exec_full(), pbx_exec(), pickup_do(), and wait_for_answer().

00466 {
00467    struct timeval eventtime;
00468    struct ast_event *ev;
00469    const char *peername = "";
00470    struct ast_channel *peer;
00471 
00472    ast_channel_lock(chan);
00473    peer = ast_bridged_channel(chan);
00474    if (peer) {
00475       ast_channel_ref(peer);
00476    }
00477    ast_channel_unlock(chan);
00478 
00479    /* Make sure a reload is not occurring while we're checking to see if this
00480     * is an event that we care about.  We could lose an important event in this
00481     * process otherwise. */
00482    ast_mutex_lock(&reload_lock);
00483 
00484    if (!cel_enabled || !ast_cel_track_event(event_type)) {
00485       ast_mutex_unlock(&reload_lock);
00486       if (peer) {
00487          ast_channel_unref(peer);
00488       }
00489       return 0;
00490    }
00491 
00492    if (event_type == AST_CEL_APP_START || event_type == AST_CEL_APP_END) {
00493       char *app;
00494       if (!(app = ao2_find(appset, (char *) chan->appl, OBJ_POINTER))) {
00495          ast_mutex_unlock(&reload_lock);
00496          if (peer) {
00497             ast_channel_unref(peer);
00498          }
00499          return 0;
00500       }
00501       ao2_ref(app, -1);
00502    }
00503 
00504    ast_mutex_unlock(&reload_lock);
00505 
00506    if (peer) {
00507       ast_channel_lock(peer);
00508       peername = ast_strdupa(peer->name);
00509       ast_channel_unlock(peer);
00510    } else if (peer2) {
00511       ast_channel_lock(peer2);
00512       peername = ast_strdupa(peer2->name);
00513       ast_channel_unlock(peer2);
00514    }
00515 
00516    if (!userdefevname) {
00517       userdefevname = "";
00518    }
00519 
00520    if (!extra) {
00521       extra = "";
00522    }
00523 
00524    eventtime = ast_tvnow();
00525 
00526    ast_channel_lock(chan);
00527 
00528    ev = ast_event_new(AST_EVENT_CEL,
00529          AST_EVENT_IE_CEL_EVENT_TYPE, AST_EVENT_IE_PLTYPE_UINT, event_type,
00530          AST_EVENT_IE_CEL_EVENT_TIME, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_sec,
00531          AST_EVENT_IE_CEL_EVENT_TIME_USEC, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_usec,
00532          AST_EVENT_IE_CEL_USEREVENT_NAME, AST_EVENT_IE_PLTYPE_STR, userdefevname,
00533          AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_PLTYPE_STR, S_OR(chan->cid.cid_name, ""),
00534          AST_EVENT_IE_CEL_CIDNUM, AST_EVENT_IE_PLTYPE_STR, S_OR(chan->cid.cid_num, ""),
00535          AST_EVENT_IE_CEL_CIDANI, AST_EVENT_IE_PLTYPE_STR, S_OR(chan->cid.cid_ani, ""),
00536          AST_EVENT_IE_CEL_CIDRDNIS, AST_EVENT_IE_PLTYPE_STR, S_OR(chan->cid.cid_rdnis, ""),
00537          AST_EVENT_IE_CEL_CIDDNID, AST_EVENT_IE_PLTYPE_STR, S_OR(chan->cid.cid_dnid, ""),
00538          AST_EVENT_IE_CEL_EXTEN, AST_EVENT_IE_PLTYPE_STR, chan->exten,
00539          AST_EVENT_IE_CEL_CONTEXT, AST_EVENT_IE_PLTYPE_STR, chan->context,
00540          AST_EVENT_IE_CEL_CHANNAME, AST_EVENT_IE_PLTYPE_STR, chan->name,
00541          AST_EVENT_IE_CEL_APPNAME, AST_EVENT_IE_PLTYPE_STR, S_OR(chan->appl, ""),
00542          AST_EVENT_IE_CEL_APPDATA, AST_EVENT_IE_PLTYPE_STR, S_OR(chan->data, ""),
00543          AST_EVENT_IE_CEL_AMAFLAGS, AST_EVENT_IE_PLTYPE_UINT, chan->amaflags,
00544          AST_EVENT_IE_CEL_ACCTCODE, AST_EVENT_IE_PLTYPE_STR, chan->accountcode,
00545          AST_EVENT_IE_CEL_PEERACCT, AST_EVENT_IE_PLTYPE_STR, chan->peeraccount,
00546          AST_EVENT_IE_CEL_UNIQUEID, AST_EVENT_IE_PLTYPE_STR, chan->uniqueid,
00547          AST_EVENT_IE_CEL_LINKEDID, AST_EVENT_IE_PLTYPE_STR, chan->linkedid,
00548          AST_EVENT_IE_CEL_USERFIELD, AST_EVENT_IE_PLTYPE_STR, chan->userfield,
00549          AST_EVENT_IE_CEL_EXTRA, AST_EVENT_IE_PLTYPE_STR, extra,
00550          AST_EVENT_IE_CEL_PEER, AST_EVENT_IE_PLTYPE_STR, peername,
00551          AST_EVENT_IE_END);
00552 
00553    ast_channel_unlock(chan);
00554 
00555    if (peer) {
00556       peer = ast_channel_unref(peer);
00557    }
00558 
00559    if (ev && ast_event_queue(ev)) {
00560       ast_event_destroy(ev);
00561       return -1;
00562    }
00563 
00564    return 0;
00565 }

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.6.3
Returns:
the ast_cel_event_type given by the string

Definition at line 208 of file cel.c.

References ARRAY_LEN.

Referenced by parse_events().

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

static int ast_cel_track_event ( enum ast_cel_event_type  et  )  [static]

Definition at line 225 of file cel.c.

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

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

static int do_reload ( void   )  [static]

Definition at line 288 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, config, CONFIG_STATUS_FILEMISSING, OBJ_MULTIPLE, OBJ_NODATA, OBJ_UNLINK, parse_apps(), parse_events(), reload_lock, and s.

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

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

Definition at line 152 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(), and ast_cli_entry::usage.

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

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

Definition at line 363 of file cel.c.

References ast_channel_lock, ast_channel_unlock, channel_find_data::chan, CMP_MATCH, CMP_STOP, channel_find_data::linkedid, and ast_channel::linkedid.

Referenced by ast_cel_check_retire_linkedid().

00364 {
00365    struct ast_channel *c = obj;
00366    struct channel_find_data *find_dat = data;
00367    int res;
00368 
00369    ast_channel_lock(c);
00370    res = (c != find_dat->chan && c->linkedid && !strcmp(find_dat->linkedid, c->linkedid));
00371    ast_channel_unlock(c);
00372 
00373    return res ? CMP_MATCH | CMP_STOP : 0;
00374 }

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

Definition at line 257 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().

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

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

Definition at line 230 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().

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

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

Definition at line 135 of file cel.c.

References ast_cli(), and ast_cli_args::fd.

Referenced by handle_cli_status().

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

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

Definition at line 144 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().

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


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]

Initial value:

 {
   [AST_CEL_AMA_FLAG_OMIT]          = "OMIT",
   [AST_CEL_AMA_FLAG_BILLING]       = "BILLING",
   [AST_CEL_AMA_FLAG_DOCUMENTATION] = "DOCUMENTATION",
}
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.

const int64_t CEL_DEFAULT_EVENTS = 0 [static]

Track no events by default.

Definition at line 68 of file cel.c.

unsigned char cel_enabled [static]

Is the CEL subsystem enabled ?

Definition at line 47 of file cel.c.

const unsigned char CEL_ENALBED_DEFAULT = 0 [static]

CEL is off by default.

Definition at line 50 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 206 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.

const int NUM_APP_BUCKETS = 97 [static]

Number of buckets for the appset container.

Definition at line 73 of file cel.c.

ast_mutex_t reload_lock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Definition at line 286 of file cel.c.

Referenced by ast_cel_report_event(), and do_reload().


Generated on Wed Oct 28 13:31:56 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6