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