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