[Asterisk-code-review] Fixed OriginateResponse message (asterisk[13])
sungtae kim
asteriskteam at digium.com
Fri Dec 11 20:37:03 CST 2015
sungtae kim has uploaded a new change for review.
https://gerrit.asterisk.org/1804
Change subject: Fixed OriginateResponse message
......................................................................
Fixed OriginateResponse message
When the asterisk sending OriginateResponse message,
it doesn't set the "Uniqueid".
And it didn't support correct response message for
Application originate.
ASTERISK-25624
Change-Id: Id47477a6f3e6b4b3051bb412e38e73b4b1d84734
---
M main/manager.c
1 file changed, 174 insertions(+), 141 deletions(-)
git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/04/1804/1
diff --git a/main/manager.c b/main/manager.c
index 99c5502..d6aadf4 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -54,7 +54,7 @@
#include "asterisk.h"
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+ASTERISK_REGISTER_FILE()
#include "asterisk/paths.h" /* use various ast_config_AST_* */
#include <ctype.h>
@@ -215,6 +215,14 @@
</parameter>
<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>
@@ -4327,19 +4335,132 @@
return 0;
}
+static void generate_status(struct mansession *s, struct ast_channel *chan, char **vars, int varc, int all_variables, char *id_text, int *count)
+{
+ 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(AST_FORMAT_CAP_NAMES_LEN);
+ 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>"),
+ (long)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);
+ ++*count;
+
+ 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(AST_FORMAT_CAP_NAMES_LEN);
int channels = 0;
int all = ast_strlen_zero(name); /* set if we want all channels */
char id_text[256];
@@ -4348,20 +4469,17 @@
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;
}
@@ -4370,7 +4488,6 @@
chan = ast_channel_get_by_name(name);
if (!chan) {
astman_send_error(s, m, "No such channel");
- ast_free(variable_str);
return 0;
}
}
@@ -4389,106 +4506,9 @@
/* 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);
- }
- }
-
- 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>"),
- (long)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);
+ generate_status(s, chan, vars.name, vars.argc, all_variables, id_text, &channels);
ast_channel_unlock(chan);
chan = ast_channel_unref(chan);
@@ -4501,8 +4521,6 @@
astman_send_list_complete_start(s, m, "StatusComplete", channels);
astman_append(s, "Items: %d\r\n", channels);
astman_send_list_complete_end(s);
-
- ast_free(variable_str);
return 0;
}
@@ -4829,11 +4847,10 @@
static int action_command(struct mansession *s, const struct message *m)
{
const char *cmd = astman_get_header(m, "Command");
- const char *id = astman_get_header(m, "ActionID");
- char *buf = NULL, *final_buf = NULL;
+ char *buf = NULL, *final_buf = NULL, *delim, *output;
char template[] = "/tmp/ast-ami-XXXXXX"; /* template for temporary file */
- int fd;
- off_t l;
+ int fd, ret;
+ off_t len;
if (ast_strlen_zero(cmd)) {
astman_send_error(s, m, "No command provided");
@@ -4846,52 +4863,59 @@
}
if ((fd = mkstemp(template)) < 0) {
- ast_log(AST_LOG_WARNING, "Failed to create temporary file for command: %s\n", strerror(errno));
- astman_send_error(s, m, "Command response construction error");
+ astman_send_error_va(s, m, "Failed to create temporary file: %s", strerror(errno));
return 0;
}
- astman_append(s, "Response: Follows\r\nPrivilege: Command\r\n");
- if (!ast_strlen_zero(id)) {
- astman_append(s, "ActionID: %s\r\n", id);
- }
- /* FIXME: Wedge a ActionID response in here, waiting for later changes */
- ast_cli_command(fd, cmd); /* XXX need to change this to use a FILE * */
+ ret = ast_cli_command(fd, cmd);
+ astman_send_response_full(s, m, ret == RESULT_SUCCESS ? "Success" : "Error", MSG_MOREDATA, NULL);
+
/* Determine number of characters available */
- if ((l = lseek(fd, 0, SEEK_END)) < 0) {
- ast_log(LOG_WARNING, "Failed to determine number of characters for command: %s\n", strerror(errno));
+ if ((len = lseek(fd, 0, SEEK_END)) < 0) {
+ astman_append(s, "Message: Failed to determine number of characters: %s\r\n", strerror(errno));
goto action_command_cleanup;
}
/* This has a potential to overflow the stack. Hence, use the heap. */
- buf = ast_malloc(l + 1);
- final_buf = ast_malloc(l + 1);
+ buf = ast_malloc(len + 1);
+ final_buf = ast_malloc(len + 1);
if (!buf || !final_buf) {
- ast_log(LOG_WARNING, "Failed to allocate memory for temporary buffer\n");
+ astman_append(s, "Message: Memory allocation failure\r\n");
goto action_command_cleanup;
}
if (lseek(fd, 0, SEEK_SET) < 0) {
- ast_log(LOG_WARNING, "Failed to set position on temporary file for command: %s\n", strerror(errno));
+ astman_append(s, "Message: Failed to set position on temporary file: %s\r\n", strerror(errno));
goto action_command_cleanup;
}
- if (read(fd, buf, l) < 0) {
- ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
+ if (read(fd, buf, len) < 0) {
+ astman_append(s, "Message: Failed to read from temporary file: %s\r\n", strerror(errno));
goto action_command_cleanup;
}
- buf[l] = '\0';
- term_strip(final_buf, buf, l);
- final_buf[l] = '\0';
- astman_append(s, "%s", final_buf);
+ buf[len] = '\0';
+ term_strip(final_buf, buf, len);
+ final_buf[len] = '\0';
+
+ /* Trim trailing newline */
+ if (len && final_buf[len - 1] == '\n') {
+ final_buf[len - 1] = '\0';
+ }
+
+ astman_append(s, "Message: Command output follows\r\n");
+
+ delim = final_buf;
+ while ((output = strsep(&delim, "\n"))) {
+ astman_append(s, "Output: %s\r\n", output);
+ }
action_command_cleanup:
+ astman_append(s, "\r\n");
close(fd);
unlink(template);
- astman_append(s, "--END COMMAND--\r\n\r\n");
ast_free(buf);
ast_free(final_buf);
@@ -5993,7 +6017,7 @@
}
astman_append(s, "Response: Success\r\n%s", idText);
#if !defined(LOW_MEMORY)
- astman_append(s, "Version: %s\r\n\r\n", ast_get_version());
+ astman_append(s, "Version: %s\r\n\r\n", "");
#endif
return 0;
}
@@ -6221,9 +6245,11 @@
return 1;
}
if (s->session->inlen >= maxlen) {
- /* no crlf found, and buffer full - sorry, too long for us */
+ /* no crlf found, and buffer full - sorry, too long for us
+ * keep the last character in case we are in the middle of a CRLF. */
ast_log(LOG_WARNING, "Discarding message from %s. Line too long: %.25s...\n", ast_sockaddr_stringify_addr(&s->session->addr), src);
- s->session->inlen = 0;
+ src[0] = src[s->session->inlen - 1];
+ s->session->inlen = 1;
s->parsing = MESSAGE_LINE_TOO_LONG;
}
res = 0;
@@ -8959,7 +8985,14 @@
} else if (!strcasecmp(var->name, "deny") ||
!strcasecmp(var->name, "permit") ||
!strcasecmp(var->name, "acl")) {
- ast_append_acl(var->name, var->value, &user->acl, NULL, &acl_subscription_flag);
+ int acl_error = 0;
+
+ ast_append_acl(var->name, var->value, &user->acl, &acl_error, &acl_subscription_flag);
+ if (acl_error) {
+ ast_log(LOG_ERROR, "Invalid ACL '%s' for manager user '%s' on line %d. Deleting user\n",
+ var->value, user->username, var->lineno);
+ user->keep = 0;
+ }
} else if (!strcasecmp(var->name, "read") ) {
user->readperm = get_perm(var->value);
} else if (!strcasecmp(var->name, "write") ) {
--
To view, visit https://gerrit.asterisk.org/1804
To unsubscribe, visit https://gerrit.asterisk.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Id47477a6f3e6b4b3051bb412e38e73b4b1d84734
Gerrit-PatchSet: 1
Gerrit-Project: asterisk
Gerrit-Branch: 13
Gerrit-Owner: sungtae kim <pchero21 at gmail.com>
More information about the asterisk-code-review
mailing list