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