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