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