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