asterisk/main/cel.c

691 lines
20 KiB
C
Raw Normal View History

/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2007 - 2009, Digium, Inc.
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*!
* \file
*
* \brief Channel Event Logging API
*
* \author Steve Murphy <murf@digium.com>
* \author 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.
*/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#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"
/*! Is the CEL subsystem enabled ? */
static unsigned char cel_enabled;
/*! \brief CEL is off by default */
#define CEL_ENABLED_DEFAULT 0
/*!
* \brief which events we want to track
*
* \note bit field, up to 64 events
*/
static int64_t eventset;
/*!
* \brief Maximum possible CEL event IDs
* \note This limit is currently imposed by the eventset definition
*/
#define CEL_MAX_EVENT_IDS 64
/*!
* \brief Track no events by default.
*/
#define CEL_DEFAULT_EVENTS 0
/*!
* \brief Number of buckets for the appset container
*/
#define NUM_APP_BUCKETS 97
/*!
* \brief 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.
*/
static struct ao2_container *appset;
Multiple revisions 365006,365068 ........ r365006 | twilson | 2012-05-02 10:49:03 -0500 (Wed, 02 May 2012) | 12 lines Fix a CEL LINKEDID_END race and local channel linkedids This patch has the ;2 channel inherit the linkedid of the ;1 channel and fixes the race condition by no longer scanning the channel list for "other" channels with the same linkedid. Instead, cel.c has an ao2 container of linkedid strings and uses the refcount of the string as a counter of how many channels with the linkedid exist. Not only does this eliminate the race condition, but it also allows us to look up the linkedid by the hashed key instead of traversing the entire channel list. Review: https://reviewboard.asterisk.org/r/1895/ ........ r365068 | twilson | 2012-05-02 12:02:39 -0500 (Wed, 02 May 2012) | 11 lines Don't leak a ref if out of memory and can't link the linkedid If the ao2_link fails, we are most likely out of memory and bad things are going to happen. Before those bad things happen, make sure to clean up the linkedid references. This patch also adds a comment explaining why linkedid can't be passed to both local channel allocations and combines two ao2_ref calls into 1. Review: https://reviewboard.asterisk.org/r/1895/ ........ Merged revisions 365006,365068 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 365083 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@365084 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-05-02 17:43:16 +00:00
static struct ao2_container *linkedids;
/*!
* \brief Configured date format for event timestamps
*/
static char cel_dateformat[256];
/*!
* \brief Map of ast_cel_event_type to strings
*/
static const char * const cel_event_types[CEL_MAX_EVENT_IDS] = {
[0] = "ALL",
[AST_CEL_CHANNEL_START] = "CHAN_START",
[AST_CEL_CHANNEL_END] = "CHAN_END",
[AST_CEL_ANSWER] = "ANSWER",
[AST_CEL_HANGUP] = "HANGUP",
[AST_CEL_APP_START] = "APP_START",
[AST_CEL_APP_END] = "APP_END",
[AST_CEL_BRIDGE_START] = "BRIDGE_START",
[AST_CEL_BRIDGE_END] = "BRIDGE_END",
[AST_CEL_BRIDGE_UPDATE] = "BRIDGE_UPDATE",
[AST_CEL_CONF_START] = "CONF_START",
[AST_CEL_CONF_END] = "CONF_END",
[AST_CEL_PARK_START] = "PARK_START",
[AST_CEL_PARK_END] = "PARK_END",
[AST_CEL_TRANSFER] = "TRANSFER",
[AST_CEL_USER_DEFINED] = "USER_DEFINED",
[AST_CEL_CONF_ENTER] = "CONF_ENTER",
[AST_CEL_CONF_EXIT] = "CONF_EXIT",
[AST_CEL_BLINDTRANSFER] = "BLINDTRANSFER",
[AST_CEL_ATTENDEDTRANSFER] = "ATTENDEDTRANSFER",
[AST_CEL_PICKUP] = "PICKUP",
[AST_CEL_FORWARD] = "FORWARD",
[AST_CEL_3WAY_START] = "3WAY_START",
[AST_CEL_3WAY_END] = "3WAY_END",
[AST_CEL_HOOKFLASH] = "HOOKFLASH",
[AST_CEL_LINKEDID_END] = "LINKEDID_END",
};
/*!
* \brief Map of ast_cel_ama_flags to strings
*/
static const char * const cel_ama_flags[AST_CEL_AMA_FLAG_TOTAL] = {
[AST_CEL_AMA_FLAG_NONE] = "NONE",
[AST_CEL_AMA_FLAG_OMIT] = "OMIT",
[AST_CEL_AMA_FLAG_BILLING] = "BILLING",
[AST_CEL_AMA_FLAG_DOCUMENTATION] = "DOCUMENTATION",
};
unsigned int ast_cel_check_enabled(void)
{
return cel_enabled;
}
static int print_app(void *obj, void *arg, int flags)
{
struct ast_cli_args *a = arg;
ast_cli(a->fd, "CEL Tracking Application: %s\n", (const char *) obj);
return 0;
}
static void print_cel_sub(const struct ast_event *event, void *data)
{
struct ast_cli_args *a = data;
ast_cli(a->fd, "CEL Event Subscriber: %s\n",
ast_event_get_ie_str(event, AST_EVENT_IE_DESCRIPTION));
}
static char *handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
unsigned int i;
struct ast_event_sub *sub;
switch (cmd) {
case CLI_INIT:
e->command = "cel show status";
e->usage =
"Usage: cel show status\n"
" Displays the Channel Event Logging system status.\n";
return NULL;
case CLI_GENERATE:
return NULL;
case CLI_HANDLER:
break;
}
if (a->argc > 3) {
return CLI_SHOWUSAGE;
}
ast_cli(a->fd, "CEL Logging: %s\n", cel_enabled ? "Enabled" : "Disabled");
if (!cel_enabled) {
return CLI_SUCCESS;
}
for (i = 0; i < (sizeof(eventset) * 8); i++) {
const char *name;
if (!(eventset & ((int64_t) 1 << i))) {
continue;
}
name = ast_cel_get_type_name(i);
if (strcasecmp(name, "Unknown")) {
ast_cli(a->fd, "CEL Tracking Event: %s\n", name);
}
}
ao2_callback(appset, OBJ_NODATA, print_app, a);
if (!(sub = ast_event_subscribe_new(AST_EVENT_SUB, print_cel_sub, a))) {
return CLI_FAILURE;
}
ast_event_sub_append_ie_uint(sub, AST_EVENT_IE_EVENTTYPE, AST_EVENT_CEL);
ast_event_report_subs(sub);
ast_event_sub_destroy(sub);
sub = NULL;
return CLI_SUCCESS;
}
static struct ast_cli_entry cli_status = AST_CLI_DEFINE(handle_cli_status, "Display the CEL status");
enum ast_cel_event_type ast_cel_str_to_event_type(const char *name)
{
unsigned int i;
for (i = 0; i < ARRAY_LEN(cel_event_types); i++) {
if (!cel_event_types[i]) {
continue;
}
if (!strcasecmp(name, cel_event_types[i])) {
return i;
}
}
return -1;
}
static int ast_cel_track_event(enum ast_cel_event_type et)
{
return (eventset & ((int64_t) 1 << et));
}
static void parse_events(const char *val)
{
char *events = ast_strdupa(val);
char *cur_event;
while ((cur_event = strsep(&events, ","))) {
enum ast_cel_event_type event_type;
cur_event = ast_strip(cur_event);
if (ast_strlen_zero(cur_event)) {
continue;
}
event_type = ast_cel_str_to_event_type(cur_event);
if (event_type == 0) {
/* All events */
eventset = (int64_t) -1;
} else if (event_type == -1) {
ast_log(LOG_WARNING, "Unknown event name '%s'\n",
cur_event);
} else {
eventset |= ((int64_t) 1 << event_type);
}
}
}
static void parse_apps(const char *val)
{
char *apps = ast_strdupa(val);
char *cur_app;
if (!ast_cel_track_event(AST_CEL_APP_START) && !ast_cel_track_event(AST_CEL_APP_END)) {
ast_log(LOG_WARNING, "An apps= config line, but not tracking APP events\n");
return;
}
while ((cur_app = strsep(&apps, ","))) {
char *app;
cur_app = ast_strip(cur_app);
if (ast_strlen_zero(cur_app)) {
continue;
}
if (!(app = ao2_alloc(strlen(cur_app) + 1, NULL))) {
continue;
}
strcpy(app, cur_app);
ao2_link(appset, app);
ao2_ref(app, -1);
app = NULL;
}
}
AST_MUTEX_DEFINE_STATIC(reload_lock);
static int do_reload(void)
{
struct ast_config *config;
const char *enabled_value;
const char *val;
int res = 0;
struct ast_flags config_flags = { 0, };
const char *s;
ast_mutex_lock(&reload_lock);
/* Reset all settings before reloading configuration */
cel_enabled = CEL_ENABLED_DEFAULT;
eventset = CEL_DEFAULT_EVENTS;
*cel_dateformat = '\0';
ao2_callback(appset, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);
config = ast_config_load2("cel.conf", "cel", config_flags);
if (config == CONFIG_STATUS_FILEMISSING) {
config = NULL;
goto return_cleanup;
}
if ((enabled_value = ast_variable_retrieve(config, "general", "enable"))) {
cel_enabled = ast_true(enabled_value);
}
if (!cel_enabled) {
goto return_cleanup;
}
/* get the date format for logging */
if ((s = ast_variable_retrieve(config, "general", "dateformat"))) {
ast_copy_string(cel_dateformat, s, sizeof(cel_dateformat));
}
if ((val = ast_variable_retrieve(config, "general", "events"))) {
parse_events(val);
}
if ((val = ast_variable_retrieve(config, "general", "apps"))) {
parse_apps(val);
}
return_cleanup:
ast_verb(3, "CEL logging %sabled.\n", cel_enabled ? "en" : "dis");
ast_mutex_unlock(&reload_lock);
if (config) {
ast_config_destroy(config);
}
return res;
}
const char *ast_cel_get_type_name(enum ast_cel_event_type type)
{
return S_OR(cel_event_types[type], "Unknown");
}
const char *ast_cel_get_ama_flag_name(enum ast_cel_ama_flag flag)
{
if (flag < 0 || flag >= ARRAY_LEN(cel_ama_flags)) {
ast_log(LOG_WARNING, "Invalid AMA flag: %d\n", flag);
return "Unknown";
}
return S_OR(cel_ama_flags[flag], "Unknown");
}
/* called whenever a channel is destroyed or a linkedid is changed to
* potentially emit a CEL_LINKEDID_END event */
void ast_cel_check_retire_linkedid(struct ast_channel *chan)
{
const char *linkedid = ast_channel_linkedid(chan);
Multiple revisions 365006,365068 ........ r365006 | twilson | 2012-05-02 10:49:03 -0500 (Wed, 02 May 2012) | 12 lines Fix a CEL LINKEDID_END race and local channel linkedids This patch has the ;2 channel inherit the linkedid of the ;1 channel and fixes the race condition by no longer scanning the channel list for "other" channels with the same linkedid. Instead, cel.c has an ao2 container of linkedid strings and uses the refcount of the string as a counter of how many channels with the linkedid exist. Not only does this eliminate the race condition, but it also allows us to look up the linkedid by the hashed key instead of traversing the entire channel list. Review: https://reviewboard.asterisk.org/r/1895/ ........ r365068 | twilson | 2012-05-02 12:02:39 -0500 (Wed, 02 May 2012) | 11 lines Don't leak a ref if out of memory and can't link the linkedid If the ao2_link fails, we are most likely out of memory and bad things are going to happen. Before those bad things happen, make sure to clean up the linkedid references. This patch also adds a comment explaining why linkedid can't be passed to both local channel allocations and combines two ao2_ref calls into 1. Review: https://reviewboard.asterisk.org/r/1895/ ........ Merged revisions 365006,365068 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 365083 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@365084 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-05-02 17:43:16 +00:00
char *lid;
/* make sure we need to do all this work */
Multiple revisions 365006,365068 ........ r365006 | twilson | 2012-05-02 10:49:03 -0500 (Wed, 02 May 2012) | 12 lines Fix a CEL LINKEDID_END race and local channel linkedids This patch has the ;2 channel inherit the linkedid of the ;1 channel and fixes the race condition by no longer scanning the channel list for "other" channels with the same linkedid. Instead, cel.c has an ao2 container of linkedid strings and uses the refcount of the string as a counter of how many channels with the linkedid exist. Not only does this eliminate the race condition, but it also allows us to look up the linkedid by the hashed key instead of traversing the entire channel list. Review: https://reviewboard.asterisk.org/r/1895/ ........ r365068 | twilson | 2012-05-02 12:02:39 -0500 (Wed, 02 May 2012) | 11 lines Don't leak a ref if out of memory and can't link the linkedid If the ao2_link fails, we are most likely out of memory and bad things are going to happen. Before those bad things happen, make sure to clean up the linkedid references. This patch also adds a comment explaining why linkedid can't be passed to both local channel allocations and combines two ao2_ref calls into 1. Review: https://reviewboard.asterisk.org/r/1895/ ........ Merged revisions 365006,365068 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 365083 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@365084 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-05-02 17:43:16 +00:00
if (ast_strlen_zero(linkedid) || !ast_cel_track_event(AST_CEL_LINKEDID_END)) {
return;
}
if (!(lid = ao2_find(linkedids, (void *) linkedid, OBJ_POINTER))) {
ast_log(LOG_ERROR, "Something weird happened, couldn't find linkedid %s\n", linkedid);
return;
}
/* We have a ref for each channel with this linkedid, the link and the above find, so if
* before unreffing the channel we have a refcount of 3, we're done. Unlink and report. */
if (ao2_ref(lid, -1) == 3) {
ao2_unlink(linkedids, lid);
ast_cel_report_event(chan, AST_CEL_LINKEDID_END, NULL, NULL, NULL);
}
Multiple revisions 365006,365068 ........ r365006 | twilson | 2012-05-02 10:49:03 -0500 (Wed, 02 May 2012) | 12 lines Fix a CEL LINKEDID_END race and local channel linkedids This patch has the ;2 channel inherit the linkedid of the ;1 channel and fixes the race condition by no longer scanning the channel list for "other" channels with the same linkedid. Instead, cel.c has an ao2 container of linkedid strings and uses the refcount of the string as a counter of how many channels with the linkedid exist. Not only does this eliminate the race condition, but it also allows us to look up the linkedid by the hashed key instead of traversing the entire channel list. Review: https://reviewboard.asterisk.org/r/1895/ ........ r365068 | twilson | 2012-05-02 12:02:39 -0500 (Wed, 02 May 2012) | 11 lines Don't leak a ref if out of memory and can't link the linkedid If the ao2_link fails, we are most likely out of memory and bad things are going to happen. Before those bad things happen, make sure to clean up the linkedid references. This patch also adds a comment explaining why linkedid can't be passed to both local channel allocations and combines two ao2_ref calls into 1. Review: https://reviewboard.asterisk.org/r/1895/ ........ Merged revisions 365006,365068 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 365083 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@365084 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-05-02 17:43:16 +00:00
ao2_ref(lid, -1);
}
struct ast_channel *ast_cel_fabricate_channel_from_event(const struct ast_event *event)
{
struct varshead *headp;
struct ast_var_t *newvariable;
const char *mixed_name;
char timebuf[30];
struct ast_channel *tchan;
struct ast_cel_event_record record = {
.version = AST_CEL_EVENT_RECORD_VERSION,
};
/* do not call ast_channel_alloc because this is not really a real channel */
if (!(tchan = ast_dummy_channel_alloc())) {
return NULL;
}
headp = ast_channel_varshead(tchan);
/* first, get the variables from the event */
if (ast_cel_fill_record(event, &record)) {
Merged revisions 337974 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/10 ................ r337974 | rmudgett | 2011-09-26 14:35:23 -0500 (Mon, 26 Sep 2011) | 37 lines Merged revisions 337973 via svnmerge from https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ r337973 | rmudgett | 2011-09-26 14:30:39 -0500 (Mon, 26 Sep 2011) | 30 lines Fix deadlock when using dummy channels. Dummy channels created by ast_dummy_channel_alloc() should be destoyed by ast_channel_unref(). Using ast_channel_release() needlessly grabs the channel container lock and can cause a deadlock as a result. * Analyzed use of ast_dummy_channel_alloc() and made use ast_channel_unref() when done with the dummy channel. (Primary reason for the reported deadlock.) * Made app_dial.c:dial_exec_full() not call ast_call() holding any channel locks. Chan_local could not perform deadlock avoidance correctly. (Potential deadlock exposed by this issue. Secondary reason for the reported deadlock since the held lock was part of the deadlock chain.) * Fixed some uses of ast_dummy_channel_alloc() not checking the returned channel pointer for failure. * Fixed some potential chan=NULL pointer usage in func_odbc.c. Protected by testing the bogus_chan value. * Fixed needlessly clearing a 1024 char auto array when setting the first char to zero is enough in manager.c:action_getvar(). (closes issue ASTERISK-18613) Reported by: Thomas Arimont Patches: jira_asterisk_18613_v1.8.patch (license #5621) patch uploaded by rmudgett Tested by: Thomas Arimont ........ ................ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@337975 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2011-09-26 19:40:12 +00:00
ast_channel_unref(tchan);
return NULL;
}
/* next, fill the channel with their data */
mixed_name = (record.event_type == AST_CEL_USER_DEFINED)
? record.user_defined_name : record.event_name;
if ((newvariable = ast_var_assign("eventtype", mixed_name))) {
AST_LIST_INSERT_HEAD(headp, newvariable, entries);
}
if (ast_strlen_zero(cel_dateformat)) {
snprintf(timebuf, sizeof(timebuf), "%ld.%06ld", (long) record.event_time.tv_sec,
(long) record.event_time.tv_usec);
} else {
struct ast_tm tm;
ast_localtime(&record.event_time, &tm, NULL);
ast_strftime(timebuf, sizeof(timebuf), cel_dateformat, &tm);
}
if ((newvariable = ast_var_assign("eventtime", timebuf))) {
AST_LIST_INSERT_HEAD(headp, newvariable, entries);
}
if ((newvariable = ast_var_assign("eventenum", record.event_name))) {
AST_LIST_INSERT_HEAD(headp, newvariable, entries);
}
if ((newvariable = ast_var_assign("userdeftype", record.user_defined_name))) {
AST_LIST_INSERT_HEAD(headp, newvariable, entries);
}
if ((newvariable = ast_var_assign("eventextra", record.extra))) {
AST_LIST_INSERT_HEAD(headp, newvariable, entries);
}
ast_channel_caller(tchan)->id.name.valid = 1;
ast_channel_caller(tchan)->id.name.str = ast_strdup(record.caller_id_name);
ast_channel_caller(tchan)->id.number.valid = 1;
ast_channel_caller(tchan)->id.number.str = ast_strdup(record.caller_id_num);
ast_channel_caller(tchan)->ani.number.valid = 1;
ast_channel_caller(tchan)->ani.number.str = ast_strdup(record.caller_id_ani);
ast_channel_redirecting(tchan)->from.number.valid = 1;
ast_channel_redirecting(tchan)->from.number.str = ast_strdup(record.caller_id_rdnis);
ast_channel_dialed(tchan)->number.str = ast_strdup(record.caller_id_dnid);
ast_channel_exten_set(tchan, record.extension);
ast_channel_context_set(tchan, record.context);
Replace direct access to channel name with accessor functions There are many benefits to making the ast_channel an opaque handle, from increasing maintainability to presenting ways to kill masquerades. This patch kicks things off by taking things a field at a time, renaming the field to '__do_not_use_${fieldname}' and then writing setters/getters and converting the existing code to using them. When all fields are done, we can move ast_channel to a C file from channel.h and lop off the '__do_not_use_'. This patch sets up main/channel_interal_api.c to be the only file that actually accesses the ast_channel's fields directly. The intent would be for any API functions in channel.c to use the accessor functions. No more monkeying around with channel internals. We should use our own APIs. The interesting changes in this patch are the addition of channel_internal_api.c, the moving of the AST_DATA stuff from channel.c to channel_internal_api.c (note: the AST_DATA stuff will have to be reworked to use accessor functions when ast_channel is really opaque), and some re-working of the way channel iterators/callbacks are handled so as to avoid creating fake ast_channels on the stack to pass in matching data by directly accessing fields (since "name" is a stringfield and the fake channel doesn't init the stringfields, you can't use the ast_channel_name_set() function). I went with ast_channel_name(chan) for a getter, and ast_channel_name_set(chan, name) for a setter. The majority of the grunt-work for this change was done by writing a semantic patch using Coccinelle ( http://coccinelle.lip6.fr/ ). Review: https://reviewboard.asterisk.org/r/1655/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@350223 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-01-09 22:15:50 +00:00
ast_channel_name_set(tchan, record.channel_name);
ast_channel_uniqueid_set(tchan, record.unique_id);
ast_channel_linkedid_set(tchan, record.linked_id);
ast_channel_accountcode_set(tchan, record.account_code);
ast_channel_peeraccount_set(tchan, record.peer_account);
ast_channel_userfield_set(tchan, record.user_field);
if ((newvariable = ast_var_assign("BRIDGEPEER", record.peer))) {
AST_LIST_INSERT_HEAD(headp, newvariable, entries);
}
ast_channel_appl_set(tchan, ast_strdup(record.application_name));
ast_channel_data_set(tchan, ast_strdup(record.application_data));
ast_channel_amaflags_set(tchan, record.amaflag);
return tchan;
}
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)
{
struct timeval eventtime;
struct ast_event *ev;
const char *peername = "";
struct ast_channel *peer;
Multiple revisions 365006,365068 ........ r365006 | twilson | 2012-05-02 10:49:03 -0500 (Wed, 02 May 2012) | 12 lines Fix a CEL LINKEDID_END race and local channel linkedids This patch has the ;2 channel inherit the linkedid of the ;1 channel and fixes the race condition by no longer scanning the channel list for "other" channels with the same linkedid. Instead, cel.c has an ao2 container of linkedid strings and uses the refcount of the string as a counter of how many channels with the linkedid exist. Not only does this eliminate the race condition, but it also allows us to look up the linkedid by the hashed key instead of traversing the entire channel list. Review: https://reviewboard.asterisk.org/r/1895/ ........ r365068 | twilson | 2012-05-02 12:02:39 -0500 (Wed, 02 May 2012) | 11 lines Don't leak a ref if out of memory and can't link the linkedid If the ao2_link fails, we are most likely out of memory and bad things are going to happen. Before those bad things happen, make sure to clean up the linkedid references. This patch also adds a comment explaining why linkedid can't be passed to both local channel allocations and combines two ao2_ref calls into 1. Review: https://reviewboard.asterisk.org/r/1895/ ........ Merged revisions 365006,365068 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 365083 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@365084 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-05-02 17:43:16 +00:00
char *linkedid = ast_strdupa(ast_channel_linkedid(chan));
/* Make sure a reload is not occurring while we're checking to see if this
* is an event that we care about. We could lose an important event in this
* process otherwise. */
ast_mutex_lock(&reload_lock);
Multiple revisions 365006,365068 ........ r365006 | twilson | 2012-05-02 10:49:03 -0500 (Wed, 02 May 2012) | 12 lines Fix a CEL LINKEDID_END race and local channel linkedids This patch has the ;2 channel inherit the linkedid of the ;1 channel and fixes the race condition by no longer scanning the channel list for "other" channels with the same linkedid. Instead, cel.c has an ao2 container of linkedid strings and uses the refcount of the string as a counter of how many channels with the linkedid exist. Not only does this eliminate the race condition, but it also allows us to look up the linkedid by the hashed key instead of traversing the entire channel list. Review: https://reviewboard.asterisk.org/r/1895/ ........ r365068 | twilson | 2012-05-02 12:02:39 -0500 (Wed, 02 May 2012) | 11 lines Don't leak a ref if out of memory and can't link the linkedid If the ao2_link fails, we are most likely out of memory and bad things are going to happen. Before those bad things happen, make sure to clean up the linkedid references. This patch also adds a comment explaining why linkedid can't be passed to both local channel allocations and combines two ao2_ref calls into 1. Review: https://reviewboard.asterisk.org/r/1895/ ........ Merged revisions 365006,365068 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 365083 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@365084 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-05-02 17:43:16 +00:00
/* Record the linkedid of new channels if we are tracking LINKEDID_END even if we aren't
* reporting on CHANNEL_START so we can track when to send LINKEDID_END */
if (cel_enabled && ast_cel_track_event(AST_CEL_LINKEDID_END) && event_type == AST_CEL_CHANNEL_START && linkedid) {
char *lid;
if (!(lid = ao2_find(linkedids, (void *) linkedid, OBJ_POINTER))) {
if (!(lid = ao2_alloc(strlen(linkedid) + 1, NULL))) {
ast_mutex_unlock(&reload_lock);
return -1;
}
strcpy(lid, linkedid);
if (!ao2_link(linkedids, lid)) {
ao2_ref(lid, -1);
ast_mutex_unlock(&reload_lock);
return -1;
}
/* Leave both the link and the alloc refs to show a count of 1 + the link */
}
/* If we've found, go ahead and keep the ref to increment count of how many channels
* have this linkedid. We'll clean it up in check_retire */
}
if (!cel_enabled || !ast_cel_track_event(event_type)) {
ast_mutex_unlock(&reload_lock);
return 0;
}
if (event_type == AST_CEL_APP_START || event_type == AST_CEL_APP_END) {
char *app;
if (!(app = ao2_find(appset, (char *) ast_channel_appl(chan), OBJ_POINTER))) {
ast_mutex_unlock(&reload_lock);
return 0;
}
ao2_ref(app, -1);
}
ast_mutex_unlock(&reload_lock);
Multiple revisions 365006,365068 ........ r365006 | twilson | 2012-05-02 10:49:03 -0500 (Wed, 02 May 2012) | 12 lines Fix a CEL LINKEDID_END race and local channel linkedids This patch has the ;2 channel inherit the linkedid of the ;1 channel and fixes the race condition by no longer scanning the channel list for "other" channels with the same linkedid. Instead, cel.c has an ao2 container of linkedid strings and uses the refcount of the string as a counter of how many channels with the linkedid exist. Not only does this eliminate the race condition, but it also allows us to look up the linkedid by the hashed key instead of traversing the entire channel list. Review: https://reviewboard.asterisk.org/r/1895/ ........ r365068 | twilson | 2012-05-02 12:02:39 -0500 (Wed, 02 May 2012) | 11 lines Don't leak a ref if out of memory and can't link the linkedid If the ao2_link fails, we are most likely out of memory and bad things are going to happen. Before those bad things happen, make sure to clean up the linkedid references. This patch also adds a comment explaining why linkedid can't be passed to both local channel allocations and combines two ao2_ref calls into 1. Review: https://reviewboard.asterisk.org/r/1895/ ........ Merged revisions 365006,365068 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 365083 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@365084 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-05-02 17:43:16 +00:00
ast_channel_lock(chan);
peer = ast_bridged_channel(chan);
if (peer) {
ast_channel_ref(peer);
}
ast_channel_unlock(chan);
if (peer) {
ast_channel_lock(peer);
Replace direct access to channel name with accessor functions There are many benefits to making the ast_channel an opaque handle, from increasing maintainability to presenting ways to kill masquerades. This patch kicks things off by taking things a field at a time, renaming the field to '__do_not_use_${fieldname}' and then writing setters/getters and converting the existing code to using them. When all fields are done, we can move ast_channel to a C file from channel.h and lop off the '__do_not_use_'. This patch sets up main/channel_interal_api.c to be the only file that actually accesses the ast_channel's fields directly. The intent would be for any API functions in channel.c to use the accessor functions. No more monkeying around with channel internals. We should use our own APIs. The interesting changes in this patch are the addition of channel_internal_api.c, the moving of the AST_DATA stuff from channel.c to channel_internal_api.c (note: the AST_DATA stuff will have to be reworked to use accessor functions when ast_channel is really opaque), and some re-working of the way channel iterators/callbacks are handled so as to avoid creating fake ast_channels on the stack to pass in matching data by directly accessing fields (since "name" is a stringfield and the fake channel doesn't init the stringfields, you can't use the ast_channel_name_set() function). I went with ast_channel_name(chan) for a getter, and ast_channel_name_set(chan, name) for a setter. The majority of the grunt-work for this change was done by writing a semantic patch using Coccinelle ( http://coccinelle.lip6.fr/ ). Review: https://reviewboard.asterisk.org/r/1655/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@350223 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-01-09 22:15:50 +00:00
peername = ast_strdupa(ast_channel_name(peer));
ast_channel_unlock(peer);
} else if (peer2) {
ast_channel_lock(peer2);
Replace direct access to channel name with accessor functions There are many benefits to making the ast_channel an opaque handle, from increasing maintainability to presenting ways to kill masquerades. This patch kicks things off by taking things a field at a time, renaming the field to '__do_not_use_${fieldname}' and then writing setters/getters and converting the existing code to using them. When all fields are done, we can move ast_channel to a C file from channel.h and lop off the '__do_not_use_'. This patch sets up main/channel_interal_api.c to be the only file that actually accesses the ast_channel's fields directly. The intent would be for any API functions in channel.c to use the accessor functions. No more monkeying around with channel internals. We should use our own APIs. The interesting changes in this patch are the addition of channel_internal_api.c, the moving of the AST_DATA stuff from channel.c to channel_internal_api.c (note: the AST_DATA stuff will have to be reworked to use accessor functions when ast_channel is really opaque), and some re-working of the way channel iterators/callbacks are handled so as to avoid creating fake ast_channels on the stack to pass in matching data by directly accessing fields (since "name" is a stringfield and the fake channel doesn't init the stringfields, you can't use the ast_channel_name_set() function). I went with ast_channel_name(chan) for a getter, and ast_channel_name_set(chan, name) for a setter. The majority of the grunt-work for this change was done by writing a semantic patch using Coccinelle ( http://coccinelle.lip6.fr/ ). Review: https://reviewboard.asterisk.org/r/1655/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@350223 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-01-09 22:15:50 +00:00
peername = ast_strdupa(ast_channel_name(peer2));
ast_channel_unlock(peer2);
}
if (!userdefevname) {
userdefevname = "";
}
if (!extra) {
extra = "";
}
eventtime = ast_tvnow();
ast_channel_lock(chan);
ev = ast_event_new(AST_EVENT_CEL,
ast_callerid restructuring The purpose of this patch is to eliminate struct ast_callerid since it has turned into a miscellaneous collection of various party information. Eliminate struct ast_callerid and replace it with the following struct organization: struct ast_party_name { char *str; int char_set; int presentation; unsigned char valid; }; struct ast_party_number { char *str; int plan; int presentation; unsigned char valid; }; struct ast_party_subaddress { char *str; int type; unsigned char odd_even_indicator; unsigned char valid; }; struct ast_party_id { struct ast_party_name name; struct ast_party_number number; struct ast_party_subaddress subaddress; char *tag; }; struct ast_party_dialed { struct { char *str; int plan; } number; struct ast_party_subaddress subaddress; int transit_network_select; }; struct ast_party_caller { struct ast_party_id id; char *ani; int ani2; }; The new organization adds some new information as well. * The party name and number now have their own presentation value that can be manipulated independently. ISDN supplies the presentation value for the name and number at different times with the possibility that they could be different. * The party name and number now have a valid flag. Before this change the name or number string could be empty if the presentation were restricted. Most channel drivers assume that the name or number is then simply not available instead of indicating that the name or number was restricted. * The party name now has a character set value. SIP and Q.SIG have the ability to indicate what character set a name string is using so it could be presented properly. * The dialed party now has a numbering plan value that could be useful to have available. The various channel drivers will need to be updated to support the new core features as needed. They have simply been converted to supply current functionality at this time. The following items of note were either corrected or enhanced: * The CONNECTEDLINE() and REDIRECTING() dialplan functions were consolidated into func_callerid.c to share party id handling code. * CALLERPRES() is now deprecated because the name and number have their own presentation values. * Fixed app_alarmreceiver.c write_metadata(). The workstring[] could contain garbage. It also can only contain the caller id number so using ast_callerid_parse() on it is silly. There was also a typo in the CALLERNAME if test. * Fixed app_rpt.c using ast_callerid_parse() on the channel's caller id number string. ast_callerid_parse() alters the given buffer which in this case is the channel's caller id number string. Then using ast_shrink_phone_number() could alter it even more. * Fixed caller ID name and number memory leak in chan_usbradio.c. * Fixed uninitialized char arrays cid_num[] and cid_name[] in sig_analog.c. * Protected access to a caller channel with lock in chan_sip.c. * Clarified intent of code in app_meetme.c sla_ring_station() and dial_trunk(). Also made save all caller ID data instead of just the name and number strings. * Simplified cdr.c set_one_cid(). It hand coded the ast_callerid_merge() function. * Corrected some weirdness with app_privacy.c's use of caller presentation. Review: https://reviewboard.asterisk.org/r/702/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@276347 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2010-07-14 15:48:36 +00:00
AST_EVENT_IE_CEL_EVENT_TYPE, AST_EVENT_IE_PLTYPE_UINT, event_type,
AST_EVENT_IE_CEL_EVENT_TIME, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_sec,
AST_EVENT_IE_CEL_EVENT_TIME_USEC, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_usec,
AST_EVENT_IE_CEL_USEREVENT_NAME, AST_EVENT_IE_PLTYPE_STR, userdefevname,
AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_PLTYPE_STR,
S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, ""),
ast_callerid restructuring The purpose of this patch is to eliminate struct ast_callerid since it has turned into a miscellaneous collection of various party information. Eliminate struct ast_callerid and replace it with the following struct organization: struct ast_party_name { char *str; int char_set; int presentation; unsigned char valid; }; struct ast_party_number { char *str; int plan; int presentation; unsigned char valid; }; struct ast_party_subaddress { char *str; int type; unsigned char odd_even_indicator; unsigned char valid; }; struct ast_party_id { struct ast_party_name name; struct ast_party_number number; struct ast_party_subaddress subaddress; char *tag; }; struct ast_party_dialed { struct { char *str; int plan; } number; struct ast_party_subaddress subaddress; int transit_network_select; }; struct ast_party_caller { struct ast_party_id id; char *ani; int ani2; }; The new organization adds some new information as well. * The party name and number now have their own presentation value that can be manipulated independently. ISDN supplies the presentation value for the name and number at different times with the possibility that they could be different. * The party name and number now have a valid flag. Before this change the name or number string could be empty if the presentation were restricted. Most channel drivers assume that the name or number is then simply not available instead of indicating that the name or number was restricted. * The party name now has a character set value. SIP and Q.SIG have the ability to indicate what character set a name string is using so it could be presented properly. * The dialed party now has a numbering plan value that could be useful to have available. The various channel drivers will need to be updated to support the new core features as needed. They have simply been converted to supply current functionality at this time. The following items of note were either corrected or enhanced: * The CONNECTEDLINE() and REDIRECTING() dialplan functions were consolidated into func_callerid.c to share party id handling code. * CALLERPRES() is now deprecated because the name and number have their own presentation values. * Fixed app_alarmreceiver.c write_metadata(). The workstring[] could contain garbage. It also can only contain the caller id number so using ast_callerid_parse() on it is silly. There was also a typo in the CALLERNAME if test. * Fixed app_rpt.c using ast_callerid_parse() on the channel's caller id number string. ast_callerid_parse() alters the given buffer which in this case is the channel's caller id number string. Then using ast_shrink_phone_number() could alter it even more. * Fixed caller ID name and number memory leak in chan_usbradio.c. * Fixed uninitialized char arrays cid_num[] and cid_name[] in sig_analog.c. * Protected access to a caller channel with lock in chan_sip.c. * Clarified intent of code in app_meetme.c sla_ring_station() and dial_trunk(). Also made save all caller ID data instead of just the name and number strings. * Simplified cdr.c set_one_cid(). It hand coded the ast_callerid_merge() function. * Corrected some weirdness with app_privacy.c's use of caller presentation. Review: https://reviewboard.asterisk.org/r/702/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@276347 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2010-07-14 15:48:36 +00:00
AST_EVENT_IE_CEL_CIDNUM, AST_EVENT_IE_PLTYPE_STR,
S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""),
ast_callerid restructuring The purpose of this patch is to eliminate struct ast_callerid since it has turned into a miscellaneous collection of various party information. Eliminate struct ast_callerid and replace it with the following struct organization: struct ast_party_name { char *str; int char_set; int presentation; unsigned char valid; }; struct ast_party_number { char *str; int plan; int presentation; unsigned char valid; }; struct ast_party_subaddress { char *str; int type; unsigned char odd_even_indicator; unsigned char valid; }; struct ast_party_id { struct ast_party_name name; struct ast_party_number number; struct ast_party_subaddress subaddress; char *tag; }; struct ast_party_dialed { struct { char *str; int plan; } number; struct ast_party_subaddress subaddress; int transit_network_select; }; struct ast_party_caller { struct ast_party_id id; char *ani; int ani2; }; The new organization adds some new information as well. * The party name and number now have their own presentation value that can be manipulated independently. ISDN supplies the presentation value for the name and number at different times with the possibility that they could be different. * The party name and number now have a valid flag. Before this change the name or number string could be empty if the presentation were restricted. Most channel drivers assume that the name or number is then simply not available instead of indicating that the name or number was restricted. * The party name now has a character set value. SIP and Q.SIG have the ability to indicate what character set a name string is using so it could be presented properly. * The dialed party now has a numbering plan value that could be useful to have available. The various channel drivers will need to be updated to support the new core features as needed. They have simply been converted to supply current functionality at this time. The following items of note were either corrected or enhanced: * The CONNECTEDLINE() and REDIRECTING() dialplan functions were consolidated into func_callerid.c to share party id handling code. * CALLERPRES() is now deprecated because the name and number have their own presentation values. * Fixed app_alarmreceiver.c write_metadata(). The workstring[] could contain garbage. It also can only contain the caller id number so using ast_callerid_parse() on it is silly. There was also a typo in the CALLERNAME if test. * Fixed app_rpt.c using ast_callerid_parse() on the channel's caller id number string. ast_callerid_parse() alters the given buffer which in this case is the channel's caller id number string. Then using ast_shrink_phone_number() could alter it even more. * Fixed caller ID name and number memory leak in chan_usbradio.c. * Fixed uninitialized char arrays cid_num[] and cid_name[] in sig_analog.c. * Protected access to a caller channel with lock in chan_sip.c. * Clarified intent of code in app_meetme.c sla_ring_station() and dial_trunk(). Also made save all caller ID data instead of just the name and number strings. * Simplified cdr.c set_one_cid(). It hand coded the ast_callerid_merge() function. * Corrected some weirdness with app_privacy.c's use of caller presentation. Review: https://reviewboard.asterisk.org/r/702/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@276347 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2010-07-14 15:48:36 +00:00
AST_EVENT_IE_CEL_CIDANI, AST_EVENT_IE_PLTYPE_STR,
S_COR(ast_channel_caller(chan)->ani.number.valid, ast_channel_caller(chan)->ani.number.str, ""),
ast_callerid restructuring The purpose of this patch is to eliminate struct ast_callerid since it has turned into a miscellaneous collection of various party information. Eliminate struct ast_callerid and replace it with the following struct organization: struct ast_party_name { char *str; int char_set; int presentation; unsigned char valid; }; struct ast_party_number { char *str; int plan; int presentation; unsigned char valid; }; struct ast_party_subaddress { char *str; int type; unsigned char odd_even_indicator; unsigned char valid; }; struct ast_party_id { struct ast_party_name name; struct ast_party_number number; struct ast_party_subaddress subaddress; char *tag; }; struct ast_party_dialed { struct { char *str; int plan; } number; struct ast_party_subaddress subaddress; int transit_network_select; }; struct ast_party_caller { struct ast_party_id id; char *ani; int ani2; }; The new organization adds some new information as well. * The party name and number now have their own presentation value that can be manipulated independently. ISDN supplies the presentation value for the name and number at different times with the possibility that they could be different. * The party name and number now have a valid flag. Before this change the name or number string could be empty if the presentation were restricted. Most channel drivers assume that the name or number is then simply not available instead of indicating that the name or number was restricted. * The party name now has a character set value. SIP and Q.SIG have the ability to indicate what character set a name string is using so it could be presented properly. * The dialed party now has a numbering plan value that could be useful to have available. The various channel drivers will need to be updated to support the new core features as needed. They have simply been converted to supply current functionality at this time. The following items of note were either corrected or enhanced: * The CONNECTEDLINE() and REDIRECTING() dialplan functions were consolidated into func_callerid.c to share party id handling code. * CALLERPRES() is now deprecated because the name and number have their own presentation values. * Fixed app_alarmreceiver.c write_metadata(). The workstring[] could contain garbage. It also can only contain the caller id number so using ast_callerid_parse() on it is silly. There was also a typo in the CALLERNAME if test. * Fixed app_rpt.c using ast_callerid_parse() on the channel's caller id number string. ast_callerid_parse() alters the given buffer which in this case is the channel's caller id number string. Then using ast_shrink_phone_number() could alter it even more. * Fixed caller ID name and number memory leak in chan_usbradio.c. * Fixed uninitialized char arrays cid_num[] and cid_name[] in sig_analog.c. * Protected access to a caller channel with lock in chan_sip.c. * Clarified intent of code in app_meetme.c sla_ring_station() and dial_trunk(). Also made save all caller ID data instead of just the name and number strings. * Simplified cdr.c set_one_cid(). It hand coded the ast_callerid_merge() function. * Corrected some weirdness with app_privacy.c's use of caller presentation. Review: https://reviewboard.asterisk.org/r/702/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@276347 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2010-07-14 15:48:36 +00:00
AST_EVENT_IE_CEL_CIDRDNIS, AST_EVENT_IE_PLTYPE_STR,
S_COR(ast_channel_redirecting(chan)->from.number.valid, ast_channel_redirecting(chan)->from.number.str, ""),
ast_callerid restructuring The purpose of this patch is to eliminate struct ast_callerid since it has turned into a miscellaneous collection of various party information. Eliminate struct ast_callerid and replace it with the following struct organization: struct ast_party_name { char *str; int char_set; int presentation; unsigned char valid; }; struct ast_party_number { char *str; int plan; int presentation; unsigned char valid; }; struct ast_party_subaddress { char *str; int type; unsigned char odd_even_indicator; unsigned char valid; }; struct ast_party_id { struct ast_party_name name; struct ast_party_number number; struct ast_party_subaddress subaddress; char *tag; }; struct ast_party_dialed { struct { char *str; int plan; } number; struct ast_party_subaddress subaddress; int transit_network_select; }; struct ast_party_caller { struct ast_party_id id; char *ani; int ani2; }; The new organization adds some new information as well. * The party name and number now have their own presentation value that can be manipulated independently. ISDN supplies the presentation value for the name and number at different times with the possibility that they could be different. * The party name and number now have a valid flag. Before this change the name or number string could be empty if the presentation were restricted. Most channel drivers assume that the name or number is then simply not available instead of indicating that the name or number was restricted. * The party name now has a character set value. SIP and Q.SIG have the ability to indicate what character set a name string is using so it could be presented properly. * The dialed party now has a numbering plan value that could be useful to have available. The various channel drivers will need to be updated to support the new core features as needed. They have simply been converted to supply current functionality at this time. The following items of note were either corrected or enhanced: * The CONNECTEDLINE() and REDIRECTING() dialplan functions were consolidated into func_callerid.c to share party id handling code. * CALLERPRES() is now deprecated because the name and number have their own presentation values. * Fixed app_alarmreceiver.c write_metadata(). The workstring[] could contain garbage. It also can only contain the caller id number so using ast_callerid_parse() on it is silly. There was also a typo in the CALLERNAME if test. * Fixed app_rpt.c using ast_callerid_parse() on the channel's caller id number string. ast_callerid_parse() alters the given buffer which in this case is the channel's caller id number string. Then using ast_shrink_phone_number() could alter it even more. * Fixed caller ID name and number memory leak in chan_usbradio.c. * Fixed uninitialized char arrays cid_num[] and cid_name[] in sig_analog.c. * Protected access to a caller channel with lock in chan_sip.c. * Clarified intent of code in app_meetme.c sla_ring_station() and dial_trunk(). Also made save all caller ID data instead of just the name and number strings. * Simplified cdr.c set_one_cid(). It hand coded the ast_callerid_merge() function. * Corrected some weirdness with app_privacy.c's use of caller presentation. Review: https://reviewboard.asterisk.org/r/702/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@276347 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2010-07-14 15:48:36 +00:00
AST_EVENT_IE_CEL_CIDDNID, AST_EVENT_IE_PLTYPE_STR,
S_OR(ast_channel_dialed(chan)->number.str, ""),
AST_EVENT_IE_CEL_EXTEN, AST_EVENT_IE_PLTYPE_STR, ast_channel_exten(chan),
AST_EVENT_IE_CEL_CONTEXT, AST_EVENT_IE_PLTYPE_STR, ast_channel_context(chan),
Replace direct access to channel name with accessor functions There are many benefits to making the ast_channel an opaque handle, from increasing maintainability to presenting ways to kill masquerades. This patch kicks things off by taking things a field at a time, renaming the field to '__do_not_use_${fieldname}' and then writing setters/getters and converting the existing code to using them. When all fields are done, we can move ast_channel to a C file from channel.h and lop off the '__do_not_use_'. This patch sets up main/channel_interal_api.c to be the only file that actually accesses the ast_channel's fields directly. The intent would be for any API functions in channel.c to use the accessor functions. No more monkeying around with channel internals. We should use our own APIs. The interesting changes in this patch are the addition of channel_internal_api.c, the moving of the AST_DATA stuff from channel.c to channel_internal_api.c (note: the AST_DATA stuff will have to be reworked to use accessor functions when ast_channel is really opaque), and some re-working of the way channel iterators/callbacks are handled so as to avoid creating fake ast_channels on the stack to pass in matching data by directly accessing fields (since "name" is a stringfield and the fake channel doesn't init the stringfields, you can't use the ast_channel_name_set() function). I went with ast_channel_name(chan) for a getter, and ast_channel_name_set(chan, name) for a setter. The majority of the grunt-work for this change was done by writing a semantic patch using Coccinelle ( http://coccinelle.lip6.fr/ ). Review: https://reviewboard.asterisk.org/r/1655/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@350223 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-01-09 22:15:50 +00:00
AST_EVENT_IE_CEL_CHANNAME, AST_EVENT_IE_PLTYPE_STR, ast_channel_name(chan),
AST_EVENT_IE_CEL_APPNAME, AST_EVENT_IE_PLTYPE_STR, S_OR(ast_channel_appl(chan), ""),
AST_EVENT_IE_CEL_APPDATA, AST_EVENT_IE_PLTYPE_STR, S_OR(ast_channel_data(chan), ""),
AST_EVENT_IE_CEL_AMAFLAGS, AST_EVENT_IE_PLTYPE_UINT, ast_channel_amaflags(chan),
AST_EVENT_IE_CEL_ACCTCODE, AST_EVENT_IE_PLTYPE_STR, ast_channel_accountcode(chan),
AST_EVENT_IE_CEL_PEERACCT, AST_EVENT_IE_PLTYPE_STR, ast_channel_peeraccount(chan),
AST_EVENT_IE_CEL_UNIQUEID, AST_EVENT_IE_PLTYPE_STR, ast_channel_uniqueid(chan),
AST_EVENT_IE_CEL_LINKEDID, AST_EVENT_IE_PLTYPE_STR, ast_channel_linkedid(chan),
AST_EVENT_IE_CEL_USERFIELD, AST_EVENT_IE_PLTYPE_STR, ast_channel_userfield(chan),
ast_callerid restructuring The purpose of this patch is to eliminate struct ast_callerid since it has turned into a miscellaneous collection of various party information. Eliminate struct ast_callerid and replace it with the following struct organization: struct ast_party_name { char *str; int char_set; int presentation; unsigned char valid; }; struct ast_party_number { char *str; int plan; int presentation; unsigned char valid; }; struct ast_party_subaddress { char *str; int type; unsigned char odd_even_indicator; unsigned char valid; }; struct ast_party_id { struct ast_party_name name; struct ast_party_number number; struct ast_party_subaddress subaddress; char *tag; }; struct ast_party_dialed { struct { char *str; int plan; } number; struct ast_party_subaddress subaddress; int transit_network_select; }; struct ast_party_caller { struct ast_party_id id; char *ani; int ani2; }; The new organization adds some new information as well. * The party name and number now have their own presentation value that can be manipulated independently. ISDN supplies the presentation value for the name and number at different times with the possibility that they could be different. * The party name and number now have a valid flag. Before this change the name or number string could be empty if the presentation were restricted. Most channel drivers assume that the name or number is then simply not available instead of indicating that the name or number was restricted. * The party name now has a character set value. SIP and Q.SIG have the ability to indicate what character set a name string is using so it could be presented properly. * The dialed party now has a numbering plan value that could be useful to have available. The various channel drivers will need to be updated to support the new core features as needed. They have simply been converted to supply current functionality at this time. The following items of note were either corrected or enhanced: * The CONNECTEDLINE() and REDIRECTING() dialplan functions were consolidated into func_callerid.c to share party id handling code. * CALLERPRES() is now deprecated because the name and number have their own presentation values. * Fixed app_alarmreceiver.c write_metadata(). The workstring[] could contain garbage. It also can only contain the caller id number so using ast_callerid_parse() on it is silly. There was also a typo in the CALLERNAME if test. * Fixed app_rpt.c using ast_callerid_parse() on the channel's caller id number string. ast_callerid_parse() alters the given buffer which in this case is the channel's caller id number string. Then using ast_shrink_phone_number() could alter it even more. * Fixed caller ID name and number memory leak in chan_usbradio.c. * Fixed uninitialized char arrays cid_num[] and cid_name[] in sig_analog.c. * Protected access to a caller channel with lock in chan_sip.c. * Clarified intent of code in app_meetme.c sla_ring_station() and dial_trunk(). Also made save all caller ID data instead of just the name and number strings. * Simplified cdr.c set_one_cid(). It hand coded the ast_callerid_merge() function. * Corrected some weirdness with app_privacy.c's use of caller presentation. Review: https://reviewboard.asterisk.org/r/702/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@276347 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2010-07-14 15:48:36 +00:00
AST_EVENT_IE_CEL_EXTRA, AST_EVENT_IE_PLTYPE_STR, extra,
AST_EVENT_IE_CEL_PEER, AST_EVENT_IE_PLTYPE_STR, peername,
AST_EVENT_IE_END);
ast_channel_unlock(chan);
if (peer) {
peer = ast_channel_unref(peer);
}
if (ev && ast_event_queue(ev)) {
ast_event_destroy(ev);
return -1;
}
return 0;
}
int ast_cel_fill_record(const struct ast_event *e, struct ast_cel_event_record *r)
{
if (r->version != AST_CEL_EVENT_RECORD_VERSION) {
ast_log(LOG_ERROR, "Module ABI mismatch for ast_cel_event_record. "
"Please ensure all modules were compiled for "
"this version of Asterisk.\n");
return -1;
}
r->event_type = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_EVENT_TYPE);
r->event_time.tv_sec = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_EVENT_TIME);
r->event_time.tv_usec = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_EVENT_TIME_USEC);
r->event_name = ast_cel_get_type_name(r->event_type);
if (r->event_type == AST_CEL_USER_DEFINED) {
r->user_defined_name = ast_event_get_ie_str(e, AST_EVENT_IE_CEL_USEREVENT_NAME);
} else {
r->user_defined_name = "";
}
r->caller_id_name = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDNAME), "");
r->caller_id_num = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDNUM), "");
r->caller_id_ani = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDANI), "");
r->caller_id_rdnis = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDRDNIS), "");
r->caller_id_dnid = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CIDDNID), "");
r->extension = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_EXTEN), "");
r->context = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CONTEXT), "");
r->channel_name = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_CHANNAME), "");
r->application_name = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_APPNAME), "");
r->application_data = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_APPDATA), "");
r->account_code = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_ACCTCODE), "");
r->peer_account = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_ACCTCODE), "");
r->unique_id = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_UNIQUEID), "");
r->linked_id = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_LINKEDID), "");
r->amaflag = ast_event_get_ie_uint(e, AST_EVENT_IE_CEL_AMAFLAGS);
r->user_field = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_USERFIELD), "");
r->peer = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_PEER), "");
r->extra = S_OR(ast_event_get_ie_str(e, AST_EVENT_IE_CEL_EXTRA), "");
return 0;
}
static int app_hash(const void *obj, const int flags)
{
return ast_str_case_hash((const char *) obj);
}
static int app_cmp(void *obj, void *arg, int flags)
{
const char *app1 = obj, *app2 = arg;
return !strcasecmp(app1, app2) ? CMP_MATCH | CMP_STOP : 0;
}
Multiple revisions 365006,365068 ........ r365006 | twilson | 2012-05-02 10:49:03 -0500 (Wed, 02 May 2012) | 12 lines Fix a CEL LINKEDID_END race and local channel linkedids This patch has the ;2 channel inherit the linkedid of the ;1 channel and fixes the race condition by no longer scanning the channel list for "other" channels with the same linkedid. Instead, cel.c has an ao2 container of linkedid strings and uses the refcount of the string as a counter of how many channels with the linkedid exist. Not only does this eliminate the race condition, but it also allows us to look up the linkedid by the hashed key instead of traversing the entire channel list. Review: https://reviewboard.asterisk.org/r/1895/ ........ r365068 | twilson | 2012-05-02 12:02:39 -0500 (Wed, 02 May 2012) | 11 lines Don't leak a ref if out of memory and can't link the linkedid If the ao2_link fails, we are most likely out of memory and bad things are going to happen. Before those bad things happen, make sure to clean up the linkedid references. This patch also adds a comment explaining why linkedid can't be passed to both local channel allocations and combines two ao2_ref calls into 1. Review: https://reviewboard.asterisk.org/r/1895/ ........ Merged revisions 365006,365068 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 365083 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@365084 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-05-02 17:43:16 +00:00
#define lid_hash app_hash
#define lid_cmp app_cmp
static void ast_cel_engine_term(void)
{
if (appset) {
ao2_ref(appset, -1);
appset = NULL;
}
}
int ast_cel_engine_init(void)
{
if (!(appset = ao2_container_alloc(NUM_APP_BUCKETS, app_hash, app_cmp))) {
return -1;
}
Multiple revisions 365006,365068 ........ r365006 | twilson | 2012-05-02 10:49:03 -0500 (Wed, 02 May 2012) | 12 lines Fix a CEL LINKEDID_END race and local channel linkedids This patch has the ;2 channel inherit the linkedid of the ;1 channel and fixes the race condition by no longer scanning the channel list for "other" channels with the same linkedid. Instead, cel.c has an ao2 container of linkedid strings and uses the refcount of the string as a counter of how many channels with the linkedid exist. Not only does this eliminate the race condition, but it also allows us to look up the linkedid by the hashed key instead of traversing the entire channel list. Review: https://reviewboard.asterisk.org/r/1895/ ........ r365068 | twilson | 2012-05-02 12:02:39 -0500 (Wed, 02 May 2012) | 11 lines Don't leak a ref if out of memory and can't link the linkedid If the ao2_link fails, we are most likely out of memory and bad things are going to happen. Before those bad things happen, make sure to clean up the linkedid references. This patch also adds a comment explaining why linkedid can't be passed to both local channel allocations and combines two ao2_ref calls into 1. Review: https://reviewboard.asterisk.org/r/1895/ ........ Merged revisions 365006,365068 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 365083 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@365084 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-05-02 17:43:16 +00:00
if (!(linkedids = ao2_container_alloc(NUM_APP_BUCKETS, lid_hash, lid_cmp))) {
ao2_ref(appset, -1);
return -1;
}
Multiple revisions 365006,365068 ........ r365006 | twilson | 2012-05-02 10:49:03 -0500 (Wed, 02 May 2012) | 12 lines Fix a CEL LINKEDID_END race and local channel linkedids This patch has the ;2 channel inherit the linkedid of the ;1 channel and fixes the race condition by no longer scanning the channel list for "other" channels with the same linkedid. Instead, cel.c has an ao2 container of linkedid strings and uses the refcount of the string as a counter of how many channels with the linkedid exist. Not only does this eliminate the race condition, but it also allows us to look up the linkedid by the hashed key instead of traversing the entire channel list. Review: https://reviewboard.asterisk.org/r/1895/ ........ r365068 | twilson | 2012-05-02 12:02:39 -0500 (Wed, 02 May 2012) | 11 lines Don't leak a ref if out of memory and can't link the linkedid If the ao2_link fails, we are most likely out of memory and bad things are going to happen. Before those bad things happen, make sure to clean up the linkedid references. This patch also adds a comment explaining why linkedid can't be passed to both local channel allocations and combines two ao2_ref calls into 1. Review: https://reviewboard.asterisk.org/r/1895/ ........ Merged revisions 365006,365068 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 365083 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@365084 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-05-02 17:43:16 +00:00
if (do_reload() || ast_cli_register(&cli_status)) {
ao2_ref(appset, -1);
appset = NULL;
Multiple revisions 365006,365068 ........ r365006 | twilson | 2012-05-02 10:49:03 -0500 (Wed, 02 May 2012) | 12 lines Fix a CEL LINKEDID_END race and local channel linkedids This patch has the ;2 channel inherit the linkedid of the ;1 channel and fixes the race condition by no longer scanning the channel list for "other" channels with the same linkedid. Instead, cel.c has an ao2 container of linkedid strings and uses the refcount of the string as a counter of how many channels with the linkedid exist. Not only does this eliminate the race condition, but it also allows us to look up the linkedid by the hashed key instead of traversing the entire channel list. Review: https://reviewboard.asterisk.org/r/1895/ ........ r365068 | twilson | 2012-05-02 12:02:39 -0500 (Wed, 02 May 2012) | 11 lines Don't leak a ref if out of memory and can't link the linkedid If the ao2_link fails, we are most likely out of memory and bad things are going to happen. Before those bad things happen, make sure to clean up the linkedid references. This patch also adds a comment explaining why linkedid can't be passed to both local channel allocations and combines two ao2_ref calls into 1. Review: https://reviewboard.asterisk.org/r/1895/ ........ Merged revisions 365006,365068 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 365083 from http://svn.asterisk.org/svn/asterisk/branches/10 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@365084 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-05-02 17:43:16 +00:00
ao2_ref(linkedids, -1);
linkedids = NULL;
return -1;
}
ast_register_atexit(ast_cel_engine_term);
return 0;
}
int ast_cel_engine_reload(void)
{
return do_reload();
}