summaryrefslogtreecommitdiff
path: root/main/manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/manager.c')
-rw-r--r--main/manager.c73
1 files changed, 68 insertions, 5 deletions
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);