From 45e79490babaa8775aad1de72bad503aa2eb23f1 Mon Sep 17 00:00:00 2001
From: Olle Johansson <oej@edvina.net>
Date: Sat, 5 Jul 2008 20:54:30 +0000
Subject: [PATCH] Implement flags for AGI in the channel structure so taht
 "show channels" and AMI commands can display that a channel is under control
 of an AGI.

Work inspired by work at customer site, but paid for by Edvina AB


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@128240 65c4cc65-6c06-0410-ace0-fbb531ad65f3
---
 include/asterisk/channel.h |  6 ++++++
 include/asterisk/pbx.h     |  3 +++
 main/cli.c                 | 16 +++++++++++++++-
 main/manager.c             |  8 ++++++--
 main/pbx.c                 | 17 +++++++++++++++--
 pbx/pbx_realtime.c         |  5 +++--
 res/res_agi.c              | 12 ++++++++++--
 7 files changed, 58 insertions(+), 9 deletions(-)

diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index 5923f7cc1c..b2695ca603 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -582,6 +582,12 @@ enum {
 	/*! This flag indicates that on a masquerade, an active stream should not
 	 *  be carried over */
 	AST_FLAG_MASQ_NOSTREAM = (1 << 16),
+	/*! If the flag is controlled by AGI (not FastAGI) */
+	AST_FLAG_AGI =           (1 << 17),
+	/*! If the flag is controlled by FastAGI  */
+	AST_FLAG_FASTAGI =       (1 << 18),
+	/*! If the flag is controlled by AsyncAGI  */
+	AST_FLAG_ASYNCAGI =      (1 << 19),
 };
 
 /*! \brief ast_bridge_config flags */
diff --git a/include/asterisk/pbx.h b/include/asterisk/pbx.h
index b4bec238ec..bfa9d3bc96 100644
--- a/include/asterisk/pbx.h
+++ b/include/asterisk/pbx.h
@@ -998,6 +998,9 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
 									 const char *context, const char *exten, int priority,
 									 const char *label, const char *callerid, enum ext_match_t action);
 
+/*! \brief Function in pbx.c that propably should be somewhere else, but not in res_agi, since it's a loadable module */
+const char *agi_state(struct ast_channel *chan);
+
 
 /* every time a write lock is obtained for contexts,
    a counter is incremented. You can check this via the
diff --git a/main/cli.c b/main/cli.c
index 1335ec6b7c..6cbaf9a72e 100644
--- a/main/cli.c
+++ b/main/cli.c
@@ -628,6 +628,20 @@ static char *handle_showcalls(struct ast_cli_entry *e, int cmd, struct ast_cli_a
 	return RESULT_SUCCESS;
 }
 
+/*! \brief Add a marker before the app if the channel is controlled by AGI/FastAGI or AsyncAGI 
+	Used for "show channels"
+*/
+static const char *agi_flag(struct ast_channel *chan)
+{
+	if (ast_test_flag(chan, AST_FLAG_AGI))
+		return "[AGI]  ";
+	if (ast_test_flag(chan, AST_FLAG_FASTAGI))
+		return "[FAGI] ";
+	if (ast_test_flag(chan, AST_FLAG_ASYNCAGI))
+		return "[AAGI] ";
+	return "";
+}
+
 static char *handle_chanlist(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 #define FORMAT_STRING  "%-20.20s %-20.20s %-7.7s %-30.30s\n"
@@ -723,7 +737,7 @@ static char *handle_chanlist(struct ast_cli_entry *e, int cmd, struct ast_cli_ar
 				if (!ast_strlen_zero(c->context) && !ast_strlen_zero(c->exten)) 
 					snprintf(locbuf, sizeof(locbuf), "%s@%s:%d", c->exten, c->context, c->priority);
 				if (c->appl)
-					snprintf(appdata, sizeof(appdata), "%s(%s)", c->appl, S_OR(c->data, ""));
+					snprintf(appdata, sizeof(appdata), "%s%s(%s)", agi_flag(c), c->appl, S_OR(c->data, ""));
 				ast_cli(fd, FORMAT_STRING, c->name, locbuf, ast_state2str(c->_state), appdata);
 			}
 		}
diff --git a/main/manager.c b/main/manager.c
index 15fbbc841f..fa92408178 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -2718,9 +2718,13 @@ static int action_coreshowchannels(struct mansession *s, const struct message *m
 			"AccountCode: %s\r\n"
 			"BridgedChannel: %s\r\n"
 			"BridgedUniqueID: %s\r\n"
-			"\r\n", c->name, c->uniqueid, c->context, c->exten, c->priority, c->_state, ast_state2str(c->_state),
+			"AGIstate: %s\r\n"
+			"\r\n",
+			c->name, c->uniqueid, c->context, c->exten, c->priority, c->_state, ast_state2str(c->_state),
 			c->appl ? c->appl : "", c->data ? S_OR(c->data, ""): "",
-			S_OR(c->cid.cid_num, ""), durbuf, S_OR(c->accountcode, ""), bc ? bc->name : "", bc ? bc->uniqueid : "");
+			S_OR(c->cid.cid_num, ""), durbuf, S_OR(c->accountcode, ""), bc ? bc->name : "", bc ? bc->uniqueid : "",
+			agi_state(c)
+			);
 		ast_channel_unlock(c);
 		numchans++;
 	}
diff --git a/main/pbx.c b/main/pbx.c
index 4bffe8665b..dfd4f5f0b9 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -2901,6 +2901,18 @@ static void pbx_substitute_variables(char *passdata, int datalen, struct ast_cha
 	pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
 }
 
+/*! \brief report AGI state for channel */
+const char *agi_state(struct ast_channel *chan)
+{
+	if (ast_test_flag(chan, AST_FLAG_AGI))
+		return "AGI";
+	if (ast_test_flag(chan, AST_FLAG_FASTAGI))
+		return "FASTAGI";
+	if (ast_test_flag(chan, AST_FLAG_ASYNCAGI))
+		return "ASYNCAGI";
+	return "";
+}
+
 /*! 
  * \brief The return value depends on the action:
  *
@@ -2981,8 +2993,9 @@ static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con,
 					"Priority: %d\r\n"
 					"Application: %s\r\n"
 					"AppData: %s\r\n"
-					"Uniqueid: %s\r\n",
-					c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid);
+					"Uniqueid: %s\r\n"
+					"AGIstate: %s\r\n",
+					c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid, agi_state(c));
 			return pbx_exec(c, app, passdata);	/* 0 on success, -1 on failure */
 		}
 	} else if (q.swo) {	/* not found here, but in another switch */
diff --git a/pbx/pbx_realtime.c b/pbx/pbx_realtime.c
index 536ed9d27e..2b7a0dd7f7 100644
--- a/pbx/pbx_realtime.c
+++ b/pbx/pbx_realtime.c
@@ -226,8 +226,9 @@ static int realtime_exec(struct ast_channel *chan, const char *context, const ch
 							  "Priority: %d\r\n"
 							  "Application: %s\r\n"
 							  "AppData: %s\r\n"
-							  "Uniqueid: %s\r\n",
-							  chan->name, chan->context, chan->exten, chan->priority, app, !ast_strlen_zero(appdata) ? appdata : "(NULL)", chan->uniqueid);
+							  "Uniqueid: %s\r\n"
+                                        		  "AGIstate: %s\r\n",
+							  chan->name, chan->context, chan->exten, chan->priority, app, !ast_strlen_zero(appdata) ? appdata : "(NULL)", chan->uniqueid, agi_state(chan));
 				
 				res = pbx_exec(chan, a, appdata);
 			} else
diff --git a/res/res_agi.c b/res/res_agi.c
index b509ef67d7..521e47fcfc 100644
--- a/res/res_agi.c
+++ b/res/res_agi.c
@@ -204,7 +204,7 @@ static struct agi_cmd *get_agi_cmd(struct ast_channel *chan)
 	return cmd;
 }
 
-/* channel is locked when calling this one either from the CLI or manager thread */
+/*! \brief channel is locked when calling this one either from the CLI or manager thread */
 static int add_agi_cmd(struct ast_channel *chan, const char *cmd_buff, const char *cmd_id)
 {
 	struct ast_datastore *store;
@@ -424,6 +424,8 @@ static enum agi_result launch_asyncagi(struct ast_channel *chan, char *argv[], i
 		returnstatus = AGI_RESULT_FAILURE;
 		goto quit;
 	}
+	ast_set_flag(chan, AST_FLAG_ASYNCAGI);
+
 	agi_buffer[res] = '\0';
 	/* encode it and send it thru the manager so whoever is going to take
 	   care of AGI commands on this channel can decide which AGI commands
@@ -606,8 +608,10 @@ static enum agi_result launch_script(struct ast_channel *chan, char *script, cha
 	int pid, toast[2], fromast[2], audio[2], res;
 	struct stat st;
 
-	if (!strncasecmp(script, "agi://", 6))
+	if (!strncasecmp(script, "agi://", 6)) {
+		ast_set_flag(chan, AST_FLAG_FASTAGI);
 		return launch_netscript(script, argv, fds, efd, opid);
+	}
 	if (!strncasecmp(script, "agi:async", sizeof("agi:async")-1))
 		return launch_asyncagi(chan, argv, efd);
 
@@ -711,6 +715,7 @@ static enum agi_result launch_script(struct ast_channel *chan, char *script, cha
 		close(audio[0]);
 
 	*opid = pid;
+	ast_set_flag(chan, AST_FLAG_AGI);
 	return AGI_RESULT_SUCCESS;
 }
 
@@ -2919,6 +2924,9 @@ static int agi_exec_full(struct ast_channel *chan, void *data, int enhanced, int
 			close(efd);
 	}
 	ast_safe_fork_cleanup();
+	ast_clear_flag(chan, AST_FLAG_AGI);
+	ast_clear_flag(chan, AST_FLAG_FASTAGI);
+	ast_clear_flag(chan, AST_FLAG_ASYNCAGI);
 
 	switch (res) {
 	case AGI_RESULT_SUCCESS:
-- 
GitLab