summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
Diffstat (limited to 'main')
-rw-r--r--main/cdr.c4
-rw-r--r--main/channel.c34
-rw-r--r--main/features.c19
-rw-r--r--main/manager.c73
4 files changed, 99 insertions, 31 deletions
diff --git a/main/cdr.c b/main/cdr.c
index 9168978a4..2cd11bb05 100644
--- a/main/cdr.c
+++ b/main/cdr.c
@@ -991,7 +991,7 @@ int ast_cdr_setaccount(struct ast_channel *chan, const char *account)
}
}
- manager_event(EVENT_FLAG_CALL, "NewAccountCode",
+ ast_manager_event(chan, EVENT_FLAG_CALL, "NewAccountCode",
"Channel: %s\r\n"
"Uniqueid: %s\r\n"
"AccountCode: %s\r\n"
@@ -1017,7 +1017,7 @@ int ast_cdr_setpeeraccount(struct ast_channel *chan, const char *account)
}
}
- manager_event(EVENT_FLAG_CALL, "NewPeerAccount",
+ ast_manager_event(chan, EVENT_FLAG_CALL, "NewPeerAccount",
"Channel: %s\r\n"
"Uniqueid: %s\r\n"
"PeerAccount: %s\r\n"
diff --git a/main/channel.c b/main/channel.c
index 3ec23f9f7..5b58b76bd 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -978,7 +978,7 @@ alertpipe_failed:
* a lot of data into this func to do it here!
*/
if (!ast_strlen_zero(name_fmt)) {
- manager_event(EVENT_FLAG_CALL, "Newchannel",
+ ast_manager_event(tmp, EVENT_FLAG_CALL, "Newchannel",
"Channel: %s\r\n"
"ChannelState: %d\r\n"
"ChannelStateDesc: %s\r\n"
@@ -2222,7 +2222,7 @@ int ast_hangup(struct ast_channel *chan)
}
ast_channel_unlock(chan);
- manager_event(EVENT_FLAG_CALL, "Hangup",
+ ast_manager_event(chan, EVENT_FLAG_CALL, "Hangup",
"Channel: %s\r\n"
"Uniqueid: %s\r\n"
"CallerIDNum: %s\r\n"
@@ -2974,9 +2974,9 @@ int ast_waitfordigit_full(struct ast_channel *c, int ms, int audiofd, int cmdfd)
return 0; /* Time is up */
}
-static void send_dtmf_event(const struct ast_channel *chan, const char *direction, const char digit, const char *begin, const char *end)
+static void send_dtmf_event(struct ast_channel *chan, const char *direction, const char digit, const char *begin, const char *end)
{
- manager_event(EVENT_FLAG_DTMF,
+ ast_manager_event(chan, EVENT_FLAG_DTMF,
"DTMF",
"Channel: %s\r\n"
"Uniqueid: %s\r\n"
@@ -4839,7 +4839,7 @@ retrymasq:
*/
static void __ast_change_name_nolink(struct ast_channel *chan, const char *newname)
{
- manager_event(EVENT_FLAG_CALL, "Rename", "Channel: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", chan->name, newname, chan->uniqueid);
+ ast_manager_event(chan, EVENT_FLAG_CALL, "Rename", "Channel: %s\r\nNewname: %s\r\nUniqueid: %s\r\n", chan->name, newname, chan->uniqueid);
ast_string_field_set(chan, name, newname);
}
@@ -5078,9 +5078,9 @@ static void ast_set_owners_and_peers(struct ast_channel *chan1,
/*!
* \pre chan is locked
*/
-static void report_new_callerid(const struct ast_channel *chan)
+static void report_new_callerid(struct ast_channel *chan)
{
- manager_event(EVENT_FLAG_CALL, "NewCallerid",
+ ast_manager_event(chan, EVENT_FLAG_CALL, "NewCallerid",
"Channel: %s\r\n"
"CallerIDNum: %s\r\n"
"CallerIDName: %s\r\n"
@@ -5116,7 +5116,7 @@ int ast_do_masquerade(struct ast_channel *original)
struct ast_party_connected_line connected;
struct ast_party_redirecting redirecting;
} exchange;
- struct ast_channel *clonechan;
+ struct ast_channel *clonechan, *chans[2];
struct ast_cdr *cdr;
format_t rformat = original->readformat;
format_t wformat = original->writeformat;
@@ -5180,7 +5180,9 @@ int ast_do_masquerade(struct ast_channel *original)
ast_debug(4, "Actually Masquerading %s(%d) into the structure of %s(%d)\n",
clonechan->name, clonechan->_state, original->name, original->_state);
- manager_event(EVENT_FLAG_CALL, "Masquerade", "Clone: %s\r\nCloneState: %s\r\nOriginal: %s\r\nOriginalState: %s\r\n",
+ chans[0] = clonechan;
+ chans[1] = original;
+ ast_manager_event_multichan(EVENT_FLAG_CALL, "Masquerade", 2, chans, "Clone: %s\r\nCloneState: %s\r\nOriginal: %s\r\nOriginalState: %s\r\n",
clonechan->name, ast_state2str(clonechan->_state), original->name, ast_state2str(original->_state));
/* Having remembered the original read/write formats, we turn off any translation on either
@@ -5409,7 +5411,7 @@ int ast_do_masquerade(struct ast_channel *original)
if (ast_test_flag(clonechan, AST_FLAG_ZOMBIE)) {
ast_debug(1, "Destroying channel clone '%s'\n", clonechan->name);
ast_channel_unlock(clonechan);
- manager_event(EVENT_FLAG_CALL, "Hangup",
+ ast_manager_event(clonechan, EVENT_FLAG_CALL, "Hangup",
"Channel: %s\r\n"
"Uniqueid: %s\r\n"
"Cause: %d\r\n"
@@ -5491,8 +5493,7 @@ int ast_setstate(struct ast_channel *chan, enum ast_channel_state state)
ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, name);
/* setstate used to conditionally report Newchannel; this is no more */
- manager_event(EVENT_FLAG_CALL,
- "Newstate",
+ ast_manager_event(chan, EVENT_FLAG_CALL, "Newstate",
"Channel: %s\r\n"
"ChannelState: %d\r\n"
"ChannelStateDesc: %s\r\n"
@@ -5759,7 +5760,8 @@ int ast_channel_early_bridge(struct ast_channel *c0, struct ast_channel *c1)
*/
static void manager_bridge_event(int onoff, int type, struct ast_channel *c0, struct ast_channel *c1)
{
- manager_event(EVENT_FLAG_CALL, "Bridge",
+ struct ast_channel *chans[2] = { c0, c1 };
+ ast_manager_event_multichan(EVENT_FLAG_CALL, "Bridge", 2, chans,
"Bridgestate: %s\r\n"
"Bridgetype: %s\r\n"
"Channel1: %s\r\n"
@@ -5843,7 +5845,7 @@ static void bridge_play_sounds(struct ast_channel *c0, struct ast_channel *c1)
enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1,
struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc)
{
- struct ast_channel *who = NULL;
+ struct ast_channel *who = NULL, *chans[2] = { c0, c1 };
enum ast_bridge_result res = AST_BRIDGE_COMPLETE;
int nativefailed=0;
format_t o0nativeformats;
@@ -6017,7 +6019,7 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
ast_set_flag(c0, AST_FLAG_NBRIDGE);
ast_set_flag(c1, AST_FLAG_NBRIDGE);
if ((res = c0->tech->bridge(c0, c1, config->flags, fo, rc, to)) == AST_BRIDGE_COMPLETE) {
- manager_event(EVENT_FLAG_CALL, "Unlink",
+ ast_manager_event_multichan(EVENT_FLAG_CALL, "Unlink", 2, chans,
"Channel1: %s\r\n"
"Channel2: %s\r\n"
"Uniqueid1: %s\r\n"
@@ -6089,7 +6091,7 @@ enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_cha
c0->_bridge = NULL;
c1->_bridge = NULL;
- manager_event(EVENT_FLAG_CALL, "Unlink",
+ ast_manager_event_multichan(EVENT_FLAG_CALL, "Unlink", 2, chans,
"Channel1: %s\r\n"
"Channel2: %s\r\n"
"Uniqueid1: %s\r\n"
diff --git a/main/features.c b/main/features.c
index fe79d4977..d062db951 100644
--- a/main/features.c
+++ b/main/features.c
@@ -890,7 +890,7 @@ static int park_call_full(struct ast_channel *chan, struct ast_channel *peer, st
event_from = pbx_builtin_getvar_helper(chan, "BLINDTRANSFER");
}
- manager_event(EVENT_FLAG_CALL, "ParkedCall",
+ ast_manager_event(pu->chan, EVENT_FLAG_CALL, "ParkedCall",
"Exten: %s\r\n"
"Channel: %s\r\n"
"Parkinglot: %s\r\n"
@@ -3641,7 +3641,7 @@ static int park_exec_full(struct ast_channel *chan, const char *data, struct ast
ast_log(LOG_WARNING, "Whoa, no parking context?\n");
ast_cel_report_event(pu->chan, AST_CEL_PARK_END, NULL, "UnParkedCall", chan);
- manager_event(EVENT_FLAG_CALL, "UnParkedCall",
+ ast_manager_event(pu->chan, EVENT_FLAG_CALL, "UnParkedCall",
"Exten: %s\r\n"
"Channel: %s\r\n"
"From: %s\r\n"
@@ -4944,7 +4944,7 @@ int ast_bridge_timelimit(struct ast_channel *chan, struct ast_bridge_config *con
*/
static int bridge_exec(struct ast_channel *chan, const char *data)
{
- struct ast_channel *current_dest_chan, *final_dest_chan;
+ struct ast_channel *current_dest_chan, *final_dest_chan, *chans[2];
char *tmp_data = NULL;
struct ast_flags opts = { 0, };
struct ast_bridge_config bconfig = { { 0, }, };
@@ -4971,7 +4971,7 @@ static int bridge_exec(struct ast_channel *chan, const char *data)
strlen(chan->name) < strlen(args.dest_chan) ?
strlen(chan->name) : strlen(args.dest_chan))) {
ast_log(LOG_WARNING, "Unable to bridge channel %s with itself\n", chan->name);
- manager_event(EVENT_FLAG_CALL, "BridgeExec",
+ ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
"Response: Failed\r\n"
"Reason: Unable to bridge channel to itself\r\n"
"Channel1: %s\r\n"
@@ -4986,7 +4986,7 @@ static int bridge_exec(struct ast_channel *chan, const char *data)
strlen(args.dest_chan)))) {
ast_log(LOG_WARNING, "Bridge failed because channel %s does not exists or we "
"cannot get its lock\n", args.dest_chan);
- manager_event(EVENT_FLAG_CALL, "BridgeExec",
+ ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
"Response: Failed\r\n"
"Reason: Cannot grab end point\r\n"
"Channel1: %s\r\n"
@@ -5004,7 +5004,7 @@ static int bridge_exec(struct ast_channel *chan, const char *data)
if (!(final_dest_chan = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL,
NULL, NULL, current_dest_chan->linkedid, 0, "Bridge/%s", current_dest_chan->name))) {
ast_log(LOG_WARNING, "Cannot create placeholder channel for chan %s\n", args.dest_chan);
- manager_event(EVENT_FLAG_CALL, "BridgeExec",
+ ast_manager_event(chan, EVENT_FLAG_CALL, "BridgeExec",
"Response: Failed\r\n"
"Reason: cannot create placeholder\r\n"
"Channel1: %s\r\n"
@@ -5015,11 +5015,14 @@ static int bridge_exec(struct ast_channel *chan, const char *data)
do_bridge_masquerade(current_dest_chan, final_dest_chan);
+ chans[0] = current_dest_chan;
+ chans[1] = final_dest_chan;
+
/* now current_dest_chan is a ZOMBIE and with softhangup set to 1 and final_dest_chan is our end point */
/* try to make compatible, send error if we fail */
if (ast_channel_make_compatible(chan, final_dest_chan) < 0) {
ast_log(LOG_WARNING, "Could not make channels %s and %s compatible for bridge\n", chan->name, final_dest_chan->name);
- manager_event(EVENT_FLAG_CALL, "BridgeExec",
+ ast_manager_event_multichan(EVENT_FLAG_CALL, "BridgeExec", 2, chans,
"Response: Failed\r\n"
"Reason: Could not make channels compatible for bridge\r\n"
"Channel1: %s\r\n"
@@ -5031,7 +5034,7 @@ static int bridge_exec(struct ast_channel *chan, const char *data)
}
/* Report that the bridge will be successfull */
- manager_event(EVENT_FLAG_CALL, "BridgeExec",
+ ast_manager_event_multichan(EVENT_FLAG_CALL, "BridgeExec", 2, chans,
"Response: Success\r\n"
"Channel1: %s\r\n"
"Channel2: %s\r\n", chan->name, final_dest_chan->name);
diff --git a/main/manager.c b/main/manager.c
index b2a21bd87..93e16fe05 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -844,6 +844,14 @@ struct mansession {
static struct ao2_container *sessions = NULL;
+struct manager_channel_variable {
+ AST_LIST_ENTRY(manager_channel_variable) entry;
+ unsigned int isfunc:1;
+ char name[0]; /* allocate off the end the real size. */
+};
+
+static AST_RWLIST_HEAD_STATIC(channelvars, manager_channel_variable);
+
#define NEW_EVENT(m) (AST_LIST_NEXT(m->session->last_ev, eq_next))
/*! \brief user descriptor, as read from the config file.
@@ -876,6 +884,7 @@ static AST_RWLIST_HEAD_STATIC(manager_hooks, manager_custom_hook);
static struct eventqent *unref_event(struct eventqent *e);
static void ref_event(struct eventqent *e);
+static void free_channelvars(void);
/*! \brief Add a custom hook to be called when an event is fired */
void ast_manager_register_hook(struct manager_custom_hook *hook)
@@ -3292,7 +3301,7 @@ static void *fast_originate(void *data)
struct fast_originate_helper *in = data;
int res;
int reason = 0;
- struct ast_channel *chan = NULL;
+ struct ast_channel *chan = NULL, *chans[1];
char requested_channel[AST_CHANNEL_NAME];
if (!ast_strlen_zero(in->app)) {
@@ -3311,7 +3320,8 @@ static void *fast_originate(void *data)
snprintf(requested_channel, AST_CHANNEL_NAME, "%s/%s", in->tech, in->data);
}
/* Tell the manager what happened with the channel */
- manager_event(EVENT_FLAG_CALL, "OriginateResponse",
+ chans[0] = chan;
+ ast_manager_event_multichan(EVENT_FLAG_CALL, "OriginateResponse", chan ? 1 : 0, chans,
"%s%s"
"Response: %s\r\n"
"Channel: %s\r\n"
@@ -4211,13 +4221,34 @@ static int append_event(const char *str, int category)
return 0;
}
+AST_THREADSTORAGE(manager_event_funcbuf);
+
+static void append_channel_vars(struct ast_str **pbuf, struct ast_channel *chan)
+{
+ struct manager_channel_variable *var;
+ AST_RWLIST_RDLOCK(&channelvars);
+ AST_LIST_TRAVERSE(&channelvars, var, entry) {
+ const char *val = "";
+ if (var->isfunc) {
+ struct ast_str *res = ast_str_thread_get(&manager_event_funcbuf, 16);
+ int ret;
+ if (res && (ret = ast_func_read2(chan, var->name, &res, 0)) == 0) {
+ val = ast_str_buffer(res);
+ }
+ } else {
+ val = pbx_builtin_getvar_helper(chan, var->name);
+ }
+ ast_str_append(pbuf, 0, "ChanVariable(%s): %s=%s\r\n", chan->name, var->name, val ? val : "");
+ }
+ AST_RWLIST_UNLOCK(&channelvars);
+}
+
/* XXX see if can be moved inside the function */
AST_THREADSTORAGE(manager_event_buf);
#define MANAGER_EVENT_BUF_INITSIZE 256
-/*! \brief manager_event: Send AMI event to client */
-int __manager_event(int category, const char *event,
- const char *file, int line, const char *func, const char *fmt, ...)
+int __ast_manager_event_multichan(int category, const char *event, int chancount, struct
+ ast_channel **chans, const char *file, int line, const char *func, const char *fmt, ...)
{
struct mansession_session *session;
struct manager_custom_hook *hook;
@@ -4226,6 +4257,7 @@ int __manager_event(int category, const char *event,
va_list ap;
struct timeval now;
struct ast_str *buf;
+ int i;
if (!(buf = ast_str_thread_get(&manager_event_buf, MANAGER_EVENT_BUF_INITSIZE))) {
return -1;
@@ -4254,6 +4286,9 @@ int __manager_event(int category, const char *event,
va_start(ap, fmt);
ast_str_append_va(&buf, 0, fmt, ap);
va_end(ap);
+ for (i = 0; i < chancount; i++) {
+ append_channel_vars(&buf, chans[i]);
+ }
ast_str_append(&buf, 0, "\r\n");
@@ -5559,6 +5594,8 @@ static int __init_manager(int reload)
}
ami_tls_cfg.cipher = ast_strdup("");
+ free_channelvars();
+
for (var = ast_variable_browse(cfg, "general"); var; var = var->next) {
val = var->value;
@@ -5589,6 +5626,21 @@ static int __init_manager(int reload)
manager_debug = ast_true(val);
} else if (!strcasecmp(var->name, "httptimeout")) {
newhttptimeout = atoi(val);
+ } else if (!strcasecmp(var->name, "channelvars")) {
+ struct manager_channel_variable *mcv;
+ char *remaining = ast_strdupa(val), *next;
+ AST_RWLIST_WRLOCK(&channelvars);
+ while ((next = strsep(&remaining, ",|"))) {
+ if (!(mcv = ast_calloc(1, sizeof(*mcv) + strlen(next) + 1))) {
+ break;
+ }
+ strcpy(mcv->name, next); /* SAFE */
+ if (strchr(next, '(')) {
+ mcv->isfunc = 1;
+ }
+ AST_RWLIST_INSERT_TAIL(&channelvars, mcv, entry);
+ }
+ AST_RWLIST_UNLOCK(&channelvars);
} else {
ast_log(LOG_NOTICE, "Invalid keyword <%s> = <%s> in manager.conf [general]\n",
var->name, val);
@@ -5830,6 +5882,17 @@ static int __init_manager(int reload)
return 0;
}
+/* clear out every entry in the channelvar list */
+static void free_channelvars(void)
+{
+ struct manager_channel_variable *var;
+ AST_RWLIST_WRLOCK(&channelvars);
+ while ((var = AST_RWLIST_REMOVE_HEAD(&channelvars, entry))) {
+ ast_free(var);
+ }
+ AST_RWLIST_UNLOCK(&channelvars);
+}
+
int init_manager(void)
{
return __init_manager(0);