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