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