diff options
Diffstat (limited to 'main/manager.c')
-rw-r--r-- | main/manager.c | 73 |
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); |