#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"

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_channel * | ast_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_container * | appset |
| 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 } |
Definition in file cel.c.
| #define CEL_DEFAULT_EVENTS 0 |
| #define CEL_ENABLED_DEFAULT 0 |
| #define CEL_MAX_EVENT_IDS 64 |
| #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().
| static int app_cmp | ( | void * | obj, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
| 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.
| 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.
| chan | channel that is being destroyed or its linkedid is changing |
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] |
| 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.
| event | the CEL event |
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.
| [in] | event | the CEL event |
| [out] | r | the ast_cel_event_record to fill in |
| 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.
| [in] | flag | the flag to convert to a string |
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.
| type | the type to get the name of |
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.
| 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. |
| 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.
| name | the event type name as a 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 }
struct ao2_container* appset [static] |
const char* const cel_ama_flags[AST_CEL_AMA_FLAG_TOTAL] [static] |
char cel_dateformat[256] [static] |
unsigned char cel_enabled [static] |
const char* const cel_event_types[CEL_MAX_EVENT_IDS] [static] |
struct ast_cli_entry cli_status = AST_CLI_DEFINE(handle_cli_status, "Display the CEL status") [static] |
int64_t eventset [static] |
ast_mutex_t reload_lock = { PTHREAD_MUTEX_INITIALIZER , NULL, 1 } [static] |
1.5.6