summaryrefslogtreecommitdiff
path: root/main/manager.c
diff options
context:
space:
mode:
authorKinsey Moore <kmoore@digium.com>2014-08-20 12:39:39 +0000
committerKinsey Moore <kmoore@digium.com>2014-08-20 12:39:39 +0000
commit01f1ff1f77101b2612ddb885dc6e22125e46a9fb (patch)
treebc2665ee19a01889263502ff44f169564b01d6c0 /main/manager.c
parent76290adf50dcafc8e35bc5267ea325285c25fdea (diff)
AMI: Add AllVariables parameter to Status
This adds the AllVariables parameter to the Status AMI action such that if defined and set to "true", all channel variables will be reported in the subsequent Status event(s). This parameter does not negate the functionality of the "Variables" parameter so that global variables and dialplan functions can be requested. Review: https://reviewboard.asterisk.org/r/3915/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@421534 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/manager.c')
-rw-r--r--main/manager.c239
1 files changed, 129 insertions, 110 deletions
diff --git a/main/manager.c b/main/manager.c
index c931b9dfb..eef5f478a 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -217,6 +217,14 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<parameter name="Variables">
<para>Comma <literal>,</literal> separated list of variable to include.</para>
</parameter>
+ <parameter name="AllVariables">
+ <para>If set to "true", the Status event will include all channel variables for
+ the requested channel(s).</para>
+ <enumlist>
+ <enum name="true"/>
+ <enum name="false"/>
+ </enumlist>
+ </parameter>
</syntax>
<description>
<para>Will return the status information of each channel along with the
@@ -3929,19 +3937,132 @@ static int action_getvar(struct mansession *s, const struct message *m)
return 0;
}
+static void generate_status(struct mansession *s, struct ast_channel *chan, char **vars, int varc, int all_variables, char *id_text)
+{
+ struct timeval now;
+ long elapsed_seconds;
+ struct ast_bridge *bridge;
+ RAII_VAR(struct ast_str *, variable_str, NULL, ast_free);
+ struct ast_str *write_transpath = ast_str_alloca(256);
+ struct ast_str *read_transpath = ast_str_alloca(256);
+ struct ast_str *codec_buf = ast_str_alloca(128);
+ struct ast_party_id effective_id;
+ int i;
+ RAII_VAR(struct ast_channel_snapshot *, snapshot,
+ ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan)),
+ ao2_cleanup);
+ RAII_VAR(struct ast_str *, snapshot_str, NULL, ast_free);
+
+ if (!snapshot) {
+ return;
+ }
+
+ snapshot_str = ast_manager_build_channel_state_string(snapshot);
+ if (!snapshot_str) {
+ return;
+ }
+
+ if (all_variables) {
+ variable_str = ast_str_create(2048);
+ } else {
+ variable_str = ast_str_create(1024);
+ }
+
+ if (!variable_str) {
+ return;
+ }
+
+ now = ast_tvnow();
+ elapsed_seconds = ast_tvdiff_sec(now, ast_channel_creationtime(chan));
+
+ /* Even if all_variables has been specified, explicitly requested variables
+ * may be global variables or dialplan functions */
+ for (i = 0; i < varc; i++) {
+ char valbuf[512], *ret = NULL;
+
+ if (vars[i][strlen(vars[i]) - 1] == ')') {
+ if (ast_func_read(chan, vars[i], valbuf, sizeof(valbuf)) < 0) {
+ valbuf[0] = '\0';
+ }
+ ret = valbuf;
+ } else {
+ pbx_retrieve_variable(chan, vars[i], &ret, valbuf, sizeof(valbuf), NULL);
+ }
+
+ ast_str_append(&variable_str, 0, "Variable: %s=%s\r\n", vars[i], ret);
+ }
+
+ /* Walk all channel variables and add them */
+ if (all_variables) {
+ struct ast_var_t *variables;
+
+ AST_LIST_TRAVERSE(ast_channel_varshead(chan), variables, entries) {
+ ast_str_append(&variable_str, 0, "Variable: %s=%s\r\n",
+ ast_var_name(variables), ast_var_value(variables));
+ }
+ }
+
+ bridge = ast_channel_get_bridge(chan);
+ effective_id = ast_channel_connected_effective_id(chan);
+
+ astman_append(s,
+ "Event: Status\r\n"
+ "Privilege: Call\r\n"
+ "%s"
+ "Type: %s\r\n"
+ "DNID: %s\r\n"
+ "EffectiveConnectedLineNum: %s\r\n"
+ "EffectiveConnectedLineName: %s\r\n"
+ "TimeToHangup: %ld\r\n"
+ "BridgeID: %s\r\n"
+ "Linkedid: %s\r\n"
+ "Application: %s\r\n"
+ "Data: %s\r\n"
+ "Nativeformats: %s\r\n"
+ "Readformat: %s\r\n"
+ "Readtrans: %s\r\n"
+ "Writeformat: %s\r\n"
+ "Writetrans: %s\r\n"
+ "Callgroup: %llu\r\n"
+ "Pickupgroup: %llu\r\n"
+ "Seconds: %ld\r\n"
+ "%s"
+ "%s"
+ "\r\n",
+ ast_str_buffer(snapshot_str),
+ ast_channel_tech(chan)->type,
+ S_OR(ast_channel_dialed(chan)->number.str, ""),
+ S_COR(effective_id.number.valid, effective_id.number.str, "<unknown>"),
+ S_COR(effective_id.name.valid, effective_id.name.str, "<unknown>"),
+ ast_channel_whentohangup(chan)->tv_sec,
+ bridge ? bridge->uniqueid : "",
+ ast_channel_linkedid(chan),
+ ast_channel_appl(chan),
+ ast_channel_data(chan),
+ ast_format_cap_get_names(ast_channel_nativeformats(chan), &codec_buf),
+ ast_format_get_name(ast_channel_readformat(chan)),
+ ast_translate_path_to_str(ast_channel_readtrans(chan), &read_transpath),
+ ast_format_get_name(ast_channel_writeformat(chan)),
+ ast_translate_path_to_str(ast_channel_writetrans(chan), &write_transpath),
+ ast_channel_callgroup(chan),
+ ast_channel_pickupgroup(chan),
+ (long)elapsed_seconds,
+ ast_str_buffer(variable_str),
+ id_text);
+
+ ao2_cleanup(bridge);
+}
+
/*! \brief Manager "status" command to show channels */
-/* Needs documentation... */
static int action_status(struct mansession *s, const struct message *m)
{
const char *name = astman_get_header(m, "Channel");
const char *chan_variables = astman_get_header(m, "Variables");
+ const char *all_chan_variables = astman_get_header(m, "AllVariables");
+ int all_variables = 0;
const char *id = astman_get_header(m, "ActionID");
char *variables = ast_strdupa(S_OR(chan_variables, ""));
- struct ast_str *variable_str = ast_str_create(1024);
- struct ast_str *write_transpath = ast_str_alloca(256);
- struct ast_str *read_transpath = ast_str_alloca(256);
struct ast_channel *chan;
- struct ast_str *codec_buf = ast_str_alloca(64);
int channels = 0;
int all = ast_strlen_zero(name); /* set if we want all channels */
char id_text[256];
@@ -3950,20 +4071,17 @@ static int action_status(struct mansession *s, const struct message *m)
AST_APP_ARG(name)[100];
);
- if (!variable_str) {
- astman_send_error(s, m, "Memory Allocation Failure");
- return 1;
+ if (!ast_strlen_zero(all_chan_variables)) {
+ all_variables = ast_true(all_chan_variables);
}
if (!(function_capable_string_allowed_with_auths(variables, s->session->writeperm))) {
- ast_free(variable_str);
astman_send_error(s, m, "Status Access Forbidden: Variables");
return 0;
}
if (all) {
if (!(it_chans = ast_channel_iterator_all_new())) {
- ast_free(variable_str);
astman_send_error(s, m, "Memory Allocation Failure");
return 1;
}
@@ -3972,7 +4090,6 @@ static int action_status(struct mansession *s, const struct message *m)
chan = ast_channel_get_by_name(name);
if (!chan) {
astman_send_error(s, m, "No such channel");
- ast_free(variable_str);
return 0;
}
}
@@ -3991,107 +4108,11 @@ static int action_status(struct mansession *s, const struct message *m)
/* if we look by name, we break after the first iteration */
for (; chan; all ? chan = ast_channel_iterator_next(it_chans) : 0) {
- struct timeval now;
- long elapsed_seconds;
- struct ast_bridge *bridge;
-
ast_channel_lock(chan);
- now = ast_tvnow();
- elapsed_seconds = ast_tvdiff_sec(now, ast_channel_creationtime(chan));
-
- if (!ast_strlen_zero(chan_variables)) {
- int i;
- ast_str_reset(variable_str);
- for (i = 0; i < vars.argc; i++) {
- char valbuf[512], *ret = NULL;
-
- if (vars.name[i][strlen(vars.name[i]) - 1] == ')') {
- if (ast_func_read(chan, vars.name[i], valbuf, sizeof(valbuf)) < 0) {
- valbuf[0] = '\0';
- }
- ret = valbuf;
- } else {
- pbx_retrieve_variable(chan, vars.name[i], &ret, valbuf, sizeof(valbuf), NULL);
- }
-
- ast_str_append(&variable_str, 0, "Variable: %s=%s\r\n", vars.name[i], ret);
- }
- }
-
+ generate_status(s, chan, vars.name, vars.argc, all_variables, id_text);
channels++;
- bridge = ast_channel_get_bridge(chan);
-
- astman_append(s,
- "Event: Status\r\n"
- "Privilege: Call\r\n"
- "Channel: %s\r\n"
- "ChannelState: %u\r\n"
- "ChannelStateDesc: %s\r\n"
- "CallerIDNum: %s\r\n"
- "CallerIDName: %s\r\n"
- "ConnectedLineNum: %s\r\n"
- "ConnectedLineName: %s\r\n"
- "Accountcode: %s\r\n"
- "Context: %s\r\n"
- "Exten: %s\r\n"
- "Priority: %d\r\n"
- "Uniqueid: %s\r\n"
- "Type: %s\r\n"
- "DNID: %s\r\n"
- "EffectiveConnectedLineNum: %s\r\n"
- "EffectiveConnectedLineName: %s\r\n"
- "TimeToHangup: %ld\r\n"
- "BridgeID: %s\r\n"
- "Linkedid: %s\r\n"
- "Application: %s\r\n"
- "Data: %s\r\n"
- "Nativeformats: %s\r\n"
- "Readformat: %s\r\n"
- "Readtrans: %s\r\n"
- "Writeformat: %s\r\n"
- "Writetrans: %s\r\n"
- "Callgroup: %llu\r\n"
- "Pickupgroup: %llu\r\n"
- "Seconds: %ld\r\n"
- "%s"
- "%s"
- "\r\n",
- ast_channel_name(chan),
- ast_channel_state(chan),
- ast_state2str(ast_channel_state(chan)),
- S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<unknown>"),
- S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, "<unknown>"),
- S_COR(ast_channel_connected(chan)->id.number.valid, ast_channel_connected(chan)->id.number.str, "<unknown>"),
- S_COR(ast_channel_connected(chan)->id.name.valid, ast_channel_connected(chan)->id.name.str, "<unknown>"),
- ast_channel_accountcode(chan),
- ast_channel_context(chan),
- ast_channel_exten(chan),
- ast_channel_priority(chan),
- ast_channel_uniqueid(chan),
- ast_channel_tech(chan)->type,
- S_OR(ast_channel_dialed(chan)->number.str, ""),
- S_COR(ast_channel_connected_effective_id(chan).number.valid, ast_channel_connected_effective_id(chan).number.str, "<unknown>"),
- S_COR(ast_channel_connected_effective_id(chan).name.valid, ast_channel_connected_effective_id(chan).name.str, "<unknown>"),
- ast_channel_whentohangup(chan)->tv_sec,
- bridge ? bridge->uniqueid : "",
- ast_channel_linkedid(chan),
- ast_channel_appl(chan),
- ast_channel_data(chan),
- ast_format_cap_get_names(ast_channel_nativeformats(chan), &codec_buf),
- ast_format_get_name(ast_channel_readformat(chan)),
- ast_translate_path_to_str(ast_channel_readtrans(chan), &read_transpath),
- ast_format_get_name(ast_channel_writeformat(chan)),
- ast_translate_path_to_str(ast_channel_writetrans(chan), &write_transpath),
- ast_channel_callgroup(chan),
- ast_channel_pickupgroup(chan),
- (long)elapsed_seconds,
- ast_str_buffer(variable_str),
- id_text);
-
- ao2_cleanup(bridge);
-
ast_channel_unlock(chan);
chan = ast_channel_unref(chan);
}
@@ -4106,8 +4127,6 @@ static int action_status(struct mansession *s, const struct message *m)
"Items: %d\r\n"
"\r\n", id_text, channels);
- ast_free(variable_str);
-
return 0;
}