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