[asterisk-commits] rmudgett: branch rmudgett/bridge_phase r392273 - in /team/rmudgett/bridge_pha...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Jun 19 14:33:14 CDT 2013


Author: rmudgett
Date: Wed Jun 19 14:33:07 2013
New Revision: 392273

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=392273
Log:
Convert AMI events AgentLogin/AgentLogoff to stasis.

Imported Kinsey Moore's refactoring of chan_agent's events and ported to
the new agent module.

Modified:
    team/rmudgett/bridge_phase/CHANGES
    team/rmudgett/bridge_phase/apps/app_agent_pool.c
    team/rmudgett/bridge_phase/channels/chan_agent.c
    team/rmudgett/bridge_phase/include/asterisk/stasis.h

Modified: team/rmudgett/bridge_phase/CHANGES
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/CHANGES?view=diff&rev=392273&r1=392272&r2=392273
==============================================================================
--- team/rmudgett/bridge_phase/CHANGES (original)
+++ team/rmudgett/bridge_phase/CHANGES Wed Jun 19 14:33:07 2013
@@ -246,6 +246,9 @@
    Events that reference channels (QueueCaller* and Agent*) will show
    information about each channel.  The (infamous) "Join" and "Leave" AMI
    events have been changed to "QueueCallerJoin" and "QueueCallerLeave".
+
+ * The AMI events "Agentlogin" and "Agentlogoff" have been renamed
+   "AgentLogin" and "AgentLogoff" respectively.
 
 AGI (Asterisk Gateway Interface)
 ------------------

Modified: team/rmudgett/bridge_phase/apps/app_agent_pool.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/apps/app_agent_pool.c?view=diff&rev=392273&r1=392272&r2=392273
==============================================================================
--- team/rmudgett/bridge_phase/apps/app_agent_pool.c (original)
+++ team/rmudgett/bridge_phase/apps/app_agent_pool.c Wed Jun 19 14:33:07 2013
@@ -47,6 +47,7 @@
 #include "asterisk/features_config.h"
 #include "asterisk/astobj2.h"
 #include "asterisk/stringfields.h"
+#include "asterisk/stasis_channels.h"
 
 /*** DOCUMENTATION
 	<application name="AgentLogin" language="en_US">
@@ -159,6 +160,35 @@
 			<para>Sets an agent as no longer logged in.</para>
 		</description>
 	</manager>
+	<managerEvent language="en_US" name="AgentLogin">
+		<managerEventInstance class="EVENT_FLAG_AGENT">
+			<synopsis>Raised when an Agent has logged in.</synopsis>
+			<syntax>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+				<parameter name="Agent">
+					<para>The name of the agent.</para>
+				</parameter>
+			</syntax>
+			<see-also>
+				<ref type="application">AgentLogin</ref>
+				<ref type="managerEvent">Agentlogoff</ref>
+			</see-also>
+		</managerEventInstance>
+	</managerEvent>
+	<managerEvent language="en_US" name="AgentLogoff">
+		<managerEventInstance class="EVENT_FLAG_AGENT">
+			<synopsis>Raised when an Agent has logged off.</synopsis>
+			<syntax>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentLogin']/managerEventInstance/syntax/parameter)" />
+				<parameter name="Logintime">
+					<para>The number of seconds the agent was logged in.</para>
+				</parameter>
+			</syntax>
+			<see-also>
+				<ref type="managerEvent">AgentLogin</ref>
+			</see-also>
+		</managerEventInstance>
+	</managerEvent>
  ***/
 
 /* ------------------------------------------------------------------- */
@@ -978,6 +1008,83 @@
 	return 0;
 }
 
+static struct ast_manager_event_blob *login_to_ami(struct stasis_message *msg)
+{
+	RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
+	RAII_VAR(struct ast_str *, party_string, ast_str_create(256), ast_free);
+	struct ast_channel_blob *obj = stasis_message_data(msg);
+	const char *agent = ast_json_string_get(ast_json_object_get(obj->blob, "agent"));
+
+	channel_string = ast_manager_build_channel_state_string(obj->snapshot);
+	if (!channel_string) {
+		return NULL;
+	}
+
+	return ast_manager_event_blob_create(EVENT_FLAG_AGENT, "AgentLogin",
+		"%s"
+		"Agent: %s\r\n",
+		ast_str_buffer(channel_string), agent);
+}
+
+STASIS_MESSAGE_TYPE_DEFN_LOCAL(login_type,
+	.to_ami = login_to_ami,
+	);
+
+static void send_agent_login(struct ast_channel *chan, const char *agent)
+{
+	RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
+
+	ast_assert(agent != NULL);
+
+	blob = ast_json_pack("{s: s}",
+		"agent", agent);
+	if (!blob) {
+		return;
+	}
+
+	ast_channel_publish_blob(chan, login_type(), blob);
+}
+
+static struct ast_manager_event_blob *logoff_to_ami(struct stasis_message *msg)
+{
+	RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
+	RAII_VAR(struct ast_str *, party_string, ast_str_create(256), ast_free);
+	struct ast_channel_blob *obj = stasis_message_data(msg);
+	const char *agent = ast_json_string_get(ast_json_object_get(obj->blob, "agent"));
+	long logintime = ast_json_integer_get(ast_json_object_get(obj->blob, "logintime"));
+
+	channel_string = ast_manager_build_channel_state_string(obj->snapshot);
+	if (!channel_string) {
+		return NULL;
+	}
+
+	return ast_manager_event_blob_create(EVENT_FLAG_AGENT, "AgentLogoff",
+		"%s"
+		"Agent: %s\r\n"
+		"Logintime: %ld\r\n",
+		ast_str_buffer(channel_string), agent, logintime);
+}
+
+STASIS_MESSAGE_TYPE_DEFN_LOCAL(logoff_type,
+	.to_ami = logoff_to_ami,
+	);
+
+static void send_agent_logoff(struct ast_channel *chan, const char *agent, long logintime)
+{
+	RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
+
+	ast_assert(agent != NULL);
+
+	blob = ast_json_pack("{s: s, s: i}",
+		"agent", agent,
+		"logintime", logintime);
+	if (!blob) {
+		return;
+	}
+
+	ast_channel_publish_blob(chan, logoff_type(), blob);
+}
+
 /*!
  * Called by the AgentRequest application (from the dial plan).
  *
@@ -1146,6 +1253,19 @@
 	ast_verb(2, "Agent '%s' logged in (format %s/%s)\n", agent->username,
 		ast_getformatname(ast_channel_readformat(chan)),
 		ast_getformatname(ast_channel_writeformat(chan)));
+	send_agent_login(chan, agent->username);
+
+	{
+		long logintime;
+	
+		agent_lock(agent);
+		logintime = time(NULL) - agent->login_start;
+		agent->login_start = 0;
+		agent->logged = ast_channel_unref(chan);
+		agent_unlock(agent);
+	
+		send_agent_logoff(chan, agent->username, logintime);
+	}
 
 	/*! \todo BUGBUG agent_login_exec() not written */
 	return -1;
@@ -1625,22 +1745,39 @@
 	destroy_config();
 	ao2_ref(agents, -1);
 	agents = NULL;
+
+	STASIS_MESSAGE_TYPE_CLEANUP(login_type);
+	STASIS_MESSAGE_TYPE_CLEANUP(logoff_type);
 	return 0;
 }
 
 static int load_module(void)
 {
 	int res = 0;
+
+/* BUGBUG need to make these message types public so app_queue can subscribe to them for its log. */
+	if (STASIS_MESSAGE_TYPE_INIT(login_type)) {
+		return AST_MODULE_LOAD_FAILURE;
+	}
+
+	if (STASIS_MESSAGE_TYPE_INIT(logoff_type)) {
+		STASIS_MESSAGE_TYPE_CLEANUP(login_type);
+		return AST_MODULE_LOAD_FAILURE;
+	}
 
 	agents = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_MUTEX,
 		AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, agent_pvt_sort_cmp, agent_pvt_cmp);
 	if (!agents) {
+		STASIS_MESSAGE_TYPE_CLEANUP(login_type);
+		STASIS_MESSAGE_TYPE_CLEANUP(logoff_type);
 		return AST_MODULE_LOAD_FAILURE;
 	}
 	if (load_config()) {
 		ast_log(LOG_ERROR, "Unable to load config. Not loading module.\n");
 		ao2_ref(agents, -1);
 		agents = NULL;
+		STASIS_MESSAGE_TYPE_CLEANUP(login_type);
+		STASIS_MESSAGE_TYPE_CLEANUP(logoff_type);
 		return AST_MODULE_LOAD_DECLINE;
 	}
 

Modified: team/rmudgett/bridge_phase/channels/chan_agent.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/channels/chan_agent.c?view=diff&rev=392273&r1=392272&r2=392273
==============================================================================
--- team/rmudgett/bridge_phase/channels/chan_agent.c (original)
+++ team/rmudgett/bridge_phase/channels/chan_agent.c Wed Jun 19 14:33:07 2013
@@ -69,6 +69,7 @@
 #include "asterisk/stringfields.h"
 #include "asterisk/event.h"
 #include "asterisk/data.h"
+#include "asterisk/stasis_channels.h"
 
 /*** DOCUMENTATION
 	<application name="AgentLoginOld" language="en_US">
@@ -193,6 +194,36 @@
 			<para>Sets an agent as no longer logged in.</para>
 		</description>
 	</manager>
+	<managerEvent language="en_US" name="AgentLogin">
+		<managerEventInstance class="EVENT_FLAG_AGENT">
+			<synopsis>Raised when an Agent has logged in.</synopsis>
+			<syntax>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+				<parameter name="Agent">
+					<para>The name of the agent.</para>
+				</parameter>
+			</syntax>
+			<see-also>
+				<ref type="application">AgentLogin</ref>
+				<ref type="managerEvent">Agentlogoff</ref>
+			</see-also>
+		</managerEventInstance>
+	</managerEvent>
+	<managerEvent language="en_US" name="AgentLogoff">
+		<managerEventInstance class="EVENT_FLAG_AGENT">
+			<synopsis>Raised when an Agent has logged off.</synopsis>
+			<syntax>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='AgentLogin']/managerEventInstance/syntax/parameter)" />
+				<parameter name="Logintime">
+					<para>The time the agent logged on.</para>
+				</parameter>
+			</syntax>
+			<see-also>
+				<ref type="managerEvent">AgentLogin</ref>
+			</see-also>
+		</managerEventInstance>
+	</managerEvent>
+
  ***/
 
 static const char tdesc[] = "Call Agent Proxy Channel";
@@ -1857,6 +1888,83 @@
 	AST_CLI_DEFINE(agent_logoff_cmd, "Sets an agent offline"),
 };
 
+static struct ast_manager_event_blob *login_to_ami(struct stasis_message *msg)
+{
+	RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
+	RAII_VAR(struct ast_str *, party_string, ast_str_create(256), ast_free);
+	struct ast_channel_blob *obj = stasis_message_data(msg);
+	const char *agent = ast_json_string_get(ast_json_object_get(obj->blob, "agent"));
+
+	channel_string = ast_manager_build_channel_state_string(obj->snapshot);
+	if (!channel_string) {
+		return NULL;
+	}
+
+	return ast_manager_event_blob_create(EVENT_FLAG_AGENT, "AgentLogin",
+		"%s"
+		"Agent: %s\r\n",
+		ast_str_buffer(channel_string), agent);
+}
+
+STASIS_MESSAGE_TYPE_DEFN_LOCAL(login_type,
+	.to_ami = login_to_ami,
+	);
+
+static void send_agent_login(struct ast_channel *chan, const char *agent)
+{
+	RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
+
+	ast_assert(agent != NULL);
+
+	blob = ast_json_pack("{s: s}",
+		"agent", agent);
+	if (!blob) {
+		return;
+	}
+
+	ast_channel_publish_blob(chan, login_type(), blob);
+}
+
+static struct ast_manager_event_blob *logoff_to_ami(struct stasis_message *msg)
+{
+	RAII_VAR(struct ast_str *, channel_string, NULL, ast_free);
+	RAII_VAR(struct ast_str *, party_string, ast_str_create(256), ast_free);
+	struct ast_channel_blob *obj = stasis_message_data(msg);
+	const char *agent = ast_json_string_get(ast_json_object_get(obj->blob, "agent"));
+	long logintime = ast_json_integer_get(ast_json_object_get(obj->blob, "logintime"));
+
+	channel_string = ast_manager_build_channel_state_string(obj->snapshot);
+	if (!channel_string) {
+		return NULL;
+	}
+
+	return ast_manager_event_blob_create(EVENT_FLAG_AGENT, "AgentLogoff",
+		"%s"
+		"Agent: %s\r\n"
+		"Logintime: %ld\r\n",
+		ast_str_buffer(channel_string), agent, logintime);
+}
+
+STASIS_MESSAGE_TYPE_DEFN_LOCAL(logoff_type,
+	.to_ami = logoff_to_ami,
+	);
+
+static void send_agent_logoff(struct ast_channel *chan, const char *agent, long logintime)
+{
+	RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
+
+	ast_assert(agent != NULL);
+
+	blob = ast_json_pack("{s: s, s: i}",
+		"agent", agent,
+		"logintime", logintime);
+	if (!blob) {
+		return;
+	}
+
+	ast_channel_publish_blob(chan, logoff_type(), blob);
+}
+
 /*!
  * Called by the AgentLogin application (from the dial plan).
  * 
@@ -2053,25 +2161,7 @@
 						p->lastdisc = ast_tvnow();
 						time(&p->loginstart);
 
-						/*** DOCUMENTATION
-							<managerEventInstance>
-								<synopsis>Raised when an Agent has logged in.</synopsis>
-								<syntax>
-									<parameter name="Agent">
-										<para>The name of the agent.</para>
-									</parameter>
-								</syntax>
-								<see-also>
-									<ref type="application">AgentLogin</ref>
-									<ref type="managerEvent">Agentlogoff</ref>
-								</see-also>
-							</managerEventInstance>
-						***/
-						manager_event(EVENT_FLAG_AGENT, "Agentlogin",
-							      "Agent: %s\r\n"
-							      "Channel: %s\r\n"
-							      "Uniqueid: %s\r\n",
-							      p->agent, ast_channel_name(chan), ast_channel_uniqueid(chan));
+						send_agent_login(chan, p->agent);
 						ast_queue_log("NONE", ast_channel_uniqueid(chan), agent, "AGENTLOGIN", "%s", ast_channel_name(chan));
 						ast_verb(2, "Agent '%s' logged in (format %s/%s)\n", p->agent,
 								    ast_getformatname(ast_channel_readformat(chan)), ast_getformatname(ast_channel_writeformat(chan)));
@@ -2153,22 +2243,7 @@
 						ast_mutex_unlock(&p->lock);
 
 						ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, "%s", agent);
-						/*** DOCUMENTATION
-							<managerEventInstance>
-								<synopsis>Raised when an Agent has logged off.</synopsis>
-								<syntax>
-									<xi:include xpointer="xpointer(/docs/managerEvent[@name='Agentlogin']/managerEventInstance/syntax/parameter[@name='Agent'])" />
-								</syntax>
-								<see-also>
-									<ref type="managerEvent">Agentlogin</ref>
-								</see-also>
-							</managerEventInstance>
-						***/
-						manager_event(EVENT_FLAG_AGENT, "Agentlogoff",
-							      "Agent: %s\r\n"
-							      "Logintime: %ld\r\n"
-							      "Uniqueid: %s\r\n",
-							      p->agent, logintime, ast_channel_uniqueid(chan));
+						send_agent_logoff(chan, p->agent, logintime);
 						ast_queue_log("NONE", ast_channel_uniqueid(chan), agent, "AGENTLOGOFF", "%s|%ld", ast_channel_name(chan), logintime);
 						ast_verb(2, "Agent '%s' logged out\n", p->agent);
 
@@ -2487,6 +2562,14 @@
  */
 static int load_module(void)
 {
+	if (STASIS_MESSAGE_TYPE_INIT(login_type)) {
+		return AST_MODULE_LOAD_FAILURE;
+	}
+
+	if (STASIS_MESSAGE_TYPE_INIT(logoff_type)) {
+		return AST_MODULE_LOAD_FAILURE;
+	}
+
 	if (!(agent_tech.capabilities = ast_format_cap_alloc())) {
 		ast_log(LOG_ERROR, "ast_format_cap_alloc_nolock fail.\n");
 		return AST_MODULE_LOAD_FAILURE;
@@ -2556,6 +2639,10 @@
 	AST_LIST_UNLOCK(&agents);
 
 	agent_tech.capabilities = ast_format_cap_destroy(agent_tech.capabilities);
+
+	STASIS_MESSAGE_TYPE_CLEANUP(login_type);
+	STASIS_MESSAGE_TYPE_CLEANUP(logoff_type);
+
 	return 0;
 }
 

Modified: team/rmudgett/bridge_phase/include/asterisk/stasis.h
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/include/asterisk/stasis.h?view=diff&rev=392273&r1=392272&r2=392273
==============================================================================
--- team/rmudgett/bridge_phase/include/asterisk/stasis.h (original)
+++ team/rmudgett/bridge_phase/include/asterisk/stasis.h Wed Jun 19 14:33:07 2013
@@ -736,6 +736,32 @@
 	}
 
 /*!
+ * \brief Boiler-plate removing macro for defining local message types.
+ *
+ * \code
+ *	STASIS_MESSAGE_TYPE_DEFN_LOCAL(ast_foo_type,
+ *		.to_ami = foo_to_ami,
+ *		.to_json = foo_to_json,
+ *		);
+ * \endcode
+ *
+ * \param name Name of message type.
+ * \param ... Virtual table methods for messages of this type.
+ * \since 12
+ */
+#define STASIS_MESSAGE_TYPE_DEFN_LOCAL(name, ...)			\
+	static struct stasis_message_vtable _priv_ ## name ## _v = {	\
+		__VA_ARGS__						\
+	};								\
+	static struct stasis_message_type *_priv_ ## name;		\
+	static struct stasis_message_type *name(void) {			\
+		if (_priv_ ## name == NULL) {				\
+			stasis_log_bad_type_access(#name);		\
+		}							\
+		return _priv_ ## name;					\
+	}
+
+/*!
 * \brief Boiler-plate removing macro for initializing message types.
  *
  * \code




More information about the asterisk-commits mailing list