[svn-commits] rmudgett: branch rmudgett/bridge_phase r392809 - /team/rmudgett/bridge_phase/...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Mon Jun 24 20:00:57 CDT 2013


Author: rmudgett
Date: Mon Jun 24 20:00:55 2013
New Revision: 392809

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=392809
Log:
Initial agent state handling.

Modified:
    team/rmudgett/bridge_phase/apps/app_agent_pool.c

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=392809&r1=392808&r2=392809
==============================================================================
--- team/rmudgett/bridge_phase/apps/app_agent_pool.c (original)
+++ team/rmudgett/bridge_phase/apps/app_agent_pool.c Mon Jun 24 20:00:55 2013
@@ -345,7 +345,7 @@
  * file has been touched.
  */
 /*
- * BUGBUG chan_agent stupidly deals with users.conf.
+ * BUGBUG chan_agent stupidly deals with users.conf.  Remove agent users.conf support.
  *
  * Agents built by users.conf will use defaults except for the
  * three parameters obtained from users.conf.  Also any agent
@@ -512,6 +512,23 @@
 	destroy_config();
 	return -1;
 }
+
+enum agent_state {
+	/*! The agent is defined but an agent is not present. */
+	AGENT_STATE_LOGGED_OUT,
+	/*! The agent is ready for a call. */
+	AGENT_STATE_READY_FOR_CALL,
+	/*! The agent has a call waiting to connect. */
+	AGENT_STATE_CALL_PRESENT,
+	/*! The agent needs to ack the call. */
+	AGENT_STATE_CALL_WAIT_ACK,
+	/*! The agent is connected with a call. */
+	AGENT_STATE_ON_CALL,
+	/*! The agent is resting between calls. */
+	AGENT_STATE_CALL_WRAPUP,
+	/*! The agent is being kicked out. */
+	AGENT_STATE_LOGGING_OUT,
+};
 
 /*! Agent config option override flags. */
 enum agent_override_flags {
@@ -550,6 +567,8 @@
 	 */
 	unsigned int dead:1;
 
+	/*! Agent control state variable. */
+	enum agent_state state;
 	/*! Custom device state of agent. */
 	enum ast_device_state devstate;
 
@@ -557,12 +576,12 @@
 	time_t login_start;
 	/*! When call started */
 	time_t call_start;
-	/*! When call first appeared */
-	struct timeval call_present;
+	/*! When ack timer started */
+	struct timeval ack_time;
 	/*! When last disconnected */
 	struct timeval last_disconnect;
 
-	/*! Caller is waiting in this bridge for agent to join. */
+	/*! Caller is waiting in this bridge for agent to join. (Holds ref) */
 	struct ast_bridge *caller_bridge;
 	/*! Agent is logged in with this channel. (Holds ref) (NULL if not logged in.) */
 	struct ast_channel *logged;
@@ -884,7 +903,7 @@
 	agents_sweep();
 }
 
-static int agent_logoff(const char *agent_id, int soft)
+static int agent_logoff_request(const char *agent_id, int soft)
 {
 	struct ast_channel *logged;
 	RAII_VAR(struct agent_pvt *, agent, ao2_find(agents, agent_id, OBJ_KEY), ao2_cleanup);
@@ -927,28 +946,32 @@
 	struct agent_pvt *agent = hook_pvt;
 	int ack_timedout = 0;
 	int wrapup_timedout = 0;
+	int deferred_logoff;
 	unsigned int wrapup_time;
 	unsigned int auto_logoff;
 
 	agent_lock(agent);
-	switch (agent->devstate) {
-	case AST_DEVICE_NOT_INUSE:
+	deferred_logoff = agent->deferred_logoff;
+	if (deferred_logoff) {
+		agent->state = AGENT_STATE_LOGGING_OUT;
+	}
+
+	switch (agent->state) {
+	case AGENT_STATE_CALL_WAIT_ACK:
 		/* Check ack call time. */
-		if (agent->caller_bridge
-			&& (ast_test_flag(agent, AGENT_FLAG_ACK_CALL)
-				? agent->override_ack_call : agent->cfg->ack_call)) {
-			auto_logoff = agent->cfg->auto_logoff;
-			if (ast_test_flag(agent, AGENT_FLAG_AUTO_LOGOFF)) {
-				auto_logoff = agent->override_auto_logoff;
+		auto_logoff = agent->cfg->auto_logoff;
+		if (ast_test_flag(agent, AGENT_FLAG_AUTO_LOGOFF)) {
+			auto_logoff = agent->override_auto_logoff;
+		}
+		if (auto_logoff) {
+			auto_logoff *= 1000;
+			ack_timedout = ast_tvdiff_ms(ast_tvnow(), agent->ack_time) > auto_logoff;
+			if (ack_timedout) {
+				agent->state = AGENT_STATE_LOGGING_OUT;
 			}
-			auto_logoff *= 1000;
-			ack_timedout = ast_tvdiff_ms(ast_tvnow(), agent->call_present) > auto_logoff;
-			if (ack_timedout) {
-				agent->devstate = AST_DEVICE_UNAVAILABLE;
-			}
 		}
 		break;
-	case AST_DEVICE_INUSE:
+	case AGENT_STATE_CALL_WRAPUP:
 		/* Check wrapup time. */
 		wrapup_time = agent->cfg->wrapup_time;
 		if (ast_test_flag(agent, AGENT_FLAG_WRAPUP_TIME)) {
@@ -956,6 +979,7 @@
 		}
 		wrapup_timedout = ast_tvdiff_ms(ast_tvnow(), agent->last_disconnect) > wrapup_time;
 		if (wrapup_timedout) {
+			agent->state = AGENT_STATE_READY_FOR_CALL;
 			agent->devstate = AST_DEVICE_NOT_INUSE;
 		}
 		break;
@@ -964,9 +988,11 @@
 	}
 	agent_unlock(agent);
 
-	if (ack_timedout) {
+	if (deferred_logoff) {
+		ast_debug(1, "Agent %s: Deferred logoff.\n", agent->username);
+		ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
+	} else if (ack_timedout) {
 		ast_debug(1, "Agent %s: Ack call timeout.\n", agent->username);
-		ast_softhangup(bridge_channel->chan, AST_SOFTHANGUP_EXPLICIT);
 		ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
 	} else if (wrapup_timedout) {
 		ast_debug(1, "Agent %s: Wrapup timeout.\n", agent->username);
@@ -993,6 +1019,7 @@
 static int bridge_agent_hold_push(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
 {
 	int res = 0;
+	unsigned int wrapup_time;
 	char dtmf[AST_FEATURE_MAX_LEN];
 	struct ast_channel *chan;
 	const char *moh_class;
@@ -1067,14 +1094,32 @@
 	bridge_channel->bridge_pvt = agent;
 
 	agent_lock(agent);
-	if (agent->devstate == AST_DEVICE_UNAVAILABLE) {
+	switch (agent->state) {
+	case AGENT_STATE_LOGGED_OUT:
 		/* Now ready for a caller. */
+		agent->state = AGENT_STATE_READY_FOR_CALL;
 		agent->devstate = AST_DEVICE_NOT_INUSE;
 		agent_unlock(agent);
 		ast_debug(1, "Agent %s: Login complete.\n", agent->username);
 		agent_devstate_changed(agent->username);
-	} else {
+		break;
+	default:
+		wrapup_time = agent->cfg->wrapup_time;
+		if (ast_test_flag(agent, AGENT_FLAG_WRAPUP_TIME)) {
+			wrapup_time = agent->override_wrapup_time;
+		}
+		if (wrapup_time) {
+			agent->state = AGENT_STATE_CALL_WRAPUP;
+		} else {
+			agent->state = AGENT_STATE_READY_FOR_CALL;
+			agent->devstate = AST_DEVICE_NOT_INUSE;
+		}
 		agent_unlock(agent);
+		if (!wrapup_time) {
+			/* No wrapup time. */
+			agent_devstate_changed(agent->username);
+		}
+		break;
 	}
 
 	return 0;
@@ -1267,6 +1312,7 @@
 	agent->logged = NULL;
 	caller_bridge = agent->caller_bridge;
 	caller_bridge = NULL;
+	agent->state = AGENT_STATE_LOGGED_OUT;
 	agent->devstate = AST_DEVICE_UNAVAILABLE;
 	agent_unlock(agent);
 	agent_devstate_changed(agent->username);
@@ -1302,7 +1348,8 @@
 
 		for (;;) {
 			struct agents_cfg *cfgs;
-			struct agent_cfg *cfg;
+			struct agent_cfg *cfg_new;
+			struct agent_cfg *cfg_old;
 			struct ast_bridge *holding;
 
 			holding = ao2_global_obj_ref(agent_holding);
@@ -1330,17 +1377,20 @@
 			if (!cfgs) {
 				break;
 			}
-			cfg = ao2_find(cfgs->agents, agent->username, OBJ_KEY);
+			cfg_new = ao2_find(cfgs->agents, agent->username, OBJ_KEY);
 			ao2_ref(cfgs, -1);
-			if (!cfg) {
+			if (!cfg_new) {
 				break;
 			}
 			agent_lock(agent);
-			ao2_cleanup(agent->cfg);
-			agent->cfg = cfg;
+			cfg_old = agent->cfg;
+			agent->cfg = cfg_new;
 			agent_unlock(agent);
-
-			if (agent->deferred_logoff || ast_check_hangup_locked(logged)) {
+			ao2_cleanup(cfg_old);
+
+			if (agent->state == AGENT_STATE_LOGGING_OUT
+				|| agent->deferred_logoff
+				|| ast_check_hangup_locked(logged)) {
 				break;
 			}
 		}
@@ -1368,12 +1418,16 @@
 		return -1;
 	}
 
+/* BUGBUG need to deal with COLP to agents when a call is pending. */
 /*
- * BUGBUG need to look at the agent->state and call bridge present to determine if can request the agent or not.
+ * Need to look at the agent->state to determine if can request the agent or not.
  *
  * The agent may not have gotten pushed into the holding bridge yet if just look at agent->logged.
  *
- * if agent->devstate == AST_DEVICE_NOT_INUSE && !agent->call_bridge
+ * if agent->state == AGENT_STATE_READY_FOR_CALL
+ * 
+ * After custom_beep plays, the beep callback needs to determine if call must be acked or not.
+ * if (ast_test_flag(agent, AGENT_FLAG_ACK_CALL) ? agent->override_ack_call : agent->cfg->ack_call)
  */
 
 	/*! \todo BUGBUG agent_request_exec() not written */
@@ -1856,7 +1910,7 @@
 		return CLI_SHOWUSAGE;
 	}
 
-	if (!agent_logoff(a->argv[2], a->argc == 4)) {
+	if (!agent_logoff_request(a->argv[2], a->argc == 4)) {
 		ast_cli(a->fd, "Logging out %s\n", a->argv[2]);
 	}
 
@@ -1911,7 +1965,6 @@
 			login_start = agent->login_start;
 			talking_to_chan = pbx_builtin_getvar_helper(logged, "BRIDGEPEER");
 			if (!ast_strlen_zero(talking_to_chan)) {
-/* BUGBUG need to deal with COLP to agents when a call is pending. */
 				party_id = ast_channel_connected_effective_id(logged);
 				talking_to = S_COR(party_id.number.valid, party_id.number.str, "n/a");
 				status = "AGENT_ONCALL";
@@ -1964,7 +2017,7 @@
 		return 0;
 	}
 
-	if (!agent_logoff(agent, ast_true(soft_s))) {
+	if (!agent_logoff_request(agent, ast_true(soft_s))) {
 		astman_send_ack(s, m, "Agent logged out");
 	} else {
 		astman_send_error(s, m, "No such agent");




More information about the svn-commits mailing list