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