[svn-commits] mmichelson: branch mmichelson/agent_experiment r372131 - /team/mmichelson/age...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Mon Sep 3 14:12:23 CDT 2012


Author: mmichelson
Date: Mon Sep  3 14:12:19 2012
New Revision: 372131

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=372131
Log:
Change login operation.

Now instead of finding an agent to use, we allocate a new one
on login. This means that there is no longer a need for the
logged out state, so it has been removed.

I have this fear that RAII_VAR may be my hammer and I'm 
seeing everything as nails right now...


Modified:
    team/mmichelson/agent_experiment/channels/chan_agent2.c

Modified: team/mmichelson/agent_experiment/channels/chan_agent2.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/agent_experiment/channels/chan_agent2.c?view=diff&rev=372131&r1=372130&r2=372131
==============================================================================
--- team/mmichelson/agent_experiment/channels/chan_agent2.c (original)
+++ team/mmichelson/agent_experiment/channels/chan_agent2.c Mon Sep  3 14:12:19 2012
@@ -100,7 +100,7 @@
 	.types = ACO_TYPES(&agent_option),
 };
 
-static AO2_GLOBAL_OBJ_STATIC(globals);
+static AO2_GLOBAL_OBJ_STATIC(config_handle);
 
 static void agent_config_destroy(void *obj)
 {
@@ -127,7 +127,7 @@
 	return config;
 }
 
-CONFIG_INFO_STANDARD(cfg_info, globals, agent_config_alloc,
+CONFIG_INFO_STANDARD(cfg_info, config_handle, agent_config_alloc,
 	.files = ACO_FILES(&agent_conf),
 );
 
@@ -136,7 +136,6 @@
 		const struct ast_channel *requestor, const char *addr, int *cause);
 
 enum agent_states {
-	AGENT_LOGGED_OUT,
 	AGENT_LOGGED_IN,
 	AGENT_RINGING,
 	AGENT_ON_CALL,
@@ -199,19 +198,6 @@
 	/*! Function called when agent exits the state */
 	agent_state_fn exit;
 };
-
-static int enter_logged_out(struct agent *agent)
-{
-	const struct ast_channel_tech *to_free;
-	SCOPED_CHANNELLOCK(lock, agent->channel);
-
-	to_free = ast_channel_tech(agent->channel);
-	ast_channel_tech_set(agent->channel, agent->saved_channel_tech);
-	ast_free((void *)to_free);
-
-	agent->saved_channel_tech = NULL;
-	return 0;
-}
 
 static struct ast_channel_tech *get_modified_channel_tech(const struct ast_channel *chan)
 {
@@ -267,30 +253,6 @@
 	return copy;
 }
 
-static int exit_logged_out(struct agent *agent)
-{
-	struct ast_channel_tech *copy;
-	SCOPED_CHANNELLOCK(lock, agent->channel);
-
-	copy = get_modified_channel_tech(agent->channel);
-
-	if (!copy) {
-		return -1;
-	}
-
-	agent->saved_channel_tech = ast_channel_tech(agent->channel);
-	ast_channel_tech_set(agent->channel, copy);
-
-	return 0;
-}
-
-static const struct agent_state LOGGED_OUT = {
-	.name = "LOGGED_OUT",
-	.state = AGENT_LOGGED_OUT,
-	.enter = enter_logged_out,
-	.exit = exit_logged_out,
-};
-
 static int enter_logged_in(struct agent *agent)
 {
 	return ast_bridge_impart(agent->bridge, agent->channel, NULL, NULL, 0);
@@ -393,28 +355,68 @@
 	ast_debug(1, "Agent %s (channel %s) is ringing\n", addr, ast_channel_name(agent->channel));
 
 	/* Everything seems good. Time to change the state to RINGING */
-	change_agent_state(agent, &RINGING);
+	return change_agent_state(agent, &RINGING);
+}
+
+static void agent_destroy(void *obj)
+{
+	struct agent *agent = obj;
+	const struct ast_channel_tech *to_free;
+
+	if (agent->saved_channel_tech) {
+		to_free = ast_channel_tech(agent->channel);
+		ast_channel_tech_set(agent->channel, agent->saved_channel_tech);
+		ast_free((void *)to_free);
+	}
+
+	ao2_cleanup(agent->channel);
+	ao2_cleanup(agent->cfg);
+}
+
+static struct agent *alloc_agent(struct ast_channel *chan, const char *id)
+{
+	RAII_VAR(struct agent_config*, config, ao2_global_obj_ref(config_handle), ao2_cleanup);
+	RAII_VAR(struct agent_cfg *, cfg, config ? ao2_find(config->agents, id, OBJ_KEY) : NULL, ao2_cleanup);
+	RAII_VAR(struct agent *, agent, ao2_alloc(sizeof(*agent), agent_destroy), ao2_cleanup);
+	struct ast_channel_tech *copy;
+
+	if (!cfg || !agent) {
+		return NULL;
+	}
+
+	{
+		SCOPED_CHANNELLOCK(lock, chan);
+
+		copy = get_modified_channel_tech(chan);
+		if (!copy) {
+			return NULL;
+		}
+
+		agent->channel = ast_channel_ref(chan);
+		agent->saved_channel_tech = ast_channel_tech(agent->channel);
+		ast_channel_tech_set(agent->channel, copy);
+		ao2_ref(cfg, +1);
+		agent->cfg = cfg;
+		ao2_ref(agent, +1);
+		return agent;
+	}
 }
 
 static int login_exec(struct ast_channel *chan, const char *data)
 {
-	/* Need to find the corresponding agent. If the agent is in anything
-	 * other than the AGENT_LOGGED_OUT state, then this operation is invalid.
-	 */
-	RAII_VAR(struct agent *, agent, find_agent(data), ao2_cleanup);
+	RAII_VAR(struct agent *, existing_agent, find_agent(data), ao2_cleanup);
+	RAII_VAR(struct agent *, agent, alloc_agent(chan, data), ao2_cleanup);
 	SCOPED_AO2LOCK(lock, agent);
+
+	if (existing_agent) {
+		ast_log(LOG_WARNING, "Attempting to log in already logged-in agent %s\n", data);
+		return -1;
+	}
 
 	if (!agent) {
 		ast_log(LOG_WARNING, "Invalid agent %s specified for AgentLogin\n", data);
 		return -1;
 	}
-
-	if (agent->current_state->state != AGENT_LOGGED_OUT) {
-		ast_log(LOG_WARNING, "Attempting to log in already logged-in agent %s\n", data);
-		return -1;
-	}
-
-	agent->channel = ast_channel_ref(chan);
 
 	if (change_agent_state(agent, &LOGGED_IN)) {
 		ast_log(LOG_WARNING, "Problem attempting to log agent %s in\n", data);




More information about the svn-commits mailing list