[asterisk-commits] rmudgett: branch rmudgett/bridge_phase r392215 - in /team/rmudgett/bridge_pha...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Jun 18 21:07:00 CDT 2013
Author: rmudgett
Date: Tue Jun 18 21:06:58 2013
New Revision: 392215
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=392215
Log:
* Add initial AgentLogin and AgentRequest code and documentation.
* Removed password and max_login_tries since AgentLogin will no longer
perform any agent authentication. The dialplan must now do this.
* Deferred agent_hold bridge creation till AgentLogin or AgentRequest is
first called. Creating the holding bridge on module load is too early for
the holding bridge technology to be loaded yet.
Modified:
team/rmudgett/bridge_phase/CHANGES
team/rmudgett/bridge_phase/UPGRADE.txt
team/rmudgett/bridge_phase/apps/app_agent_pool.c
team/rmudgett/bridge_phase/configs/agents.conf.sample
Modified: team/rmudgett/bridge_phase/CHANGES
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/CHANGES?view=diff&rev=392215&r1=392214&r2=392215
==============================================================================
--- team/rmudgett/bridge_phase/CHANGES (original)
+++ team/rmudgett/bridge_phase/CHANGES Tue Jun 18 21:06:58 2013
@@ -14,6 +14,13 @@
Applications
------------------
+AgentLogin
+------------------
+ * The application no longer does agent authentication. The dialplan needs to
+ perform this function before running AgentLogin. If the agent is already
+ logged in, dialplan will continue with the AGENT_STATUS channel variable
+ set to ALREADY_LOGGED_IN.
+
AgentMonitorOutgoing
------------------
* The 'c' option has been removed. It is not possible to modify the name of a
@@ -382,6 +389,12 @@
reason as the updatecdr option.
* The driver is no longer a Data retrieval API data provider for the
AMI DataGet action.
+ * The endcall and enddtmf configuration options are removed. Use the
+ dialplan function CHANNEL(dtmf-features) to set DTMF features on the agent
+ channel before calling AgentLogin.
+ * chan_agent is removed and replaced with AgentLogin and AgentRequest dialplan
+ applications. Agents are connected with callers using the new AgentRequest
+ dialplan application. See agents.conf.sample for valid configuration options.
chan_local
------------------
Modified: team/rmudgett/bridge_phase/UPGRADE.txt
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/UPGRADE.txt?view=diff&rev=392215&r1=392214&r2=392215
==============================================================================
--- team/rmudgett/bridge_phase/UPGRADE.txt (original)
+++ team/rmudgett/bridge_phase/UPGRADE.txt Tue Jun 18 21:06:58 2013
@@ -24,6 +24,8 @@
AgentMonitorOutgoing
- The 'c' option has been removed. It is not possible to modify the name of a
channel involved in a CDR.
+ - Application removed. It was a holdover from when AgentCallbackLogin was
+ removed.
NoCDR:
- This application is deprecated. Please use the CDR_PROP function instead.
@@ -124,6 +126,9 @@
and pretending otherwise helps no one.
- The AGENTUPDATECDR channel variable has also been removed, for the same
reason as the updatecdr option.
+ - chan_agent is removed and replaced with AgentLogin and AgentRequest dialplan
+ applications. Agents are connected with callers using the new AgentRequest
+ dialplan application. See agents.conf.sample for valid configuration options.
chan_dahdi:
- Analog port dialing and deferred DTMF dialing for PRI now distinguishes
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=392215&r1=392214&r2=392215
==============================================================================
--- team/rmudgett/bridge_phase/apps/app_agent_pool.c (original)
+++ team/rmudgett/bridge_phase/apps/app_agent_pool.c Tue Jun 18 21:06:58 2013
@@ -51,37 +51,65 @@
/*** DOCUMENTATION
<application name="AgentLogin" language="en_US">
<synopsis>
- Call agent login.
+ Login an agent.
</synopsis>
- <syntax>
- <parameter name="AgentId">
- <para>
- If not present the agent is prompted for an identifier.
- </para>
- </parameter>
+ <syntax argsep=",">
+ <parameter name="AgentId" required="true" />
<parameter name="options">
<optionlist>
<option name="s">
<para>silent login - do not announce the login ok segment after
- agent logged on/off</para>
+ agent logged on.</para>
</option>
</optionlist>
</parameter>
</syntax>
<description>
- <para>Login an agent to the system. Always returns <literal>-1</literal>.
+ <para>Login an agent to the system. Any agent authentication is assumed to
+ already be done by dialplan. If the agent is already logged in, the
+ application will continue in the dialplan with <variable>AGENT_STATUS</variable>
+ set to <literal>ALREADY_LOGGED_IN</literal>.
While logged in, the agent can receive calls and will hear a <literal>beep</literal>
when a new call comes in.</para>
</description>
<see-also>
+ <ref type="application">Authenticate</ref>
<ref type="application">Queue</ref>
<ref type="application">AddQueueMember</ref>
<ref type="application">RemoveQueueMember</ref>
<ref type="application">PauseQueueMember</ref>
<ref type="application">UnpauseQueueMember</ref>
<ref type="function">AGENT</ref>
+ <ref type="function">CHANNEL(dtmf-features)</ref>
<ref type="filename">agents.conf</ref>
<ref type="filename">queues.conf</ref>
+ </see-also>
+ </application>
+ <application name="AgentRequest" language="en_US">
+ <synopsis>
+ Request an agent to connect with the channel.
+ </synopsis>
+ <syntax argsep=",">
+ <parameter name="Locator" required="true">
+ <para>The value can be:</para>
+ <para>1) A specific agent id.</para>
+ <para>2) Use @<replaceable>group-id</replaceable> to locate an available
+ agent in a group.</para>
+ <para>3) Use :<replaceable>group-id</replaceable> to locate an available
+ agent in a group or wait for one to become available.</para>
+ </parameter>
+ <parameter name="timeout">
+ <para>Specifies the number of seconds to wait for an available agent.</para>
+ </parameter>
+ </syntax>
+ <description>
+ <para>
+ Request a specific agent or an agent from a group to connect
+ with the channel.
+ </para>
+ </description>
+ <see-also>
+ <ref type="application">AgentLogin</ref>
</see-also>
</application>
<function name="AGENT" language="en_US">
@@ -89,7 +117,7 @@
Gets information about an Agent
</synopsis>
<syntax argsep=":">
- <parameter name="agentid" required="true" />
+ <parameter name="AgentId" required="true" />
<parameter name="item">
<para>The valid items to retrieve are:</para>
<enumlist>
@@ -97,7 +125,7 @@
<para>(default) The status of the agent (LOGGEDIN | LOGGEDOUT)</para>
</enum>
<enum name="password">
- <para>The password of the agent</para>
+ <para>Deprecated. The dialplan handles any agent authentication.</para>
</enum>
<enum name="name">
<para>The name of the agent</para>
@@ -150,15 +178,14 @@
#define AST_MAX_BUF 256
-/* BUGBUG Document in CHANGES that endcall and enddtmf are going away in favor of the normal bridge disconnect feature. Override using FEATUREMAP. */
+static const char app_agent_login[] = "AgentLogin";
+static const char app_agent_request[] = "AgentRequest";
/*! Agent config parameters. */
struct agent_cfg {
AST_DECLARE_STRING_FIELDS(
/*! Identification of the agent. (agents config container key) */
AST_STRING_FIELD(username);
- /*! Password the agent needs when logging in. */
- AST_STRING_FIELD(password);
/*! Name of agent for logging and querying purposes */
AST_STRING_FIELD(full_name);
@@ -179,13 +206,6 @@
);
/*! Agent groups an agent belongs to. */
ast_group_t group;
- /*!
- * \brief Number of failed login attempts allowed.
- *
- * \note The channel variable AGENTLMAXLOGINTRIES overrides on login.
- * \note If zero then unlimited attempts.
- */
- unsigned int max_login_tries;
/*!
* \brief Number of seconds for agent to ack a call before being logged off.
*
@@ -323,7 +343,6 @@
* [user] <- agent-id/username
* hasagent = yes/no
* fullname=name
- * secret=password
*
*static struct aco_file users_conf = {
* .filename = "users.conf",
@@ -371,6 +390,10 @@
}
cfg->agents = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_NOLOCK,
AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, agent_cfg_sort_cmp, NULL);
+ if (!cfg->agents) {
+ ao2_ref(cfg, -1);
+ cfg = NULL;
+ }
return cfg;
}
@@ -472,7 +495,6 @@
}
/* Agent options */
- aco_option_register(&cfg_info, "maxlogintries", ACO_EXACT, agent_types, "3", OPT_UINT_T, 0, FLDSET(struct agent_cfg, max_login_tries));
aco_option_register(&cfg_info, "autologoff", ACO_EXACT, agent_types, "0", OPT_UINT_T, 0, FLDSET(struct agent_cfg, auto_logoff));
aco_option_register(&cfg_info, "ackcall", ACO_EXACT, agent_types, "no", OPT_BOOL_T, 1, FLDSET(struct agent_cfg, ack_call));
aco_option_register(&cfg_info, "acceptdtmf", ACO_EXACT, agent_types, "#", OPT_STRINGFIELD_T, 0, STRFLDSET(struct agent_cfg, dtmf_accept));
@@ -483,7 +505,6 @@
aco_option_register(&cfg_info, "recordformat", ACO_EXACT, agent_types, "wav", OPT_STRINGFIELD_T, 0, STRFLDSET(struct agent_cfg, record_format));
aco_option_register_custom(&cfg_info, "savecallsin", ACO_EXACT, agent_types, "", agent_savecallsin_handler, 0);
aco_option_register_custom(&cfg_info, "custom_beep", ACO_EXACT, agent_types, "beep", agent_custom_beep_handler, 0);
- aco_option_register(&cfg_info, "password", ACO_EXACT, agent_types, "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct agent_cfg, password));
aco_option_register(&cfg_info, "fullname", ACO_EXACT, agent_types, "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct agent_cfg, full_name));
/*! \todo BUGBUG load_config() needs users.conf handling. */
@@ -803,6 +824,15 @@
if (agent) {
agent_lock(agent);
agent->the_mark = 0;
+ if (!agent->logged) {
+ struct agent_cfg *cfg_old;
+
+ /* Replace the config of agents not logged in. */
+ cfg_old = agent->cfg;
+ ao2_ref(cfg, +1);
+ agent->cfg = cfg;
+ ao2_cleanup(cfg_old);
+ }
agent_unlock(agent);
continue;
}
@@ -843,6 +873,9 @@
/*! Agent holding bridge instance. */
static struct ast_bridge *agent_holding;
+/*! Agent holding bridge deferred creation lock. */
+AST_MUTEX_DEFINE_STATIC(agent_holding_lock);
+
static int bridge_agent_hold_ack(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
{
/*! \todo BUGBUG bridge_agent_hold_ack() not written */
@@ -966,6 +999,110 @@
bridge_agent_hold_v_table.push = bridge_agent_hold_push;
}
+static int bridge_agent_hold_deferred_create(void)
+{
+ if (!agent_holding) {
+ ast_mutex_lock(&agent_holding_lock);
+ if (!agent_holding) {
+ agent_holding = bridge_agent_hold_new();
+ }
+ ast_mutex_unlock(&agent_holding_lock);
+ if (!agent_holding) {
+ ast_log(LOG_ERROR, "Could not create agent holding bridge.\n");
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*!
+ * Called by the AgentRequest application (from the dial plan).
+ *
+ * \brief Application to locate an agent to talk with.
+ *
+ * \param chan Channel wanting to talk with an agent.
+ * \param data Application parameters
+ *
+ * \retval 0 To continue in dialplan.
+ * \retval -1 To hangup.
+ */
+static int agent_request_exec(struct ast_channel *chan, const char *data)
+{
+ if (bridge_agent_hold_deferred_create()) {
+ return -1;
+ }
+
+ /*! \todo BUGBUG agent_request_exec() not written */
+ return -1;
+}
+
+enum AGENT_LOGIN_OPT_FLAGS {
+ OPT_SILENT = (1 << 0),
+};
+AST_APP_OPTIONS(agent_login_opts, BEGIN_OPTIONS
+ AST_APP_OPTION('s', OPT_SILENT),
+END_OPTIONS);
+
+/*!
+ * Called by the AgentLogin application (from the dial plan).
+ *
+ * \brief Application to log in an agent.
+ *
+ * \param chan Channel attempting to login as an agent.
+ * \param data Application parameters
+ *
+ * \retval 0 To continue in dialplan.
+ * \retval -1 To hangup.
+ */
+static int agent_login_exec(struct ast_channel *chan, const char *data)
+{
+ char *parse;
+ struct ast_flags opts;
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(agent_id);
+ AST_APP_ARG(options);
+ AST_APP_ARG(other); /* Any remaining unused arguments */
+ );
+
+ RAII_VAR(struct agent_pvt *, agent, NULL, ao2_cleanup);
+
+ if (bridge_agent_hold_deferred_create()) {
+ return -1;
+ }
+
+ if (ast_channel_state(chan) != AST_STATE_UP && ast_answer(chan)) {
+ return -1;
+ }
+
+ parse = ast_strdupa(data ?: "");
+ AST_STANDARD_APP_ARGS(args, parse);
+
+ if (ast_strlen_zero(args.agent_id)) {
+ ast_log(LOG_WARNING, "AgentLogin requires an AgentId\n");
+ return -1;
+ }
+
+ if (ast_app_parse_options(agent_login_opts, &opts, NULL, args.options)) {
+ /* General invalid option syntax. */
+ return -1;
+ }
+
+ /* Find the agent. */
+ agent = ao2_find(agents, args.agent_id, OBJ_KEY);
+ if (!agent) {
+ ast_verb(3, "Agent '%s' does not exist.\n", args.agent_id);
+ pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "UNKNOWN_AGENT");
+ return 0;
+ }
+
+
+
+
+
+ /*! \todo BUGBUG agent_login_exec() not written */
+ return -1;
+}
+
static int agent_function_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
{
char *parse;
@@ -978,14 +1115,13 @@
buf[0] = '\0';
- if (ast_strlen_zero(data)) {
+ parse = ast_strdupa(data ?: "");
+ AST_NONSTANDARD_APP_ARGS(args, parse, ':');
+
+ if (ast_strlen_zero(args.agentid)) {
ast_log(LOG_WARNING, "The AGENT function requires an argument - agentid!\n");
return -1;
}
-
- parse = ast_strdupa(data);
-
- AST_NONSTANDARD_APP_ARGS(args, parse, ':');
if (!args.item) {
args.item = "status";
}
@@ -1006,8 +1142,6 @@
status = "LOGGEDOUT";
}
ast_copy_string(buf, status, len);
- } else if (!strcasecmp(args.item, "password")) {
- ast_copy_string(buf, agent->cfg->password, len);
} else if (!strcasecmp(args.item, "name")) {
ast_copy_string(buf, agent->cfg->full_name, len);
} else if (!strcasecmp(args.item, "mohclass")) {
@@ -1418,6 +1552,10 @@
static int unload_module(void)
{
+ /* Unregister dialplan applications */
+ ast_unregister_application(app_agent_login);
+ ast_unregister_application(app_agent_request);
+
/* Unregister dialplan functions */
ast_custom_function_unregister(&agent_function);
@@ -1458,13 +1596,8 @@
return AST_MODULE_LOAD_DECLINE;
}
- /* Create agent holding bridge. */
+ /* Init agent holding bridge v_table. */
bridging_init_agent_hold();
- agent_holding = bridge_agent_hold_new();
- if (!agent_holding) {
- unload_module();
- return AST_MODULE_LOAD_FAILURE;
- }
/* BUGBUG Agent:agent-id device state not written. */
/* Setup to provide Agent:agent-id device state. */
@@ -1480,9 +1613,11 @@
/* Dialplan Functions */
res |= ast_custom_function_register(&agent_function);
+ /* Dialplan applications */
+ res |= ast_register_application_xml(app_agent_login, agent_login_exec);
+ res |= ast_register_application_xml(app_agent_request, agent_request_exec);
+
/* BUGBUG bridge channel swap hook not written. */
-/* BUGBUG AgentLogin dialplan application not written. */
-/* BUGBUG AgentRequest dialplan application not written. */
if (res) {
unload_module();
Modified: team/rmudgett/bridge_phase/configs/agents.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/configs/agents.conf.sample?view=diff&rev=392215&r1=392214&r2=392215
==============================================================================
--- team/rmudgett/bridge_phase/configs/agents.conf.sample (original)
+++ team/rmudgett/bridge_phase/configs/agents.conf.sample Tue Jun 18 21:06:58 2013
@@ -7,25 +7,12 @@
; for future use.
;[agent-id]
-;
-; Define maxlogintries to allow the agent to try max logins before failed.
-; The channel variable AGENTLMAXLOGINTRIES overrides on login.
-; Default is 3.
-;maxlogintries=5
-;
; Set how long a call for the agent has to wait for the agent to acknowledge
; the call before the agent is automatically logged off (in seconds).
; If set to zero then the call will wait forever for the agent to acknowledge.
; The channel variable AGENTAUTOLOGOFF overrides on login.
; Default is 0.
;autologoff=15
-;
-;BUGBUG the following is going away: autologoffunavail
-; Define autologoffunavail to have agents automatically logged
-; out when the extension that they are at returns a CHANUNAVAIL
-; status when a call is attempted to be sent there.
-; Default is "no".
-;autologoffunavail=yes
;
; Define ackcall to require the agent to give a DTMF acknowledgement
; when the agent receives a call.
@@ -38,17 +25,6 @@
; Default is "#".
;acceptdtmf=#
;
-;BUGBUG endcall and enddtmf need to go away in favor of the normal bridge disconnect feature.
-; Define endcall to allow the agent to hangup a call with a DTMF key
-; sequence.
-; Default is "yes".
-;endcall=yes
-;
-; Set what DTMF key sequence the agent should use to end a call.
-; The channel variable AGENTENDDTMF overrides on login.
-; Default is "*".
-;enddtmf=*
-;
; Set the minimum amount of time after disconnecting a call before
; the agent can receive a new call in milliseconds.
; The channel variable AGENTWRAPUPTIME overrides on login.
@@ -58,17 +34,6 @@
; Set the musiconhold class for the agent.
; Default is "default".
;musiconhold=default
-;
-;BUGBUG the following is going away: goodbye
-; Define the default good bye sound file for agents
-; default to vm-goodbye
-;goodbye => goodbye_file
-;
-;BUGBUG the following is going away: updatecdr
-; Define updatecdr. This is whether or not to change the source
-; channel in the CDR record for this call to agent/agent_id so
-; that we know which agent generates the call
-;updatecdr=no
;
; Set the agent groups this agent belongs to.
; Default is "".
@@ -84,10 +49,6 @@
; Default is "wav".
;recordformat=gsm
;
-;BUGBUG the following is going away: urlprefix
-; The text to be added to the name of the recording. Allows forming a url link.
-;urlprefix=http://localhost/calls/
-;
; Set the absolute directory to save the agent's conversations in.
; Default is "".
; An empty string becomes asterisk.conf's astspooldir/monitor
@@ -97,10 +58,6 @@
; A custom beep sound file to play to the agent.
; Default is "beep".
;custom_beep=beep
-;
-; Set the password the agent uses to login.
-; Default is "".
-;password=1234
;
; Set the agent name used in logging messages.
; Default is "".
@@ -112,19 +69,14 @@
;
; Define a template called my-agents:
;[my-agents](!)
-;maxlogintries=5
;autologoff=15
;ackcall=yes
;acceptdtmf=##
-;endcall=yes
-;enddtmf=**
;
; Define agent 1001 using the my-agents template:
;[1001](my-agents)
-;password=1234
;fullname=Mark Spencer
;
; Define agent 1002 using the my-agents template:
;[1002](my-agents)
-;password=4321
;fullname=Will Meadows
More information about the asterisk-commits
mailing list