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