[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