Replace chan_agent with app_agent_pool.
[asterisk/asterisk.git] / apps / app_agent_pool.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2013 Digium, Inc.
5  *
6  * Richard Mudgett <rmudgett@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*!
20  * \file
21  * \brief Call center agent pool.
22  *
23  * \author Richard Mudgett <rmudgett@digium.com>
24  *
25  * See Also:
26  * \arg \ref AstCREDITS
27  * \arg \ref Config_agent
28  */
29 /*** MODULEINFO
30         <support_level>core</support_level>
31  ***/
32
33
34 #include "asterisk.h"
35
36 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
37
38 #include "asterisk/cli.h"
39 #include "asterisk/app.h"
40 #include "asterisk/pbx.h"
41 #include "asterisk/module.h"
42 #include "asterisk/channel.h"
43 #include "asterisk/bridging.h"
44 #include "asterisk/bridging_basic.h"
45 #include "asterisk/config_options.h"
46 #include "asterisk/features_config.h"
47 #include "asterisk/astobj2.h"
48 #include "asterisk/stringfields.h"
49 #include "asterisk/stasis_channels.h"
50
51 /*** DOCUMENTATION
52         <application name="AgentLogin" language="en_US">
53                 <synopsis>
54                         Login an agent.
55                 </synopsis>
56                 <syntax argsep=",">
57                         <parameter name="AgentId" required="true" />
58                         <parameter name="options">
59                                 <optionlist>
60                                         <option name="s">
61                                                 <para>silent login - do not announce the login ok segment after
62                                                 agent logged on.</para>
63                                         </option>
64                                 </optionlist>
65                         </parameter>
66                 </syntax>
67                 <description>
68                         <para>Login an agent to the system.  Any agent authentication is assumed to
69                         already be done by dialplan.  While logged in, the agent can receive calls
70                         and will hear the sound file specified by the config option custom_beep
71                         when a new call comes in for the agent.  Login failures will continue in
72                         the dialplan with <variable>AGENT_STATUS</variable> set.</para>
73                         <para>Before logging in, you can setup on the real agent channel the
74                         CHANNEL(dtmf-features) an agent will have when talking to a caller
75                         and you can setup on the channel running this application the
76                         CONNECTEDLINE() information the agent will see while waiting for a
77                         caller.</para>
78                         <para><variable>AGENT_STATUS</variable> enumeration values:</para>
79                         <enumlist>
80                                 <enum name = "INVALID"><para>The specified agent is invalid.</para></enum>
81                                 <enum name = "ALREADY_LOGGED_IN"><para>The agent is already logged in.</para></enum>
82                         </enumlist>
83                         <note><para>The Agents:<replaceable>AgentId</replaceable> device state is
84                         available to monitor the status of the agent.</para></note>
85                 </description>
86                 <see-also>
87                         <ref type="application">Authenticate</ref>
88                         <ref type="application">Queue</ref>
89                         <ref type="application">AddQueueMember</ref>
90                         <ref type="application">RemoveQueueMember</ref>
91                         <ref type="application">PauseQueueMember</ref>
92                         <ref type="application">UnpauseQueueMember</ref>
93                         <ref type="function">AGENT</ref>
94                         <ref type="function">CHANNEL(dtmf-features)</ref>
95                         <ref type="function">CONNECTEDLINE()</ref>
96                         <ref type="filename">agents.conf</ref>
97                         <ref type="filename">queues.conf</ref>
98                 </see-also>
99         </application>
100         <application name="AgentRequest" language="en_US">
101                 <synopsis>
102                         Request an agent to connect with the channel.
103                 </synopsis>
104                 <syntax argsep=",">
105                         <parameter name="AgentId" required="true" />
106                 </syntax>
107                 <description>
108                         <para>Request an agent to connect with the channel.  Failure to find and
109                         alert an agent will continue in the dialplan with <variable>AGENT_STATUS</variable> set.</para>
110                         <para><variable>AGENT_STATUS</variable> enumeration values:</para>
111                         <enumlist>
112                                 <enum name = "INVALID"><para>The specified agent is invalid.</para></enum>
113                                 <enum name = "NOT_LOGGED_IN"><para>The agent is not available.</para></enum>
114                                 <enum name = "BUSY"><para>The agent is on another call.</para></enum>
115                                 <enum name = "ERROR"><para>Alerting the agent failed.</para></enum>
116                         </enumlist>
117                 </description>
118                 <see-also>
119                         <ref type="application">AgentLogin</ref>
120                 </see-also>
121         </application>
122         <function name="AGENT" language="en_US">
123                 <synopsis>
124                         Gets information about an Agent
125                 </synopsis>
126                 <syntax argsep=":">
127                         <parameter name="AgentId" required="true" />
128                         <parameter name="item">
129                                 <para>The valid items to retrieve are:</para>
130                                 <enumlist>
131                                         <enum name="status">
132                                                 <para>(default) The status of the agent (LOGGEDIN | LOGGEDOUT)</para>
133                                         </enum>
134                                         <enum name="password">
135                                                 <para>Deprecated.  The dialplan handles any agent authentication.</para>
136                                         </enum>
137                                         <enum name="name">
138                                                 <para>The name of the agent</para>
139                                         </enum>
140                                         <enum name="mohclass">
141                                                 <para>MusicOnHold class</para>
142                                         </enum>
143                                         <enum name="channel">
144                                                 <para>The name of the active channel for the Agent (AgentLogin)</para>
145                                         </enum>
146                                         <enum name="fullchannel">
147                                                 <para>The untruncated name of the active channel for the Agent (AgentLogin)</para>
148                                         </enum>
149                                 </enumlist>
150                         </parameter>
151                 </syntax>
152                 <description></description>
153         </function>
154         <manager name="Agents" language="en_US">
155                 <synopsis>
156                         Lists agents and their status.
157                 </synopsis>
158                 <syntax>
159                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
160                 </syntax>
161                 <description>
162                         <para>Will list info about all defined agents.</para>
163                 </description>
164                 <see-also>
165                         <ref type="managerEvent">Agents</ref>
166                         <ref type="managerEvent">AgentsComplete</ref>
167                 </see-also>
168         </manager>
169         <managerEvent language="en_US" name="Agents">
170                 <managerEventInstance class="EVENT_FLAG_AGENT">
171                         <synopsis>
172                                 Response event in a series to the Agents AMI action containing
173                                 information about a defined agent.
174                         </synopsis>
175                         <syntax>
176                                 <parameter name="Agent">
177                                         <para>Agent ID of the agent.</para>
178                                 </parameter>
179                                 <parameter name="Name">
180                                         <para>User friendly name of the agent.</para>
181                                 </parameter>
182                                 <parameter name="Status">
183                                         <para>Current status of the agent.</para>
184                                         <para>The valid values are:</para>
185                                         <enumlist>
186                                                 <enum name="AGENT_LOGGEDOFF" />
187                                                 <enum name="AGENT_IDLE" />
188                                                 <enum name="AGENT_ONCALL" />
189                                         </enumlist>
190                                 </parameter>
191                                 <parameter name="TalkingToChan">
192                                         <para><variable>BRIDGEPEER</variable> value on agent channel.</para>
193                                         <para>Present if Status value is <literal>AGENT_ONCALL</literal>.</para>
194                                 </parameter>
195                                 <parameter name="CallStarted">
196                                         <para>Epoche time when the agent started talking with the caller.</para>
197                                         <para>Present if Status value is <literal>AGENT_ONCALL</literal>.</para>
198                                 </parameter>
199                                 <parameter name="LoggedInTime">
200                                         <para>Epoche time when the agent logged in.</para>
201                                         <para>Present if Status value is <literal>AGENT_IDLE</literal> or <literal>AGENT_ONCALL</literal>.</para>
202                                 </parameter>
203                                 <parameter name="Channel">
204                                         <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter[@name='Channel']/para)" />
205                                         <para>Present if Status value is <literal>AGENT_IDLE</literal> or <literal>AGENT_ONCALL</literal>.</para>
206                                 </parameter>
207                                 <parameter name="ChannelState">
208                                         <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter[@name='ChannelState']/para)" />
209                                         <para>Present if Status value is <literal>AGENT_IDLE</literal> or <literal>AGENT_ONCALL</literal>.</para>
210                                 </parameter>
211                                 <parameter name="ChannelStateDesc">
212                                         <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter[@name='ChannelStateDesc']/para)" />
213                                         <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter[@name='ChannelStateDesc']/enumlist)" />
214                                         <para>Present if Status value is <literal>AGENT_IDLE</literal> or <literal>AGENT_ONCALL</literal>.</para>
215                                 </parameter>
216                                 <parameter name="CallerIDNum">
217                                         <para>Present if Status value is <literal>AGENT_IDLE</literal> or <literal>AGENT_ONCALL</literal>.</para>
218                                 </parameter>
219                                 <parameter name="CallerIDName">
220                                         <para>Present if Status value is <literal>AGENT_IDLE</literal> or <literal>AGENT_ONCALL</literal>.</para>
221                                 </parameter>
222                                 <parameter name="ConnectedLineNum">
223                                         <para>Present if Status value is <literal>AGENT_IDLE</literal> or <literal>AGENT_ONCALL</literal>.</para>
224                                 </parameter>
225                                 <parameter name="ConnectedLineName">
226                                         <para>Present if Status value is <literal>AGENT_IDLE</literal> or <literal>AGENT_ONCALL</literal>.</para>
227                                 </parameter>
228                                 <parameter name="AccountCode">
229                                         <para>Present if Status value is <literal>AGENT_IDLE</literal> or <literal>AGENT_ONCALL</literal>.</para>
230                                 </parameter>
231                                 <parameter name="Context">
232                                         <para>Present if Status value is <literal>AGENT_IDLE</literal> or <literal>AGENT_ONCALL</literal>.</para>
233                                 </parameter>
234                                 <parameter name="Exten">
235                                         <para>Present if Status value is <literal>AGENT_IDLE</literal> or <literal>AGENT_ONCALL</literal>.</para>
236                                 </parameter>
237                                 <parameter name="Priority">
238                                         <para>Present if Status value is <literal>AGENT_IDLE</literal> or <literal>AGENT_ONCALL</literal>.</para>
239                                 </parameter>
240                                 <parameter name="Uniqueid">
241                                         <xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter[@name='Uniqueid']/para)" />
242                                         <para>Present if Status value is <literal>AGENT_IDLE</literal> or <literal>AGENT_ONCALL</literal>.</para>
243                                 </parameter>
244                                 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
245                         </syntax>
246                         <see-also>
247                                 <ref type="manager">Agents</ref>
248                         </see-also>
249                 </managerEventInstance>
250         </managerEvent>
251         <managerEvent language="en_US" name="AgentsComplete">
252                 <managerEventInstance class="EVENT_FLAG_AGENT">
253                         <synopsis>
254                                 Final response event in a series of events to the Agents AMI action.
255                         </synopsis>
256                         <syntax>
257                                 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
258                         </syntax>
259                         <see-also>
260                                 <ref type="manager">Agents</ref>
261                         </see-also>
262                 </managerEventInstance>
263         </managerEvent>
264         <manager name="AgentLogoff" language="en_US">
265                 <synopsis>
266                         Sets an agent as no longer logged in.
267                 </synopsis>
268                 <syntax>
269                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
270                         <parameter name="Agent" required="true">
271                                 <para>Agent ID of the agent to log off.</para>
272                         </parameter>
273                         <parameter name="Soft">
274                                 <para>Set to <literal>true</literal> to not hangup existing calls.</para>
275                         </parameter>
276                 </syntax>
277                 <description>
278                         <para>Sets an agent as no longer logged in.</para>
279                 </description>
280         </manager>
281         <configInfo name="app_agent_pool" language="en_US">
282                 <synopsis>Agent pool applications</synopsis>
283                 <description>
284                         <note><para>Option changes take effect on agent login or after an agent
285                         disconnects from a call.</para></note>
286                 </description>
287                 <configFile name="agents.conf">
288                         <configObject name="global">
289                                 <synopsis>Unused, but reserved.</synopsis>
290                         </configObject>
291                         <configObject name="agent-id">
292                                 <synopsis>Configure an agent for the pool.</synopsis>
293                                 <description>
294                                         <xi:include xpointer="xpointer(/docs/configInfo[@name='app_agent_pool']/description/note)" />
295                                 </description>
296                                 <configOption name="ackcall">
297                                         <synopsis>Enable to require the agent to acknowledge a call.</synopsis>
298                                         <description>
299                                                 <para>Enable to require the agent to give a DTMF acknowledgement
300                                                 when the agent receives a call.</para>
301                                                 <note><para>The option is overridden by <variable>AGENTACKCALL</variable> on agent login.</para></note>
302                                                 <xi:include xpointer="xpointer(/docs/configInfo[@name='app_agent_pool']/description/note)" />
303                                         </description>
304                                 </configOption>
305                                 <configOption name="acceptdtmf">
306                                         <synopsis>DTMF key sequence the agent uses to acknowledge a call.</synopsis>
307                                         <description>
308                                                 <note><para>The option is overridden by <variable>AGENTACCEPTDTMF</variable> on agent login.</para></note>
309                                                 <note><para>The option is ignored unless the ackcall option is enabled.</para></note>
310                                                 <xi:include xpointer="xpointer(/docs/configInfo[@name='app_agent_pool']/description/note)" />
311                                         </description>
312                                 </configOption>
313                                 <configOption name="autologoff">
314                                         <synopsis>Time the agent has to acknowledge a call before being logged off.</synopsis>
315                                         <description>
316                                                 <para>Set how many seconds a call for the agent has to wait for the
317                                                 agent to acknowledge the call before the agent is automatically
318                                                 logged off.  If set to zero then the call will wait forever for
319                                                 the agent to acknowledge.</para>
320                                                 <note><para>The option is overridden by <variable>AGENTAUTOLOGOFF</variable> on agent login.</para></note>
321                                                 <note><para>The option is ignored unless the ackcall option is enabled.</para></note>
322                                                 <xi:include xpointer="xpointer(/docs/configInfo[@name='app_agent_pool']/description/note)" />
323                                         </description>
324                                 </configOption>
325                                 <configOption name="wrapuptime">
326                                         <synopsis>Minimum time the agent has between calls.</synopsis>
327                                         <description>
328                                                 <para>Set the minimum amount of time in milliseconds after
329                                                 disconnecting a call before the agent can receive a new call.</para>
330                                                 <note><para>The option is overridden by <variable>AGENTWRAPUPTIME</variable> on agent login.</para></note>
331                                                 <xi:include xpointer="xpointer(/docs/configInfo[@name='app_agent_pool']/description/note)" />
332                                         </description>
333                                 </configOption>
334                                 <configOption name="musiconhold">
335                                         <synopsis>Music on hold class the agent listens to between calls.</synopsis>
336                                         <description>
337                                                 <xi:include xpointer="xpointer(/docs/configInfo[@name='app_agent_pool']/description/note)" />
338                                         </description>
339                                 </configOption>
340                                 <configOption name="recordagentcalls">
341                                         <synopsis>Enable to automatically record calls the agent takes.</synopsis>
342                                         <description>
343                                                 <para>Enable recording calls the agent takes automatically by
344                                                 invoking the automixmon DTMF feature when the agent connects
345                                                 to a caller.  See <filename>features.conf.sample</filename> for information about
346                                                 the automixmon feature.</para>
347                                                 <xi:include xpointer="xpointer(/docs/configInfo[@name='app_agent_pool']/description/note)" />
348                                         </description>
349                                 </configOption>
350                                 <configOption name="custom_beep">
351                                         <synopsis>Sound file played to alert the agent when a call is present.</synopsis>
352                                         <description>
353                                                 <xi:include xpointer="xpointer(/docs/configInfo[@name='app_agent_pool']/description/note)" />
354                                         </description>
355                                 </configOption>
356                                 <configOption name="fullname">
357                                         <synopsis>A friendly name for the agent used in log messages.</synopsis>
358                                         <description>
359                                                 <xi:include xpointer="xpointer(/docs/configInfo[@name='app_agent_pool']/description/note)" />
360                                         </description>
361                                 </configOption>
362                         </configObject>
363                 </configFile>
364         </configInfo>
365  ***/
366
367 /* ------------------------------------------------------------------- */
368
369 #define AST_MAX_BUF     256
370
371 /*! Maximum wait time (in ms) for the custom_beep file to play announcing the caller. */
372 #define CALLER_SAFETY_TIMEOUT_TIME      (2 * 60 * 1000)
373
374 /*! Number of seconds to wait for local channel optimizations to complete. */
375 #define LOGIN_WAIT_TIMEOUT_TIME         5
376
377 static const char app_agent_login[] = "AgentLogin";
378 static const char app_agent_request[] = "AgentRequest";
379
380 /*! Agent config parameters. */
381 struct agent_cfg {
382         AST_DECLARE_STRING_FIELDS(
383                 /*! Identification of the agent.  (agents config container key) */
384                 AST_STRING_FIELD(username);
385                 /*! Name of agent for logging and querying purposes */
386                 AST_STRING_FIELD(full_name);
387
388                 /*!
389                  * \brief DTMF string for an agent to accept a call.
390                  *
391                  * \note The channel variable AGENTACCEPTDTMF overrides on login.
392                  */
393                 AST_STRING_FIELD(dtmf_accept);
394                 /*! Beep sound file to use.  Alert the agent a call is waiting. */
395                 AST_STRING_FIELD(beep_sound);
396                 /*! MOH class to use while agent waiting for call. */
397                 AST_STRING_FIELD(moh);
398         );
399         /*!
400          * \brief Number of seconds for agent to ack a call before being logged off.
401          *
402          * \note The channel variable AGENTAUTOLOGOFF overrides on login.
403          * \note If zero then timer is disabled.
404          */
405         unsigned int auto_logoff;
406         /*!
407          * \brief Time after a call in ms before the agent can get a new call.
408          *
409          * \note The channel variable AGENTWRAPUPTIME overrides on login.
410          */
411         unsigned int wrapup_time;
412         /*!
413          * \brief TRUE if agent needs to ack a call to accept it.
414          *
415          * \note The channel variable AGENTACKCALL overrides on login.
416          */
417         int ack_call;
418         /*! TRUE if agent calls are automatically recorded. */
419         int record_agent_calls;
420 };
421
422 /*!
423  * \internal
424  * \brief Agent config ao2 container sort function.
425  * \since 12.0.0
426  *
427  * \param obj_left pointer to the (user-defined part) of an object.
428  * \param obj_right pointer to the (user-defined part) of an object.
429  * \param flags flags from ao2_callback()
430  *   OBJ_POINTER - if set, 'obj_right', is an object.
431  *   OBJ_KEY - if set, 'obj_right', is a search key item that is not an object.
432  *   OBJ_PARTIAL_KEY - if set, 'obj_right', is a partial search key item that is not an object.
433  *
434  * \retval <0 if obj_left < obj_right
435  * \retval =0 if obj_left == obj_right
436  * \retval >0 if obj_left > obj_right
437  */
438 static int agent_cfg_sort_cmp(const void *obj_left, const void *obj_right, int flags)
439 {
440         const struct agent_cfg *cfg_left = obj_left;
441         const struct agent_cfg *cfg_right = obj_right;
442         const char *right_key = obj_right;
443         int cmp;
444
445         switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
446         default:
447         case OBJ_POINTER:
448                 right_key = cfg_right->username;
449                 /* Fall through */
450         case OBJ_KEY:
451                 cmp = strcmp(cfg_left->username, right_key);
452                 break;
453         case OBJ_PARTIAL_KEY:
454                 cmp = strncmp(cfg_left->username, right_key, strlen(right_key));
455                 break;
456         }
457         return cmp;
458 }
459
460 static void agent_cfg_destructor(void *vdoomed)
461 {
462         struct agent_cfg *doomed = vdoomed;
463
464         ast_string_field_free_memory(doomed);
465 }
466
467 static void *agent_cfg_alloc(const char *name)
468 {
469         struct agent_cfg *cfg;
470
471         cfg = ao2_alloc_options(sizeof(*cfg), agent_cfg_destructor,
472                 AO2_ALLOC_OPT_LOCK_NOLOCK);
473         if (!cfg || ast_string_field_init(cfg, 64)) {
474                 return NULL;
475         }
476         ast_string_field_set(cfg, username, name);
477         return cfg;
478 }
479
480 static void *agent_cfg_find(struct ao2_container *agents, const char *username)
481 {
482         return ao2_find(agents, username, OBJ_KEY);
483 }
484
485 /*! Agents configuration */
486 struct agents_cfg {
487         /*! Master configured agents container. */
488         struct ao2_container *agents;
489 };
490
491 static struct aco_type agent_type = {
492         .type = ACO_ITEM,
493         .name = "agent-id",
494         .category_match = ACO_BLACKLIST,
495         .category = "^(general|agents)$",
496         .item_alloc = agent_cfg_alloc,
497         .item_find = agent_cfg_find,
498         .item_offset = offsetof(struct agents_cfg, agents),
499 };
500
501 static struct aco_type *agent_types[] = ACO_TYPES(&agent_type);
502
503 /* The general category is reserved, but unused */
504 static struct aco_type general_type = {
505         .type = ACO_GLOBAL,
506         .name = "global",
507         .category_match = ACO_WHITELIST,
508         .category = "^general$",
509 };
510
511 static struct aco_file agents_conf = {
512         .filename = "agents.conf",
513         .types = ACO_TYPES(&general_type, &agent_type),
514 };
515
516 static AO2_GLOBAL_OBJ_STATIC(cfg_handle);
517
518 static void agents_cfg_destructor(void *vdoomed)
519 {
520         struct agents_cfg *doomed = vdoomed;
521
522         ao2_cleanup(doomed->agents);
523         doomed->agents = NULL;
524 }
525
526 /*!
527  * \internal
528  * \brief Create struct agents_cfg object.
529  * \since 12.0.0
530  *
531  * \note A lock is not needed for the object or any secondary
532  * created cfg objects.  These objects are immutable after the
533  * config is loaded and applied.
534  *
535  * \retval New struct agents_cfg object.
536  * \retval NULL on error.
537  */
538 static void *agents_cfg_alloc(void)
539 {
540         struct agents_cfg *cfg;
541
542         cfg = ao2_alloc_options(sizeof(*cfg), agents_cfg_destructor,
543                 AO2_ALLOC_OPT_LOCK_NOLOCK);
544         if (!cfg) {
545                 return NULL;
546         }
547         cfg->agents = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_NOLOCK,
548                 AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, agent_cfg_sort_cmp, NULL);
549         if (!cfg->agents) {
550                 ao2_ref(cfg, -1);
551                 cfg = NULL;
552         }
553         return cfg;
554 }
555
556 static void agents_post_apply_config(void);
557
558 CONFIG_INFO_STANDARD(cfg_info, cfg_handle, agents_cfg_alloc,
559         .files = ACO_FILES(&agents_conf),
560         .post_apply_config = agents_post_apply_config,
561 );
562
563 static void destroy_config(void)
564 {
565         ao2_global_obj_release(cfg_handle);
566         aco_info_destroy(&cfg_info);
567 }
568
569 static int load_config(void)
570 {
571         if (aco_info_init(&cfg_info)) {
572                 return -1;
573         }
574
575         /* Agent options */
576         aco_option_register(&cfg_info, "ackcall", ACO_EXACT, agent_types, "no", OPT_BOOL_T, 1, FLDSET(struct agent_cfg, ack_call));
577         aco_option_register(&cfg_info, "acceptdtmf", ACO_EXACT, agent_types, "#", OPT_STRINGFIELD_T, 1, STRFLDSET(struct agent_cfg, dtmf_accept));
578         aco_option_register(&cfg_info, "autologoff", ACO_EXACT, agent_types, "0", OPT_UINT_T, 0, FLDSET(struct agent_cfg, auto_logoff));
579         aco_option_register(&cfg_info, "wrapuptime", ACO_EXACT, agent_types, "0", OPT_UINT_T, 0, FLDSET(struct agent_cfg, wrapup_time));
580         aco_option_register(&cfg_info, "musiconhold", ACO_EXACT, agent_types, "default", OPT_STRINGFIELD_T, 0, STRFLDSET(struct agent_cfg, moh));
581         aco_option_register(&cfg_info, "recordagentcalls", ACO_EXACT, agent_types, "no", OPT_BOOL_T, 1, FLDSET(struct agent_cfg, record_agent_calls));
582         aco_option_register(&cfg_info, "custom_beep", ACO_EXACT, agent_types, "beep", OPT_STRINGFIELD_T, 1, STRFLDSET(struct agent_cfg, beep_sound));
583         aco_option_register(&cfg_info, "fullname", ACO_EXACT, agent_types, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct agent_cfg, full_name));
584
585         if (aco_process_config(&cfg_info, 0) == ACO_PROCESS_ERROR) {
586                 goto error;
587         }
588
589         return 0;
590
591 error:
592         destroy_config();
593         return -1;
594 }
595
596 enum agent_state {
597         /*! The agent is defined but an agent is not present. */
598         AGENT_STATE_LOGGED_OUT,
599         /*! Forced initial login wait to allow any local channel optimizations to happen. */
600         AGENT_STATE_PROBATION_WAIT,
601         /*! The agent is ready for a call. */
602         AGENT_STATE_READY_FOR_CALL,
603         /*! The agent has a call waiting to connect. */
604         AGENT_STATE_CALL_PRESENT,
605         /*! The agent needs to ack the call. */
606         AGENT_STATE_CALL_WAIT_ACK,
607         /*! The agent is connected with a call. */
608         AGENT_STATE_ON_CALL,
609         /*! The agent is resting between calls. */
610         AGENT_STATE_CALL_WRAPUP,
611         /*! The agent is being kicked out. */
612         AGENT_STATE_LOGGING_OUT,
613 };
614
615 /*! Agent config option override flags. */
616 enum agent_override_flags {
617         AGENT_FLAG_ACK_CALL = (1 << 0),
618         AGENT_FLAG_DTMF_ACCEPT = (1 << 1),
619         AGENT_FLAG_AUTO_LOGOFF = (1 << 2),
620         AGENT_FLAG_WRAPUP_TIME = (1 << 3),
621 };
622
623 /*! \brief Structure representing an agent. */
624 struct agent_pvt {
625         AST_DECLARE_STRING_FIELDS(
626                 /*! Identification of the agent.  (agents container key) */
627                 AST_STRING_FIELD(username);
628                 /*! Login override DTMF string for an agent to accept a call. */
629                 AST_STRING_FIELD(override_dtmf_accept);
630         );
631         /*! Connected line information to send when reentering the holding bridge. */
632         struct ast_party_connected_line waiting_colp;
633         /*! Flags show if settings were overridden by channel vars. */
634         unsigned int flags;
635         /*! Login override number of seconds for agent to ack a call before being logged off. */
636         unsigned int override_auto_logoff;
637         /*! Login override time after a call in ms before the agent can get a new call. */
638         unsigned int override_wrapup_time;
639         /*! Login override if agent needs to ack a call to accept it. */
640         unsigned int override_ack_call:1;
641
642         /*! TRUE if the agent is requested to logoff when the current call ends. */
643         unsigned int deferred_logoff:1;
644
645         /*! Mark and sweep config update to determine if an agent is dead. */
646         unsigned int the_mark:1;
647         /*!
648          * \brief TRUE if the agent is no longer configured and is being destroyed.
649          *
650          * \note Agents cannot log in if they are dead.
651          */
652         unsigned int dead:1;
653
654         /*! Agent control state variable. */
655         enum agent_state state;
656         /*! Custom device state of agent. */
657         enum ast_device_state devstate;
658
659         /*! When agent first logged in */
660         time_t login_start;
661         /*! When agent login probation started. */
662         time_t probation_start;
663         /*! When call started */
664         time_t call_start;
665         /*! When ack timer started */
666         struct timeval ack_time;
667         /*! When last disconnected */
668         struct timeval last_disconnect;
669
670         /*! Caller is waiting in this bridge for agent to join. (Holds ref) */
671         struct ast_bridge *caller_bridge;
672         /*! Agent is logged in with this channel. (Holds ref) (NULL if not logged in.) */
673         struct ast_channel *logged;
674         /*! Active config values from config file. (Holds ref) */
675         struct agent_cfg *cfg;
676 };
677
678 /*! Container of defined agents. */
679 static struct ao2_container *agents;
680
681 /*!
682  * \brief Lock the agent.
683  *
684  * \param agent Agent to lock
685  *
686  * \return Nothing
687  */
688 #define agent_lock(agent)       _agent_lock(agent, __FILE__, __PRETTY_FUNCTION__, __LINE__, #agent)
689 static inline void _agent_lock(struct agent_pvt *agent, const char *file, const char *function, int line, const char *var)
690 {
691         __ao2_lock(agent, AO2_LOCK_REQ_MUTEX, file, function, line, var);
692 }
693
694 /*!
695  * \brief Unlock the agent.
696  *
697  * \param agent Agent to unlock
698  *
699  * \return Nothing
700  */
701 #define agent_unlock(agent)     _agent_unlock(agent, __FILE__, __PRETTY_FUNCTION__, __LINE__, #agent)
702 static inline void _agent_unlock(struct agent_pvt *agent, const char *file, const char *function, int line, const char *var)
703 {
704         __ao2_unlock(agent, file, function, line, var);
705 }
706
707 /*!
708  * \internal
709  * \brief Obtain the agent logged in channel lock if it exists.
710  * \since 12.0.0
711  *
712  * \param agent Pointer to the LOCKED agent_pvt.
713  *
714  * \note Assumes the agent lock is already obtained.
715  *
716  * \note Defined locking order is channel lock then agent lock.
717  *
718  * \return Nothing
719  */
720 static struct ast_channel *agent_lock_logged(struct agent_pvt *agent)
721 {
722         struct ast_channel *logged;
723
724         for (;;) {
725                 if (!agent->logged) { /* No owner. Nothing to do. */
726                         return NULL;
727                 }
728
729                 /* If we don't ref the logged, it could be killed when we unlock the agent. */
730                 logged = ast_channel_ref(agent->logged);
731
732                 /* Locking logged requires us to lock channel, then agent. */
733                 agent_unlock(agent);
734                 ast_channel_lock(logged);
735                 agent_lock(agent);
736
737                 /* Check if logged changed during agent unlock period */
738                 if (logged != agent->logged) {
739                         /* Channel changed. Unref and do another pass. */
740                         ast_channel_unlock(logged);
741                         ast_channel_unref(logged);
742                 } else {
743                         /* Channel stayed the same. Return it. */
744                         return logged;
745                 }
746         }
747 }
748
749 /*!
750  * \internal
751  * \brief Get the Agent:agent_id device state.
752  * \since 12.0.0
753  *
754  * \param agent_id Username of the agent.
755  *
756  * \details
757  * Search the agents container for the agent and return the
758  * current state.
759  *
760  * \return Device state of the agent.
761  */
762 static enum ast_device_state agent_pvt_devstate_get(const char *agent_id)
763 {
764         RAII_VAR(struct agent_pvt *, agent, ao2_find(agents, agent_id, OBJ_KEY), ao2_cleanup);
765
766         if (agent) {
767                 return agent->devstate;
768         }
769         return AST_DEVICE_INVALID;
770 }
771
772 /*!
773  * \internal
774  * \brief Request an agent device state be updated.
775  * \since 12.0.0
776  *
777  * \param agent_id Which agent needs the device state updated.
778  *
779  * \return Nothing
780  */
781 static void agent_devstate_changed(const char *agent_id)
782 {
783         ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, "Agent:%s", agent_id);
784 }
785
786 static void agent_pvt_destructor(void *vdoomed)
787 {
788         struct agent_pvt *doomed = vdoomed;
789
790         /* Make sure device state reflects agent destruction. */
791         if (!ast_strlen_zero(doomed->username)) {
792                 ast_debug(1, "Agent %s: Destroyed.\n", doomed->username);
793                 agent_devstate_changed(doomed->username);
794         }
795
796         ast_party_connected_line_free(&doomed->waiting_colp);
797         if (doomed->caller_bridge) {
798                 ast_bridge_destroy(doomed->caller_bridge);
799                 doomed->caller_bridge = NULL;
800         }
801         if (doomed->logged) {
802                 doomed->logged = ast_channel_unref(doomed->logged);
803         }
804         ao2_cleanup(doomed->cfg);
805         doomed->cfg = NULL;
806         ast_string_field_free_memory(doomed);
807 }
808
809 static struct agent_pvt *agent_pvt_new(struct agent_cfg *cfg)
810 {
811         struct agent_pvt *agent;
812
813         agent = ao2_alloc(sizeof(*agent), agent_pvt_destructor);
814         if (!agent) {
815                 return NULL;
816         }
817         if (ast_string_field_init(agent, 32)) {
818                 ao2_ref(agent, -1);
819                 return NULL;
820         }
821         ast_string_field_set(agent, username, cfg->username);
822         ast_party_connected_line_init(&agent->waiting_colp);
823         ao2_ref(cfg, +1);
824         agent->cfg = cfg;
825         agent->devstate = AST_DEVICE_UNAVAILABLE;
826         return agent;
827 }
828
829 /*!
830  * \internal
831  * \brief Agents ao2 container sort function.
832  * \since 12.0.0
833  *
834  * \param obj_left pointer to the (user-defined part) of an object.
835  * \param obj_right pointer to the (user-defined part) of an object.
836  * \param flags flags from ao2_callback()
837  *   OBJ_POINTER - if set, 'obj_right', is an object.
838  *   OBJ_KEY - if set, 'obj_right', is a search key item that is not an object.
839  *   OBJ_PARTIAL_KEY - if set, 'obj_right', is a partial search key item that is not an object.
840  *
841  * \retval <0 if obj_left < obj_right
842  * \retval =0 if obj_left == obj_right
843  * \retval >0 if obj_left > obj_right
844  */
845 static int agent_pvt_sort_cmp(const void *obj_left, const void *obj_right, int flags)
846 {
847         const struct agent_pvt *agent_left = obj_left;
848         const struct agent_pvt *agent_right = obj_right;
849         const char *right_key = obj_right;
850         int cmp;
851
852         switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
853         default:
854         case OBJ_POINTER:
855                 right_key = agent_right->username;
856                 /* Fall through */
857         case OBJ_KEY:
858                 cmp = strcmp(agent_left->username, right_key);
859                 break;
860         case OBJ_PARTIAL_KEY:
861                 cmp = strncmp(agent_left->username, right_key, strlen(right_key));
862                 break;
863         }
864         return cmp;
865 }
866
867 /*!
868  * \internal
869  * \brief ao2_find() callback function.
870  * \since 12.0.0
871  *
872  * Usage:
873  * found = ao2_find(agents, agent, OBJ_POINTER);
874  * found = ao2_find(agents, "agent-id", OBJ_KEY);
875  * found = ao2_find(agents, agent->logged, 0);
876  */
877 static int agent_pvt_cmp(void *obj, void *arg, int flags)
878 {
879         const struct agent_pvt *agent = obj;
880         int cmp;
881
882         switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
883         case OBJ_POINTER:
884         case OBJ_KEY:
885         case OBJ_PARTIAL_KEY:
886                 cmp = CMP_MATCH;
887                 break;
888         default:
889                 if (agent->logged == arg) {
890                         cmp = CMP_MATCH;
891                 } else {
892                         cmp = 0;
893                 }
894                 break;
895         }
896         return cmp;
897 }
898
899 static int agent_mark(void *obj, void *arg, int flags)
900 {
901         struct agent_pvt *agent = obj;
902
903         agent_lock(agent);
904         agent->the_mark = 1;
905         agent_unlock(agent);
906         return 0;
907 }
908
909 static void agents_mark(void)
910 {
911         ao2_callback(agents, 0, agent_mark, NULL);
912 }
913
914 static int agent_sweep(void *obj, void *arg, int flags)
915 {
916         struct agent_pvt *agent = obj;
917         int cmp = 0;
918
919         agent_lock(agent);
920         if (agent->the_mark) {
921                 agent->the_mark = 0;
922                 agent->dead = 1;
923                 /* Unlink dead agents immediately. */
924                 cmp = CMP_MATCH;
925         }
926         agent_unlock(agent);
927         return cmp;
928 }
929
930 static void agents_sweep(void)
931 {
932         struct ao2_iterator *iter;
933         struct agent_pvt *agent;
934         struct ast_channel *logged;
935
936         iter = ao2_callback(agents, OBJ_MULTIPLE | OBJ_UNLINK, agent_sweep, NULL);
937         if (!iter) {
938                 return;
939         }
940         for (; (agent = ao2_iterator_next(iter)); ao2_ref(agent, -1)) {
941                 agent_lock(agent);
942                 if (agent->logged) {
943                         logged = ast_channel_ref(agent->logged);
944                 } else {
945                         logged = NULL;
946                 }
947                 agent_unlock(agent);
948                 if (!logged) {
949                         continue;
950                 }
951                 ast_log(LOG_NOTICE,
952                         "Forced logoff of agent %s(%s).  Agent no longer configured.\n",
953                         agent->username, ast_channel_name(logged));
954                 ast_softhangup(logged, AST_SOFTHANGUP_EXPLICIT);
955                 ast_channel_unref(logged);
956         }
957         ao2_iterator_destroy(iter);
958 }
959
960 static void agents_post_apply_config(void)
961 {
962         struct ao2_iterator iter;
963         struct agent_cfg *cfg;
964         RAII_VAR(struct agents_cfg *, cfgs, ao2_global_obj_ref(cfg_handle), ao2_cleanup);
965
966         ast_assert(cfgs != NULL);
967
968         agents_mark();
969         iter = ao2_iterator_init(cfgs->agents, 0);
970         for (; (cfg = ao2_iterator_next(&iter)); ao2_ref(cfg, -1)) {
971                 RAII_VAR(struct agent_pvt *, agent, ao2_find(agents, cfg->username, OBJ_KEY), ao2_cleanup);
972
973                 if (agent) {
974                         agent_lock(agent);
975                         agent->the_mark = 0;
976                         if (!agent->logged) {
977                                 struct agent_cfg *cfg_old;
978
979                                 /* Replace the config of agents not logged in. */
980                                 cfg_old = agent->cfg;
981                                 ao2_ref(cfg, +1);
982                                 agent->cfg = cfg;
983                                 ao2_cleanup(cfg_old);
984                         }
985                         agent_unlock(agent);
986                         continue;
987                 }
988                 agent = agent_pvt_new(cfg);
989                 if (!agent) {
990                         continue;
991                 }
992                 ao2_link(agents, agent);
993                 ast_debug(1, "Agent %s: Created.\n", agent->username);
994                 agent_devstate_changed(agent->username);
995         }
996         ao2_iterator_destroy(&iter);
997         agents_sweep();
998 }
999
1000 static int agent_logoff_request(const char *agent_id, int soft)
1001 {
1002         struct ast_channel *logged;
1003         RAII_VAR(struct agent_pvt *, agent, ao2_find(agents, agent_id, OBJ_KEY), ao2_cleanup);
1004
1005         if (!agent) {
1006                 return -1;
1007         }
1008
1009         agent_lock(agent);
1010         logged = agent_lock_logged(agent);
1011         if (logged) {
1012                 if (soft) {
1013                         agent->deferred_logoff = 1;
1014                 } else {
1015                         ast_softhangup(logged, AST_SOFTHANGUP_EXPLICIT);
1016                 }
1017                 ast_channel_unlock(logged);
1018                 ast_channel_unref(logged);
1019         }
1020         agent_unlock(agent);
1021         return 0;
1022 }
1023
1024 /*! Agent holding bridge instance holder. */
1025 static AO2_GLOBAL_OBJ_STATIC(agent_holding);
1026
1027 /*! Agent holding bridge deferred creation lock. */
1028 AST_MUTEX_DEFINE_STATIC(agent_holding_lock);
1029
1030 /*!
1031  * \internal
1032  * \brief Connect the agent with the waiting caller.
1033  * \since 12.0.0
1034  *
1035  * \param bridge_channel Agent channel connecting to the caller.
1036  * \param agent Which agent is connecting to the caller.
1037  *
1038  * \note The agent is locked on entry and not locked on exit.
1039  *
1040  * \return Nothing
1041  */
1042 static void agent_connect_caller(struct ast_bridge_channel *bridge_channel, struct agent_pvt *agent)
1043 {
1044         struct ast_bridge *caller_bridge;
1045         int record_agent_calls;
1046         int res;
1047
1048         record_agent_calls = agent->cfg->record_agent_calls;
1049         caller_bridge = agent->caller_bridge;
1050         agent->caller_bridge = NULL;
1051         agent->state = AGENT_STATE_ON_CALL;
1052         time(&agent->call_start);
1053         agent_unlock(agent);
1054
1055         if (!caller_bridge) {
1056                 /* Reset agent. */
1057                 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
1058                 return;
1059         }
1060         res = ast_bridge_move(caller_bridge, bridge_channel->bridge, bridge_channel->chan,
1061                 NULL, 0);
1062         if (res) {
1063                 /* Reset agent. */
1064                 ast_bridge_destroy(caller_bridge);
1065                 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
1066                 return;
1067         }
1068         ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_ANSWER, NULL, 0);
1069
1070         if (record_agent_calls) {
1071                 struct ast_bridge_features_automixmonitor options = {
1072                         .start_stop = AUTO_MONITOR_START,
1073                         };
1074
1075                 /*
1076                  * The agent is in the new bridge so we can invoke the
1077                  * mixmonitor hook to only start recording.
1078                  */
1079                 ast_bridge_features_do(AST_BRIDGE_BUILTIN_AUTOMIXMON, caller_bridge,
1080                         bridge_channel, &options);
1081         }
1082 }
1083
1084 static int bridge_agent_hold_ack(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
1085 {
1086         struct agent_pvt *agent = hook_pvt;
1087
1088         agent_lock(agent);
1089         switch (agent->state) {
1090         case AGENT_STATE_CALL_WAIT_ACK:
1091                 /* Connect to caller now. */
1092                 ast_debug(1, "Agent %s: Acked call.\n", agent->username);
1093                 agent_connect_caller(bridge_channel, agent);/* Will unlock agent. */
1094                 return 0;
1095         default:
1096                 break;
1097         }
1098         agent_unlock(agent);
1099         return 0;
1100 }
1101
1102 static int bridge_agent_hold_heartbeat(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
1103 {
1104         struct agent_pvt *agent = hook_pvt;
1105         int probation_timedout = 0;
1106         int ack_timedout = 0;
1107         int wrapup_timedout = 0;
1108         int deferred_logoff;
1109         unsigned int wrapup_time;
1110         unsigned int auto_logoff;
1111
1112         agent_lock(agent);
1113         deferred_logoff = agent->deferred_logoff;
1114         if (deferred_logoff) {
1115                 agent->state = AGENT_STATE_LOGGING_OUT;
1116         }
1117
1118         switch (agent->state) {
1119         case AGENT_STATE_PROBATION_WAIT:
1120                 probation_timedout =
1121                         LOGIN_WAIT_TIMEOUT_TIME <= (time(NULL) - agent->probation_start);
1122                 if (probation_timedout) {
1123                         /* Now ready for a caller. */
1124                         agent->state = AGENT_STATE_READY_FOR_CALL;
1125                         agent->devstate = AST_DEVICE_NOT_INUSE;
1126                 }
1127                 break;
1128         case AGENT_STATE_CALL_WAIT_ACK:
1129                 /* Check ack call time. */
1130                 auto_logoff = agent->cfg->auto_logoff;
1131                 if (ast_test_flag(agent, AGENT_FLAG_AUTO_LOGOFF)) {
1132                         auto_logoff = agent->override_auto_logoff;
1133                 }
1134                 if (auto_logoff) {
1135                         auto_logoff *= 1000;
1136                         ack_timedout = ast_tvdiff_ms(ast_tvnow(), agent->ack_time) > auto_logoff;
1137                         if (ack_timedout) {
1138                                 agent->state = AGENT_STATE_LOGGING_OUT;
1139                         }
1140                 }
1141                 break;
1142         case AGENT_STATE_CALL_WRAPUP:
1143                 /* Check wrapup time. */
1144                 wrapup_time = agent->cfg->wrapup_time;
1145                 if (ast_test_flag(agent, AGENT_FLAG_WRAPUP_TIME)) {
1146                         wrapup_time = agent->override_wrapup_time;
1147                 }
1148                 wrapup_timedout = ast_tvdiff_ms(ast_tvnow(), agent->last_disconnect) > wrapup_time;
1149                 if (wrapup_timedout) {
1150                         agent->state = AGENT_STATE_READY_FOR_CALL;
1151                         agent->devstate = AST_DEVICE_NOT_INUSE;
1152                 }
1153                 break;
1154         default:
1155                 break;
1156         }
1157         agent_unlock(agent);
1158
1159         if (deferred_logoff) {
1160                 ast_debug(1, "Agent %s: Deferred logoff.\n", agent->username);
1161                 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
1162         } else if (probation_timedout) {
1163                 ast_debug(1, "Agent %s: Login complete.\n", agent->username);
1164                 agent_devstate_changed(agent->username);
1165         } else if (ack_timedout) {
1166                 ast_debug(1, "Agent %s: Ack call timeout.\n", agent->username);
1167                 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
1168         } else if (wrapup_timedout) {
1169                 ast_debug(1, "Agent %s: Wrapup timeout. Ready for new call.\n", agent->username);
1170                 agent_devstate_changed(agent->username);
1171         }
1172
1173         return 0;
1174 }
1175
1176 static void agent_after_bridge_cb(struct ast_channel *chan, void *data);
1177 static void agent_after_bridge_cb_failed(enum ast_after_bridge_cb_reason reason, void *data);
1178
1179 /*!
1180  * \internal
1181  * \brief ast_bridge agent_hold push method.
1182  * \since 12.0.0
1183  *
1184  * \param self Bridge to operate upon.
1185  * \param bridge_channel Bridge channel to push.
1186  * \param swap Bridge channel to swap places with if not NULL.
1187  *
1188  * \note On entry, self is already locked.
1189  *
1190  * \retval 0 on success
1191  * \retval -1 on failure
1192  */
1193 static int bridge_agent_hold_push(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
1194 {
1195         int res = 0;
1196         unsigned int wrapup_time;
1197         char dtmf[AST_FEATURE_MAX_LEN];
1198         struct ast_channel *chan;
1199         const char *moh_class;
1200         RAII_VAR(struct agent_pvt *, agent, NULL, ao2_cleanup);
1201
1202         chan = bridge_channel->chan;
1203
1204         agent = ao2_find(agents, swap ? swap->chan : chan, 0);
1205         if (!agent) {
1206                 /* Could not find the agent. */
1207                 return -1;
1208         }
1209
1210         /* Setup agent entertainment */
1211         agent_lock(agent);
1212         moh_class = ast_strdupa(agent->cfg->moh);
1213         agent_unlock(agent);
1214         res |= ast_channel_add_bridge_role(chan, "holding_participant");
1215         res |= ast_channel_set_bridge_role_option(chan, "holding_participant", "idle_mode", "musiconhold");
1216         res |= ast_channel_set_bridge_role_option(chan, "holding_participant", "moh_class", moh_class);
1217
1218         /* Add DTMF acknowledge hook. */
1219         dtmf[0] = '\0';
1220         agent_lock(agent);
1221         if (ast_test_flag(agent, AGENT_FLAG_ACK_CALL)
1222                 ? agent->override_ack_call : agent->cfg->ack_call) {
1223                 const char *dtmf_accept;
1224
1225                 dtmf_accept = ast_test_flag(agent, AGENT_FLAG_DTMF_ACCEPT)
1226                         ? agent->override_dtmf_accept : agent->cfg->dtmf_accept;
1227                 ast_copy_string(dtmf, dtmf_accept, sizeof(dtmf));
1228         }
1229         agent_unlock(agent);
1230         if (!ast_strlen_zero(dtmf)) {
1231                 ao2_ref(agent, +1);
1232                 if (ast_bridge_dtmf_hook(bridge_channel->features, dtmf, bridge_agent_hold_ack,
1233                         agent, __ao2_cleanup, AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
1234                         ao2_ref(agent, -1);
1235                         res = -1;
1236                 }
1237         }
1238
1239         /* Add heartbeat interval hook. */
1240         ao2_ref(agent, +1);
1241         if (ast_bridge_interval_hook(bridge_channel->features, 1000,
1242                 bridge_agent_hold_heartbeat, agent, __ao2_cleanup, AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
1243                 ao2_ref(agent, -1);
1244                 res = -1;
1245         }
1246
1247         res |= ast_bridge_base_v_table.push(self, bridge_channel, swap);
1248         if (res) {
1249                 ast_channel_remove_bridge_role(chan, "holding_participant");
1250                 return -1;
1251         }
1252
1253         if (swap) {
1254                 res = ast_after_bridge_callback_set(chan, agent_after_bridge_cb,
1255                         agent_after_bridge_cb_failed, chan);
1256                 if (res) {
1257                         ast_channel_remove_bridge_role(chan, "holding_participant");
1258                         return -1;
1259                 }
1260
1261                 agent_lock(agent);
1262                 ast_channel_unref(agent->logged);
1263                 agent->logged = ast_channel_ref(chan);
1264                 agent_unlock(agent);
1265
1266                 /*
1267                  * Kick the channel out so it can come back in fully controlled.
1268                  * Otherwise, the after bridge callback will linger and the
1269                  * agent will have some slightly different behavior in corner
1270                  * cases.
1271                  */
1272                 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
1273                 return 0;
1274         }
1275
1276         agent_lock(agent);
1277         switch (agent->state) {
1278         case AGENT_STATE_LOGGED_OUT:
1279                 /*!
1280                  * \todo XXX the login probation time should be only if it is needed.
1281                  *
1282                  * Need to determine if there are any local channels that can
1283                  * optimize and wait until they actually do before leaving the
1284                  * AGENT_STATE_PROBATION_WAIT state.  For now, the blind
1285                  * timer of LOGIN_WAIT_TIMEOUT_TIME will do.
1286                  */
1287                 /*
1288                  * Start the login probation timer.
1289                  *
1290                  * We cannot handle an agent local channel optimization when the
1291                  * agent is on a call.  The optimization may kick the agent
1292                  * channel we know about out of the call without our being able
1293                  * to switch to the replacement channel.  Get any agent local
1294                  * channel optimization out of the way while the agent is in the
1295                  * holding bridge.
1296                  */
1297                 time(&agent->probation_start);
1298                 agent->state = AGENT_STATE_PROBATION_WAIT;
1299                 agent_unlock(agent);
1300                 break;
1301         case AGENT_STATE_PROBATION_WAIT:
1302                 /* Restart the probation timer. */
1303                 time(&agent->probation_start);
1304                 agent_unlock(agent);
1305                 break;
1306         case AGENT_STATE_READY_FOR_CALL:
1307                 /*
1308                  * Likely someone manually kicked us out of the holding bridge
1309                  * and we came right back in.
1310                  */
1311                 agent_unlock(agent);
1312                 break;
1313         default:
1314                 /* Unexpected agent state. */
1315                 ast_assert(0);
1316                 /* Fall through */
1317         case AGENT_STATE_CALL_PRESENT:
1318         case AGENT_STATE_CALL_WAIT_ACK:
1319                 agent->state = AGENT_STATE_READY_FOR_CALL;
1320                 agent->devstate = AST_DEVICE_NOT_INUSE;
1321                 agent_unlock(agent);
1322                 ast_debug(1, "Agent %s: Call abort recovery complete.\n", agent->username);
1323                 agent_devstate_changed(agent->username);
1324                 break;
1325         case AGENT_STATE_ON_CALL:
1326         case AGENT_STATE_CALL_WRAPUP:
1327                 wrapup_time = agent->cfg->wrapup_time;
1328                 if (ast_test_flag(agent, AGENT_FLAG_WRAPUP_TIME)) {
1329                         wrapup_time = agent->override_wrapup_time;
1330                 }
1331                 if (wrapup_time) {
1332                         agent->state = AGENT_STATE_CALL_WRAPUP;
1333                 } else {
1334                         agent->state = AGENT_STATE_READY_FOR_CALL;
1335                         agent->devstate = AST_DEVICE_NOT_INUSE;
1336                 }
1337                 agent_unlock(agent);
1338                 if (!wrapup_time) {
1339                         /* No wrapup time. */
1340                         ast_debug(1, "Agent %s: Ready for new call.\n", agent->username);
1341                         agent_devstate_changed(agent->username);
1342                 }
1343                 break;
1344         }
1345
1346         return 0;
1347 }
1348
1349 /*!
1350  * \internal
1351  * \brief ast_bridge agent_hold pull method.
1352  *
1353  * \param self Bridge to operate upon.
1354  * \param bridge_channel Bridge channel to pull.
1355  *
1356  * \details
1357  * Remove any channel hooks controlled by the bridge.  Release
1358  * any resources held by bridge_channel->bridge_pvt and release
1359  * bridge_channel->bridge_pvt.
1360  *
1361  * \note On entry, self is already locked.
1362  *
1363  * \return Nothing
1364  */
1365 static void bridge_agent_hold_pull(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)
1366 {
1367         ast_channel_remove_bridge_role(bridge_channel->chan, "holding_participant");
1368         ast_bridge_base_v_table.pull(self, bridge_channel);
1369 }
1370
1371 /*!
1372  * \brief The bridge is being dissolved.
1373  *
1374  * \param self Bridge to operate upon.
1375  *
1376  * \details
1377  * The bridge is being dissolved.  Remove any external
1378  * references to the bridge so it can be destroyed.
1379  *
1380  * \note On entry, self must NOT be locked.
1381  *
1382  * \return Nothing
1383  */
1384 static void bridge_agent_hold_dissolving(struct ast_bridge *self)
1385 {
1386         ao2_global_obj_replace_unref(agent_holding, NULL);
1387         ast_bridge_base_v_table.dissolving(self);
1388 }
1389
1390 static struct ast_bridge_methods bridge_agent_hold_v_table;
1391
1392 static struct ast_bridge *bridge_agent_hold_new(void)
1393 {
1394         struct ast_bridge *bridge;
1395
1396         bridge = ast_bridge_alloc(sizeof(struct ast_bridge), &bridge_agent_hold_v_table);
1397         bridge = ast_bridge_base_init(bridge, AST_BRIDGE_CAPABILITY_HOLDING,
1398                 AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM
1399                         | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM | AST_BRIDGE_FLAG_TRANSFER_PROHIBITED);
1400         bridge = ast_bridge_register(bridge);
1401         return bridge;
1402 }
1403
1404 static void bridging_init_agent_hold(void)
1405 {
1406         /* Setup bridge agent_hold subclass v_table. */
1407         bridge_agent_hold_v_table = ast_bridge_base_v_table;
1408         bridge_agent_hold_v_table.name = "agent_hold";
1409         bridge_agent_hold_v_table.dissolving = bridge_agent_hold_dissolving;
1410         bridge_agent_hold_v_table.push = bridge_agent_hold_push;
1411         bridge_agent_hold_v_table.pull = bridge_agent_hold_pull;
1412 }
1413
1414 static int bridge_agent_hold_deferred_create(void)
1415 {
1416         RAII_VAR(struct ast_bridge *, holding, ao2_global_obj_ref(agent_holding), ao2_cleanup);
1417
1418         if (!holding) {
1419                 ast_mutex_lock(&agent_holding_lock);
1420                 holding = ao2_global_obj_ref(agent_holding);
1421                 if (!holding) {
1422                         holding = bridge_agent_hold_new();
1423                         ao2_global_obj_replace_unref(agent_holding, holding);
1424                 }
1425                 ast_mutex_unlock(&agent_holding_lock);
1426                 if (!holding) {
1427                         ast_log(LOG_ERROR, "Could not create agent holding bridge.\n");
1428                         return -1;
1429                 }
1430         }
1431         return 0;
1432 }
1433
1434 static void send_agent_login(struct ast_channel *chan, const char *agent)
1435 {
1436         RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
1437
1438         ast_assert(agent != NULL);
1439
1440         blob = ast_json_pack("{s: s}",
1441                 "agent", agent);
1442         if (!blob) {
1443                 return;
1444         }
1445
1446         ast_channel_publish_blob(chan, ast_channel_agent_login_type(), blob);
1447 }
1448
1449 static void send_agent_logoff(struct ast_channel *chan, const char *agent, long logintime)
1450 {
1451         RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
1452
1453         ast_assert(agent != NULL);
1454
1455         blob = ast_json_pack("{s: s, s: i}",
1456                 "agent", agent,
1457                 "logintime", logintime);
1458         if (!blob) {
1459                 return;
1460         }
1461
1462         ast_channel_publish_blob(chan, ast_channel_agent_logoff_type(), blob);
1463 }
1464
1465 /*!
1466  * \internal
1467  * \brief Logout the agent.
1468  * \since 12.0.0
1469  *
1470  * \param agent Which agent logging out.
1471  *
1472  * \note On entry agent is already locked.  On exit it is no longer locked.
1473  *
1474  * \return Nothing
1475  */
1476 static void agent_logout(struct agent_pvt *agent)
1477 {
1478         struct ast_channel *logged;
1479         struct ast_bridge *caller_bridge;
1480         long time_logged_in;
1481
1482         time_logged_in = time(NULL) - agent->login_start;
1483         logged = agent->logged;
1484         agent->logged = NULL;
1485         caller_bridge = agent->caller_bridge;
1486         agent->caller_bridge = NULL;
1487         agent->state = AGENT_STATE_LOGGED_OUT;
1488         agent->devstate = AST_DEVICE_UNAVAILABLE;
1489         ast_clear_flag(agent, AST_FLAGS_ALL);
1490         agent_unlock(agent);
1491         agent_devstate_changed(agent->username);
1492
1493         if (caller_bridge) {
1494                 ast_bridge_destroy(caller_bridge);
1495         }
1496
1497         send_agent_logoff(logged, agent->username, time_logged_in);
1498         ast_verb(2, "Agent '%s' logged out.  Logged in for %ld seconds.\n",
1499                 agent->username, time_logged_in);
1500         ast_channel_unref(logged);
1501 }
1502
1503 /*!
1504  * \internal
1505  * \brief Agent driver loop.
1506  * \since 12.0.0
1507  *
1508  * \param agent Which agent.
1509  * \param logged The logged in channel.
1510  *
1511  * \return Nothing
1512  */
1513 static void agent_run(struct agent_pvt *agent, struct ast_channel *logged)
1514 {
1515         struct ast_bridge_features features;
1516
1517         if (ast_bridge_features_init(&features)) {
1518                 goto agent_run_cleanup;
1519         }
1520         for (;;) {
1521                 struct agents_cfg *cfgs;
1522                 struct agent_cfg *cfg_new;
1523                 struct agent_cfg *cfg_old;
1524                 struct ast_bridge *holding;
1525                 struct ast_bridge *caller_bridge;
1526
1527                 holding = ao2_global_obj_ref(agent_holding);
1528                 if (!holding) {
1529                         ast_debug(1, "Agent %s: Someone destroyed the agent holding bridge.\n",
1530                                 agent->username);
1531                         break;
1532                 }
1533
1534                 /*
1535                  * When the agent channel leaves the bridging system we usually
1536                  * want to put the agent back into the holding bridge for the
1537                  * next caller.
1538                  */
1539                 ast_bridge_join(holding, logged, NULL, &features, NULL, 1);
1540                 if (logged != agent->logged) {
1541                         /* This channel is no longer the logged in agent. */
1542                         break;
1543                 }
1544
1545                 if (agent->dead) {
1546                         /* The agent is no longer configured. */
1547                         break;
1548                 }
1549
1550                 /* Update the agent's config before rejoining the holding bridge. */
1551                 cfgs = ao2_global_obj_ref(cfg_handle);
1552                 if (!cfgs) {
1553                         /* There is no agent configuration.  All agents were destroyed. */
1554                         break;
1555                 }
1556                 cfg_new = ao2_find(cfgs->agents, agent->username, OBJ_KEY);
1557                 ao2_ref(cfgs, -1);
1558                 if (!cfg_new) {
1559                         /* The agent is no longer configured. */
1560                         break;
1561                 }
1562                 agent_lock(agent);
1563                 cfg_old = agent->cfg;
1564                 agent->cfg = cfg_new;
1565
1566                 agent->last_disconnect = ast_tvnow();
1567
1568                 /* Clear out any caller bridge before rejoining the holding bridge. */
1569                 caller_bridge = agent->caller_bridge;
1570                 agent->caller_bridge = NULL;
1571                 agent_unlock(agent);
1572                 ao2_ref(cfg_old, -1);
1573                 if (caller_bridge) {
1574                         ast_bridge_destroy(caller_bridge);
1575                 }
1576
1577                 if (agent->state == AGENT_STATE_LOGGING_OUT
1578                         || agent->deferred_logoff
1579                         || ast_check_hangup_locked(logged)) {
1580                         /* The agent was requested to logout or hungup. */
1581                         break;
1582                 }
1583
1584                 /*
1585                  * It is safe to access agent->waiting_colp without a lock.  It
1586                  * is only setup on agent login and not changed.
1587                  */
1588                 ast_channel_update_connected_line(logged, &agent->waiting_colp, NULL);
1589         }
1590         ast_bridge_features_cleanup(&features);
1591
1592 agent_run_cleanup:
1593         agent_lock(agent);
1594         if (logged != agent->logged) {
1595                 /*
1596                  * We are no longer the agent channel because of local channel
1597                  * optimization.
1598                  */
1599                 agent_unlock(agent);
1600                 ast_debug(1, "Agent %s: Channel %s is no longer the agent.\n",
1601                         agent->username, ast_channel_name(logged));
1602                 return;
1603         }
1604         agent_logout(agent);
1605 }
1606
1607 static void agent_after_bridge_cb(struct ast_channel *chan, void *data)
1608 {
1609         struct agent_pvt *agent;
1610
1611         agent = ao2_find(agents, chan, 0);
1612         if (!agent) {
1613                 return;
1614         }
1615
1616         ast_debug(1, "Agent %s: New agent channel %s.\n",
1617                 agent->username, ast_channel_name(chan));
1618         agent_run(agent, chan);
1619         ao2_ref(agent, -1);
1620 }
1621
1622 static void agent_after_bridge_cb_failed(enum ast_after_bridge_cb_reason reason, void *data)
1623 {
1624         struct ast_channel *chan = data;
1625         struct agent_pvt *agent;
1626
1627         agent = ao2_find(agents, chan, 0);
1628         if (!agent) {
1629                 return;
1630         }
1631         ast_log(LOG_WARNING, "Agent %s: Forced logout.  Lost control of %s because: %s\n",
1632                 agent->username, ast_channel_name(chan),
1633                 ast_after_bridge_cb_reason_string(reason));
1634         agent_lock(agent);
1635         agent_logout(agent);
1636         ao2_ref(agent, -1);
1637 }
1638
1639 /*!
1640  * \internal
1641  * \brief Get the lock on the agent bridge_channel and return it.
1642  * \since 12.0.0
1643  *
1644  * \param agent Whose bridge_channel to get.
1645  *
1646  * \retval bridge_channel on success (Reffed and locked).
1647  * \retval NULL on error.
1648  */
1649 static struct ast_bridge_channel *agent_bridge_channel_get_lock(struct agent_pvt *agent)
1650 {
1651         struct ast_channel *logged;
1652         struct ast_bridge_channel *bc;
1653
1654         for (;;) {
1655                 agent_lock(agent);
1656                 logged = agent->logged;
1657                 if (!logged) {
1658                         agent_unlock(agent);
1659                         return NULL;
1660                 }
1661                 ast_channel_ref(logged);
1662                 agent_unlock(agent);
1663
1664                 ast_channel_lock(logged);
1665                 bc = ast_channel_get_bridge_channel(logged);
1666                 ast_channel_unlock(logged);
1667                 ast_channel_unref(logged);
1668                 if (!bc) {
1669                         if (agent->logged != logged) {
1670                                 continue;
1671                         }
1672                         return NULL;
1673                 }
1674
1675                 ast_bridge_channel_lock(bc);
1676                 if (bc->chan != logged || agent->logged != logged) {
1677                         ast_bridge_channel_unlock(bc);
1678                         ao2_ref(bc, -1);
1679                         continue;
1680                 }
1681                 return bc;
1682         }
1683 }
1684
1685 static void caller_abort_agent(struct agent_pvt *agent)
1686 {
1687         struct ast_bridge_channel *logged;
1688
1689         logged = agent_bridge_channel_get_lock(agent);
1690         if (!logged) {
1691                 struct ast_bridge *caller_bridge;
1692
1693                 ast_debug(1, "Agent '%s' no longer logged in.\n", agent->username);
1694
1695                 agent_lock(agent);
1696                 caller_bridge = agent->caller_bridge;
1697                 agent->caller_bridge = NULL;
1698                 agent_unlock(agent);
1699                 if (caller_bridge) {
1700                         ast_bridge_destroy(caller_bridge);
1701                 }
1702                 return;
1703         }
1704
1705         /* Kick the agent out of the holding bridge to reset it. */
1706         ast_bridge_change_state_nolock(logged, AST_BRIDGE_CHANNEL_STATE_END);
1707         ast_bridge_channel_unlock(logged);
1708 }
1709
1710 static int caller_safety_timeout(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
1711 {
1712         struct agent_pvt *agent = hook_pvt;
1713
1714         if (agent->state == AGENT_STATE_CALL_PRESENT) {
1715                 ast_verb(3, "Agent '%s' did not respond.  Safety timeout.\n", agent->username);
1716                 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
1717                 caller_abort_agent(agent);
1718         }
1719
1720         return -1;
1721 }
1722
1723 static void agent_alert(struct ast_bridge_channel *bridge_channel, const void *payload, size_t payload_size)
1724 {
1725         const char *agent_id = payload;
1726         const char *playfile;
1727         RAII_VAR(struct agent_pvt *, agent, NULL, ao2_cleanup);
1728
1729         agent = ao2_find(agents, agent_id, OBJ_KEY);
1730         if (!agent) {
1731                 ast_debug(1, "Agent '%s' does not exist.  Where did it go?\n", agent_id);
1732                 return;
1733         }
1734
1735         /* Alert the agent. */
1736         agent_lock(agent);
1737         playfile = ast_strdupa(agent->cfg->beep_sound);
1738         agent_unlock(agent);
1739         ast_stream_and_wait(bridge_channel->chan, playfile, AST_DIGIT_NONE);
1740
1741         agent_lock(agent);
1742         switch (agent->state) {
1743         case AGENT_STATE_CALL_PRESENT:
1744                 if (ast_test_flag(agent, AGENT_FLAG_ACK_CALL)
1745                         ? agent->override_ack_call : agent->cfg->ack_call) {
1746                         agent->state = AGENT_STATE_CALL_WAIT_ACK;
1747                         agent->ack_time = ast_tvnow();
1748                         break;
1749                 }
1750
1751                 /* Connect to caller now. */
1752                 ast_debug(1, "Agent %s: Immediately connecting to call.\n", agent->username);
1753                 agent_connect_caller(bridge_channel, agent);/* Will unlock agent. */
1754                 return;
1755         default:
1756                 break;
1757         }
1758         agent_unlock(agent);
1759 }
1760
1761 static int send_alert_to_agent(struct ast_bridge_channel *bridge_channel, const char *agent_id)
1762 {
1763         return ast_bridge_channel_queue_callback(bridge_channel, agent_alert, agent_id,
1764                 strlen(agent_id) + 1);
1765 }
1766
1767 static int send_colp_to_agent(struct ast_bridge_channel *bridge_channel, struct ast_party_connected_line *connected)
1768 {
1769         struct ast_set_party_connected_line update = {
1770                 .id.name = 1,
1771                 .id.number = 1,
1772                 .id.subaddress = 1,
1773         };
1774         unsigned char data[1024];       /* This should be large enough */
1775         size_t datalen;
1776
1777         datalen = ast_connected_line_build_data(data, sizeof(data), connected, &update);
1778         if (datalen == (size_t) -1) {
1779                 return 0;
1780         }
1781
1782         return ast_bridge_channel_queue_control_data(bridge_channel,
1783                 AST_CONTROL_CONNECTED_LINE, data, datalen);
1784 }
1785
1786 /*!
1787  * \brief Dialplan AgentRequest application to locate an agent to talk with.
1788  *
1789  * \param chan Channel wanting to talk with an agent.
1790  * \param data Application parameters
1791  *
1792  * \retval 0 To continue in dialplan.
1793  * \retval -1 To hangup.
1794  */
1795 static int agent_request_exec(struct ast_channel *chan, const char *data)
1796 {
1797         struct ast_bridge *caller_bridge;
1798         struct ast_bridge_channel *logged;
1799         char *parse;
1800         int res;
1801         struct ast_bridge_features caller_features;
1802         struct ast_party_connected_line connected;
1803         AST_DECLARE_APP_ARGS(args,
1804                 AST_APP_ARG(agent_id);
1805                 AST_APP_ARG(other);             /* Any remaining unused arguments */
1806         );
1807
1808         RAII_VAR(struct agent_pvt *, agent, NULL, ao2_cleanup);
1809
1810         if (bridge_agent_hold_deferred_create()) {
1811                 return -1;
1812         }
1813
1814         parse = ast_strdupa(data);
1815         AST_STANDARD_APP_ARGS(args, parse);
1816
1817         if (ast_strlen_zero(args.agent_id)) {
1818                 ast_log(LOG_WARNING, "AgentRequest requires an AgentId\n");
1819                 return -1;
1820         }
1821
1822         /* Find the agent. */
1823         agent = ao2_find(agents, args.agent_id, OBJ_KEY);
1824         if (!agent) {
1825                 ast_verb(3, "Agent '%s' does not exist.\n", args.agent_id);
1826                 pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "INVALID");
1827                 return 0;
1828         }
1829
1830         if (ast_bridge_features_init(&caller_features)) {
1831                 return -1;
1832         }
1833
1834         /* Add safety timeout hook. */
1835         ao2_ref(agent, +1);
1836         if (ast_bridge_interval_hook(&caller_features, CALLER_SAFETY_TIMEOUT_TIME,
1837                 caller_safety_timeout, agent, __ao2_cleanup, AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
1838                 ao2_ref(agent, -1);
1839                 ast_bridge_features_cleanup(&caller_features);
1840                 return -1;
1841         }
1842
1843         caller_bridge = ast_bridge_basic_new();
1844         if (!caller_bridge) {
1845                 ast_bridge_features_cleanup(&caller_features);
1846                 return -1;
1847         }
1848
1849         /* Get COLP for agent. */
1850         ast_party_connected_line_init(&connected);
1851         ast_channel_lock(chan);
1852         ast_connected_line_copy_from_caller(&connected, ast_channel_caller(chan));
1853         ast_channel_unlock(chan);
1854
1855         agent_lock(agent);
1856         switch (agent->state) {
1857         case AGENT_STATE_LOGGED_OUT:
1858         case AGENT_STATE_LOGGING_OUT:
1859                 agent_unlock(agent);
1860                 ast_party_connected_line_free(&connected);
1861                 ast_bridge_destroy(caller_bridge);
1862                 ast_bridge_features_cleanup(&caller_features);
1863                 ast_verb(3, "Agent '%s' not logged in.\n", agent->username);
1864                 pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "NOT_LOGGED_IN");
1865                 return 0;
1866         case AGENT_STATE_READY_FOR_CALL:
1867                 ao2_ref(caller_bridge, +1);
1868                 agent->caller_bridge = caller_bridge;
1869                 agent->state = AGENT_STATE_CALL_PRESENT;
1870                 agent->devstate = AST_DEVICE_INUSE;
1871                 break;
1872         default:
1873                 agent_unlock(agent);
1874                 ast_party_connected_line_free(&connected);
1875                 ast_bridge_destroy(caller_bridge);
1876                 ast_bridge_features_cleanup(&caller_features);
1877                 ast_verb(3, "Agent '%s' is busy.\n", agent->username);
1878                 pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "BUSY");
1879                 return 0;
1880         }
1881         agent_unlock(agent);
1882         agent_devstate_changed(agent->username);
1883
1884         logged = agent_bridge_channel_get_lock(agent);
1885         if (!logged) {
1886                 ast_party_connected_line_free(&connected);
1887                 ast_bridge_destroy(caller_bridge);
1888                 ast_bridge_features_cleanup(&caller_features);
1889                 ast_verb(3, "Agent '%s' not logged in.\n", agent->username);
1890                 pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "NOT_LOGGED_IN");
1891                 caller_abort_agent(agent);
1892                 return 0;
1893         }
1894
1895         send_colp_to_agent(logged, &connected);
1896         ast_party_connected_line_free(&connected);
1897
1898         res = send_alert_to_agent(logged, agent->username);
1899         ast_bridge_channel_unlock(logged);
1900         ao2_ref(logged, -1);
1901         if (res) {
1902                 ast_bridge_destroy(caller_bridge);
1903                 ast_bridge_features_cleanup(&caller_features);
1904                 ast_verb(3, "Agent '%s': Failed to alert the agent.\n", agent->username);
1905                 pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "ERROR");
1906                 caller_abort_agent(agent);
1907                 return 0;
1908         }
1909
1910         ast_indicate(chan, AST_CONTROL_RINGING);
1911         ast_bridge_join(caller_bridge, chan, NULL, &caller_features, NULL, 1);
1912         ast_bridge_features_cleanup(&caller_features);
1913
1914         return -1;
1915 }
1916
1917 /*!
1918  * \internal
1919  * \brief Get agent config values from the login channel.
1920  * \since 12.0.0
1921  *
1922  * \param agent What to setup channel config values on.
1923  * \param chan Channel logging in as an agent.
1924  *
1925  * \return Nothing
1926  */
1927 static void agent_login_channel_config(struct agent_pvt *agent, struct ast_channel *chan)
1928 {
1929         struct ast_flags opts = { 0 };
1930         struct ast_party_connected_line connected;
1931         unsigned int override_ack_call = 0;
1932         unsigned int override_auto_logoff = 0;
1933         unsigned int override_wrapup_time = 0;
1934         const char *override_dtmf_accept = NULL;
1935         const char *var;
1936
1937         ast_party_connected_line_init(&connected);
1938
1939         /* Get config values from channel. */
1940         ast_channel_lock(chan);
1941         ast_party_connected_line_copy(&connected, ast_channel_connected(chan));
1942
1943         var = pbx_builtin_getvar_helper(chan, "AGENTACKCALL");
1944         if (!ast_strlen_zero(var)) {
1945                 override_ack_call = ast_true(var) ? 1 : 0;
1946                 ast_set_flag(&opts, AGENT_FLAG_ACK_CALL);
1947         }
1948
1949         var = pbx_builtin_getvar_helper(chan, "AGENTACCEPTDTMF");
1950         if (!ast_strlen_zero(var)) {
1951                 override_dtmf_accept = ast_strdupa(var);
1952                 ast_set_flag(&opts, AGENT_FLAG_DTMF_ACCEPT);
1953         }
1954
1955         var = pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF");
1956         if (!ast_strlen_zero(var)) {
1957                 if (sscanf(var, "%u", &override_auto_logoff) == 1) {
1958                         ast_set_flag(&opts, AGENT_FLAG_AUTO_LOGOFF);
1959                 }
1960         }
1961
1962         var = pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME");
1963         if (!ast_strlen_zero(var)) {
1964                 if (sscanf(var, "%u", &override_wrapup_time) == 1) {
1965                         ast_set_flag(&opts, AGENT_FLAG_WRAPUP_TIME);
1966                 }
1967         }
1968         ast_channel_unlock(chan);
1969
1970         /* Set config values on agent. */
1971         agent_lock(agent);
1972         ast_party_connected_line_free(&agent->waiting_colp);
1973         agent->waiting_colp = connected;
1974
1975         ast_string_field_set(agent, override_dtmf_accept, override_dtmf_accept);
1976         ast_copy_flags(agent, &opts, AST_FLAGS_ALL);
1977         agent->override_auto_logoff = override_auto_logoff;
1978         agent->override_wrapup_time = override_wrapup_time;
1979         agent->override_ack_call = override_ack_call;
1980         agent_unlock(agent);
1981 }
1982
1983 enum AGENT_LOGIN_OPT_FLAGS {
1984         OPT_SILENT = (1 << 0),
1985 };
1986 AST_APP_OPTIONS(agent_login_opts, BEGIN_OPTIONS
1987         AST_APP_OPTION('s', OPT_SILENT),
1988 END_OPTIONS);
1989
1990 /*!
1991  * \brief Dialplan AgentLogin application to log in an agent.
1992  *
1993  * \param chan Channel attempting to login as an agent.
1994  * \param data Application parameters
1995  *
1996  * \retval 0 To continue in dialplan.
1997  * \retval -1 To hangup.
1998  */
1999 static int agent_login_exec(struct ast_channel *chan, const char *data)
2000 {
2001         char *parse;
2002         struct ast_flags opts;
2003         AST_DECLARE_APP_ARGS(args,
2004                 AST_APP_ARG(agent_id);
2005                 AST_APP_ARG(options);
2006                 AST_APP_ARG(other);             /* Any remaining unused arguments */
2007         );
2008
2009         RAII_VAR(struct agent_pvt *, agent, NULL, ao2_cleanup);
2010
2011         if (bridge_agent_hold_deferred_create()) {
2012                 return -1;
2013         }
2014
2015         if (ast_channel_state(chan) != AST_STATE_UP && ast_answer(chan)) {
2016                 return -1;
2017         }
2018
2019         parse = ast_strdupa(data);
2020         AST_STANDARD_APP_ARGS(args, parse);
2021
2022         if (ast_strlen_zero(args.agent_id)) {
2023                 ast_log(LOG_WARNING, "AgentLogin requires an AgentId\n");
2024                 return -1;
2025         }
2026
2027         if (ast_app_parse_options(agent_login_opts, &opts, NULL, args.options)) {
2028                 /* General invalid option syntax. */
2029                 return -1;
2030         }
2031
2032         /* Find the agent. */
2033         agent = ao2_find(agents, args.agent_id, OBJ_KEY);
2034         if (!agent) {
2035                 ast_verb(3, "Agent '%s' does not exist.\n", args.agent_id);
2036                 pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "INVALID");
2037                 return 0;
2038         }
2039
2040         /* Has someone already logged in as this agent already? */
2041         agent_lock(agent);
2042         if (agent->logged) {
2043                 agent_unlock(agent);
2044                 ast_verb(3, "Agent '%s' already logged in.\n", agent->username);
2045                 pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "ALREADY_LOGGED_IN");
2046                 return 0;
2047         }
2048         agent->logged = ast_channel_ref(chan);
2049         agent->last_disconnect = ast_tvnow();
2050         time(&agent->login_start);
2051         agent_unlock(agent);
2052
2053         agent_login_channel_config(agent, chan);
2054
2055         if (!ast_test_flag(&opts, OPT_SILENT)
2056                 && !ast_streamfile(chan, "agent-loginok", ast_channel_language(chan))) {
2057                 ast_waitstream(chan, "");
2058         }
2059
2060         ast_verb(2, "Agent '%s' logged in (format %s/%s)\n", agent->username,
2061                 ast_getformatname(ast_channel_readformat(chan)),
2062                 ast_getformatname(ast_channel_writeformat(chan)));
2063         send_agent_login(chan, agent->username);
2064
2065         agent_run(agent, chan);
2066         return -1;
2067 }
2068
2069 static int agent_function_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
2070 {
2071         char *parse;
2072         struct agent_pvt *agent;
2073         struct ast_channel *logged;
2074         AST_DECLARE_APP_ARGS(args,
2075                 AST_APP_ARG(agentid);
2076                 AST_APP_ARG(item);
2077         );
2078
2079         buf[0] = '\0';
2080
2081         parse = ast_strdupa(data ?: "");
2082         AST_NONSTANDARD_APP_ARGS(args, parse, ':');
2083
2084         if (ast_strlen_zero(args.agentid)) {
2085                 ast_log(LOG_WARNING, "The AGENT function requires an argument - agentid!\n");
2086                 return -1;
2087         }
2088         if (!args.item) {
2089                 args.item = "status";
2090         }
2091
2092         agent = ao2_find(agents, args.agentid, OBJ_KEY);
2093         if (!agent) {
2094                 ast_log(LOG_WARNING, "Agent '%s' not found!\n", args.agentid);
2095                 return -1;
2096         }
2097
2098         agent_lock(agent);
2099         if (!strcasecmp(args.item, "status")) {
2100                 const char *status;
2101
2102                 if (agent->logged) {
2103                         status = "LOGGEDIN";
2104                 } else {
2105                         status = "LOGGEDOUT";
2106                 }
2107                 ast_copy_string(buf, status, len);
2108         } else if (!strcasecmp(args.item, "name")) {
2109                 ast_copy_string(buf, agent->cfg->full_name, len);
2110         } else if (!strcasecmp(args.item, "mohclass")) {
2111                 ast_copy_string(buf, agent->cfg->moh, len);
2112         } else if (!strcasecmp(args.item, "channel")) {
2113                 logged = agent_lock_logged(agent);
2114                 if (logged) {
2115                         char *pos;
2116
2117                         ast_copy_string(buf, ast_channel_name(logged), len);
2118                         ast_channel_unlock(logged);
2119                         ast_channel_unref(logged);
2120
2121                         pos = strrchr(buf, '-');
2122                         if (pos) {
2123                                 *pos = '\0';
2124                         }
2125                 }
2126         } else if (!strcasecmp(args.item, "fullchannel")) {
2127                 logged = agent_lock_logged(agent);
2128                 if (logged) {
2129                         ast_copy_string(buf, ast_channel_name(logged), len);
2130                         ast_channel_unlock(logged);
2131                         ast_channel_unref(logged);
2132                 }
2133         }
2134         agent_unlock(agent);
2135         ao2_ref(agent, -1);
2136
2137         return 0;
2138 }
2139
2140 static struct ast_custom_function agent_function = {
2141         .name = "AGENT",
2142         .read = agent_function_read,
2143 };
2144
2145 struct agent_complete {
2146         /*! Nth match to return. */
2147         int state;
2148         /*! Which match currently on. */
2149         int which;
2150 };
2151
2152 static int complete_agent_search(void *obj, void *arg, void *data, int flags)
2153 {
2154         struct agent_complete *search = data;
2155
2156         if (++search->which > search->state) {
2157                 return CMP_MATCH;
2158         }
2159         return 0;
2160 }
2161
2162 static char *complete_agent(const char *word, int state)
2163 {
2164         char *ret;
2165         struct agent_pvt *agent;
2166         struct agent_complete search = {
2167                 .state = state,
2168         };
2169
2170         agent = ao2_callback_data(agents, ast_strlen_zero(word) ? 0 : OBJ_PARTIAL_KEY,
2171                 complete_agent_search, (char *) word, &search);
2172         if (!agent) {
2173                 return NULL;
2174         }
2175         ret = ast_strdup(agent->username);
2176         ao2_ref(agent, -1);
2177         return ret;
2178 }
2179
2180 static int complete_agent_logoff_search(void *obj, void *arg, void *data, int flags)
2181 {
2182         struct agent_pvt *agent = obj;
2183         struct agent_complete *search = data;
2184
2185         if (!agent->logged) {
2186                 return 0;
2187         }
2188         if (++search->which > search->state) {
2189                 return CMP_MATCH;
2190         }
2191         return 0;
2192 }
2193
2194 static char *complete_agent_logoff(const char *word, int state)
2195 {
2196         char *ret;
2197         struct agent_pvt *agent;
2198         struct agent_complete search = {
2199                 .state = state,
2200         };
2201
2202         agent = ao2_callback_data(agents, ast_strlen_zero(word) ? 0 : OBJ_PARTIAL_KEY,
2203                 complete_agent_logoff_search, (char *) word, &search);
2204         if (!agent) {
2205                 return NULL;
2206         }
2207         ret = ast_strdup(agent->username);
2208         ao2_ref(agent, -1);
2209         return ret;
2210 }
2211
2212 static void agent_show_requested(struct ast_cli_args *a, int online_only)
2213 {
2214 #define FORMAT_HDR "%-8s %-20s %-11s %-30s %s\n"
2215 #define FORMAT_ROW "%-8s %-20s %-11s %-30s %s\n"
2216
2217         struct ao2_iterator iter;
2218         struct agent_pvt *agent;
2219         struct ast_str *out = ast_str_alloca(512);
2220         unsigned int agents_total = 0;
2221         unsigned int agents_logged_in = 0;
2222         unsigned int agents_talking = 0;
2223
2224         ast_cli(a->fd, FORMAT_HDR, "Agent-ID", "Name", "State", "Channel", "Talking with");
2225         iter = ao2_iterator_init(agents, 0);
2226         for (; (agent = ao2_iterator_next(&iter)); ao2_ref(agent, -1)) {
2227                 struct ast_channel *logged;
2228
2229                 ++agents_total;
2230
2231                 agent_lock(agent);
2232                 logged = agent_lock_logged(agent);
2233                 if (logged) {
2234                         const char *talking_with;
2235
2236                         ++agents_logged_in;
2237
2238                         talking_with = pbx_builtin_getvar_helper(logged, "BRIDGEPEER");
2239                         if (!ast_strlen_zero(talking_with)) {
2240                                 ++agents_talking;
2241                         } else {
2242                                 talking_with = "";
2243                         }
2244                         ast_str_set(&out, 0, FORMAT_ROW, agent->username, agent->cfg->full_name,
2245                                 ast_devstate_str(agent->devstate), ast_channel_name(logged), talking_with);
2246                         ast_channel_unlock(logged);
2247                         ast_channel_unref(logged);
2248                 } else {
2249                         ast_str_set(&out, 0, FORMAT_ROW, agent->username, agent->cfg->full_name,
2250                                 ast_devstate_str(agent->devstate), "", "");
2251                 }
2252                 agent_unlock(agent);
2253
2254                 if (!online_only || logged) {
2255                         ast_cli(a->fd, "%s", ast_str_buffer(out));
2256                 }
2257         }
2258         ao2_iterator_destroy(&iter);
2259
2260         ast_cli(a->fd, "\nDefined agents: %u, Logged in: %u, Talking: %u\n",
2261                 agents_total, agents_logged_in, agents_talking);
2262
2263 #undef FORMAT_HDR
2264 #undef FORMAT_ROW
2265 }
2266
2267 static char *agent_handle_show_online(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2268 {
2269         switch (cmd) {
2270         case CLI_INIT:
2271                 e->command = "agent show online";
2272                 e->usage =
2273                         "Usage: agent show online\n"
2274                         "       Provides summary information for logged in agents.\n";
2275                 return NULL;
2276         case CLI_GENERATE:
2277                 return NULL;
2278         }
2279
2280         if (a->argc != 3) {
2281                 return CLI_SHOWUSAGE;
2282         }
2283
2284         agent_show_requested(a, 1);
2285
2286         return CLI_SUCCESS;
2287 }
2288
2289 static char *agent_handle_show_all(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2290 {
2291         switch (cmd) {
2292         case CLI_INIT:
2293                 e->command = "agent show all";
2294                 e->usage =
2295                         "Usage: agent show all\n"
2296                         "       Provides summary information for all agents.\n";
2297                 return NULL;
2298         case CLI_GENERATE:
2299                 return NULL;
2300         }
2301
2302         if (a->argc != 3) {
2303                 return CLI_SHOWUSAGE;
2304         }
2305
2306         agent_show_requested(a, 0);
2307
2308         return CLI_SUCCESS;
2309 }
2310
2311 static char *agent_handle_show_specific(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2312 {
2313         struct agent_pvt *agent;
2314         struct ast_channel *logged;
2315         struct ast_str *out = ast_str_alloca(4096);
2316
2317         switch (cmd) {
2318         case CLI_INIT:
2319                 e->command = "agent show";
2320                 e->usage =
2321                         "Usage: agent show <agent-id>\n"
2322                         "       Show information about the <agent-id> agent\n";
2323                 return NULL;
2324         case CLI_GENERATE:
2325                 if (a->pos == 2) {
2326                         return complete_agent(a->word, a->n);
2327                 }
2328                 return NULL;
2329         }
2330
2331         if (a->argc != 3) {
2332                 return CLI_SHOWUSAGE;
2333         }
2334
2335         agent = ao2_find(agents, a->argv[2], OBJ_KEY);
2336         if (!agent) {
2337                 ast_cli(a->fd, "Agent '%s' not found\n", a->argv[2]);
2338                 return CLI_SUCCESS;
2339         }
2340
2341         agent_lock(agent);
2342         logged = agent_lock_logged(agent);
2343         ast_str_set(&out, 0, "Id: %s\n", agent->username);
2344         ast_str_append(&out, 0, "Name: %s\n", agent->cfg->full_name);
2345         ast_str_append(&out, 0, "Beep: %s\n", agent->cfg->beep_sound);
2346         ast_str_append(&out, 0, "MOH: %s\n", agent->cfg->moh);
2347         ast_str_append(&out, 0, "RecordCalls: %s\n", AST_CLI_YESNO(agent->cfg->record_agent_calls));
2348         ast_str_append(&out, 0, "State: %s\n", ast_devstate_str(agent->devstate));
2349         if (logged) {
2350                 const char *talking_with;
2351
2352                 ast_str_append(&out, 0, "LoggedInChannel: %s\n", ast_channel_name(logged));
2353                 ast_str_append(&out, 0, "LoggedInTime: %ld\n", (long) agent->login_start);
2354                 talking_with = pbx_builtin_getvar_helper(logged, "BRIDGEPEER");
2355                 if (!ast_strlen_zero(talking_with)) {
2356                         ast_str_append(&out, 0, "TalkingWith: %s\n", talking_with);
2357                         ast_str_append(&out, 0, "CallStarted: %ld\n", (long) agent->call_start);
2358                 }
2359                 ast_channel_unlock(logged);
2360                 ast_channel_unref(logged);
2361         }
2362         agent_unlock(agent);
2363         ao2_ref(agent, -1);
2364
2365         ast_cli(a->fd, "%s", ast_str_buffer(out));
2366
2367         return CLI_SUCCESS;
2368 }
2369
2370 static char *agent_handle_logoff_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2371 {
2372         switch (cmd) {
2373         case CLI_INIT:
2374                 e->command = "agent logoff";
2375                 e->usage =
2376                         "Usage: agent logoff <agent-id> [soft]\n"
2377                         "       Sets an agent as no longer logged in.\n"
2378                         "       If 'soft' is specified, do not hangup existing calls.\n";
2379                 return NULL;
2380         case CLI_GENERATE:
2381                 if (a->pos == 2) {
2382                         return complete_agent_logoff(a->word, a->n);
2383                 } else if (a->pos == 3 && a->n == 0
2384                         && (ast_strlen_zero(a->word)
2385                                 || !strncasecmp("soft", a->word, strlen(a->word)))) {
2386                         return ast_strdup("soft");
2387                 }
2388                 return NULL;
2389         }
2390
2391         if (a->argc < 3 || 4 < a->argc) {
2392                 return CLI_SHOWUSAGE;
2393         }
2394         if (a->argc == 4 && strcasecmp(a->argv[3], "soft")) {
2395                 return CLI_SHOWUSAGE;
2396         }
2397
2398         if (!agent_logoff_request(a->argv[2], a->argc == 4)) {
2399                 ast_cli(a->fd, "Logging out %s\n", a->argv[2]);
2400         }
2401
2402         return CLI_SUCCESS;
2403 }
2404
2405 static struct ast_cli_entry cli_agents[] = {
2406         AST_CLI_DEFINE(agent_handle_show_online, "Show status of online agents"),
2407         AST_CLI_DEFINE(agent_handle_show_all, "Show status of all agents"),
2408         AST_CLI_DEFINE(agent_handle_show_specific, "Show information about an agent"),
2409         AST_CLI_DEFINE(agent_handle_logoff_cmd, "Sets an agent offline"),
2410 };
2411
2412 static int action_agents(struct mansession *s, const struct message *m)
2413 {
2414         const char *id = astman_get_header(m, "ActionID");
2415         char id_text[AST_MAX_BUF];
2416         struct ao2_iterator iter;
2417         struct agent_pvt *agent;
2418         struct ast_str *out = ast_str_alloca(4096);
2419
2420         if (!ast_strlen_zero(id)) {
2421                 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
2422         } else {
2423                 id_text[0] = '\0';
2424         }
2425         astman_send_ack(s, m, "Agents will follow");
2426
2427         iter = ao2_iterator_init(agents, 0);
2428         for (; (agent = ao2_iterator_next(&iter)); ao2_ref(agent, -1)) {
2429                 struct ast_channel *logged;
2430
2431                 agent_lock(agent);
2432                 logged = agent_lock_logged(agent);
2433
2434                 /*
2435                  * Status Values:
2436                  * AGENT_LOGGEDOFF - Agent isn't logged in
2437                  * AGENT_IDLE      - Agent is logged in, and waiting for call
2438                  * AGENT_ONCALL    - Agent is logged in, and on a call
2439                  * AGENT_UNKNOWN   - Don't know anything about agent. Shouldn't ever get this.
2440                  */
2441                 ast_str_set(&out, 0, "Agent: %s\r\n", agent->username);
2442                 ast_str_append(&out, 0, "Name: %s\r\n", agent->cfg->full_name);
2443
2444                 if (logged) {
2445                         const char *talking_to_chan;
2446                         struct ast_str *logged_headers;
2447                         RAII_VAR(struct ast_channel_snapshot *, logged_snapshot, ast_channel_snapshot_create(logged), ao2_cleanup);
2448
2449                         if (!logged_snapshot
2450                                 || !(logged_headers =
2451                                          ast_manager_build_channel_state_string(logged_snapshot))) {
2452                                 ast_channel_unlock(logged);
2453                                 ast_channel_unref(logged);
2454                                 agent_unlock(agent);
2455                                 continue;
2456                         }
2457
2458                         talking_to_chan = pbx_builtin_getvar_helper(logged, "BRIDGEPEER");
2459                         if (!ast_strlen_zero(talking_to_chan)) {
2460                                 ast_str_append(&out, 0, "Status: %s\r\n", "AGENT_ONCALL");
2461                                 ast_str_append(&out, 0, "TalkingToChan: %s\r\n", talking_to_chan);
2462                                 ast_str_append(&out, 0, "CallStarted: %ld\n", (long) agent->call_start);
2463                         } else {
2464                                 ast_str_append(&out, 0, "Status: %s\r\n", "AGENT_IDLE");
2465                         }
2466                         ast_str_append(&out, 0, "LoggedInTime: %ld\r\n", (long) agent->login_start);
2467                         ast_str_append(&out, 0, "%s", ast_str_buffer(logged_headers));
2468                         ast_channel_unlock(logged);
2469                         ast_channel_unref(logged);
2470                         ast_free(logged_headers);
2471                 } else {
2472                         ast_str_append(&out, 0, "Status: %s\r\n", "AGENT_LOGGEDOFF");
2473                 }
2474
2475                 agent_unlock(agent);
2476
2477                 astman_append(s, "Event: Agents\r\n"
2478                         "%s%s\r\n",
2479                         ast_str_buffer(out), id_text);
2480         }
2481         ao2_iterator_destroy(&iter);
2482
2483         astman_append(s, "Event: AgentsComplete\r\n"
2484                 "%s"
2485                 "\r\n", id_text);
2486         return 0;
2487 }
2488
2489 static int action_agent_logoff(struct mansession *s, const struct message *m)
2490 {
2491         const char *agent = astman_get_header(m, "Agent");
2492         const char *soft_s = astman_get_header(m, "Soft"); /* "true" is don't hangup */
2493
2494         if (ast_strlen_zero(agent)) {
2495                 astman_send_error(s, m, "No agent specified");
2496                 return 0;
2497         }
2498
2499         if (!agent_logoff_request(agent, ast_true(soft_s))) {
2500                 astman_send_ack(s, m, "Agent logged out");
2501         } else {
2502                 astman_send_error(s, m, "No such agent");
2503         }
2504
2505         return 0;
2506 }
2507
2508 static int unload_module(void)
2509 {
2510         struct ast_bridge *holding;
2511
2512         /* Unregister dialplan applications */
2513         ast_unregister_application(app_agent_login);
2514         ast_unregister_application(app_agent_request);
2515
2516         /* Unregister dialplan functions */
2517         ast_custom_function_unregister(&agent_function);
2518
2519         /* Unregister manager command */
2520         ast_manager_unregister("Agents");
2521         ast_manager_unregister("AgentLogoff");
2522
2523         /* Unregister CLI commands */
2524         ast_cli_unregister_multiple(cli_agents, ARRAY_LEN(cli_agents));
2525
2526         ast_devstate_prov_del("Agent");
2527
2528         /* Destroy agent holding bridge. */
2529         holding = ao2_global_obj_replace(agent_holding, NULL);
2530         if (holding) {
2531                 ast_bridge_destroy(holding);
2532         }
2533
2534         destroy_config();
2535         ao2_ref(agents, -1);
2536         agents = NULL;
2537         return 0;
2538 }
2539
2540 static int load_module(void)
2541 {
2542         int res = 0;
2543
2544         agents = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_MUTEX,
2545                 AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, agent_pvt_sort_cmp, agent_pvt_cmp);
2546         if (!agents) {
2547                 return AST_MODULE_LOAD_FAILURE;
2548         }
2549         if (load_config()) {
2550                 ast_log(LOG_ERROR, "Unable to load config. Not loading module.\n");
2551                 ao2_ref(agents, -1);
2552                 agents = NULL;
2553                 return AST_MODULE_LOAD_DECLINE;
2554         }
2555
2556         /* Init agent holding bridge v_table. */
2557         bridging_init_agent_hold();
2558
2559         /* Setup to provide Agent:agent-id device state. */
2560         res |= ast_devstate_prov_add("Agent", agent_pvt_devstate_get);
2561
2562         /* CLI Commands */
2563         res |= ast_cli_register_multiple(cli_agents, ARRAY_LEN(cli_agents));
2564
2565         /* Manager commands */
2566         res |= ast_manager_register_xml("Agents", EVENT_FLAG_AGENT, action_agents);
2567         res |= ast_manager_register_xml("AgentLogoff", EVENT_FLAG_AGENT, action_agent_logoff);
2568
2569         /* Dialplan Functions */
2570         res |= ast_custom_function_register(&agent_function);
2571
2572         /* Dialplan applications */
2573         res |= ast_register_application_xml(app_agent_login, agent_login_exec);
2574         res |= ast_register_application_xml(app_agent_request, agent_request_exec);
2575
2576         if (res) {
2577                 unload_module();
2578                 return AST_MODULE_LOAD_FAILURE;
2579         }
2580         return AST_MODULE_LOAD_SUCCESS;
2581 }
2582
2583 static int reload(void)
2584 {
2585         if (aco_process_config(&cfg_info, 1) == ACO_PROCESS_ERROR) {
2586                 /* Just keep the config we already have in place. */
2587                 return -1;
2588         }
2589         return 0;
2590 }
2591
2592 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Call center agent pool applications",
2593         .load = load_module,
2594         .unload = unload_module,
2595         .reload = reload,
2596         .load_pri = AST_MODPRI_DEVSTATE_PROVIDER,
2597 );