6ed2ccad1be42cfd30a3592fd69db9ed8fac7067
[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, caller_bridge,
1082                         bridge_channel, &options);
1083         }
1084 }
1085
1086 static int bridge_agent_hold_ack(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
1087 {
1088         struct agent_pvt *agent = hook_pvt;
1089
1090         agent_lock(agent);
1091         switch (agent->state) {
1092         case AGENT_STATE_CALL_WAIT_ACK:
1093                 /* Connect to caller now. */
1094                 ast_debug(1, "Agent %s: Acked call.\n", agent->username);
1095                 agent_connect_caller(bridge_channel, agent);/* Will unlock agent. */
1096                 return 0;
1097         default:
1098                 break;
1099         }
1100         agent_unlock(agent);
1101         return 0;
1102 }
1103
1104 static int bridge_agent_hold_heartbeat(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
1105 {
1106         struct agent_pvt *agent = hook_pvt;
1107         int probation_timedout = 0;
1108         int ack_timedout = 0;
1109         int wrapup_timedout = 0;
1110         int deferred_logoff;
1111         unsigned int wrapup_time;
1112         unsigned int auto_logoff;
1113
1114         agent_lock(agent);
1115         deferred_logoff = agent->deferred_logoff;
1116         if (deferred_logoff) {
1117                 agent->state = AGENT_STATE_LOGGING_OUT;
1118         }
1119
1120         switch (agent->state) {
1121         case AGENT_STATE_PROBATION_WAIT:
1122                 probation_timedout =
1123                         LOGIN_WAIT_TIMEOUT_TIME <= (time(NULL) - agent->probation_start);
1124                 if (probation_timedout) {
1125                         /* Now ready for a caller. */
1126                         agent->state = AGENT_STATE_READY_FOR_CALL;
1127                         agent->devstate = AST_DEVICE_NOT_INUSE;
1128                 }
1129                 break;
1130         case AGENT_STATE_CALL_WAIT_ACK:
1131                 /* Check ack call time. */
1132                 auto_logoff = agent->cfg->auto_logoff;
1133                 if (ast_test_flag(agent, AGENT_FLAG_AUTO_LOGOFF)) {
1134                         auto_logoff = agent->override_auto_logoff;
1135                 }
1136                 if (auto_logoff) {
1137                         auto_logoff *= 1000;
1138                         ack_timedout = ast_tvdiff_ms(ast_tvnow(), agent->ack_time) > auto_logoff;
1139                         if (ack_timedout) {
1140                                 agent->state = AGENT_STATE_LOGGING_OUT;
1141                         }
1142                 }
1143                 break;
1144         case AGENT_STATE_CALL_WRAPUP:
1145                 /* Check wrapup time. */
1146                 wrapup_time = agent->cfg->wrapup_time;
1147                 if (ast_test_flag(agent, AGENT_FLAG_WRAPUP_TIME)) {
1148                         wrapup_time = agent->override_wrapup_time;
1149                 }
1150                 wrapup_timedout = ast_tvdiff_ms(ast_tvnow(), agent->last_disconnect) > wrapup_time;
1151                 if (wrapup_timedout) {
1152                         agent->state = AGENT_STATE_READY_FOR_CALL;
1153                         agent->devstate = AST_DEVICE_NOT_INUSE;
1154                 }
1155                 break;
1156         default:
1157                 break;
1158         }
1159         agent_unlock(agent);
1160
1161         if (deferred_logoff) {
1162                 ast_debug(1, "Agent %s: Deferred logoff.\n", agent->username);
1163                 ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
1164         } else if (probation_timedout) {
1165                 ast_debug(1, "Agent %s: Login complete.\n", agent->username);
1166                 agent_devstate_changed(agent->username);
1167         } else if (ack_timedout) {
1168                 ast_debug(1, "Agent %s: Ack call timeout.\n", agent->username);
1169                 ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
1170         } else if (wrapup_timedout) {
1171                 ast_debug(1, "Agent %s: Wrapup timeout. Ready for new call.\n", agent->username);
1172                 agent_devstate_changed(agent->username);
1173         }
1174
1175         return 0;
1176 }
1177
1178 static void agent_after_bridge_cb(struct ast_channel *chan, void *data);
1179 static void agent_after_bridge_cb_failed(enum ast_bridge_after_cb_reason reason, void *data);
1180
1181 /*!
1182  * \internal
1183  * \brief ast_bridge agent_hold push method.
1184  * \since 12.0.0
1185  *
1186  * \param self Bridge to operate upon.
1187  * \param bridge_channel Bridge channel to push.
1188  * \param swap Bridge channel to swap places with if not NULL.
1189  *
1190  * \note On entry, self is already locked.
1191  *
1192  * \retval 0 on success
1193  * \retval -1 on failure
1194  */
1195 static int bridge_agent_hold_push(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
1196 {
1197         int res = 0;
1198         unsigned int wrapup_time;
1199         char dtmf[AST_FEATURE_MAX_LEN];
1200         struct ast_channel *chan;
1201         const char *moh_class;
1202         RAII_VAR(struct agent_pvt *, agent, NULL, ao2_cleanup);
1203
1204         chan = bridge_channel->chan;
1205
1206         agent = ao2_find(agents, swap ? swap->chan : chan, 0);
1207         if (!agent) {
1208                 /* Could not find the agent. */
1209                 return -1;
1210         }
1211
1212         /* Setup agent entertainment */
1213         agent_lock(agent);
1214         moh_class = ast_strdupa(agent->cfg->moh);
1215         agent_unlock(agent);
1216         res |= ast_channel_add_bridge_role(chan, "holding_participant");
1217         res |= ast_channel_set_bridge_role_option(chan, "holding_participant", "idle_mode", "musiconhold");
1218         res |= ast_channel_set_bridge_role_option(chan, "holding_participant", "moh_class", moh_class);
1219
1220         /* Add DTMF acknowledge hook. */
1221         dtmf[0] = '\0';
1222         agent_lock(agent);
1223         if (ast_test_flag(agent, AGENT_FLAG_ACK_CALL)
1224                 ? agent->override_ack_call : agent->cfg->ack_call) {
1225                 const char *dtmf_accept;
1226
1227                 dtmf_accept = ast_test_flag(agent, AGENT_FLAG_DTMF_ACCEPT)
1228                         ? agent->override_dtmf_accept : agent->cfg->dtmf_accept;
1229                 ast_copy_string(dtmf, dtmf_accept, sizeof(dtmf));
1230         }
1231         agent_unlock(agent);
1232         if (!ast_strlen_zero(dtmf)) {
1233                 ao2_ref(agent, +1);
1234                 if (ast_bridge_dtmf_hook(bridge_channel->features, dtmf, bridge_agent_hold_ack,
1235                         agent, __ao2_cleanup, AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
1236                         ao2_ref(agent, -1);
1237                         res = -1;
1238                 }
1239         }
1240
1241         /* Add heartbeat interval hook. */
1242         ao2_ref(agent, +1);
1243         if (ast_bridge_interval_hook(bridge_channel->features, 1000,
1244                 bridge_agent_hold_heartbeat, agent, __ao2_cleanup, AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
1245                 ao2_ref(agent, -1);
1246                 res = -1;
1247         }
1248
1249         res |= ast_bridge_base_v_table.push(self, bridge_channel, swap);
1250         if (res) {
1251                 ast_channel_remove_bridge_role(chan, "holding_participant");
1252                 return -1;
1253         }
1254
1255         if (swap) {
1256                 res = ast_bridge_set_after_callback(chan, agent_after_bridge_cb,
1257                         agent_after_bridge_cb_failed, chan);
1258                 if (res) {
1259                         ast_channel_remove_bridge_role(chan, "holding_participant");
1260                         return -1;
1261                 }
1262
1263                 agent_lock(agent);
1264                 ast_channel_unref(agent->logged);
1265                 agent->logged = ast_channel_ref(chan);
1266                 agent_unlock(agent);
1267
1268                 /*
1269                  * Kick the channel out so it can come back in fully controlled.
1270                  * Otherwise, the after bridge callback will linger and the
1271                  * agent will have some slightly different behavior in corner
1272                  * cases.
1273                  */
1274                 ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
1275                 return 0;
1276         }
1277
1278         agent_lock(agent);
1279         switch (agent->state) {
1280         case AGENT_STATE_LOGGED_OUT:
1281                 /*!
1282                  * \todo XXX the login probation time should be only if it is needed.
1283                  *
1284                  * Need to determine if there are any local channels that can
1285                  * optimize and wait until they actually do before leaving the
1286                  * AGENT_STATE_PROBATION_WAIT state.  For now, the blind
1287                  * timer of LOGIN_WAIT_TIMEOUT_TIME will do.
1288                  */
1289                 /*
1290                  * Start the login probation timer.
1291                  *
1292                  * We cannot handle an agent local channel optimization when the
1293                  * agent is on a call.  The optimization may kick the agent
1294                  * channel we know about out of the call without our being able
1295                  * to switch to the replacement channel.  Get any agent local
1296                  * channel optimization out of the way while the agent is in the
1297                  * holding bridge.
1298                  */
1299                 time(&agent->probation_start);
1300                 agent->state = AGENT_STATE_PROBATION_WAIT;
1301                 agent_unlock(agent);
1302                 break;
1303         case AGENT_STATE_PROBATION_WAIT:
1304                 /* Restart the probation timer. */
1305                 time(&agent->probation_start);
1306                 agent_unlock(agent);
1307                 break;
1308         case AGENT_STATE_READY_FOR_CALL:
1309                 /*
1310                  * Likely someone manually kicked us out of the holding bridge
1311                  * and we came right back in.
1312                  */
1313                 agent_unlock(agent);
1314                 break;
1315         default:
1316                 /* Unexpected agent state. */
1317                 ast_assert(0);
1318                 /* Fall through */
1319         case AGENT_STATE_CALL_PRESENT:
1320         case AGENT_STATE_CALL_WAIT_ACK:
1321                 agent->state = AGENT_STATE_READY_FOR_CALL;
1322                 agent->devstate = AST_DEVICE_NOT_INUSE;
1323                 agent_unlock(agent);
1324                 ast_debug(1, "Agent %s: Call abort recovery complete.\n", agent->username);
1325                 agent_devstate_changed(agent->username);
1326                 break;
1327         case AGENT_STATE_ON_CALL:
1328         case AGENT_STATE_CALL_WRAPUP:
1329                 wrapup_time = agent->cfg->wrapup_time;
1330                 if (ast_test_flag(agent, AGENT_FLAG_WRAPUP_TIME)) {
1331                         wrapup_time = agent->override_wrapup_time;
1332                 }
1333                 if (wrapup_time) {
1334                         agent->state = AGENT_STATE_CALL_WRAPUP;
1335                 } else {
1336                         agent->state = AGENT_STATE_READY_FOR_CALL;
1337                         agent->devstate = AST_DEVICE_NOT_INUSE;
1338                 }
1339                 agent_unlock(agent);
1340                 if (!wrapup_time) {
1341                         /* No wrapup time. */
1342                         ast_debug(1, "Agent %s: Ready for new call.\n", agent->username);
1343                         agent_devstate_changed(agent->username);
1344                 }
1345                 break;
1346         }
1347
1348         return 0;
1349 }
1350
1351 /*!
1352  * \internal
1353  * \brief ast_bridge agent_hold pull method.
1354  *
1355  * \param self Bridge to operate upon.
1356  * \param bridge_channel Bridge channel to pull.
1357  *
1358  * \details
1359  * Remove any channel hooks controlled by the bridge.  Release
1360  * any resources held by bridge_channel->bridge_pvt and release
1361  * bridge_channel->bridge_pvt.
1362  *
1363  * \note On entry, self is already locked.
1364  *
1365  * \return Nothing
1366  */
1367 static void bridge_agent_hold_pull(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)
1368 {
1369         ast_channel_remove_bridge_role(bridge_channel->chan, "holding_participant");
1370         ast_bridge_base_v_table.pull(self, bridge_channel);
1371 }
1372
1373 /*!
1374  * \brief The bridge is being dissolved.
1375  *
1376  * \param self Bridge to operate upon.
1377  *
1378  * \details
1379  * The bridge is being dissolved.  Remove any external
1380  * references to the bridge so it can be destroyed.
1381  *
1382  * \note On entry, self must NOT be locked.
1383  *
1384  * \return Nothing
1385  */
1386 static void bridge_agent_hold_dissolving(struct ast_bridge *self)
1387 {
1388         ao2_global_obj_replace_unref(agent_holding, NULL);
1389         ast_bridge_base_v_table.dissolving(self);
1390 }
1391
1392 static struct ast_bridge_methods bridge_agent_hold_v_table;
1393
1394 static struct ast_bridge *bridge_agent_hold_new(void)
1395 {
1396         struct ast_bridge *bridge;
1397
1398         bridge = bridge_alloc(sizeof(struct ast_bridge), &bridge_agent_hold_v_table);
1399         bridge = bridge_base_init(bridge, AST_BRIDGE_CAPABILITY_HOLDING,
1400                 AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM
1401                         | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM | AST_BRIDGE_FLAG_TRANSFER_PROHIBITED);
1402         bridge = bridge_register(bridge);
1403         return bridge;
1404 }
1405
1406 static void bridge_init_agent_hold(void)
1407 {
1408         /* Setup bridge agent_hold subclass v_table. */
1409         bridge_agent_hold_v_table = ast_bridge_base_v_table;
1410         bridge_agent_hold_v_table.name = "agent_hold";
1411         bridge_agent_hold_v_table.dissolving = bridge_agent_hold_dissolving;
1412         bridge_agent_hold_v_table.push = bridge_agent_hold_push;
1413         bridge_agent_hold_v_table.pull = bridge_agent_hold_pull;
1414 }
1415
1416 static int bridge_agent_hold_deferred_create(void)
1417 {
1418         RAII_VAR(struct ast_bridge *, holding, ao2_global_obj_ref(agent_holding), ao2_cleanup);
1419
1420         if (!holding) {
1421                 ast_mutex_lock(&agent_holding_lock);
1422                 holding = ao2_global_obj_ref(agent_holding);
1423                 if (!holding) {
1424                         holding = bridge_agent_hold_new();
1425                         ao2_global_obj_replace_unref(agent_holding, holding);
1426                 }
1427                 ast_mutex_unlock(&agent_holding_lock);
1428                 if (!holding) {
1429                         ast_log(LOG_ERROR, "Could not create agent holding bridge.\n");
1430                         return -1;
1431                 }
1432         }
1433         return 0;
1434 }
1435
1436 static void send_agent_login(struct ast_channel *chan, const char *agent)
1437 {
1438         RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
1439
1440         ast_assert(agent != NULL);
1441
1442         blob = ast_json_pack("{s: s}",
1443                 "agent", agent);
1444         if (!blob) {
1445                 return;
1446         }
1447
1448         ast_channel_publish_blob(chan, ast_channel_agent_login_type(), blob);
1449 }
1450
1451 static void send_agent_logoff(struct ast_channel *chan, const char *agent, long logintime)
1452 {
1453         RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
1454
1455         ast_assert(agent != NULL);
1456
1457         blob = ast_json_pack("{s: s, s: i}",
1458                 "agent", agent,
1459                 "logintime", logintime);
1460         if (!blob) {
1461                 return;
1462         }
1463
1464         ast_channel_publish_blob(chan, ast_channel_agent_logoff_type(), blob);
1465 }
1466
1467 /*!
1468  * \internal
1469  * \brief Logout the agent.
1470  * \since 12.0.0
1471  *
1472  * \param agent Which agent logging out.
1473  *
1474  * \note On entry agent is already locked.  On exit it is no longer locked.
1475  *
1476  * \return Nothing
1477  */
1478 static void agent_logout(struct agent_pvt *agent)
1479 {
1480         struct ast_channel *logged;
1481         struct ast_bridge *caller_bridge;
1482         long time_logged_in;
1483
1484         time_logged_in = time(NULL) - agent->login_start;
1485         logged = agent->logged;
1486         agent->logged = NULL;
1487         caller_bridge = agent->caller_bridge;
1488         agent->caller_bridge = NULL;
1489         agent->state = AGENT_STATE_LOGGED_OUT;
1490         agent->devstate = AST_DEVICE_UNAVAILABLE;
1491         ast_clear_flag(agent, AST_FLAGS_ALL);
1492         agent_unlock(agent);
1493         agent_devstate_changed(agent->username);
1494
1495         if (caller_bridge) {
1496                 ast_bridge_destroy(caller_bridge);
1497         }
1498
1499         send_agent_logoff(logged, agent->username, time_logged_in);
1500         ast_verb(2, "Agent '%s' logged out.  Logged in for %ld seconds.\n",
1501                 agent->username, time_logged_in);
1502         ast_channel_unref(logged);
1503 }
1504
1505 /*!
1506  * \internal
1507  * \brief Agent driver loop.
1508  * \since 12.0.0
1509  *
1510  * \param agent Which agent.
1511  * \param logged The logged in channel.
1512  *
1513  * \return Nothing
1514  */
1515 static void agent_run(struct agent_pvt *agent, struct ast_channel *logged)
1516 {
1517         struct ast_bridge_features features;
1518
1519         if (ast_bridge_features_init(&features)) {
1520                 goto agent_run_cleanup;
1521         }
1522         for (;;) {
1523                 struct agents_cfg *cfgs;
1524                 struct agent_cfg *cfg_new;
1525                 struct agent_cfg *cfg_old;
1526                 struct ast_bridge *holding;
1527                 struct ast_bridge *caller_bridge;
1528
1529                 holding = ao2_global_obj_ref(agent_holding);
1530                 if (!holding) {
1531                         ast_debug(1, "Agent %s: Someone destroyed the agent holding bridge.\n",
1532                                 agent->username);
1533                         break;
1534                 }
1535
1536                 /*
1537                  * When the agent channel leaves the bridging system we usually
1538                  * want to put the agent back into the holding bridge for the
1539                  * next caller.
1540                  */
1541                 ast_bridge_join(holding, logged, NULL, &features, NULL, 1);
1542                 if (logged != agent->logged) {
1543                         /* This channel is no longer the logged in agent. */
1544                         break;
1545                 }
1546
1547                 if (agent->dead) {
1548                         /* The agent is no longer configured. */
1549                         break;
1550                 }
1551
1552                 /* Update the agent's config before rejoining the holding bridge. */
1553                 cfgs = ao2_global_obj_ref(cfg_handle);
1554                 if (!cfgs) {
1555                         /* There is no agent configuration.  All agents were destroyed. */
1556                         break;
1557                 }
1558                 cfg_new = ao2_find(cfgs->agents, agent->username, OBJ_KEY);
1559                 ao2_ref(cfgs, -1);
1560                 if (!cfg_new) {
1561                         /* The agent is no longer configured. */
1562                         break;
1563                 }
1564                 agent_lock(agent);
1565                 cfg_old = agent->cfg;
1566                 agent->cfg = cfg_new;
1567
1568                 agent->last_disconnect = ast_tvnow();
1569
1570                 /* Clear out any caller bridge before rejoining the holding bridge. */
1571                 caller_bridge = agent->caller_bridge;
1572                 agent->caller_bridge = NULL;
1573                 agent_unlock(agent);
1574                 ao2_ref(cfg_old, -1);
1575                 if (caller_bridge) {
1576                         ast_bridge_destroy(caller_bridge);
1577                 }
1578
1579                 if (agent->state == AGENT_STATE_LOGGING_OUT
1580                         || agent->deferred_logoff
1581                         || ast_check_hangup_locked(logged)) {
1582                         /* The agent was requested to logout or hungup. */
1583                         break;
1584                 }
1585
1586                 /*
1587                  * It is safe to access agent->waiting_colp without a lock.  It
1588                  * is only setup on agent login and not changed.
1589                  */
1590                 ast_channel_update_connected_line(logged, &agent->waiting_colp, NULL);
1591         }
1592         ast_bridge_features_cleanup(&features);
1593
1594 agent_run_cleanup:
1595         agent_lock(agent);
1596         if (logged != agent->logged) {
1597                 /*
1598                  * We are no longer the agent channel because of local channel
1599                  * optimization.
1600                  */
1601                 agent_unlock(agent);
1602                 ast_debug(1, "Agent %s: Channel %s is no longer the agent.\n",
1603                         agent->username, ast_channel_name(logged));
1604                 return;
1605         }
1606         agent_logout(agent);
1607 }
1608
1609 static void agent_after_bridge_cb(struct ast_channel *chan, void *data)
1610 {
1611         struct agent_pvt *agent;
1612
1613         agent = ao2_find(agents, chan, 0);
1614         if (!agent) {
1615                 return;
1616         }
1617
1618         ast_debug(1, "Agent %s: New agent channel %s.\n",
1619                 agent->username, ast_channel_name(chan));
1620         agent_run(agent, chan);
1621         ao2_ref(agent, -1);
1622 }
1623
1624 static void agent_after_bridge_cb_failed(enum ast_bridge_after_cb_reason reason, void *data)
1625 {
1626         struct ast_channel *chan = data;
1627         struct agent_pvt *agent;
1628
1629         agent = ao2_find(agents, chan, 0);
1630         if (!agent) {
1631                 return;
1632         }
1633         ast_log(LOG_WARNING, "Agent %s: Forced logout.  Lost control of %s because: %s\n",
1634                 agent->username, ast_channel_name(chan),
1635                 ast_bridge_after_cb_reason_string(reason));
1636         agent_lock(agent);
1637         agent_logout(agent);
1638         ao2_ref(agent, -1);
1639 }
1640
1641 /*!
1642  * \internal
1643  * \brief Get the lock on the agent bridge_channel and return it.
1644  * \since 12.0.0
1645  *
1646  * \param agent Whose bridge_channel to get.
1647  *
1648  * \retval bridge_channel on success (Reffed and locked).
1649  * \retval NULL on error.
1650  */
1651 static struct ast_bridge_channel *agent_bridge_channel_get_lock(struct agent_pvt *agent)
1652 {
1653         struct ast_channel *logged;
1654         struct ast_bridge_channel *bc;
1655
1656         for (;;) {
1657                 agent_lock(agent);
1658                 logged = agent->logged;
1659                 if (!logged) {
1660                         agent_unlock(agent);
1661                         return NULL;
1662                 }
1663                 ast_channel_ref(logged);
1664                 agent_unlock(agent);
1665
1666                 ast_channel_lock(logged);
1667                 bc = ast_channel_get_bridge_channel(logged);
1668                 ast_channel_unlock(logged);
1669                 ast_channel_unref(logged);
1670                 if (!bc) {
1671                         if (agent->logged != logged) {
1672                                 continue;
1673                         }
1674                         return NULL;
1675                 }
1676
1677                 ast_bridge_channel_lock(bc);
1678                 if (bc->chan != logged || agent->logged != logged) {
1679                         ast_bridge_channel_unlock(bc);
1680                         ao2_ref(bc, -1);
1681                         continue;
1682                 }
1683                 return bc;
1684         }
1685 }
1686
1687 static void caller_abort_agent(struct agent_pvt *agent)
1688 {
1689         struct ast_bridge_channel *logged;
1690
1691         logged = agent_bridge_channel_get_lock(agent);
1692         if (!logged) {
1693                 struct ast_bridge *caller_bridge;
1694
1695                 ast_debug(1, "Agent '%s' no longer logged in.\n", agent->username);
1696
1697                 agent_lock(agent);
1698                 caller_bridge = agent->caller_bridge;
1699                 agent->caller_bridge = NULL;
1700                 agent_unlock(agent);
1701                 if (caller_bridge) {
1702                         ast_bridge_destroy(caller_bridge);
1703                 }
1704                 return;
1705         }
1706
1707         /* Kick the agent out of the holding bridge to reset it. */
1708         ast_bridge_channel_leave_bridge_nolock(logged, BRIDGE_CHANNEL_STATE_END);
1709         ast_bridge_channel_unlock(logged);
1710 }
1711
1712 static int caller_safety_timeout(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
1713 {
1714         struct agent_pvt *agent = hook_pvt;
1715
1716         if (agent->state == AGENT_STATE_CALL_PRESENT) {
1717                 ast_verb(3, "Agent '%s' did not respond.  Safety timeout.\n", agent->username);
1718                 ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
1719                 caller_abort_agent(agent);
1720         }
1721
1722         return -1;
1723 }
1724
1725 static void agent_alert(struct ast_bridge_channel *bridge_channel, const void *payload, size_t payload_size)
1726 {
1727         const char *agent_id = payload;
1728         const char *playfile;
1729         RAII_VAR(struct agent_pvt *, agent, NULL, ao2_cleanup);
1730
1731         agent = ao2_find(agents, agent_id, OBJ_KEY);
1732         if (!agent) {
1733                 ast_debug(1, "Agent '%s' does not exist.  Where did it go?\n", agent_id);
1734                 return;
1735         }
1736
1737         /* Alert the agent. */
1738         agent_lock(agent);
1739         playfile = ast_strdupa(agent->cfg->beep_sound);
1740         agent_unlock(agent);
1741         ast_stream_and_wait(bridge_channel->chan, playfile, AST_DIGIT_NONE);
1742
1743         agent_lock(agent);
1744         switch (agent->state) {
1745         case AGENT_STATE_CALL_PRESENT:
1746                 if (ast_test_flag(agent, AGENT_FLAG_ACK_CALL)
1747                         ? agent->override_ack_call : agent->cfg->ack_call) {
1748                         agent->state = AGENT_STATE_CALL_WAIT_ACK;
1749                         agent->ack_time = ast_tvnow();
1750                         break;
1751                 }
1752
1753                 /* Connect to caller now. */
1754                 ast_debug(1, "Agent %s: Immediately connecting to call.\n", agent->username);
1755                 agent_connect_caller(bridge_channel, agent);/* Will unlock agent. */
1756                 return;
1757         default:
1758                 break;
1759         }
1760         agent_unlock(agent);
1761 }
1762
1763 static int send_alert_to_agent(struct ast_bridge_channel *bridge_channel, const char *agent_id)
1764 {
1765         return ast_bridge_channel_queue_callback(bridge_channel, agent_alert, agent_id,
1766                 strlen(agent_id) + 1);
1767 }
1768
1769 static int send_colp_to_agent(struct ast_bridge_channel *bridge_channel, struct ast_party_connected_line *connected)
1770 {
1771         struct ast_set_party_connected_line update = {
1772                 .id.name = 1,
1773                 .id.number = 1,
1774                 .id.subaddress = 1,
1775         };
1776         unsigned char data[1024];       /* This should be large enough */
1777         size_t datalen;
1778
1779         datalen = ast_connected_line_build_data(data, sizeof(data), connected, &update);
1780         if (datalen == (size_t) -1) {
1781                 return 0;
1782         }
1783
1784         return ast_bridge_channel_queue_control_data(bridge_channel,
1785                 AST_CONTROL_CONNECTED_LINE, data, datalen);
1786 }
1787
1788 /*!
1789  * \brief Dialplan AgentRequest application to locate an agent to talk with.
1790  *
1791  * \param chan Channel wanting to talk with an agent.
1792  * \param data Application parameters
1793  *
1794  * \retval 0 To continue in dialplan.
1795  * \retval -1 To hangup.
1796  */
1797 static int agent_request_exec(struct ast_channel *chan, const char *data)
1798 {
1799         struct ast_bridge *caller_bridge;
1800         struct ast_bridge_channel *logged;
1801         char *parse;
1802         int res;
1803         struct ast_bridge_features caller_features;
1804         struct ast_party_connected_line connected;
1805         AST_DECLARE_APP_ARGS(args,
1806                 AST_APP_ARG(agent_id);
1807                 AST_APP_ARG(other);             /* Any remaining unused arguments */
1808         );
1809
1810         RAII_VAR(struct agent_pvt *, agent, NULL, ao2_cleanup);
1811
1812         if (bridge_agent_hold_deferred_create()) {
1813                 return -1;
1814         }
1815
1816         parse = ast_strdupa(data);
1817         AST_STANDARD_APP_ARGS(args, parse);
1818
1819         if (ast_strlen_zero(args.agent_id)) {
1820                 ast_log(LOG_WARNING, "AgentRequest requires an AgentId\n");
1821                 return -1;
1822         }
1823
1824         /* Find the agent. */
1825         agent = ao2_find(agents, args.agent_id, OBJ_KEY);
1826         if (!agent) {
1827                 ast_verb(3, "Agent '%s' does not exist.\n", args.agent_id);
1828                 pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "INVALID");
1829                 return 0;
1830         }
1831
1832         if (ast_bridge_features_init(&caller_features)) {
1833                 return -1;
1834         }
1835
1836         /* Add safety timeout hook. */
1837         ao2_ref(agent, +1);
1838         if (ast_bridge_interval_hook(&caller_features, CALLER_SAFETY_TIMEOUT_TIME,
1839                 caller_safety_timeout, agent, __ao2_cleanup, AST_BRIDGE_HOOK_REMOVE_ON_PULL)) {
1840                 ao2_ref(agent, -1);
1841                 ast_bridge_features_cleanup(&caller_features);
1842                 return -1;
1843         }
1844
1845         caller_bridge = ast_bridge_basic_new();
1846         if (!caller_bridge) {
1847                 ast_bridge_features_cleanup(&caller_features);
1848                 return -1;
1849         }
1850
1851         /* Get COLP for agent. */
1852         ast_party_connected_line_init(&connected);
1853         ast_channel_lock(chan);
1854         ast_connected_line_copy_from_caller(&connected, ast_channel_caller(chan));
1855         ast_channel_unlock(chan);
1856
1857         agent_lock(agent);
1858         switch (agent->state) {
1859         case AGENT_STATE_LOGGED_OUT:
1860         case AGENT_STATE_LOGGING_OUT:
1861                 agent_unlock(agent);
1862                 ast_party_connected_line_free(&connected);
1863                 ast_bridge_destroy(caller_bridge);
1864                 ast_bridge_features_cleanup(&caller_features);
1865                 ast_verb(3, "Agent '%s' not logged in.\n", agent->username);
1866                 pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "NOT_LOGGED_IN");
1867                 return 0;
1868         case AGENT_STATE_READY_FOR_CALL:
1869                 ao2_ref(caller_bridge, +1);
1870                 agent->caller_bridge = caller_bridge;
1871                 agent->state = AGENT_STATE_CALL_PRESENT;
1872                 agent->devstate = AST_DEVICE_INUSE;
1873                 break;
1874         default:
1875                 agent_unlock(agent);
1876                 ast_party_connected_line_free(&connected);
1877                 ast_bridge_destroy(caller_bridge);
1878                 ast_bridge_features_cleanup(&caller_features);
1879                 ast_verb(3, "Agent '%s' is busy.\n", agent->username);
1880                 pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "BUSY");
1881                 return 0;
1882         }
1883         agent_unlock(agent);
1884         agent_devstate_changed(agent->username);
1885
1886         logged = agent_bridge_channel_get_lock(agent);
1887         if (!logged) {
1888                 ast_party_connected_line_free(&connected);
1889                 ast_bridge_destroy(caller_bridge);
1890                 ast_bridge_features_cleanup(&caller_features);
1891                 ast_verb(3, "Agent '%s' not logged in.\n", agent->username);
1892                 pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "NOT_LOGGED_IN");
1893                 caller_abort_agent(agent);
1894                 return 0;
1895         }
1896
1897         send_colp_to_agent(logged, &connected);
1898         ast_party_connected_line_free(&connected);
1899
1900         res = send_alert_to_agent(logged, agent->username);
1901         ast_bridge_channel_unlock(logged);
1902         ao2_ref(logged, -1);
1903         if (res) {
1904                 ast_bridge_destroy(caller_bridge);
1905                 ast_bridge_features_cleanup(&caller_features);
1906                 ast_verb(3, "Agent '%s': Failed to alert the agent.\n", agent->username);
1907                 pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "ERROR");
1908                 caller_abort_agent(agent);
1909                 return 0;
1910         }
1911
1912         ast_indicate(chan, AST_CONTROL_RINGING);
1913         ast_bridge_join(caller_bridge, chan, NULL, &caller_features, NULL, 1);
1914         ast_bridge_features_cleanup(&caller_features);
1915
1916         return -1;
1917 }
1918
1919 /*!
1920  * \internal
1921  * \brief Get agent config values from the login channel.
1922  * \since 12.0.0
1923  *
1924  * \param agent What to setup channel config values on.
1925  * \param chan Channel logging in as an agent.
1926  *
1927  * \return Nothing
1928  */
1929 static void agent_login_channel_config(struct agent_pvt *agent, struct ast_channel *chan)
1930 {
1931         struct ast_flags opts = { 0 };
1932         struct ast_party_connected_line connected;
1933         unsigned int override_ack_call = 0;
1934         unsigned int override_auto_logoff = 0;
1935         unsigned int override_wrapup_time = 0;
1936         const char *override_dtmf_accept = NULL;
1937         const char *var;
1938
1939         ast_party_connected_line_init(&connected);
1940
1941         /* Get config values from channel. */
1942         ast_channel_lock(chan);
1943         ast_party_connected_line_copy(&connected, ast_channel_connected(chan));
1944
1945         var = pbx_builtin_getvar_helper(chan, "AGENTACKCALL");
1946         if (!ast_strlen_zero(var)) {
1947                 override_ack_call = ast_true(var) ? 1 : 0;
1948                 ast_set_flag(&opts, AGENT_FLAG_ACK_CALL);
1949         }
1950
1951         var = pbx_builtin_getvar_helper(chan, "AGENTACCEPTDTMF");
1952         if (!ast_strlen_zero(var)) {
1953                 override_dtmf_accept = ast_strdupa(var);
1954                 ast_set_flag(&opts, AGENT_FLAG_DTMF_ACCEPT);
1955         }
1956
1957         var = pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF");
1958         if (!ast_strlen_zero(var)) {
1959                 if (sscanf(var, "%u", &override_auto_logoff) == 1) {
1960                         ast_set_flag(&opts, AGENT_FLAG_AUTO_LOGOFF);
1961                 }
1962         }
1963
1964         var = pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME");
1965         if (!ast_strlen_zero(var)) {
1966                 if (sscanf(var, "%u", &override_wrapup_time) == 1) {
1967                         ast_set_flag(&opts, AGENT_FLAG_WRAPUP_TIME);
1968                 }
1969         }
1970         ast_channel_unlock(chan);
1971
1972         /* Set config values on agent. */
1973         agent_lock(agent);
1974         ast_party_connected_line_free(&agent->waiting_colp);
1975         agent->waiting_colp = connected;
1976
1977         ast_string_field_set(agent, override_dtmf_accept, override_dtmf_accept);
1978         ast_copy_flags(agent, &opts, AST_FLAGS_ALL);
1979         agent->override_auto_logoff = override_auto_logoff;
1980         agent->override_wrapup_time = override_wrapup_time;
1981         agent->override_ack_call = override_ack_call;
1982         agent_unlock(agent);
1983 }
1984
1985 enum AGENT_LOGIN_OPT_FLAGS {
1986         OPT_SILENT = (1 << 0),
1987 };
1988 AST_APP_OPTIONS(agent_login_opts, BEGIN_OPTIONS
1989         AST_APP_OPTION('s', OPT_SILENT),
1990 END_OPTIONS);
1991
1992 /*!
1993  * \brief Dialplan AgentLogin application to log in an agent.
1994  *
1995  * \param chan Channel attempting to login as an agent.
1996  * \param data Application parameters
1997  *
1998  * \retval 0 To continue in dialplan.
1999  * \retval -1 To hangup.
2000  */
2001 static int agent_login_exec(struct ast_channel *chan, const char *data)
2002 {
2003         char *parse;
2004         struct ast_flags opts;
2005         AST_DECLARE_APP_ARGS(args,
2006                 AST_APP_ARG(agent_id);
2007                 AST_APP_ARG(options);
2008                 AST_APP_ARG(other);             /* Any remaining unused arguments */
2009         );
2010
2011         RAII_VAR(struct agent_pvt *, agent, NULL, ao2_cleanup);
2012
2013         if (bridge_agent_hold_deferred_create()) {
2014                 return -1;
2015         }
2016
2017         if (ast_channel_state(chan) != AST_STATE_UP && ast_answer(chan)) {
2018                 return -1;
2019         }
2020
2021         parse = ast_strdupa(data);
2022         AST_STANDARD_APP_ARGS(args, parse);
2023
2024         if (ast_strlen_zero(args.agent_id)) {
2025                 ast_log(LOG_WARNING, "AgentLogin requires an AgentId\n");
2026                 return -1;
2027         }
2028
2029         if (ast_app_parse_options(agent_login_opts, &opts, NULL, args.options)) {
2030                 /* General invalid option syntax. */
2031                 return -1;
2032         }
2033
2034         /* Find the agent. */
2035         agent = ao2_find(agents, args.agent_id, OBJ_KEY);
2036         if (!agent) {
2037                 ast_verb(3, "Agent '%s' does not exist.\n", args.agent_id);
2038                 pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "INVALID");
2039                 return 0;
2040         }
2041
2042         /* Has someone already logged in as this agent already? */
2043         agent_lock(agent);
2044         if (agent->logged) {
2045                 agent_unlock(agent);
2046                 ast_verb(3, "Agent '%s' already logged in.\n", agent->username);
2047                 pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "ALREADY_LOGGED_IN");
2048                 return 0;
2049         }
2050         agent->logged = ast_channel_ref(chan);
2051         agent->last_disconnect = ast_tvnow();
2052         time(&agent->login_start);
2053         agent_unlock(agent);
2054
2055         agent_login_channel_config(agent, chan);
2056
2057         if (!ast_test_flag(&opts, OPT_SILENT)
2058                 && !ast_streamfile(chan, "agent-loginok", ast_channel_language(chan))) {
2059                 ast_waitstream(chan, "");
2060         }
2061
2062         ast_verb(2, "Agent '%s' logged in (format %s/%s)\n", agent->username,
2063                 ast_getformatname(ast_channel_readformat(chan)),
2064                 ast_getformatname(ast_channel_writeformat(chan)));
2065         send_agent_login(chan, agent->username);
2066
2067         agent_run(agent, chan);
2068         return -1;
2069 }
2070
2071 static int agent_function_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
2072 {
2073         char *parse;
2074         struct agent_pvt *agent;
2075         struct ast_channel *logged;
2076         AST_DECLARE_APP_ARGS(args,
2077                 AST_APP_ARG(agentid);
2078                 AST_APP_ARG(item);
2079         );
2080
2081         buf[0] = '\0';
2082
2083         parse = ast_strdupa(data ?: "");
2084         AST_NONSTANDARD_APP_ARGS(args, parse, ':');
2085
2086         if (ast_strlen_zero(args.agentid)) {
2087                 ast_log(LOG_WARNING, "The AGENT function requires an argument - agentid!\n");
2088                 return -1;
2089         }
2090         if (!args.item) {
2091                 args.item = "status";
2092         }
2093
2094         agent = ao2_find(agents, args.agentid, OBJ_KEY);
2095         if (!agent) {
2096                 ast_log(LOG_WARNING, "Agent '%s' not found!\n", args.agentid);
2097                 return -1;
2098         }
2099
2100         agent_lock(agent);
2101         if (!strcasecmp(args.item, "status")) {
2102                 const char *status;
2103
2104                 if (agent->logged) {
2105                         status = "LOGGEDIN";
2106                 } else {
2107                         status = "LOGGEDOUT";
2108                 }
2109                 ast_copy_string(buf, status, len);
2110         } else if (!strcasecmp(args.item, "name")) {
2111                 ast_copy_string(buf, agent->cfg->full_name, len);
2112         } else if (!strcasecmp(args.item, "mohclass")) {
2113                 ast_copy_string(buf, agent->cfg->moh, len);
2114         } else if (!strcasecmp(args.item, "channel")) {
2115                 logged = agent_lock_logged(agent);
2116                 if (logged) {
2117                         char *pos;
2118
2119                         ast_copy_string(buf, ast_channel_name(logged), len);
2120                         ast_channel_unlock(logged);
2121                         ast_channel_unref(logged);
2122
2123                         pos = strrchr(buf, '-');
2124                         if (pos) {
2125                                 *pos = '\0';
2126                         }
2127                 }
2128         } else if (!strcasecmp(args.item, "fullchannel")) {
2129                 logged = agent_lock_logged(agent);
2130                 if (logged) {
2131                         ast_copy_string(buf, ast_channel_name(logged), len);
2132                         ast_channel_unlock(logged);
2133                         ast_channel_unref(logged);
2134                 }
2135         }
2136         agent_unlock(agent);
2137         ao2_ref(agent, -1);
2138
2139         return 0;
2140 }
2141
2142 static struct ast_custom_function agent_function = {
2143         .name = "AGENT",
2144         .read = agent_function_read,
2145 };
2146
2147 struct agent_complete {
2148         /*! Nth match to return. */
2149         int state;
2150         /*! Which match currently on. */
2151         int which;
2152 };
2153
2154 static int complete_agent_search(void *obj, void *arg, void *data, int flags)
2155 {
2156         struct agent_complete *search = data;
2157
2158         if (++search->which > search->state) {
2159                 return CMP_MATCH;
2160         }
2161         return 0;
2162 }
2163
2164 static char *complete_agent(const char *word, int state)
2165 {
2166         char *ret;
2167         struct agent_pvt *agent;
2168         struct agent_complete search = {
2169                 .state = state,
2170         };
2171
2172         agent = ao2_callback_data(agents, ast_strlen_zero(word) ? 0 : OBJ_PARTIAL_KEY,
2173                 complete_agent_search, (char *) word, &search);
2174         if (!agent) {
2175                 return NULL;
2176         }
2177         ret = ast_strdup(agent->username);
2178         ao2_ref(agent, -1);
2179         return ret;
2180 }
2181
2182 static int complete_agent_logoff_search(void *obj, void *arg, void *data, int flags)
2183 {
2184         struct agent_pvt *agent = obj;
2185         struct agent_complete *search = data;
2186
2187         if (!agent->logged) {
2188                 return 0;
2189         }
2190         if (++search->which > search->state) {
2191                 return CMP_MATCH;
2192         }
2193         return 0;
2194 }
2195
2196 static char *complete_agent_logoff(const char *word, int state)
2197 {
2198         char *ret;
2199         struct agent_pvt *agent;
2200         struct agent_complete search = {
2201                 .state = state,
2202         };
2203
2204         agent = ao2_callback_data(agents, ast_strlen_zero(word) ? 0 : OBJ_PARTIAL_KEY,
2205                 complete_agent_logoff_search, (char *) word, &search);
2206         if (!agent) {
2207                 return NULL;
2208         }
2209         ret = ast_strdup(agent->username);
2210         ao2_ref(agent, -1);
2211         return ret;
2212 }
2213
2214 static void agent_show_requested(struct ast_cli_args *a, int online_only)
2215 {
2216 #define FORMAT_HDR "%-8s %-20s %-11s %-30s %s\n"
2217 #define FORMAT_ROW "%-8s %-20s %-11s %-30s %s\n"
2218
2219         struct ao2_iterator iter;
2220         struct agent_pvt *agent;
2221         struct ast_str *out = ast_str_alloca(512);
2222         unsigned int agents_total = 0;
2223         unsigned int agents_logged_in = 0;
2224         unsigned int agents_talking = 0;
2225
2226         ast_cli(a->fd, FORMAT_HDR, "Agent-ID", "Name", "State", "Channel", "Talking with");
2227         iter = ao2_iterator_init(agents, 0);
2228         for (; (agent = ao2_iterator_next(&iter)); ao2_ref(agent, -1)) {
2229                 struct ast_channel *logged;
2230
2231                 ++agents_total;
2232
2233                 agent_lock(agent);
2234                 logged = agent_lock_logged(agent);
2235                 if (logged) {
2236                         const char *talking_with;
2237
2238                         ++agents_logged_in;
2239
2240                         talking_with = pbx_builtin_getvar_helper(logged, "BRIDGEPEER");
2241                         if (!ast_strlen_zero(talking_with)) {
2242                                 ++agents_talking;
2243                         } else {
2244                                 talking_with = "";
2245                         }
2246                         ast_str_set(&out, 0, FORMAT_ROW, agent->username, agent->cfg->full_name,
2247                                 ast_devstate_str(agent->devstate), ast_channel_name(logged), talking_with);
2248                         ast_channel_unlock(logged);
2249                         ast_channel_unref(logged);
2250                 } else {
2251                         ast_str_set(&out, 0, FORMAT_ROW, agent->username, agent->cfg->full_name,
2252                                 ast_devstate_str(agent->devstate), "", "");
2253                 }
2254                 agent_unlock(agent);
2255
2256                 if (!online_only || logged) {
2257                         ast_cli(a->fd, "%s", ast_str_buffer(out));
2258                 }
2259         }
2260         ao2_iterator_destroy(&iter);
2261
2262         ast_cli(a->fd, "\nDefined agents: %u, Logged in: %u, Talking: %u\n",
2263                 agents_total, agents_logged_in, agents_talking);
2264
2265 #undef FORMAT_HDR
2266 #undef FORMAT_ROW
2267 }
2268
2269 static char *agent_handle_show_online(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2270 {
2271         switch (cmd) {
2272         case CLI_INIT:
2273                 e->command = "agent show online";
2274                 e->usage =
2275                         "Usage: agent show online\n"
2276                         "       Provides summary information for logged in agents.\n";
2277                 return NULL;
2278         case CLI_GENERATE:
2279                 return NULL;
2280         }
2281
2282         if (a->argc != 3) {
2283                 return CLI_SHOWUSAGE;
2284         }
2285
2286         agent_show_requested(a, 1);
2287
2288         return CLI_SUCCESS;
2289 }
2290
2291 static char *agent_handle_show_all(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2292 {
2293         switch (cmd) {
2294         case CLI_INIT:
2295                 e->command = "agent show all";
2296                 e->usage =
2297                         "Usage: agent show all\n"
2298                         "       Provides summary information for all agents.\n";
2299                 return NULL;
2300         case CLI_GENERATE:
2301                 return NULL;
2302         }
2303
2304         if (a->argc != 3) {
2305                 return CLI_SHOWUSAGE;
2306         }
2307
2308         agent_show_requested(a, 0);
2309
2310         return CLI_SUCCESS;
2311 }
2312
2313 static char *agent_handle_show_specific(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2314 {
2315         struct agent_pvt *agent;
2316         struct ast_channel *logged;
2317         struct ast_str *out = ast_str_alloca(4096);
2318
2319         switch (cmd) {
2320         case CLI_INIT:
2321                 e->command = "agent show";
2322                 e->usage =
2323                         "Usage: agent show <agent-id>\n"
2324                         "       Show information about the <agent-id> agent\n";
2325                 return NULL;
2326         case CLI_GENERATE:
2327                 if (a->pos == 2) {
2328                         return complete_agent(a->word, a->n);
2329                 }
2330                 return NULL;
2331         }
2332
2333         if (a->argc != 3) {
2334                 return CLI_SHOWUSAGE;
2335         }
2336
2337         agent = ao2_find(agents, a->argv[2], OBJ_KEY);
2338         if (!agent) {
2339                 ast_cli(a->fd, "Agent '%s' not found\n", a->argv[2]);
2340                 return CLI_SUCCESS;
2341         }
2342
2343         agent_lock(agent);
2344         logged = agent_lock_logged(agent);
2345         ast_str_set(&out, 0, "Id: %s\n", agent->username);
2346         ast_str_append(&out, 0, "Name: %s\n", agent->cfg->full_name);
2347         ast_str_append(&out, 0, "Beep: %s\n", agent->cfg->beep_sound);
2348         ast_str_append(&out, 0, "MOH: %s\n", agent->cfg->moh);
2349         ast_str_append(&out, 0, "RecordCalls: %s\n", AST_CLI_YESNO(agent->cfg->record_agent_calls));
2350         ast_str_append(&out, 0, "State: %s\n", ast_devstate_str(agent->devstate));
2351         if (logged) {
2352                 const char *talking_with;
2353
2354                 ast_str_append(&out, 0, "LoggedInChannel: %s\n", ast_channel_name(logged));
2355                 ast_str_append(&out, 0, "LoggedInTime: %ld\n", (long) agent->login_start);
2356                 talking_with = pbx_builtin_getvar_helper(logged, "BRIDGEPEER");
2357                 if (!ast_strlen_zero(talking_with)) {
2358                         ast_str_append(&out, 0, "TalkingWith: %s\n", talking_with);
2359                         ast_str_append(&out, 0, "CallStarted: %ld\n", (long) agent->call_start);
2360                 }
2361                 ast_channel_unlock(logged);
2362                 ast_channel_unref(logged);
2363         }
2364         agent_unlock(agent);
2365         ao2_ref(agent, -1);
2366
2367         ast_cli(a->fd, "%s", ast_str_buffer(out));
2368
2369         return CLI_SUCCESS;
2370 }
2371
2372 static char *agent_handle_logoff_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2373 {
2374         switch (cmd) {
2375         case CLI_INIT:
2376                 e->command = "agent logoff";
2377                 e->usage =
2378                         "Usage: agent logoff <agent-id> [soft]\n"
2379                         "       Sets an agent as no longer logged in.\n"
2380                         "       If 'soft' is specified, do not hangup existing calls.\n";
2381                 return NULL;
2382         case CLI_GENERATE:
2383                 if (a->pos == 2) {
2384                         return complete_agent_logoff(a->word, a->n);
2385                 } else if (a->pos == 3 && a->n == 0
2386                         && (ast_strlen_zero(a->word)
2387                                 || !strncasecmp("soft", a->word, strlen(a->word)))) {
2388                         return ast_strdup("soft");
2389                 }
2390                 return NULL;
2391         }
2392
2393         if (a->argc < 3 || 4 < a->argc) {
2394                 return CLI_SHOWUSAGE;
2395         }
2396         if (a->argc == 4 && strcasecmp(a->argv[3], "soft")) {
2397                 return CLI_SHOWUSAGE;
2398         }
2399
2400         if (!agent_logoff_request(a->argv[2], a->argc == 4)) {
2401                 ast_cli(a->fd, "Logging out %s\n", a->argv[2]);
2402         }
2403
2404         return CLI_SUCCESS;
2405 }
2406
2407 static struct ast_cli_entry cli_agents[] = {
2408         AST_CLI_DEFINE(agent_handle_show_online, "Show status of online agents"),
2409         AST_CLI_DEFINE(agent_handle_show_all, "Show status of all agents"),
2410         AST_CLI_DEFINE(agent_handle_show_specific, "Show information about an agent"),
2411         AST_CLI_DEFINE(agent_handle_logoff_cmd, "Sets an agent offline"),
2412 };
2413
2414 static int action_agents(struct mansession *s, const struct message *m)
2415 {
2416         const char *id = astman_get_header(m, "ActionID");
2417         char id_text[AST_MAX_BUF];
2418         struct ao2_iterator iter;
2419         struct agent_pvt *agent;
2420         struct ast_str *out = ast_str_alloca(4096);
2421
2422         if (!ast_strlen_zero(id)) {
2423                 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
2424         } else {
2425                 id_text[0] = '\0';
2426         }
2427         astman_send_ack(s, m, "Agents will follow");
2428
2429         iter = ao2_iterator_init(agents, 0);
2430         for (; (agent = ao2_iterator_next(&iter)); ao2_ref(agent, -1)) {
2431                 struct ast_channel *logged;
2432
2433                 agent_lock(agent);
2434                 logged = agent_lock_logged(agent);
2435
2436                 /*
2437                  * Status Values:
2438                  * AGENT_LOGGEDOFF - Agent isn't logged in
2439                  * AGENT_IDLE      - Agent is logged in, and waiting for call
2440                  * AGENT_ONCALL    - Agent is logged in, and on a call
2441                  * AGENT_UNKNOWN   - Don't know anything about agent. Shouldn't ever get this.
2442                  */
2443                 ast_str_set(&out, 0, "Agent: %s\r\n", agent->username);
2444                 ast_str_append(&out, 0, "Name: %s\r\n", agent->cfg->full_name);
2445
2446                 if (logged) {
2447                         const char *talking_to_chan;
2448                         struct ast_str *logged_headers;
2449                         RAII_VAR(struct ast_channel_snapshot *, logged_snapshot, ast_channel_snapshot_create(logged), ao2_cleanup);
2450
2451                         if (!logged_snapshot
2452                                 || !(logged_headers =
2453                                          ast_manager_build_channel_state_string(logged_snapshot))) {
2454                                 ast_channel_unlock(logged);
2455                                 ast_channel_unref(logged);
2456                                 agent_unlock(agent);
2457                                 continue;
2458                         }
2459
2460                         talking_to_chan = pbx_builtin_getvar_helper(logged, "BRIDGEPEER");
2461                         if (!ast_strlen_zero(talking_to_chan)) {
2462                                 ast_str_append(&out, 0, "Status: %s\r\n", "AGENT_ONCALL");
2463                                 ast_str_append(&out, 0, "TalkingToChan: %s\r\n", talking_to_chan);
2464                                 ast_str_append(&out, 0, "CallStarted: %ld\n", (long) agent->call_start);
2465                         } else {
2466                                 ast_str_append(&out, 0, "Status: %s\r\n", "AGENT_IDLE");
2467                         }
2468                         ast_str_append(&out, 0, "LoggedInTime: %ld\r\n", (long) agent->login_start);
2469                         ast_str_append(&out, 0, "%s", ast_str_buffer(logged_headers));
2470                         ast_channel_unlock(logged);
2471                         ast_channel_unref(logged);
2472                         ast_free(logged_headers);
2473                 } else {
2474                         ast_str_append(&out, 0, "Status: %s\r\n", "AGENT_LOGGEDOFF");
2475                 }
2476
2477                 agent_unlock(agent);
2478
2479                 astman_append(s, "Event: Agents\r\n"
2480                         "%s%s\r\n",
2481                         ast_str_buffer(out), id_text);
2482         }
2483         ao2_iterator_destroy(&iter);
2484
2485         astman_append(s, "Event: AgentsComplete\r\n"
2486                 "%s"
2487                 "\r\n", id_text);
2488         return 0;
2489 }
2490
2491 static int action_agent_logoff(struct mansession *s, const struct message *m)
2492 {
2493         const char *agent = astman_get_header(m, "Agent");
2494         const char *soft_s = astman_get_header(m, "Soft"); /* "true" is don't hangup */
2495
2496         if (ast_strlen_zero(agent)) {
2497                 astman_send_error(s, m, "No agent specified");
2498                 return 0;
2499         }
2500
2501         if (!agent_logoff_request(agent, ast_true(soft_s))) {
2502                 astman_send_ack(s, m, "Agent logged out");
2503         } else {
2504                 astman_send_error(s, m, "No such agent");
2505         }
2506
2507         return 0;
2508 }
2509
2510 static int unload_module(void)
2511 {
2512         struct ast_bridge *holding;
2513
2514         /* Unregister dialplan applications */
2515         ast_unregister_application(app_agent_login);
2516         ast_unregister_application(app_agent_request);
2517
2518         /* Unregister dialplan functions */
2519         ast_custom_function_unregister(&agent_function);
2520
2521         /* Unregister manager command */
2522         ast_manager_unregister("Agents");
2523         ast_manager_unregister("AgentLogoff");
2524
2525         /* Unregister CLI commands */
2526         ast_cli_unregister_multiple(cli_agents, ARRAY_LEN(cli_agents));
2527
2528         ast_devstate_prov_del("Agent");
2529
2530         /* Destroy agent holding bridge. */
2531         holding = ao2_global_obj_replace(agent_holding, NULL);
2532         if (holding) {
2533                 ast_bridge_destroy(holding);
2534         }
2535
2536         destroy_config();
2537         ao2_ref(agents, -1);
2538         agents = NULL;
2539         return 0;
2540 }
2541
2542 static int load_module(void)
2543 {
2544         int res = 0;
2545
2546         agents = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_MUTEX,
2547                 AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, agent_pvt_sort_cmp, agent_pvt_cmp);
2548         if (!agents) {
2549                 return AST_MODULE_LOAD_FAILURE;
2550         }
2551         if (load_config()) {
2552                 ast_log(LOG_ERROR, "Unable to load config. Not loading module.\n");
2553                 ao2_ref(agents, -1);
2554                 agents = NULL;
2555                 return AST_MODULE_LOAD_DECLINE;
2556         }
2557
2558         /* Init agent holding bridge v_table. */
2559         bridge_init_agent_hold();
2560
2561         /* Setup to provide Agent:agent-id device state. */
2562         res |= ast_devstate_prov_add("Agent", agent_pvt_devstate_get);
2563
2564         /* CLI Commands */
2565         res |= ast_cli_register_multiple(cli_agents, ARRAY_LEN(cli_agents));
2566
2567         /* Manager commands */
2568         res |= ast_manager_register_xml("Agents", EVENT_FLAG_AGENT, action_agents);
2569         res |= ast_manager_register_xml("AgentLogoff", EVENT_FLAG_AGENT, action_agent_logoff);
2570
2571         /* Dialplan Functions */
2572         res |= ast_custom_function_register(&agent_function);
2573
2574         /* Dialplan applications */
2575         res |= ast_register_application_xml(app_agent_login, agent_login_exec);
2576         res |= ast_register_application_xml(app_agent_request, agent_request_exec);
2577
2578         if (res) {
2579                 unload_module();
2580                 return AST_MODULE_LOAD_FAILURE;
2581         }
2582         return AST_MODULE_LOAD_SUCCESS;
2583 }
2584
2585 static int reload(void)
2586 {
2587         if (aco_process_config(&cfg_info, 1) == ACO_PROCESS_ERROR) {
2588                 /* Just keep the config we already have in place. */
2589                 return -1;
2590         }
2591         return 0;
2592 }
2593
2594 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Call center agent pool applications",
2595         .load = load_module,
2596         .unload = unload_module,
2597         .reload = reload,
2598         .load_pri = AST_MODPRI_DEVSTATE_PROVIDER,
2599 );