Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Enumerations | Functions | Variables
app_agent_pool.c File Reference

Call center agent pool. More...

#include "asterisk.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/bridge.h"
#include "asterisk/bridge_internal.h"
#include "asterisk/bridge_basic.h"
#include "asterisk/bridge_after.h"
#include "asterisk/config_options.h"
#include "asterisk/features_config.h"
#include "asterisk/astobj2.h"
#include "asterisk/stringfields.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/causes.h"
Include dependency graph for app_agent_pool.c:

Go to the source code of this file.

Data Structures

struct  agent_cfg
 
struct  agent_complete
 
struct  agent_pvt
 Structure representing an agent. More...
 
struct  agents_cfg
 

Macros

#define agent_lock(agent)   _agent_lock(agent, __FILE__, __PRETTY_FUNCTION__, __LINE__, #agent)
 Lock the agent. More...
 
#define agent_unlock(agent)   _agent_unlock(agent, __FILE__, __PRETTY_FUNCTION__, __LINE__, #agent)
 Unlock the agent. More...
 
#define AST_MAX_BUF   256
 
#define CALLER_SAFETY_TIMEOUT_TIME   (2 * 60 * 1000)
 
#define FORMAT_HDR   "%-8s %-20s %-11s %-30s %s\n"
 
#define FORMAT_ROW   "%-8s %-20s %-11s %-30s %s\n"
 
#define LOGIN_WAIT_TIMEOUT_TIME   5
 

Enumerations

enum  AGENT_LOGIN_OPT_FLAGS { OPT_SILENT = (1 << 0) }
 
enum  agent_override_flags { AGENT_FLAG_ACK_CALL = (1 << 0), AGENT_FLAG_DTMF_ACCEPT = (1 << 1), AGENT_FLAG_AUTO_LOGOFF = (1 << 2), AGENT_FLAG_WRAPUP_TIME = (1 << 3) }
 
enum  agent_state {
  AGENT_STATE_LOGGED_OUT, AGENT_STATE_PROBATION_WAIT, AGENT_STATE_READY_FOR_CALL, AGENT_STATE_CALL_PRESENT,
  AGENT_STATE_CALL_WAIT_ACK, AGENT_STATE_ON_CALL, AGENT_STATE_CALL_WRAPUP, AGENT_STATE_LOGGING_OUT
}
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static void _agent_lock (struct agent_pvt *agent, const char *file, const char *function, int line, const char *var)
 
static void _agent_unlock (struct agent_pvt *agent, const char *file, const char *function, int line, const char *var)
 
static int action_agent_logoff (struct mansession *s, const struct message *m)
 
static int action_agents (struct mansession *s, const struct message *m)
 
static void agent_after_bridge_cb (struct ast_channel *chan, void *data)
 
static void agent_after_bridge_cb_failed (enum ast_bridge_after_cb_reason reason, void *data)
 
static void agent_alert (struct ast_bridge_channel *bridge_channel, const void *payload, size_t payload_size)
 
static struct ast_bridge_channelagent_bridge_channel_get_lock (struct agent_pvt *agent)
 
static void * agent_cfg_alloc (const char *name)
 
static void agent_cfg_destructor (void *vdoomed)
 
static void * agent_cfg_find (struct ao2_container *agents, const char *username)
 
static int agent_cfg_sort_cmp (const void *obj_left, const void *obj_right, int flags)
 
static void agent_connect_caller (struct ast_bridge_channel *bridge_channel, struct agent_pvt *agent)
 
static void agent_devstate_changed (const char *agent_id)
 
static int agent_function_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 
static char * agent_handle_logoff_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * agent_handle_show_all (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * agent_handle_show_online (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * agent_handle_show_specific (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static struct ast_channelagent_lock_logged (struct agent_pvt *agent)
 
static void agent_login_channel_config (struct agent_pvt *agent, struct ast_channel *chan)
 
static int agent_login_exec (struct ast_channel *chan, const char *data)
 Dialplan AgentLogin application to log in an agent. More...
 
static int agent_logoff_request (const char *agent_id, int soft)
 
static void agent_logout (struct agent_pvt *agent)
 
static int agent_mark (void *obj, void *arg, int flags)
 
static int agent_pvt_cmp (void *obj, void *arg, int flags)
 
static void agent_pvt_destructor (void *vdoomed)
 
static enum ast_device_state agent_pvt_devstate_get (const char *agent_id)
 
static struct agent_pvtagent_pvt_new (struct agent_cfg *cfg)
 
static int agent_pvt_sort_cmp (const void *obj_left, const void *obj_right, int flags)
 
static int agent_request_exec (struct ast_channel *chan, const char *data)
 Dialplan AgentRequest application to locate an agent to talk with. More...
 
static void agent_run (struct agent_pvt *agent, struct ast_channel *logged)
 
static void agent_show_requested (struct ast_cli_args *a, int online_only)
 
static int agent_sweep (void *obj, void *arg, int flags)
 
static void * agents_cfg_alloc (void)
 
static void agents_cfg_destructor (void *vdoomed)
 
static void agents_mark (void)
 
static void agents_post_apply_config (void)
 
static void agents_sweep (void)
 
static AO2_GLOBAL_OBJ_STATIC (cfg_handle)
 
static AO2_GLOBAL_OBJ_STATIC (agent_holding)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int bridge_agent_hold_ack (struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 
static int bridge_agent_hold_deferred_create (void)
 
static void bridge_agent_hold_dissolving (struct ast_bridge *self)
 The bridge is being dissolved. More...
 
static int bridge_agent_hold_heartbeat (struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 
static struct ast_bridgebridge_agent_hold_new (void)
 
static void bridge_agent_hold_pull (struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)
 
static int bridge_agent_hold_push (struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
 
static void bridge_init_agent_hold (void)
 
static void caller_abort_agent (struct agent_pvt *agent)
 
static int caller_joined_bridge (struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 
static int caller_safety_timeout (struct ast_bridge_channel *bridge_channel, void *hook_pvt)
 
static void clear_agent_status (struct ast_bridge_channel *bridge_channel, const void *payload, size_t payload_size)
 
static char * complete_agent (const char *word, int state)
 
static char * complete_agent_logoff (const char *word, int state)
 
static int complete_agent_logoff_search (void *obj, void *arg, void *data, int flags)
 
static int complete_agent_search (void *obj, void *arg, void *data, int flags)
 
 CONFIG_INFO_STANDARD (cfg_info, cfg_handle, agents_cfg_alloc,.files=ACO_FILES(&agents_conf),.post_apply_config=agents_post_apply_config,)
 
static void destroy_config (void)
 
static int load_config (void)
 
static int load_module (void)
 
static int reload (void)
 
static void send_agent_login (struct ast_channel *chan, const char *agent)
 
static void send_agent_logoff (struct ast_channel *chan, const char *agent, long logintime)
 
static int send_alert_to_agent (struct ast_bridge_channel *bridge_channel, const char *agent_id)
 
static int send_colp_to_agent (struct ast_bridge_channel *bridge_channel, struct ast_party_connected_line *connected)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Call center agent pool applications" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_DEVSTATE_PROVIDER, }
 
static struct ast_custom_function agent_function
 
static ast_mutex_t agent_holding_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
 
static const struct ast_app_option agent_login_opts [128] = { [ 's' ] = { .flag = OPT_SILENT }, }
 
static struct aco_type agent_type
 
static const char * agent_type_blacklist []
 
static struct aco_typeagent_types [] = ACO_TYPES(&agent_type)
 
static struct ao2_containeragents
 
static struct aco_file agents_conf
 
static const char app_agent_login [] = "AgentLogin"
 
static const char app_agent_request [] = "AgentRequest"
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_bridge_methods bridge_agent_hold_v_table
 
static struct ast_cli_entry cli_agents []
 
static struct aco_type general_type
 

Detailed Description

Call center agent pool.

Author
Richard Mudgett rmudg.nosp@m.ett@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

See Also:

Definition in file app_agent_pool.c.

Macro Definition Documentation

◆ agent_lock

#define agent_lock (   agent)    _agent_lock(agent, __FILE__, __PRETTY_FUNCTION__, __LINE__, #agent)

◆ agent_unlock

#define agent_unlock (   agent)    _agent_unlock(agent, __FILE__, __PRETTY_FUNCTION__, __LINE__, #agent)

◆ AST_MAX_BUF

#define AST_MAX_BUF   256

Definition at line 336 of file app_agent_pool.c.

Referenced by action_agents().

◆ CALLER_SAFETY_TIMEOUT_TIME

#define CALLER_SAFETY_TIMEOUT_TIME   (2 * 60 * 1000)

Maximum wait time (in ms) for the custom_beep file to play announcing the caller.

Definition at line 339 of file app_agent_pool.c.

Referenced by agent_request_exec().

◆ FORMAT_HDR

#define FORMAT_HDR   "%-8s %-20s %-11s %-30s %s\n"

Referenced by agent_show_requested().

◆ FORMAT_ROW

#define FORMAT_ROW   "%-8s %-20s %-11s %-30s %s\n"

Referenced by agent_show_requested().

◆ LOGIN_WAIT_TIMEOUT_TIME

#define LOGIN_WAIT_TIMEOUT_TIME   5

Number of seconds to wait for local channel optimizations to complete.

Definition at line 342 of file app_agent_pool.c.

Referenced by bridge_agent_hold_heartbeat().

Enumeration Type Documentation

◆ AGENT_LOGIN_OPT_FLAGS

Enumerator
OPT_SILENT 

Definition at line 2096 of file app_agent_pool.c.

2096  {
2097  OPT_SILENT = (1 << 0),
2098 };

◆ agent_override_flags

Agent config option override flags.

Enumerator
AGENT_FLAG_ACK_CALL 
AGENT_FLAG_DTMF_ACCEPT 
AGENT_FLAG_AUTO_LOGOFF 
AGENT_FLAG_WRAPUP_TIME 

Definition at line 586 of file app_agent_pool.c.

◆ agent_state

Enumerator
AGENT_STATE_LOGGED_OUT 

The agent is defined but an agent is not present.

AGENT_STATE_PROBATION_WAIT 

Forced initial login wait to allow any local channel optimizations to happen.

AGENT_STATE_READY_FOR_CALL 

The agent is ready for a call.

AGENT_STATE_CALL_PRESENT 

The agent has a call waiting to connect.

AGENT_STATE_CALL_WAIT_ACK 

The agent needs to ack the call.

AGENT_STATE_ON_CALL 

The agent is connected with a call.

AGENT_STATE_CALL_WRAPUP 

The agent is resting between calls.

AGENT_STATE_LOGGING_OUT 

The agent is being kicked out.

Definition at line 566 of file app_agent_pool.c.

566  {
567  /*! The agent is defined but an agent is not present. */
569  /*! Forced initial login wait to allow any local channel optimizations to happen. */
571  /*! The agent is ready for a call. */
573  /*! The agent has a call waiting to connect. */
575  /*! The agent needs to ack the call. */
577  /*! The agent is connected with a call. */
579  /*! The agent is resting between calls. */
581  /*! The agent is being kicked out. */
583 };

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 2716 of file app_agent_pool.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 2716 of file app_agent_pool.c.

◆ _agent_lock()

static void _agent_lock ( struct agent_pvt agent,
const char *  file,
const char *  function,
int  line,
const char *  var 
)
inlinestatic

Definition at line 659 of file app_agent_pool.c.

References __ao2_lock(), and AO2_LOCK_REQ_MUTEX.

660 {
661  __ao2_lock(agent, AO2_LOCK_REQ_MUTEX, file, function, line, var);
662 }
int __ao2_lock(void *a, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
Lock an object.
Definition: astobj2.c:222
#define var
Definition: ast_expr2f.c:614

◆ _agent_unlock()

static void _agent_unlock ( struct agent_pvt agent,
const char *  file,
const char *  function,
int  line,
const char *  var 
)
inlinestatic

Definition at line 672 of file app_agent_pool.c.

References __ao2_unlock().

673 {
674  __ao2_unlock(agent, file, function, line, var);
675 }
#define var
Definition: ast_expr2f.c:614
int __ao2_unlock(void *a, const char *file, const char *func, int line, const char *var)
Unlock an object.
Definition: astobj2.c:288

◆ action_agent_logoff()

static int action_agent_logoff ( struct mansession s,
const struct message m 
)
static

Definition at line 2605 of file app_agent_pool.c.

References agent_logoff_request(), ast_strlen_zero, ast_true(), astman_get_header(), astman_send_ack(), and astman_send_error().

Referenced by load_module().

2606 {
2607  const char *agent = astman_get_header(m, "Agent");
2608  const char *soft_s = astman_get_header(m, "Soft"); /* "true" is don't hangup */
2609 
2610  if (ast_strlen_zero(agent)) {
2611  astman_send_error(s, m, "No agent specified");
2612  return 0;
2613  }
2614 
2615  if (!agent_logoff_request(agent, ast_true(soft_s))) {
2616  astman_send_ack(s, m, "Agent logged out");
2617  } else {
2618  astman_send_error(s, m, "No such agent");
2619  }
2620 
2621  return 0;
2622 }
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strlen_zero(foo)
Definition: strings.h:52
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
static int agent_logoff_request(const char *agent_id, int soft)
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159

◆ action_agents()

static int action_agents ( struct mansession s,
const struct message m 
)
static

Definition at line 2527 of file app_agent_pool.c.

References agent_lock, agent_lock_logged(), agent_unlock, ao2_cleanup, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_channel_snapshot_create(), ast_channel_unlock, ast_channel_unref, ast_free, ast_manager_build_channel_state_string(), AST_MAX_BUF, ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_str_set(), ast_strlen_zero, astman_append(), astman_get_header(), astman_send_list_complete_end(), astman_send_list_complete_start(), astman_send_listack(), agent_pvt::call_start, agent_pvt::cfg, agent_cfg::full_name, agent_pvt::login_start, out, pbx_builtin_getvar_helper(), RAII_VAR, and agent_pvt::username.

Referenced by load_module().

2528 {
2529  const char *id = astman_get_header(m, "ActionID");
2530  char id_text[AST_MAX_BUF];
2531  struct ao2_iterator iter;
2532  struct agent_pvt *agent;
2533  struct ast_str *out = ast_str_alloca(4096);
2534  int num_agents = 0;
2535 
2536  if (!ast_strlen_zero(id)) {
2537  snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
2538  } else {
2539  id_text[0] = '\0';
2540  }
2541  astman_send_listack(s, m, "Agents will follow", "start");
2542 
2543  iter = ao2_iterator_init(agents, 0);
2544  for (; (agent = ao2_iterator_next(&iter)); ao2_ref(agent, -1)) {
2545  struct ast_channel *logged;
2546 
2547  agent_lock(agent);
2548  logged = agent_lock_logged(agent);
2549 
2550  /*
2551  * Status Values:
2552  * AGENT_LOGGEDOFF - Agent isn't logged in
2553  * AGENT_IDLE - Agent is logged in, and waiting for call
2554  * AGENT_ONCALL - Agent is logged in, and on a call
2555  * AGENT_UNKNOWN - Don't know anything about agent. Shouldn't ever get this.
2556  */
2557  ast_str_set(&out, 0, "Agent: %s\r\n", agent->username);
2558  ast_str_append(&out, 0, "Name: %s\r\n", agent->cfg->full_name);
2559 
2560  if (logged) {
2561  const char *talking_to_chan;
2562  struct ast_str *logged_headers;
2563  RAII_VAR(struct ast_channel_snapshot *, logged_snapshot, ast_channel_snapshot_create(logged), ao2_cleanup);
2564 
2565  if (!logged_snapshot
2566  || !(logged_headers =
2567  ast_manager_build_channel_state_string(logged_snapshot))) {
2568  ast_channel_unlock(logged);
2569  ast_channel_unref(logged);
2570  agent_unlock(agent);
2571  continue;
2572  }
2573 
2574  talking_to_chan = pbx_builtin_getvar_helper(logged, "BRIDGEPEER");
2575  if (!ast_strlen_zero(talking_to_chan)) {
2576  ast_str_append(&out, 0, "Status: %s\r\n", "AGENT_ONCALL");
2577  ast_str_append(&out, 0, "TalkingToChan: %s\r\n", talking_to_chan);
2578  ast_str_append(&out, 0, "CallStarted: %ld\n", (long) agent->call_start);
2579  } else {
2580  ast_str_append(&out, 0, "Status: %s\r\n", "AGENT_IDLE");
2581  }
2582  ast_str_append(&out, 0, "LoggedInTime: %ld\r\n", (long) agent->login_start);
2583  ast_str_append(&out, 0, "%s", ast_str_buffer(logged_headers));
2584  ast_channel_unlock(logged);
2585  ast_channel_unref(logged);
2586  ast_free(logged_headers);
2587  } else {
2588  ast_str_append(&out, 0, "Status: %s\r\n", "AGENT_LOGGEDOFF");
2589  }
2590 
2591  agent_unlock(agent);
2592 
2593  astman_append(s, "Event: Agents\r\n"
2594  "%s%s\r\n",
2595  ast_str_buffer(out), id_text);
2596  ++num_agents;
2597  }
2598  ao2_iterator_destroy(&iter);
2599 
2600  astman_send_list_complete_start(s, m, "AgentsComplete", num_agents);
2602  return 0;
2603 }
Main Channel structure associated with a channel.
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
const ast_string_field full_name
#define agent_unlock(agent)
Unlock the agent.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:3237
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
Structure representing a snapshot of channel state.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ast_str_alloca(init_len)
Definition: strings.h:800
struct ast_channel_snapshot * ast_channel_snapshot_create(struct ast_channel *chan)
Generate a snapshot of the channel state. This is an ao2 object, so ao2_cleanup() to deallocate...
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strlen_zero(foo)
Definition: strings.h:52
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
#define AST_MAX_BUF
#define agent_lock(agent)
Lock the agent.
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:3245
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
const ast_string_field username
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct ast_channel * agent_lock_logged(struct agent_pvt *agent)
struct ast_str * ast_manager_build_channel_state_string(const struct ast_channel_snapshot *snapshot)
Generate the AMI message body from a channel snapshot.
struct agent_cfg * cfg
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
time_t login_start
Structure representing an agent.
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_free(a)
Definition: astmm.h:182
FILE * out
Definition: utils/frame.c:33
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
time_t call_start
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
static struct ao2_container * agents
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:3201

◆ agent_after_bridge_cb()

static void agent_after_bridge_cb ( struct ast_channel chan,
void *  data 
)
static

Definition at line 1618 of file app_agent_pool.c.

References agent_run(), ao2_find, ao2_ref, ast_channel_name(), ast_debug, and agent_pvt::username.

Referenced by bridge_agent_hold_heartbeat().

1619 {
1620  struct agent_pvt *agent;
1621 
1622  agent = ao2_find(agents, chan, 0);
1623  if (!agent) {
1624  return;
1625  }
1626 
1627  ast_debug(1, "Agent %s: New agent channel %s.\n",
1628  agent->username, ast_channel_name(chan));
1629  agent_run(agent, chan);
1630  ao2_ref(agent, -1);
1631 }
static void agent_run(struct agent_pvt *agent, struct ast_channel *logged)
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
const ast_string_field username
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Structure representing an agent.
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
const char * ast_channel_name(const struct ast_channel *chan)
static struct ao2_container * agents

◆ agent_after_bridge_cb_failed()

static void agent_after_bridge_cb_failed ( enum ast_bridge_after_cb_reason  reason,
void *  data 
)
static

Definition at line 1633 of file app_agent_pool.c.

References agent_lock, agent_logout(), ao2_find, ao2_ref, ast_bridge_after_cb_reason_string(), ast_channel_name(), ast_log, ast_channel::data, LOG_WARNING, and agent_pvt::username.

Referenced by bridge_agent_hold_heartbeat().

1634 {
1635  struct ast_channel *chan = data;
1636  struct agent_pvt *agent;
1637 
1638  agent = ao2_find(agents, chan, 0);
1639  if (!agent) {
1640  return;
1641  }
1642  ast_log(LOG_WARNING, "Agent %s: Forced logout. Lost control of %s because: %s\n",
1643  agent->username, ast_channel_name(chan),
1645  agent_lock(agent);
1646  agent_logout(agent);
1647  ao2_ref(agent, -1);
1648 }
Main Channel structure associated with a channel.
const char * ast_bridge_after_cb_reason_string(enum ast_bridge_after_cb_reason reason)
Get a string representation of an after bridge callback reason.
Definition: bridge_after.c:296
#define LOG_WARNING
Definition: logger.h:274
const char * data
#define agent_lock(agent)
Lock the agent.
#define ast_log
Definition: astobj2.c:42
const ast_string_field username
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static void agent_logout(struct agent_pvt *agent)
Structure representing an agent.
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
const char * ast_channel_name(const struct ast_channel *chan)
static struct ao2_container * agents

◆ agent_alert()

static void agent_alert ( struct ast_bridge_channel bridge_channel,
const void *  payload,
size_t  payload_size 
)
static

Definition at line 1738 of file app_agent_pool.c.

References agent_cfg::ack_call, agent_pvt::ack_time, agent_connect_caller(), AGENT_FLAG_ACK_CALL, AGENT_FLAG_DTMF_ACCEPT, agent_lock, AGENT_STATE_CALL_PRESENT, AGENT_STATE_CALL_WAIT_ACK, agent_unlock, ao2_find, ao2_ref, ast_bridge_channel_clear_roles(), ast_bridge_channel_establish_roles(), ast_bridge_channel_feature_digit(), ast_bridge_channel_lock_bridge(), ast_bridge_unlock, ast_channel_set_bridge_role_option(), ast_debug, AST_DIGIT_ANY, ast_stopstream(), ast_strdupa, ast_stream_and_wait(), ast_strlen_zero, ast_test_flag, ast_tvnow(), agent_cfg::beep_sound, ast_bridge_channel::bridge, agent_pvt::cfg, ast_bridge_channel::chan, digit, agent_cfg::dtmf_accept, NULL, OBJ_KEY, agent_pvt::override_ack_call, agent_pvt::override_dtmf_accept, agent_pvt::state, and agent_pvt::username.

Referenced by send_alert_to_agent().

1739 {
1740  const char *agent_id = payload;
1741  const char *playfile;
1742  const char *dtmf_accept;
1743  struct agent_pvt *agent;
1744  int digit;
1745  char dtmf[2];
1746 
1747  agent = ao2_find(agents, agent_id, OBJ_KEY);
1748  if (!agent) {
1749  ast_debug(1, "Agent '%s' does not exist. Where did it go?\n", agent_id);
1750  return;
1751  }
1752 
1753  /* Change holding bridge participant role's idle mode to silence */
1754  ast_bridge_channel_lock_bridge(bridge_channel);
1755  ast_bridge_channel_clear_roles(bridge_channel);
1756  ast_channel_set_bridge_role_option(bridge_channel->chan, "holding_participant", "idle_mode", "silence");
1757  ast_bridge_channel_establish_roles(bridge_channel);
1758  ast_bridge_unlock(bridge_channel->bridge);
1759 
1760  agent_lock(agent);
1761  playfile = ast_strdupa(agent->cfg->beep_sound);
1762 
1763  /* Determine which DTMF digits interrupt the alerting signal. */
1765  ? agent->override_ack_call : agent->cfg->ack_call) {
1766  dtmf_accept = ast_test_flag(agent, AGENT_FLAG_DTMF_ACCEPT)
1767  ? agent->override_dtmf_accept : agent->cfg->dtmf_accept;
1768 
1769  /* Only the first digit of the ack will stop playback. */
1770  dtmf[0] = *dtmf_accept;
1771  dtmf[1] = '\0';
1772  dtmf_accept = dtmf;
1773  } else {
1774  dtmf_accept = NULL;
1775  }
1776  agent_unlock(agent);
1777 
1778  /* Alert the agent. */
1779  digit = ast_stream_and_wait(bridge_channel->chan, playfile,
1780  ast_strlen_zero(dtmf_accept) ? AST_DIGIT_ANY : dtmf_accept);
1781  ast_stopstream(bridge_channel->chan);
1782 
1783  agent_lock(agent);
1784  switch (agent->state) {
1786  if (!ast_strlen_zero(dtmf_accept)) {
1788  agent->ack_time = ast_tvnow();
1789 
1790  if (0 < digit) {
1791  /* Playback was interrupted by a digit. */
1792  agent_unlock(agent);
1793  ao2_ref(agent, -1);
1794  ast_bridge_channel_feature_digit(bridge_channel, digit);
1795  return;
1796  }
1797  break;
1798  }
1799 
1800  /* Connect to caller now. */
1801  ast_debug(1, "Agent %s: Immediately connecting to call.\n", agent->username);
1802  agent_connect_caller(bridge_channel, agent);/* Will unlock agent. */
1803  ao2_ref(agent, -1);
1804  return;
1805  default:
1806  break;
1807  }
1808  agent_unlock(agent);
1809  ao2_ref(agent, -1);
1810 }
char digit
struct timeval ack_time
void ast_bridge_channel_clear_roles(struct ast_bridge_channel *bridge_channel)
Clear all roles from a bridge_channel&#39;s role list.
Definition: bridge_roles.c:495
const ast_string_field override_dtmf_accept
#define agent_unlock(agent)
Unlock the agent.
#define AST_DIGIT_ANY
Definition: file.h:48
#define ast_test_flag(p, flag)
Definition: utils.h:63
enum agent_state state
const ast_string_field beep_sound
#define OBJ_KEY
Definition: astobj2.h:1155
int ack_call
TRUE if agent needs to ack a call to accept it.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define NULL
Definition: resample.c:96
void ast_bridge_channel_feature_digit(struct ast_bridge_channel *bridge_channel, int digit)
Add a DTMF digit to the collected digits to match against DTMF features.
int ast_bridge_channel_establish_roles(struct ast_bridge_channel *bridge_channel)
Clone the roles from a bridge_channel&#39;s attached ast_channel onto the bridge_channel&#39;s role list...
Definition: bridge_roles.c:447
struct ast_bridge * bridge
Bridge this channel is participating in.
#define ast_strlen_zero(foo)
Definition: strings.h:52
const ast_string_field dtmf_accept
DTMF string for an agent to accept a call. * *.
int ast_channel_set_bridge_role_option(struct ast_channel *channel, const char *role_name, const char *option, const char *value)
Set a role option on a channel.
Definition: bridge_roles.c:379
#define agent_lock(agent)
Lock the agent.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
const ast_string_field username
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
struct agent_cfg * cfg
Structure representing an agent.
#define ast_bridge_unlock(bridge)
Unlock the bridge.
Definition: bridge.h:493
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition: file.c:1814
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static void agent_connect_caller(struct ast_bridge_channel *bridge_channel, struct agent_pvt *agent)
struct ast_channel * chan
void ast_bridge_channel_lock_bridge(struct ast_bridge_channel *bridge_channel)
Lock the bridge associated with the bridge channel.
unsigned int override_ack_call
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:187
static struct ao2_container * agents

◆ agent_bridge_channel_get_lock()

static struct ast_bridge_channel* agent_bridge_channel_get_lock ( struct agent_pvt agent)
static

Definition at line 1660 of file app_agent_pool.c.

References agent_lock, agent_unlock, ao2_ref, ast_bridge_channel_lock, ast_bridge_channel_unlock, ast_channel_get_bridge_channel(), ast_channel_lock, ast_channel_ref, ast_channel_unlock, ast_channel_unref, bc, ast_bridge_channel::chan, agent_pvt::logged, and NULL.

Referenced by agent_request_exec(), caller_abort_agent(), and caller_joined_bridge().

1661 {
1662  struct ast_channel *logged;
1663  struct ast_bridge_channel *bc;
1664 
1665  for (;;) {
1666  agent_lock(agent);
1667  logged = agent->logged;
1668  if (!logged) {
1669  agent_unlock(agent);
1670  return NULL;
1671  }
1672  ast_channel_ref(logged);
1673  agent_unlock(agent);
1674 
1675  ast_channel_lock(logged);
1676  bc = ast_channel_get_bridge_channel(logged);
1677  ast_channel_unlock(logged);
1678  ast_channel_unref(logged);
1679  if (!bc) {
1680  if (agent->logged != logged) {
1681  continue;
1682  }
1683  return NULL;
1684  }
1685 
1687  if (bc->chan != logged || agent->logged != logged) {
1689  ao2_ref(bc, -1);
1690  continue;
1691  }
1692  return bc;
1693  }
1694 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
#define agent_unlock(agent)
Unlock the agent.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
#define bc
struct ast_channel * logged
#define NULL
Definition: resample.c:96
#define agent_lock(agent)
Lock the agent.
#define ast_bridge_channel_lock(bridge_channel)
Lock the bridge_channel.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_bridge_channel_unlock(bridge_channel)
Unlock the bridge_channel.
#define ast_channel_unlock(chan)
Definition: channel.h:2946
struct ast_bridge_channel * ast_channel_get_bridge_channel(struct ast_channel *chan)
Get a reference to the channel&#39;s bridge pointer.
Definition: channel.c:10783
struct ast_channel * chan
Structure that contains information regarding a channel in a bridge.
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2970

◆ agent_cfg_alloc()

static void* agent_cfg_alloc ( const char *  name)
static

Definition at line 434 of file app_agent_pool.c.

References agent_cfg_destructor(), AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, ao2_cleanup, ast_string_field_init, ast_string_field_set, NULL, and agent_cfg::username.

435 {
436  struct agent_cfg *cfg;
437 
438  cfg = ao2_alloc_options(sizeof(*cfg), agent_cfg_destructor,
440  if (!cfg || ast_string_field_init(cfg, 64)) {
441  ao2_cleanup(cfg);
442  return NULL;
443  }
445  return cfg;
446 }
const ast_string_field username
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define NULL
Definition: resample.c:96
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
static void agent_cfg_destructor(void *vdoomed)
static const char name[]
Definition: cdr_mysql.c:74
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ agent_cfg_destructor()

static void agent_cfg_destructor ( void *  vdoomed)
static

Definition at line 427 of file app_agent_pool.c.

References ast_string_field_free_memory.

Referenced by agent_cfg_alloc().

428 {
429  struct agent_cfg *doomed = vdoomed;
430 
432 }
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368

◆ agent_cfg_find()

static void* agent_cfg_find ( struct ao2_container agents,
const char *  username 
)
static

Definition at line 448 of file app_agent_pool.c.

References ao2_find, and OBJ_KEY.

449 {
450  return ao2_find(agents, username, OBJ_KEY);
451 }
const ast_string_field username
#define OBJ_KEY
Definition: astobj2.h:1155
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756

◆ agent_cfg_sort_cmp()

static int agent_cfg_sort_cmp ( const void *  obj_left,
const void *  obj_right,
int  flags 
)
static

Definition at line 405 of file app_agent_pool.c.

References OBJ_KEY, OBJ_PARTIAL_KEY, OBJ_POINTER, and agent_cfg::username.

Referenced by agents_cfg_alloc().

406 {
407  const struct agent_cfg *cfg_left = obj_left;
408  const struct agent_cfg *cfg_right = obj_right;
409  const char *right_key = obj_right;
410  int cmp;
411 
412  switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
413  default:
414  case OBJ_POINTER:
415  right_key = cfg_right->username;
416  /* Fall through */
417  case OBJ_KEY:
418  cmp = strcmp(cfg_left->username, right_key);
419  break;
420  case OBJ_PARTIAL_KEY:
421  cmp = strncmp(cfg_left->username, right_key, strlen(right_key));
422  break;
423  }
424  return cmp;
425 }
const ast_string_field username
#define OBJ_KEY
Definition: astobj2.h:1155
#define OBJ_POINTER
Definition: astobj2.h:1154
#define OBJ_PARTIAL_KEY
Definition: astobj2.h:1156

◆ agent_connect_caller()

static void agent_connect_caller ( struct ast_bridge_channel bridge_channel,
struct agent_pvt agent 
)
static

Definition at line 1034 of file app_agent_pool.c.

References AGENT_STATE_ON_CALL, agent_unlock, ao2_t_ref, AST_BRIDGE_BUILTIN_AUTOMIXMON, ast_bridge_channel_leave_bridge(), ast_bridge_channel_write_callback(), ast_bridge_channel_write_control_data(), ast_bridge_destroy(), ast_bridge_features_do(), ast_bridge_move(), AST_CAUSE_NORMAL_CLEARING, AST_CONTROL_ANSWER, AUTO_MONITOR_START, ast_bridge_channel::bridge, BRIDGE_CHANNEL_STATE_END, agent_pvt::call_start, agent_pvt::caller_bridge, agent_pvt::cfg, ast_bridge_channel::chan, clear_agent_status(), NULL, agent_cfg::record_agent_calls, ast_bridge_features_automixmonitor::start_stop, and agent_pvt::state.

Referenced by agent_alert(), and bridge_agent_hold_ack().

1035 {
1036  struct ast_bridge *caller_bridge;
1037  int record_agent_calls;
1038  int res;
1039 
1040  record_agent_calls = agent->cfg->record_agent_calls;
1041  caller_bridge = agent->caller_bridge;
1042  agent->caller_bridge = NULL;
1043  agent->state = AGENT_STATE_ON_CALL;
1044  time(&agent->call_start);
1045  agent_unlock(agent);
1046 
1047  if (!caller_bridge) {
1048  /* Reset agent. */
1051  return;
1052  }
1053  res = ast_bridge_move(caller_bridge, bridge_channel->bridge, bridge_channel->chan,
1054  NULL, 0);
1055  if (res) {
1056  /* Reset agent. */
1057  ast_bridge_destroy(caller_bridge, 0);
1060  return;
1061  }
1063  || ast_bridge_channel_write_callback(bridge_channel, 0, clear_agent_status, NULL, 0);
1064  if (res) {
1065  /* Reset agent. */
1066  ast_bridge_destroy(caller_bridge, 0);
1067  return;
1068  }
1069 
1070  if (record_agent_calls) {
1072  .start_stop = AUTO_MONITOR_START,
1073  };
1074 
1075  /*
1076  * The agent is in the new bridge so we can invoke the
1077  * mixmonitor hook to only start recording.
1078  */
1079  ast_bridge_features_do(AST_BRIDGE_BUILTIN_AUTOMIXMON, bridge_channel, &options);
1080  }
1081 
1082  ao2_t_ref(caller_bridge, -1, "Agent successfully in caller_bridge");
1083 }
#define ao2_t_ref(o, delta, tag)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:463
int ast_bridge_features_do(enum ast_bridge_builtin_feature feature, struct ast_bridge_channel *bridge_channel, void *hook_pvt)
Invoke a built in feature hook now.
Definition: bridge.c:3151
#define agent_unlock(agent)
Unlock the agent.
enum agent_state state
int record_agent_calls
int ast_bridge_channel_write_control_data(struct ast_bridge_channel *bridge_channel, enum ast_control_frame_type control, const void *data, size_t datalen)
Write a control frame into the bridge with data.
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:970
int ast_bridge_channel_write_callback(struct ast_bridge_channel *bridge_channel, enum ast_bridge_channel_custom_callback_option flags, ast_bridge_custom_callback_fn callback, const void *payload, size_t payload_size)
Write a bridge action custom callback frame into the bridge.
#define NULL
Definition: resample.c:96
struct ast_bridge * bridge
Bridge this channel is participating in.
struct ast_bridge * caller_bridge
static void clear_agent_status(struct ast_bridge_channel *bridge_channel, const void *payload, size_t payload_size)
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:105
struct agent_cfg * cfg
Structure that contains information about a bridge.
Definition: bridge.h:357
void ast_bridge_channel_leave_bridge(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state, int cause)
Set bridge channel state to leave bridge (if not leaving already).
struct ast_channel * chan
int ast_bridge_move(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge, struct ast_channel *chan, struct ast_channel *swap, int attempt_recovery)
Move a channel from one bridge to another.
Definition: bridge.c:2508
time_t call_start
static struct test_options options

◆ agent_devstate_changed()

static void agent_devstate_changed ( const char *  agent_id)
static

Definition at line 756 of file app_agent_pool.c.

References AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, and ast_devstate_changed().

Referenced by agent_logout(), agent_pvt_destructor(), agent_request_exec(), agents_post_apply_config(), bridge_agent_hold_heartbeat(), and bridge_agent_hold_push().

757 {
759 }
int ast_devstate_changed(enum ast_device_state state, enum ast_devstate_cache cachable, const char *fmt,...)
Tells Asterisk the State for Device is changed.
Definition: devicestate.c:510

◆ agent_function_read()

static int agent_function_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

Definition at line 2184 of file app_agent_pool.c.

References agent_lock, agent_lock_logged(), agent_unlock, ao2_find, ao2_ref, args, AST_APP_ARG, ast_channel_name(), ast_channel_unlock, ast_channel_unref, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_log, AST_NONSTANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero, agent_pvt::cfg, agent_cfg::full_name, item, LOG_WARNING, agent_pvt::logged, agent_cfg::moh, OBJ_KEY, parse(), and status.

2185 {
2186  char *parse;
2187  struct agent_pvt *agent;
2188  struct ast_channel *logged;
2190  AST_APP_ARG(agentid);
2191  AST_APP_ARG(item);
2192  );
2193 
2194  buf[0] = '\0';
2195 
2196  parse = ast_strdupa(data ?: "");
2197  AST_NONSTANDARD_APP_ARGS(args, parse, ':');
2198 
2199  if (ast_strlen_zero(args.agentid)) {
2200  ast_log(LOG_WARNING, "The AGENT function requires an argument - agentid!\n");
2201  return -1;
2202  }
2203  if (!args.item) {
2204  args.item = "status";
2205  }
2206 
2207  agent = ao2_find(agents, args.agentid, OBJ_KEY);
2208  if (!agent) {
2209  ast_log(LOG_WARNING, "Agent '%s' not found!\n", args.agentid);
2210  return -1;
2211  }
2212 
2213  agent_lock(agent);
2214  if (!strcasecmp(args.item, "status")) {
2215  const char *status;
2216 
2217  if (agent->logged) {
2218  status = "LOGGEDIN";
2219  } else {
2220  status = "LOGGEDOUT";
2221  }
2222  ast_copy_string(buf, status, len);
2223  } else if (!strcasecmp(args.item, "name")) {
2224  ast_copy_string(buf, agent->cfg->full_name, len);
2225  } else if (!strcasecmp(args.item, "mohclass")) {
2226  ast_copy_string(buf, agent->cfg->moh, len);
2227  } else if (!strcasecmp(args.item, "channel")) {
2228  logged = agent_lock_logged(agent);
2229  if (logged) {
2230  char *pos;
2231 
2232  ast_copy_string(buf, ast_channel_name(logged), len);
2233  ast_channel_unlock(logged);
2234  ast_channel_unref(logged);
2235 
2236  pos = strrchr(buf, '-');
2237  if (pos) {
2238  *pos = '\0';
2239  }
2240  }
2241  } else if (!strcasecmp(args.item, "fullchannel")) {
2242  logged = agent_lock_logged(agent);
2243  if (logged) {
2244  ast_copy_string(buf, ast_channel_name(logged), len);
2245  ast_channel_unlock(logged);
2246  ast_channel_unref(logged);
2247  }
2248  }
2249  agent_unlock(agent);
2250  ao2_ref(agent, -1);
2251 
2252  return 0;
2253 }
Main Channel structure associated with a channel.
const ast_string_field full_name
#define agent_unlock(agent)
Unlock the agent.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
#define OBJ_KEY
Definition: astobj2.h:1155
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
struct ast_channel * logged
static struct aco_type item
Definition: test_config.c:1463
const char * args
const char * data
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define agent_lock(agent)
Lock the agent.
#define ast_log
Definition: astobj2.c:42
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static struct ast_channel * agent_lock_logged(struct agent_pvt *agent)
struct agent_cfg * cfg
Structure representing an agent.
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the &#39;nonstandard&#39; argument separation process for an application.
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
const ast_string_field moh
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
const char * ast_channel_name(const struct ast_channel *chan)
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
jack_status_t status
Definition: app_jack.c:146
#define AST_APP_ARG(name)
Define an application argument.
static struct ao2_container * agents

◆ agent_handle_logoff_cmd()

static char* agent_handle_logoff_cmd ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2485 of file app_agent_pool.c.

References agent_logoff_request(), ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_strdup, ast_strlen_zero, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_agent_logoff(), ast_cli_args::fd, ast_cli_args::n, NULL, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

2486 {
2487  switch (cmd) {
2488  case CLI_INIT:
2489  e->command = "agent logoff";
2490  e->usage =
2491  "Usage: agent logoff <agent-id> [soft]\n"
2492  " Sets an agent as no longer logged in.\n"
2493  " If 'soft' is specified, do not hangup existing calls.\n";
2494  return NULL;
2495  case CLI_GENERATE:
2496  if (a->pos == 2) {
2497  return complete_agent_logoff(a->word, a->n);
2498  } else if (a->pos == 3 && a->n == 0
2499  && (ast_strlen_zero(a->word)
2500  || !strncasecmp("soft", a->word, strlen(a->word)))) {
2501  return ast_strdup("soft");
2502  }
2503  return NULL;
2504  }
2505 
2506  if (a->argc < 3 || 4 < a->argc) {
2507  return CLI_SHOWUSAGE;
2508  }
2509  if (a->argc == 4 && strcasecmp(a->argv[3], "soft")) {
2510  return CLI_SHOWUSAGE;
2511  }
2512 
2513  if (!agent_logoff_request(a->argv[2], a->argc == 4)) {
2514  ast_cli(a->fd, "Logging out %s\n", a->argv[2]);
2515  }
2516 
2517  return CLI_SUCCESS;
2518 }
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
#define ast_strlen_zero(foo)
Definition: strings.h:52
const int fd
Definition: cli.h:159
const int n
Definition: cli.h:165
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
char * command
Definition: cli.h:186
const char * word
Definition: cli.h:163
static int agent_logoff_request(const char *agent_id, int soft)
const char * usage
Definition: cli.h:177
static char * complete_agent_logoff(const char *word, int state)
#define CLI_SUCCESS
Definition: cli.h:44
const int pos
Definition: cli.h:164

◆ agent_handle_show_all()

static char* agent_handle_show_all ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2404 of file app_agent_pool.c.

References agent_show_requested(), ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, and ast_cli_entry::usage.

2405 {
2406  switch (cmd) {
2407  case CLI_INIT:
2408  e->command = "agent show all";
2409  e->usage =
2410  "Usage: agent show all\n"
2411  " Provides summary information for all agents.\n";
2412  return NULL;
2413  case CLI_GENERATE:
2414  return NULL;
2415  }
2416 
2417  if (a->argc != 3) {
2418  return CLI_SHOWUSAGE;
2419  }
2420 
2421  agent_show_requested(a, 0);
2422 
2423  return CLI_SUCCESS;
2424 }
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
static void agent_show_requested(struct ast_cli_args *a, int online_only)
#define CLI_SHOWUSAGE
Definition: cli.h:45
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44

◆ agent_handle_show_online()

static char* agent_handle_show_online ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2382 of file app_agent_pool.c.

References agent_show_requested(), ast_cli_args::argc, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, NULL, and ast_cli_entry::usage.

2383 {
2384  switch (cmd) {
2385  case CLI_INIT:
2386  e->command = "agent show online";
2387  e->usage =
2388  "Usage: agent show online\n"
2389  " Provides summary information for logged in agents.\n";
2390  return NULL;
2391  case CLI_GENERATE:
2392  return NULL;
2393  }
2394 
2395  if (a->argc != 3) {
2396  return CLI_SHOWUSAGE;
2397  }
2398 
2399  agent_show_requested(a, 1);
2400 
2401  return CLI_SUCCESS;
2402 }
const int argc
Definition: cli.h:160
Definition: cli.h:152
#define NULL
Definition: resample.c:96
static void agent_show_requested(struct ast_cli_args *a, int online_only)
#define CLI_SHOWUSAGE
Definition: cli.h:45
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44

◆ agent_handle_show_specific()

static char* agent_handle_show_specific ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 2426 of file app_agent_pool.c.

References agent_lock, agent_lock_logged(), agent_unlock, ao2_find, ao2_ref, ast_cli_args::argc, ast_cli_args::argv, ast_channel_name(), ast_channel_unlock, ast_channel_unref, ast_cli(), AST_CLI_YESNO, ast_devstate_str(), ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_str_set(), ast_strlen_zero, agent_cfg::beep_sound, agent_pvt::call_start, agent_pvt::cfg, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_agent(), agent_pvt::devstate, ast_cli_args::fd, agent_cfg::full_name, agent_pvt::login_start, agent_cfg::moh, ast_cli_args::n, NULL, OBJ_KEY, out, pbx_builtin_getvar_helper(), ast_cli_args::pos, agent_cfg::record_agent_calls, ast_cli_entry::usage, agent_pvt::username, and ast_cli_args::word.

2427 {
2428  struct agent_pvt *agent;
2429  struct ast_channel *logged;
2430  struct ast_str *out = ast_str_alloca(4096);
2431 
2432  switch (cmd) {
2433  case CLI_INIT:
2434  e->command = "agent show";
2435  e->usage =
2436  "Usage: agent show <agent-id>\n"
2437  " Show information about the <agent-id> agent\n";
2438  return NULL;
2439  case CLI_GENERATE:
2440  if (a->pos == 2) {
2441  return complete_agent(a->word, a->n);
2442  }
2443  return NULL;
2444  }
2445 
2446  if (a->argc != 3) {
2447  return CLI_SHOWUSAGE;
2448  }
2449 
2450  agent = ao2_find(agents, a->argv[2], OBJ_KEY);
2451  if (!agent) {
2452  ast_cli(a->fd, "Agent '%s' not found\n", a->argv[2]);
2453  return CLI_SUCCESS;
2454  }
2455 
2456  agent_lock(agent);
2457  logged = agent_lock_logged(agent);
2458  ast_str_set(&out, 0, "Id: %s\n", agent->username);
2459  ast_str_append(&out, 0, "Name: %s\n", agent->cfg->full_name);
2460  ast_str_append(&out, 0, "Beep: %s\n", agent->cfg->beep_sound);
2461  ast_str_append(&out, 0, "MOH: %s\n", agent->cfg->moh);
2462  ast_str_append(&out, 0, "RecordCalls: %s\n", AST_CLI_YESNO(agent->cfg->record_agent_calls));
2463  ast_str_append(&out, 0, "State: %s\n", ast_devstate_str(agent->devstate));
2464  if (logged) {
2465  const char *talking_with;
2466 
2467  ast_str_append(&out, 0, "LoggedInChannel: %s\n", ast_channel_name(logged));
2468  ast_str_append(&out, 0, "LoggedInTime: %ld\n", (long) agent->login_start);
2469  talking_with = pbx_builtin_getvar_helper(logged, "BRIDGEPEER");
2470  if (!ast_strlen_zero(talking_with)) {
2471  ast_str_append(&out, 0, "TalkingWith: %s\n", talking_with);
2472  ast_str_append(&out, 0, "CallStarted: %ld\n", (long) agent->call_start);
2473  }
2474  ast_channel_unlock(logged);
2475  ast_channel_unref(logged);
2476  }
2477  agent_unlock(agent);
2478  ao2_ref(agent, -1);
2479 
2480  ast_cli(a->fd, "%s", ast_str_buffer(out));
2481 
2482  return CLI_SUCCESS;
2483 }
Main Channel structure associated with a channel.
const ast_string_field full_name
#define agent_unlock(agent)
Unlock the agent.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
const ast_string_field beep_sound
int record_agent_calls
#define OBJ_KEY
Definition: astobj2.h:1155
const int argc
Definition: cli.h:160
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
Definition: cli.h:152
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1091
#define ast_str_alloca(init_len)
Definition: strings.h:800
#define NULL
Definition: resample.c:96
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
#define ast_strlen_zero(foo)
Definition: strings.h:52
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
enum ast_device_state devstate
#define agent_lock(agent)
Lock the agent.
const int fd
Definition: cli.h:159
const int n
Definition: cli.h:165
const ast_string_field username
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct ast_channel * agent_lock_logged(struct agent_pvt *agent)
const char *const * argv
Definition: cli.h:161
const char * ast_devstate_str(enum ast_device_state devstate) attribute_pure
Convert device state to text string that is easier to parse.
Definition: devicestate.c:255
struct agent_cfg * cfg
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
time_t login_start
Structure representing an agent.
#define CLI_SHOWUSAGE
Definition: cli.h:45
const ast_string_field moh
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static char * complete_agent(const char *word, int state)
char * command
Definition: cli.h:186
const char * word
Definition: cli.h:163
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
FILE * out
Definition: utils/frame.c:33
const char * ast_channel_name(const struct ast_channel *chan)
const int pos
Definition: cli.h:164
time_t call_start
#define AST_CLI_YESNO(x)
Return Yes or No depending on the argument.
Definition: cli.h:71
static struct ao2_container * agents

◆ agent_lock_logged()

static struct ast_channel* agent_lock_logged ( struct agent_pvt agent)
static

Definition at line 690 of file app_agent_pool.c.

References agent_lock, agent_unlock, ast_channel_lock, ast_channel_ref, ast_channel_unlock, ast_channel_unref, agent_pvt::logged, and NULL.

Referenced by action_agents(), agent_function_read(), agent_handle_show_specific(), agent_logoff_request(), and agent_show_requested().

691 {
692  struct ast_channel *logged;
693 
694  for (;;) {
695  if (!agent->logged) { /* No owner. Nothing to do. */
696  return NULL;
697  }
698 
699  /* If we don't ref the logged, it could be killed when we unlock the agent. */
700  logged = ast_channel_ref(agent->logged);
701 
702  /* Locking logged requires us to lock channel, then agent. */
703  agent_unlock(agent);
704  ast_channel_lock(logged);
705  agent_lock(agent);
706 
707  /* Check if logged changed during agent unlock period */
708  if (logged != agent->logged) {
709  /* Channel changed. Unref and do another pass. */
710  ast_channel_unlock(logged);
711  ast_channel_unref(logged);
712  } else {
713  /* Channel stayed the same. Return it. */
714  return logged;
715  }
716  }
717 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
#define agent_unlock(agent)
Unlock the agent.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
struct ast_channel * logged
#define NULL
Definition: resample.c:96
#define agent_lock(agent)
Lock the agent.
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2970

◆ agent_login_channel_config()

static void agent_login_channel_config ( struct agent_pvt agent,
struct ast_channel chan 
)
static

Definition at line 2040 of file app_agent_pool.c.

References AGENT_FLAG_ACK_CALL, AGENT_FLAG_AUTO_LOGOFF, AGENT_FLAG_DTMF_ACCEPT, AGENT_FLAG_WRAPUP_TIME, agent_lock, agent_unlock, ast_channel_connected(), ast_channel_lock, ast_channel_unlock, ast_copy_flags, AST_FLAGS_ALL, ast_party_connected_line_copy(), ast_party_connected_line_free(), ast_party_connected_line_init(), ast_set_flag, ast_strdupa, ast_string_field_set, ast_strlen_zero, ast_true(), connected, NULL, agent_pvt::override_ack_call, agent_pvt::override_auto_logoff, agent_pvt::override_wrapup_time, pbx_builtin_getvar_helper(), var, and agent_pvt::waiting_colp.

Referenced by agent_login_exec().

2041 {
2042  struct ast_flags opts = { 0 };
2044  unsigned int override_ack_call = 0;
2045  unsigned int override_auto_logoff = 0;
2046  unsigned int override_wrapup_time = 0;
2047  const char *override_dtmf_accept = NULL;
2048  const char *var;
2049 
2051 
2052  /* Get config values from channel. */
2053  ast_channel_lock(chan);
2055 
2056  var = pbx_builtin_getvar_helper(chan, "AGENTACKCALL");
2057  if (!ast_strlen_zero(var)) {
2058  override_ack_call = ast_true(var) ? 1 : 0;
2060  }
2061 
2062  var = pbx_builtin_getvar_helper(chan, "AGENTACCEPTDTMF");
2063  if (!ast_strlen_zero(var)) {
2064  override_dtmf_accept = ast_strdupa(var);
2066  }
2067 
2068  var = pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF");
2069  if (!ast_strlen_zero(var)) {
2070  if (sscanf(var, "%u", &override_auto_logoff) == 1) {
2072  }
2073  }
2074 
2075  var = pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME");
2076  if (!ast_strlen_zero(var)) {
2077  if (sscanf(var, "%u", &override_wrapup_time) == 1) {
2079  }
2080  }
2081  ast_channel_unlock(chan);
2082 
2083  /* Set config values on agent. */
2084  agent_lock(agent);
2086  agent->waiting_colp = connected;
2087 
2088  ast_string_field_set(agent, override_dtmf_accept, override_dtmf_accept);
2089  ast_copy_flags(agent, &opts, AST_FLAGS_ALL);
2090  agent->override_auto_logoff = override_auto_logoff;
2091  agent->override_wrapup_time = override_wrapup_time;
2092  agent->override_ack_call = override_ack_call;
2093  agent_unlock(agent);
2094 }
void ast_party_connected_line_init(struct ast_party_connected_line *init)
Initialize the given connected line structure.
Definition: channel.c:2022
#define ast_channel_lock(chan)
Definition: channel.h:2945
#define agent_unlock(agent)
Unlock the agent.
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define var
Definition: ast_expr2f.c:614
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
Definition: channel.c:2072
#define NULL
Definition: resample.c:96
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define agent_lock(agent)
Lock the agent.
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
Connected Line/Party information.
Definition: channel.h:457
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define AST_FLAGS_ALL
Definition: utils.h:196
unsigned int override_wrapup_time
Structure used to handle boolean flags.
Definition: utils.h:199
void ast_party_connected_line_copy(struct ast_party_connected_line *dest, const struct ast_party_connected_line *src)
Copy the source connected line information to the destination connected line.
Definition: channel.c:2031
unsigned int override_auto_logoff
char connected
Definition: eagi_proxy.c:82
struct ast_party_connected_line waiting_colp
unsigned int override_ack_call
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ agent_login_exec()

static int agent_login_exec ( struct ast_channel chan,
const char *  data 
)
static

Dialplan AgentLogin application to log in an agent.

Parameters
chanChannel attempting to login as an agent.
dataApplication parameters
Return values
0To continue in dialplan.
-1To hangup.

Definition at line 2112 of file app_agent_pool.c.

References agent_lock, agent_login_channel_config(), agent_login_opts, agent_run(), agent_unlock, ao2_cleanup, ao2_find, args, ast_answer(), AST_APP_ARG, ast_app_parse_options(), ast_channel_lock, ast_channel_readformat(), ast_channel_ref, ast_channel_unlock, ast_channel_writeformat(), AST_DECLARE_APP_ARGS, AST_DIGIT_NONE, ast_format_get_name(), ast_log, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_stream_and_wait(), ast_strlen_zero, ast_test_flag, ast_tvnow(), ast_verb, bridge_agent_hold_deferred_create(), LOG_WARNING, NULL, OBJ_KEY, OPT_SILENT, options, parse(), pbx_builtin_setvar_helper(), RAII_VAR, and send_agent_login().

Referenced by load_module().

2113 {
2114  char *parse;
2115  struct ast_flags opts;
2117  AST_APP_ARG(agent_id);
2119  AST_APP_ARG(other); /* Any remaining unused arguments */
2120  );
2121 
2122  RAII_VAR(struct agent_pvt *, agent, NULL, ao2_cleanup);
2123 
2125  return -1;
2126  }
2127 
2128  if (ast_channel_state(chan) != AST_STATE_UP && ast_answer(chan)) {
2129  return -1;
2130  }
2131 
2132  parse = ast_strdupa(data);
2133  AST_STANDARD_APP_ARGS(args, parse);
2134 
2135  if (ast_strlen_zero(args.agent_id)) {
2136  ast_log(LOG_WARNING, "AgentLogin requires an AgentId\n");
2137  return -1;
2138  }
2139 
2140  if (ast_app_parse_options(agent_login_opts, &opts, NULL, args.options)) {
2141  /* General invalid option syntax. */
2142  return -1;
2143  }
2144 
2145  /* Find the agent. */
2146  agent = ao2_find(agents, args.agent_id, OBJ_KEY);
2147  if (!agent) {
2148  ast_verb(3, "Agent '%s' does not exist.\n", args.agent_id);
2149  pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "INVALID");
2150  return 0;
2151  }
2152 
2153  /* Has someone already logged in as this agent already? */
2154  agent_lock(agent);
2155  if (agent->logged) {
2156  agent_unlock(agent);
2157  ast_verb(3, "Agent '%s' already logged in.\n", agent->username);
2158  pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "ALREADY_LOGGED_IN");
2159  return 0;
2160  }
2161  agent->logged = ast_channel_ref(chan);
2162  agent->last_disconnect = ast_tvnow();
2163  time(&agent->login_start);
2164  agent->deferred_logoff = 0;
2165  agent_unlock(agent);
2166 
2167  agent_login_channel_config(agent, chan);
2168 
2169  if (!ast_test_flag(&opts, OPT_SILENT)) {
2170  ast_stream_and_wait(chan, "agent-loginok", AST_DIGIT_NONE);
2171  }
2172 
2173  ast_verb(2, "Agent '%s' logged in (format %s/%s)\n", agent->username,
2176  ast_channel_lock(chan);
2177  send_agent_login(chan, agent->username);
2178  ast_channel_unlock(chan);
2179 
2180  agent_run(agent, chan);
2181  return -1;
2182 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
static void agent_run(struct agent_pvt *agent, struct ast_channel *logged)
static void send_agent_login(struct ast_channel *chan, const char *agent)
#define agent_unlock(agent)
Unlock the agent.
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define OBJ_KEY
Definition: astobj2.h:1155
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
ast_channel_state
ast_channel states
Definition: channelstate.h:35
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
const char * args
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
static void agent_login_channel_config(struct agent_pvt *agent, struct ast_channel *chan)
#define agent_lock(agent)
Lock the agent.
#define ast_log
Definition: astobj2.c:42
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:2906
Structure representing an agent.
#define AST_DIGIT_NONE
Definition: file.h:47
static int bridge_agent_hold_deferred_create(void)
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition: file.c:1814
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
Structure used to handle boolean flags.
Definition: utils.h:199
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
static const struct ast_app_option agent_login_opts[128]
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2970
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2814
static struct test_options options
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.
static struct ao2_container * agents

◆ agent_logoff_request()

static int agent_logoff_request ( const char *  agent_id,
int  soft 
)
static

Definition at line 975 of file app_agent_pool.c.

References agent_lock, agent_lock_logged(), agent_unlock, ao2_cleanup, ao2_find, AO2_GLOBAL_OBJ_STATIC(), ast_channel_unlock, ast_channel_unref, ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, OBJ_KEY, and RAII_VAR.

Referenced by action_agent_logoff(), and agent_handle_logoff_cmd().

976 {
977  struct ast_channel *logged;
978  RAII_VAR(struct agent_pvt *, agent, ao2_find(agents, agent_id, OBJ_KEY), ao2_cleanup);
979 
980  if (!agent) {
981  return -1;
982  }
983 
984  agent_lock(agent);
985  logged = agent_lock_logged(agent);
986  if (logged) {
987  if (soft) {
988  agent->deferred_logoff = 1;
989  } else {
991  }
992  ast_channel_unlock(logged);
993  ast_channel_unref(logged);
994  }
995  agent_unlock(agent);
996  return 0;
997 }
Main Channel structure associated with a channel.
#define agent_unlock(agent)
Unlock the agent.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
#define OBJ_KEY
Definition: astobj2.h:1155
#define agent_lock(agent)
Lock the agent.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2476
static struct ast_channel * agent_lock_logged(struct agent_pvt *agent)
Structure representing an agent.
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct ao2_container * agents

◆ agent_logout()

static void agent_logout ( struct agent_pvt agent)
static

Definition at line 1481 of file app_agent_pool.c.

References agent_devstate_changed(), AGENT_STATE_LOGGED_OUT, agent_unlock, ast_bridge_destroy(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_clear_flag, AST_DEVICE_UNAVAILABLE, AST_FLAGS_ALL, ast_verb, agent_pvt::caller_bridge, agent_pvt::devstate, agent_pvt::logged, agent_pvt::login_start, NULL, send_agent_logoff(), agent_pvt::state, and agent_pvt::username.

Referenced by agent_after_bridge_cb_failed(), and agent_run().

1482 {
1483  struct ast_channel *logged;
1484  struct ast_bridge *caller_bridge;
1485  long time_logged_in;
1486 
1487  time_logged_in = time(NULL) - agent->login_start;
1488  logged = agent->logged;
1489  agent->logged = NULL;
1490  caller_bridge = agent->caller_bridge;
1491  agent->caller_bridge = NULL;
1492  agent->state = AGENT_STATE_LOGGED_OUT;
1494  ast_clear_flag(agent, AST_FLAGS_ALL);
1495  agent_unlock(agent);
1497 
1498  if (caller_bridge) {
1499  ast_bridge_destroy(caller_bridge, 0);
1500  }
1501 
1502  ast_channel_lock(logged);
1503  send_agent_logoff(logged, agent->username, time_logged_in);
1504  ast_channel_unlock(logged);
1505  ast_verb(2, "Agent '%s' logged out. Logged in for %ld seconds.\n",
1506  agent->username, time_logged_in);
1507  ast_channel_unref(logged);
1508 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
Main Channel structure associated with a channel.
#define agent_unlock(agent)
Unlock the agent.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
enum agent_state state
struct ast_channel * logged
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:970
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
struct ast_bridge * caller_bridge
enum ast_device_state devstate
const ast_string_field username
Structure that contains information about a bridge.
Definition: bridge.h:357
time_t login_start
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define AST_FLAGS_ALL
Definition: utils.h:196
#define ast_clear_flag(p, flag)
Definition: utils.h:77
static void send_agent_logoff(struct ast_channel *chan, const char *agent, long logintime)
static void agent_devstate_changed(const char *agent_id)

◆ agent_mark()

static int agent_mark ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 874 of file app_agent_pool.c.

References agent_lock, agent_unlock, and agent_pvt::the_mark.

Referenced by agents_mark().

875 {
876  struct agent_pvt *agent = obj;
877 
878  agent_lock(agent);
879  agent->the_mark = 1;
880  agent_unlock(agent);
881  return 0;
882 }
#define agent_unlock(agent)
Unlock the agent.
#define agent_lock(agent)
Lock the agent.
Structure representing an agent.
unsigned int the_mark

◆ agent_pvt_cmp()

static int agent_pvt_cmp ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 852 of file app_agent_pool.c.

References CMP_MATCH, agent_pvt::logged, OBJ_KEY, OBJ_PARTIAL_KEY, and OBJ_POINTER.

Referenced by load_module().

853 {
854  const struct agent_pvt *agent = obj;
855  int cmp;
856 
857  switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
858  case OBJ_POINTER:
859  case OBJ_KEY:
860  case OBJ_PARTIAL_KEY:
861  cmp = CMP_MATCH;
862  break;
863  default:
864  if (agent->logged == arg) {
865  cmp = CMP_MATCH;
866  } else {
867  cmp = 0;
868  }
869  break;
870  }
871  return cmp;
872 }
#define OBJ_KEY
Definition: astobj2.h:1155
#define OBJ_POINTER
Definition: astobj2.h:1154
struct ast_channel * logged
#define OBJ_PARTIAL_KEY
Definition: astobj2.h:1156
Structure representing an agent.
unsigned int flags

◆ agent_pvt_destructor()

static void agent_pvt_destructor ( void *  vdoomed)
static

Definition at line 761 of file app_agent_pool.c.

References agent_devstate_changed(), ao2_cleanup, ast_bridge_destroy(), ast_channel_unref, ast_debug, ast_party_connected_line_free(), ast_string_field_free_memory, ast_strlen_zero, agent_pvt::caller_bridge, agent_pvt::cfg, agent_pvt::logged, NULL, agent_pvt::username, and agent_pvt::waiting_colp.

Referenced by agent_pvt_new().

762 {
763  struct agent_pvt *doomed = vdoomed;
764 
765  /* Make sure device state reflects agent destruction. */
766  if (!ast_strlen_zero(doomed->username)) {
767  ast_debug(1, "Agent %s: Destroyed.\n", doomed->username);
769  }
770 
772  if (doomed->caller_bridge) {
773  ast_bridge_destroy(doomed->caller_bridge, 0);
774  doomed->caller_bridge = NULL;
775  }
776  if (doomed->logged) {
777  doomed->logged = ast_channel_unref(doomed->logged);
778  }
779  ao2_cleanup(doomed->cfg);
780  doomed->cfg = NULL;
782 }
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
struct ast_channel * logged
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:970
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
Definition: channel.c:2072
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ast_bridge * caller_bridge
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
const ast_string_field username
struct agent_cfg * cfg
Structure representing an agent.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368
struct ast_party_connected_line waiting_colp
static void agent_devstate_changed(const char *agent_id)

◆ agent_pvt_devstate_get()

static enum ast_device_state agent_pvt_devstate_get ( const char *  agent_id)
static

Definition at line 732 of file app_agent_pool.c.

References agent_lock, agent_unlock, ao2_find, ao2_ref, AST_DEVICE_INVALID, agent_pvt::devstate, and OBJ_KEY.

Referenced by load_module().

733 {
734  enum ast_device_state dev_state = AST_DEVICE_INVALID;
735  struct agent_pvt *agent;
736 
737  agent = ao2_find(agents, agent_id, OBJ_KEY);
738  if (agent) {
739  agent_lock(agent);
740  dev_state = agent->devstate;
741  agent_unlock(agent);
742  ao2_ref(agent, -1);
743  }
744  return dev_state;
745 }
ast_device_state
Device States.
Definition: devicestate.h:52
#define agent_unlock(agent)
Unlock the agent.
#define OBJ_KEY
Definition: astobj2.h:1155
enum ast_device_state devstate
#define agent_lock(agent)
Lock the agent.
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Structure representing an agent.
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static struct ao2_container * agents

◆ agent_pvt_new()

static struct agent_pvt* agent_pvt_new ( struct agent_cfg cfg)
static

Definition at line 784 of file app_agent_pool.c.

References agent_pvt_destructor(), ao2_alloc, ao2_ref, AST_DEVICE_UNAVAILABLE, ast_party_connected_line_init(), ast_string_field_init, ast_string_field_set, agent_pvt::cfg, agent_pvt::devstate, NULL, agent_cfg::username, and agent_pvt::waiting_colp.

Referenced by agents_post_apply_config().

785 {
786  struct agent_pvt *agent;
787 
788  agent = ao2_alloc(sizeof(*agent), agent_pvt_destructor);
789  if (!agent) {
790  return NULL;
791  }
792  if (ast_string_field_init(agent, 32)) {
793  ao2_ref(agent, -1);
794  return NULL;
795  }
796  ast_string_field_set(agent, username, cfg->username);
798  ao2_ref(cfg, +1);
799  agent->cfg = cfg;
801  return agent;
802 }
void ast_party_connected_line_init(struct ast_party_connected_line *init)
Initialize the given connected line structure.
Definition: channel.c:2022
const ast_string_field username
static void agent_pvt_destructor(void *vdoomed)
#define NULL
Definition: resample.c:96
enum ast_device_state devstate
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
const ast_string_field username
#define ao2_ref(o, delta)
Definition: astobj2.h:464
struct agent_cfg * cfg
Structure representing an agent.
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
struct ast_party_connected_line waiting_colp
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514

◆ agent_pvt_sort_cmp()

static int agent_pvt_sort_cmp ( const void *  obj_left,
const void *  obj_right,
int  flags 
)
static

Definition at line 820 of file app_agent_pool.c.

References OBJ_KEY, OBJ_PARTIAL_KEY, OBJ_POINTER, and agent_pvt::username.

Referenced by load_module().

821 {
822  const struct agent_pvt *agent_left = obj_left;
823  const struct agent_pvt *agent_right = obj_right;
824  const char *right_key = obj_right;
825  int cmp;
826 
827  switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
828  default:
829  case OBJ_POINTER:
830  right_key = agent_right->username;
831  /* Fall through */
832  case OBJ_KEY:
833  cmp = strcmp(agent_left->username, right_key);
834  break;
835  case OBJ_PARTIAL_KEY:
836  cmp = strncmp(agent_left->username, right_key, strlen(right_key));
837  break;
838  }
839  return cmp;
840 }
#define OBJ_KEY
Definition: astobj2.h:1155
#define OBJ_POINTER
Definition: astobj2.h:1154
#define OBJ_PARTIAL_KEY
Definition: astobj2.h:1156
const ast_string_field username
Structure representing an agent.
unsigned int flags

◆ agent_request_exec()

static int agent_request_exec ( struct ast_channel chan,
const char *  data 
)
static

Dialplan AgentRequest application to locate an agent to talk with.

Parameters
chanChannel wanting to talk with an agent.
dataApplication parameters
Return values
0To continue in dialplan.
-1To hangup.

Definition at line 1889 of file app_agent_pool.c.

References __ao2_cleanup(), agent_bridge_channel_get_lock(), agent_devstate_changed(), agent_lock, AGENT_STATE_CALL_PRESENT, AGENT_STATE_LOGGED_OUT, AGENT_STATE_LOGGING_OUT, AGENT_STATE_READY_FOR_CALL, agent_unlock, ao2_cleanup, ao2_find, ao2_ref, args, AST_APP_ARG, ast_bridge_basic_new(), ast_bridge_channel_unlock, ast_bridge_destroy(), ast_bridge_features_cleanup(), ast_bridge_features_init(), AST_BRIDGE_HOOK_REMOVE_ON_PULL, ast_bridge_interval_hook(), ast_bridge_join(), ast_bridge_join_hook(), AST_BRIDGE_JOIN_PASS_REFERENCE, ast_channel_caller(), ast_channel_flags(), ast_channel_lock, ast_channel_name(), ast_channel_softhangup_internal_flag(), ast_channel_unlock, ast_check_hangup(), ast_connected_line_copy_from_caller(), AST_DECLARE_APP_ARGS, AST_DEVICE_INUSE, AST_FLAG_ZOMBIE, ast_log, ast_party_connected_line_free(), ast_party_connected_line_init(), AST_SOFTHANGUP_ASYNCGOTO, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero, ast_test_flag, ast_verb, bridge_agent_hold_deferred_create(), caller_abort_agent(), caller_joined_bridge(), caller_safety_timeout(), CALLER_SAFETY_TIMEOUT_TIME, LOG_WARNING, NULL, OBJ_KEY, parse(), pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), RAII_VAR, and send_colp_to_agent().

Referenced by load_module().

1890 {
1891  struct ast_bridge *caller_bridge;
1892  struct ast_bridge_channel *logged;
1893  char *parse;
1894  int res;
1895  struct ast_bridge_features caller_features;
1898  AST_APP_ARG(agent_id);
1899  AST_APP_ARG(other); /* Any remaining unused arguments */
1900  );
1901 
1902  RAII_VAR(struct agent_pvt *, agent, NULL, ao2_cleanup);
1903 
1905  return -1;
1906  }
1907 
1908  parse = ast_strdupa(data);
1909  AST_STANDARD_APP_ARGS(args, parse);
1910 
1911  if (ast_strlen_zero(args.agent_id)) {
1912  ast_log(LOG_WARNING, "AgentRequest requires an AgentId\n");
1913  return -1;
1914  }
1915 
1916  /* Find the agent. */
1917  agent = ao2_find(agents, args.agent_id, OBJ_KEY);
1918  if (!agent) {
1919  ast_verb(3, "Agent '%s' does not exist.\n", args.agent_id);
1920  pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "INVALID");
1921  return 0;
1922  }
1923 
1924  if (ast_bridge_features_init(&caller_features)) {
1925  return -1;
1926  }
1927 
1928  /* Add safety timeout hook. */
1929  ao2_ref(agent, +1);
1930  if (ast_bridge_interval_hook(&caller_features, 0, CALLER_SAFETY_TIMEOUT_TIME,
1932  ao2_ref(agent, -1);
1933  ast_bridge_features_cleanup(&caller_features);
1934  return -1;
1935  }
1936 
1937  /* Setup the alert agent on caller joining the bridge hook. */
1938  ao2_ref(agent, +1);
1939  if (ast_bridge_join_hook(&caller_features, caller_joined_bridge, agent,
1940  __ao2_cleanup, 0)) {
1941  ao2_ref(agent, -1);
1942  ast_bridge_features_cleanup(&caller_features);
1943  return -1;
1944  }
1945 
1946  caller_bridge = ast_bridge_basic_new();
1947  if (!caller_bridge) {
1948  ast_bridge_features_cleanup(&caller_features);
1949  return -1;
1950  }
1951 
1952  agent_lock(agent);
1953  switch (agent->state) {
1956  agent_unlock(agent);
1957  ast_bridge_destroy(caller_bridge, 0);
1958  ast_bridge_features_cleanup(&caller_features);
1959  ast_verb(3, "Agent '%s' not logged in.\n", agent->username);
1960  pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "NOT_LOGGED_IN");
1961  return 0;
1963  ao2_ref(caller_bridge, +1);
1964  agent->caller_bridge = caller_bridge;
1965  agent->state = AGENT_STATE_CALL_PRESENT;
1966  agent->devstate = AST_DEVICE_INUSE;
1967  break;
1968  default:
1969  agent_unlock(agent);
1970  ast_bridge_destroy(caller_bridge, 0);
1971  ast_bridge_features_cleanup(&caller_features);
1972  ast_verb(3, "Agent '%s' is busy.\n", agent->username);
1973  pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "BUSY");
1974  return 0;
1975  }
1976  agent_unlock(agent);
1977  agent_devstate_changed(agent->username);
1978 
1979  /* Get COLP for agent. */
1981  ast_channel_lock(chan);
1983  ast_channel_unlock(chan);
1984 
1985  logged = agent_bridge_channel_get_lock(agent);
1986  if (!logged) {
1988  caller_abort_agent(agent);
1989  ast_bridge_destroy(caller_bridge, 0);
1990  ast_bridge_features_cleanup(&caller_features);
1991  ast_verb(3, "Agent '%s' not logged in.\n", agent->username);
1992  pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "NOT_LOGGED_IN");
1993  return 0;
1994  }
1995 
1996  send_colp_to_agent(logged, &connected);
1997  ast_bridge_channel_unlock(logged);
1998  ao2_ref(logged, -1);
2000 
2001  if (ast_bridge_join(caller_bridge, chan, NULL, &caller_features, NULL,
2003  caller_abort_agent(agent);
2004  ast_verb(3, "Agent '%s': Caller %s failed to join the bridge.\n",
2005  agent->username, ast_channel_name(chan));
2006  pbx_builtin_setvar_helper(chan, "AGENT_STATUS", "ERROR");
2007  }
2008  ast_bridge_features_cleanup(&caller_features);
2009 
2010  /* Determine if we need to continue in the dialplan after the bridge. */
2011  ast_channel_lock(chan);
2013  /*
2014  * The bridge was broken for a hangup that isn't real.
2015  * Don't run the h extension, because the channel isn't
2016  * really hung up. This should really only happen with
2017  * AST_SOFTHANGUP_ASYNCGOTO.
2018  */
2019  res = 0;
2020  } else {
2021  res = ast_check_hangup(chan)
2023  || ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENT_STATUS"));
2024  }
2025  ast_channel_unlock(chan);
2026 
2027  return res ? -1 : 0;
2028 }
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
void ast_party_connected_line_init(struct ast_party_connected_line *init)
Initialize the given connected line structure.
Definition: channel.c:2022
#define ast_channel_lock(chan)
Definition: channel.h:2945
void ast_bridge_features_cleanup(struct ast_bridge_features *features)
Clean up the contents of a bridge features structure.
Definition: bridge.c:3720
#define CALLER_SAFETY_TIMEOUT_TIME
#define agent_unlock(agent)
Unlock the agent.
Structure that contains features information.
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define OBJ_KEY
Definition: astobj2.h:1155
int ast_bridge_join_hook(struct ast_bridge_features *features, ast_bridge_hook_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Unregisters a handler for a built in interval feature.
Definition: bridge.c:3338
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
int ast_bridge_features_init(struct ast_bridge_features *features)
Initialize bridge features structure.
Definition: bridge.c:3687
void __ao2_cleanup(void *obj)
Definition: astobj2.c:674
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:970
void ast_party_connected_line_free(struct ast_party_connected_line *doomed)
Destroy the connected line information contents.
Definition: channel.c:2072
const char * args
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:463
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
#define ast_strlen_zero(foo)
Definition: strings.h:52
static int caller_joined_bridge(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
#define agent_lock(agent)
Lock the agent.
#define ast_log
Definition: astobj2.c:42
static int send_colp_to_agent(struct ast_bridge_channel *bridge_channel, struct ast_party_connected_line *connected)
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int ast_bridge_interval_hook(struct ast_bridge_features *features, enum ast_bridge_hook_timer_option flags, unsigned int interval, ast_bridge_hook_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Attach an interval hook to a bridge features structure.
Definition: bridge.c:3382
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:445
#define ast_bridge_channel_unlock(bridge_channel)
Unlock the bridge_channel.
Structure that contains information about a bridge.
Definition: bridge.h:357
Structure representing an agent.
static void caller_abort_agent(struct agent_pvt *agent)
Connected Line/Party information.
Definition: channel.h:457
static int bridge_agent_hold_deferred_create(void)
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
int ast_bridge_join(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, struct ast_bridge_tech_optimizations *tech_args, enum ast_bridge_join_flags flags)
Join a channel to a bridge (blocking)
Definition: bridge.c:1667
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
int ast_channel_softhangup_internal_flag(struct ast_channel *chan)
struct ast_bridge * ast_bridge_basic_new(void)
Create a new basic class bridge.
Structure that contains information regarding a channel in a bridge.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void ast_connected_line_copy_from_caller(struct ast_party_connected_line *dest, const struct ast_party_caller *src)
Copy the caller information to the connected line information.
Definition: channel.c:8389
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
static struct ast_bridge_channel * agent_bridge_channel_get_lock(struct agent_pvt *agent)
char connected
Definition: eagi_proxy.c:82
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
static int caller_safety_timeout(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
static void agent_devstate_changed(const char *agent_id)
#define AST_APP_ARG(name)
Define an application argument.
static struct ao2_container * agents

◆ agent_run()

static void agent_run ( struct agent_pvt agent,
struct ast_channel logged 
)
static

Definition at line 1520 of file app_agent_pool.c.

References agent_lock, agent_logout(), AGENT_STATE_LOGGING_OUT, agent_unlock, agents_cfg::agents, ao2_find, ao2_global_obj_ref, ao2_ref, ast_bridge_destroy(), ast_bridge_features_cleanup(), ast_bridge_features_init(), ast_bridge_join(), AST_BRIDGE_JOIN_PASS_REFERENCE, AST_CAUSE_NORMAL_CLEARING, ast_channel_hangupcause_set(), ast_channel_name(), ast_channel_update_connected_line(), ast_check_hangup_locked(), ast_debug, ast_tvnow(), agent_pvt::caller_bridge, agent_pvt::cfg, cfg_handle, agent_pvt::dead, agent_pvt::deferred_logoff, agent_pvt::last_disconnect, agent_pvt::logged, NULL, OBJ_KEY, agent_pvt::state, agent_pvt::username, and agent_pvt::waiting_colp.

Referenced by agent_after_bridge_cb(), and agent_login_exec().

1521 {
1522  struct ast_bridge_features features;
1523 
1524  if (ast_bridge_features_init(&features)) {
1526  goto agent_run_cleanup;
1527  }
1528  for (;;) {
1529  struct agents_cfg *cfgs;
1530  struct agent_cfg *cfg_new;
1531  struct agent_cfg *cfg_old;
1532  struct ast_bridge *holding;
1533  struct ast_bridge *caller_bridge;
1534 
1536 
1537  holding = ao2_global_obj_ref(agent_holding);
1538  if (!holding) {
1539  ast_debug(1, "Agent %s: Someone destroyed the agent holding bridge.\n",
1540  agent->username);
1541  break;
1542  }
1543 
1544  /*
1545  * When the agent channel leaves the bridging system we usually
1546  * want to put the agent back into the holding bridge for the
1547  * next caller.
1548  */
1549  ast_bridge_join(holding, logged, NULL, &features, NULL,
1551  if (logged != agent->logged) {
1552  /* This channel is no longer the logged in agent. */
1553  break;
1554  }
1555 
1556  if (agent->dead) {
1557  /* The agent is no longer configured. */
1558  break;
1559  }
1560 
1561  /* Update the agent's config before rejoining the holding bridge. */
1563  if (!cfgs) {
1564  /* There is no agent configuration. All agents were destroyed. */
1565  break;
1566  }
1567  cfg_new = ao2_find(cfgs->agents, agent->username, OBJ_KEY);
1568  ao2_ref(cfgs, -1);
1569  if (!cfg_new) {
1570  /* The agent is no longer configured. */
1571  break;
1572  }
1573  agent_lock(agent);
1574  cfg_old = agent->cfg;
1575  agent->cfg = cfg_new;
1576 
1577  agent->last_disconnect = ast_tvnow();
1578 
1579  /* Clear out any caller bridge before rejoining the holding bridge. */
1580  caller_bridge = agent->caller_bridge;
1581  agent->caller_bridge = NULL;
1582  agent_unlock(agent);
1583  ao2_ref(cfg_old, -1);
1584  if (caller_bridge) {
1585  ast_bridge_destroy(caller_bridge, 0);
1586  }
1587 
1588  if (agent->state == AGENT_STATE_LOGGING_OUT
1589  || agent->deferred_logoff
1590  || ast_check_hangup_locked(logged)) {
1591  /* The agent was requested to logout or hungup. */
1592  break;
1593  }
1594 
1595  /*
1596  * It is safe to access agent->waiting_colp without a lock. It
1597  * is only setup on agent login and not changed.
1598  */
1600  }
1601  ast_bridge_features_cleanup(&features);
1602 
1603 agent_run_cleanup:
1604  agent_lock(agent);
1605  if (logged != agent->logged) {
1606  /*
1607  * We are no longer the agent channel because of local channel
1608  * optimization.
1609  */
1610  agent_unlock(agent);
1611  ast_debug(1, "Agent %s: Channel %s is no longer the agent.\n",
1612  agent->username, ast_channel_name(logged));
1613  return;
1614  }
1615  agent_logout(agent);
1616 }
void ast_bridge_features_cleanup(struct ast_bridge_features *features)
Clean up the contents of a bridge features structure.
Definition: bridge.c:3720
#define agent_unlock(agent)
Unlock the agent.
Structure that contains features information.
enum agent_state state
#define OBJ_KEY
Definition: astobj2.h:1155
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
int ast_check_hangup_locked(struct ast_channel *chan)
Definition: channel.c:459
unsigned int deferred_logoff
struct ao2_container * agents
void ast_channel_update_connected_line(struct ast_channel *chan, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Indicate that the connected line information has changed.
Definition: channel.c:9189
int ast_bridge_features_init(struct ast_bridge_features *features)
Initialize bridge features structure.
Definition: bridge.c:3687
struct ast_channel * logged
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:970
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define NULL
Definition: resample.c:96
struct ast_bridge * caller_bridge
#define agent_lock(agent)
Lock the agent.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:105
const ast_string_field username
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static void agent_logout(struct agent_pvt *agent)
struct agent_cfg * cfg
Structure that contains information about a bridge.
Definition: bridge.h:357
struct timeval last_disconnect
unsigned int dead
TRUE if the agent is no longer configured and is being destroyed.
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
int ast_bridge_join(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, struct ast_bridge_tech_optimizations *tech_args, enum ast_bridge_join_flags flags)
Join a channel to a bridge (blocking)
Definition: bridge.c:1667
static corosync_cfg_handle_t cfg_handle
Definition: res_corosync.c:284
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_party_connected_line waiting_colp

◆ agent_show_requested()

static void agent_show_requested ( struct ast_cli_args a,
int  online_only 
)
static

Definition at line 2327 of file app_agent_pool.c.

References agent_lock, agent_lock_logged(), agent_unlock, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_ref, ast_channel_name(), ast_channel_unlock, ast_channel_unref, ast_cli(), ast_devstate_str(), ast_str_alloca, ast_str_buffer(), ast_str_set(), ast_strlen_zero, agent_pvt::cfg, agent_pvt::devstate, ast_cli_args::fd, FORMAT_HDR, FORMAT_ROW, agent_cfg::full_name, out, pbx_builtin_getvar_helper(), and agent_pvt::username.

Referenced by agent_handle_show_all(), and agent_handle_show_online().

2328 {
2329 #define FORMAT_HDR "%-8s %-20s %-11s %-30s %s\n"
2330 #define FORMAT_ROW "%-8s %-20s %-11s %-30s %s\n"
2331 
2332  struct ao2_iterator iter;
2333  struct agent_pvt *agent;
2334  struct ast_str *out = ast_str_alloca(512);
2335  unsigned int agents_total = 0;
2336  unsigned int agents_logged_in = 0;
2337  unsigned int agents_talking = 0;
2338 
2339  ast_cli(a->fd, FORMAT_HDR, "Agent-ID", "Name", "State", "Channel", "Talking with");
2340  iter = ao2_iterator_init(agents, 0);
2341  for (; (agent = ao2_iterator_next(&iter)); ao2_ref(agent, -1)) {
2342  struct ast_channel *logged;
2343 
2344  ++agents_total;
2345 
2346  agent_lock(agent);
2347  logged = agent_lock_logged(agent);
2348  if (logged) {
2349  const char *talking_with;
2350 
2351  ++agents_logged_in;
2352 
2353  talking_with = pbx_builtin_getvar_helper(logged, "BRIDGEPEER");
2354  if (!ast_strlen_zero(talking_with)) {
2355  ++agents_talking;
2356  } else {
2357  talking_with = "";
2358  }
2359  ast_str_set(&out, 0, FORMAT_ROW, agent->username, agent->cfg->full_name,
2360  ast_devstate_str(agent->devstate), ast_channel_name(logged), talking_with);
2361  ast_channel_unlock(logged);
2362  ast_channel_unref(logged);
2363  } else {
2364  ast_str_set(&out, 0, FORMAT_ROW, agent->username, agent->cfg->full_name,
2365  ast_devstate_str(agent->devstate), "", "");
2366  }
2367  agent_unlock(agent);
2368 
2369  if (!online_only || logged) {
2370  ast_cli(a->fd, "%s", ast_str_buffer(out));
2371  }
2372  }
2373  ao2_iterator_destroy(&iter);
2374 
2375  ast_cli(a->fd, "\nDefined agents: %u, Logged in: %u, Talking: %u\n",
2376  agents_total, agents_logged_in, agents_talking);
2377 
2378 #undef FORMAT_HDR
2379 #undef FORMAT_ROW
2380 }
Main Channel structure associated with a channel.
#define FORMAT_ROW
const ast_string_field full_name
#define agent_unlock(agent)
Unlock the agent.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:714
#define FORMAT_HDR
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ast_str_alloca(init_len)
Definition: strings.h:800
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
#define ast_strlen_zero(foo)
Definition: strings.h:52
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1065
enum ast_device_state devstate
#define agent_lock(agent)
Lock the agent.
const int fd
Definition: cli.h:159
const ast_string_field username
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static struct ast_channel * agent_lock_logged(struct agent_pvt *agent)
const char * ast_devstate_str(enum ast_device_state devstate) attribute_pure
Convert device state to text string that is easier to parse.
Definition: devicestate.c:255
struct agent_cfg * cfg
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:584
Structure representing an agent.
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
#define ast_channel_unlock(chan)
Definition: channel.h:2946
FILE * out
Definition: utils/frame.c:33
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
const char * ast_channel_name(const struct ast_channel *chan)
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
static struct ao2_container * agents

◆ agent_sweep()

static int agent_sweep ( void *  obj,
void *  arg,
int  flags 
)
static

Definition at line 889 of file app_agent_pool.c.

References agent_lock, agent_unlock, CMP_MATCH, agent_pvt::dead, and agent_pvt::the_mark.

Referenced by agents_sweep().

890 {
891  struct agent_pvt *agent = obj;
892  int cmp = 0;
893 
894  agent_lock(agent);
895  if (agent->the_mark) {
896  agent->the_mark = 0;
897  agent->dead = 1;
898  /* Unlink dead agents immediately. */
899  cmp = CMP_MATCH;
900  }
901  agent_unlock(agent);
902  return cmp;
903 }
#define agent_unlock(agent)
Unlock the agent.
#define agent_lock(agent)
Lock the agent.
Structure representing an agent.
unsigned int the_mark
unsigned int dead
TRUE if the agent is no longer configured and is being destroyed.

◆ agents_cfg_alloc()

static void* agents_cfg_alloc ( void  )
static

Definition at line 512 of file app_agent_pool.c.

References ACO_FILES, agent_cfg_sort_cmp(), agents_cfg::agents, agents_cfg_destructor(), agents_post_apply_config(), AO2_ALLOC_OPT_LOCK_NOLOCK, ao2_alloc_options, AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, ao2_container_alloc_rbtree, ao2_ref, cfg_handle, CONFIG_INFO_STANDARD(), and NULL.

513 {
514  struct agents_cfg *cfg;
515 
516  cfg = ao2_alloc_options(sizeof(*cfg), agents_cfg_destructor,
518  if (!cfg) {
519  return NULL;
520  }
523  if (!cfg->agents) {
524  ao2_ref(cfg, -1);
525  cfg = NULL;
526  }
527  return cfg;
528 }
static int agent_cfg_sort_cmp(const void *obj_left, const void *obj_right, int flags)
struct ao2_container * agents
#define ao2_alloc_options(data_size, destructor_fn, options)
Definition: astobj2.h:406
#define NULL
Definition: resample.c:96
#define ao2_ref(o, delta)
Definition: astobj2.h:464
static void agents_cfg_destructor(void *vdoomed)
#define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn)
Definition: astobj2.h:1358
Reject objects with duplicate keys in container.
Definition: astobj2.h:1192

◆ agents_cfg_destructor()

static void agents_cfg_destructor ( void *  vdoomed)
static

Definition at line 492 of file app_agent_pool.c.

References agents_cfg::agents, ao2_cleanup, and NULL.

Referenced by agents_cfg_alloc().

493 {
494  struct agents_cfg *doomed = vdoomed;
495 
496  ao2_cleanup(doomed->agents);
497  doomed->agents = NULL;
498 }
struct ao2_container * agents
#define NULL
Definition: resample.c:96
#define ao2_cleanup(obj)
Definition: astobj2.h:1958

◆ agents_mark()

static void agents_mark ( void  )
static

Definition at line 884 of file app_agent_pool.c.

References agent_mark(), ao2_callback, and NULL.

Referenced by agents_post_apply_config().

885 {
887 }
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
#define NULL
Definition: resample.c:96
static int agent_mark(void *obj, void *arg, int flags)
static struct ao2_container * agents

◆ agents_post_apply_config()

static void agents_post_apply_config ( void  )
static

Definition at line 935 of file app_agent_pool.c.

References agent_devstate_changed(), agent_lock, agent_pvt_new(), agent_unlock, agents_mark(), agents_sweep(), ao2_cleanup, ao2_find, ao2_global_obj_ref, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_link, ao2_ref, ast_assert, ast_debug, cfg_handle, NULL, OBJ_KEY, RAII_VAR, and agent_cfg::username.

Referenced by agents_cfg_alloc().

936 {
937  struct ao2_iterator iter;
938  struct agent_cfg *cfg;
940 
941  ast_assert(cfgs != NULL);
942 
943  agents_mark();
944  iter = ao2_iterator_init(cfgs->agents, 0);
945  for (; (cfg = ao2_iterator_next(&iter)); ao2_ref(cfg, -1)) {
946  RAII_VAR(struct agent_pvt *, agent, ao2_find(agents, cfg->username, OBJ_KEY), ao2_cleanup);
947 
948  if (agent) {
949  agent_lock(agent);
950  agent->the_mark = 0;
951  if (!agent->logged) {
952  struct agent_cfg *cfg_old;
953 
954  /* Replace the config of agents not logged in. */
955  cfg_old = agent->cfg;
956  ao2_ref(cfg, +1);
957  agent->cfg = cfg;
958  ao2_cleanup(cfg_old);
959  }
960  agent_unlock(agent);
961  continue;
962  }
963  agent = agent_pvt_new(cfg);
964  if (!agent) {
965  continue;
966  }
967  ao2_link(agents, agent);
968  ast_debug(1, "Agent %s: Created.\n", agent->username);
969  agent_devstate_changed(agent->username);
970  }
971  ao2_iterator_destroy(&iter);
972  agents_sweep();
973 }
const ast_string_field username
#define agent_unlock(agent)
Unlock the agent.
#define OBJ_KEY
Definition: astobj2.h:1155
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
#define agent_lock(agent)
Lock the agent.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Structure representing an agent.
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static corosync_cfg_handle_t cfg_handle
Definition: res_corosync.c:284
static void agents_sweep(void)
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct agent_pvt * agent_pvt_new(struct agent_cfg *cfg)
static void agents_mark(void)
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
static void agent_devstate_changed(const char *agent_id)
static struct ao2_container * agents
#define ao2_link(container, obj)
Definition: astobj2.h:1549

◆ agents_sweep()

static void agents_sweep ( void  )
static

Definition at line 905 of file app_agent_pool.c.

References agent_lock, agent_sweep(), agent_unlock, ao2_callback, ao2_iterator_destroy(), ao2_iterator_next, ao2_ref, ast_channel_name(), ast_channel_ref, ast_channel_unref, ast_log, ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, LOG_NOTICE, agent_pvt::logged, NULL, OBJ_MULTIPLE, OBJ_UNLINK, and agent_pvt::username.

Referenced by agents_post_apply_config().

906 {
907  struct ao2_iterator *iter;
908  struct agent_pvt *agent;
909  struct ast_channel *logged;
910 
912  if (!iter) {
913  return;
914  }
915  for (; (agent = ao2_iterator_next(iter)); ao2_ref(agent, -1)) {
916  agent_lock(agent);
917  if (agent->logged) {
918  logged = ast_channel_ref(agent->logged);
919  } else {
920  logged = NULL;
921  }
922  agent_unlock(agent);
923  if (!logged) {
924  continue;
925  }
927  "Forced logoff of agent %s(%s). Agent no longer configured.\n",
928  agent->username, ast_channel_name(logged));
930  ast_channel_unref(logged);
931  }
932  ao2_iterator_destroy(iter);
933 }
Main Channel structure associated with a channel.
#define agent_unlock(agent)
Unlock the agent.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:1716
struct ast_channel * logged
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
#define NULL
Definition: resample.c:96
#define agent_lock(agent)
Lock the agent.
#define ast_log
Definition: astobj2.c:42
const ast_string_field username
#define ao2_ref(o, delta)
Definition: astobj2.h:464
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2476
Structure representing an agent.
#define ao2_iterator_next(iter)
Definition: astobj2.h:1933
#define LOG_NOTICE
Definition: logger.h:263
static int agent_sweep(void *obj, void *arg, int flags)
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2970
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1841
const char * ast_channel_name(const struct ast_channel *chan)
static struct ao2_container * agents

◆ AO2_GLOBAL_OBJ_STATIC() [1/2]

static AO2_GLOBAL_OBJ_STATIC ( cfg_handle  )
static

Referenced by agent_logoff_request().

◆ AO2_GLOBAL_OBJ_STATIC() [2/2]

static AO2_GLOBAL_OBJ_STATIC ( agent_holding  )
static

Agent holding bridge instance holder.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 2716 of file app_agent_pool.c.

◆ bridge_agent_hold_ack()

static int bridge_agent_hold_ack ( struct ast_bridge_channel bridge_channel,
void *  hook_pvt 
)
static

Definition at line 1085 of file app_agent_pool.c.

References agent_connect_caller(), agent_lock, AGENT_STATE_CALL_WAIT_ACK, agent_unlock, ast_debug, agent_pvt::state, and agent_pvt::username.

Referenced by bridge_agent_hold_push().

1086 {
1087  struct agent_pvt *agent = hook_pvt;
1088 
1089  agent_lock(agent);
1090  switch (agent->state) {
1092  /* Connect to caller now. */
1093  ast_debug(1, "Agent %s: Acked call.\n", agent->username);
1094  agent_connect_caller(bridge_channel, agent);/* Will unlock agent. */
1095  return 0;
1096  default:
1097  break;
1098  }
1099  agent_unlock(agent);
1100  return 0;
1101 }
#define agent_unlock(agent)
Unlock the agent.
enum agent_state state
#define agent_lock(agent)
Lock the agent.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
const ast_string_field username
Structure representing an agent.
static void agent_connect_caller(struct ast_bridge_channel *bridge_channel, struct agent_pvt *agent)

◆ bridge_agent_hold_deferred_create()

static int bridge_agent_hold_deferred_create ( void  )
static

Definition at line 1419 of file app_agent_pool.c.

References agent_holding_lock, ao2_cleanup, ao2_global_obj_ref, ao2_global_obj_replace_unref, ast_log, ast_mutex_lock, ast_mutex_unlock, bridge_agent_hold_new(), LOG_ERROR, and RAII_VAR.

Referenced by agent_login_exec(), and agent_request_exec().

1420 {
1421  RAII_VAR(struct ast_bridge *, holding, ao2_global_obj_ref(agent_holding), ao2_cleanup);
1422 
1423  if (!holding) {
1425  holding = ao2_global_obj_ref(agent_holding);
1426  if (!holding) {
1427  holding = bridge_agent_hold_new();
1428  ao2_global_obj_replace_unref(agent_holding, holding);
1429  }
1431  if (!holding) {
1432  ast_log(LOG_ERROR, "Could not create agent holding bridge.\n");
1433  return -1;
1434  }
1435  }
1436  return 0;
1437 }
#define ao2_global_obj_ref(holder)
Definition: astobj2.h:925
#define ast_mutex_lock(a)
Definition: lock.h:187
static ast_mutex_t agent_holding_lock
#define ast_log
Definition: astobj2.c:42
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
Structure that contains information about a bridge.
Definition: bridge.h:357
#define LOG_ERROR
Definition: logger.h:285
#define ao2_global_obj_replace_unref(holder, obj)
Definition: astobj2.h:908
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct ast_bridge * bridge_agent_hold_new(void)
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ bridge_agent_hold_dissolving()

static void bridge_agent_hold_dissolving ( struct ast_bridge self)
static

The bridge is being dissolved.

Parameters
selfBridge to operate upon.

The bridge is being dissolved. Remove any external references to the bridge so it can be destroyed.

Note
On entry, self must NOT be locked.
Returns
Nothing

Definition at line 1388 of file app_agent_pool.c.

References ao2_global_obj_release, ast_bridge_base_v_table, and ast_bridge_methods::dissolving.

Referenced by bridge_init_agent_hold().

1389 {
1390  ao2_global_obj_release(agent_holding);
1392 }
ast_bridge_dissolving_fn dissolving
Definition: bridge.h:271
struct ast_bridge_methods ast_bridge_base_v_table
Bridge base class virtual method table.
Definition: bridge.c:949
#define ao2_global_obj_release(holder)
Definition: astobj2.h:865

◆ bridge_agent_hold_heartbeat()

static int bridge_agent_hold_heartbeat ( struct ast_bridge_channel bridge_channel,
void *  hook_pvt 
)
static

Definition at line 1103 of file app_agent_pool.c.

References agent_pvt::ack_time, agent_after_bridge_cb(), agent_after_bridge_cb_failed(), agent_devstate_changed(), AGENT_FLAG_AUTO_LOGOFF, AGENT_FLAG_WRAPUP_TIME, agent_lock, AGENT_STATE_CALL_WAIT_ACK, AGENT_STATE_CALL_WRAPUP, AGENT_STATE_LOGGING_OUT, AGENT_STATE_PROBATION_WAIT, AGENT_STATE_READY_FOR_CALL, agent_unlock, ast_bridge_channel_leave_bridge(), AST_CAUSE_NORMAL_CLEARING, ast_debug, AST_DEVICE_NOT_INUSE, ast_test_flag, ast_tvdiff_ms(), ast_tvnow(), agent_cfg::auto_logoff, BRIDGE_CHANNEL_STATE_END, agent_pvt::cfg, agent_pvt::deferred_logoff, agent_pvt::devstate, agent_pvt::last_disconnect, LOGIN_WAIT_TIMEOUT_TIME, NULL, agent_pvt::override_auto_logoff, agent_pvt::override_wrapup_time, agent_pvt::probation_start, agent_pvt::state, agent_pvt::username, and agent_cfg::wrapup_time.

Referenced by bridge_agent_hold_push().

1104 {
1105  struct agent_pvt *agent = hook_pvt;
1106  int probation_timedout = 0;
1107  int ack_timedout = 0;
1108  int wrapup_timedout = 0;
1109  int deferred_logoff;
1110  unsigned int wrapup_time;
1111  unsigned int auto_logoff;
1112 
1113  agent_lock(agent);
1114  deferred_logoff = agent->deferred_logoff;
1115  if (deferred_logoff) {
1116  agent->state = AGENT_STATE_LOGGING_OUT;
1117  }
1118 
1119  switch (agent->state) {
1121  probation_timedout =
1122  LOGIN_WAIT_TIMEOUT_TIME <= (time(NULL) - agent->probation_start);
1123  if (probation_timedout) {
1124  /* Now ready for a caller. */
1126  agent->devstate = AST_DEVICE_NOT_INUSE;
1127  }
1128  break;
1130  /* Check ack call time. */
1131  auto_logoff = agent->cfg->auto_logoff;
1132  if (ast_test_flag(agent, AGENT_FLAG_AUTO_LOGOFF)) {
1133  auto_logoff = agent->override_auto_logoff;
1134  }
1135  if (auto_logoff) {
1136  auto_logoff *= 1000;
1137  ack_timedout = ast_tvdiff_ms(ast_tvnow(), agent->ack_time) > auto_logoff;
1138  if (ack_timedout) {
1139  agent->state = AGENT_STATE_LOGGING_OUT;
1140  }
1141  }
1142  break;
1144  /* Check wrapup time. */
1145  wrapup_time = agent->cfg->wrapup_time;
1146  if (ast_test_flag(agent, AGENT_FLAG_WRAPUP_TIME)) {
1147  wrapup_time = agent->override_wrapup_time;
1148  }
1149  wrapup_timedout = ast_tvdiff_ms(ast_tvnow(), agent->last_disconnect) > wrapup_time;
1150  if (wrapup_timedout) {
1152  agent->devstate = AST_DEVICE_NOT_INUSE;
1153  }
1154  break;
1155  default:
1156  break;
1157  }
1158  agent_unlock(agent);
1159 
1160  if (deferred_logoff) {
1161  ast_debug(1, "Agent %s: Deferred logoff.\n", agent->username);
1164  } else if (probation_timedout) {
1165  ast_debug(1, "Agent %s: Login complete.\n", agent->username);
1167  } else if (ack_timedout) {
1168  ast_debug(1, "Agent %s: Ack call timeout.\n", agent->username);
1171  } else if (wrapup_timedout) {
1172  ast_debug(1, "Agent %s: Wrapup timeout. Ready for new call.\n", agent->username);
1174  }
1175 
1176  return 0;
1177 }
struct timeval ack_time
#define agent_unlock(agent)
Unlock the agent.
#define ast_test_flag(p, flag)
Definition: utils.h:63
enum agent_state state
unsigned int deferred_logoff
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
#define NULL
Definition: resample.c:96
enum ast_device_state devstate
#define agent_lock(agent)
Lock the agent.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:105
const ast_string_field username
unsigned int auto_logoff
Number of seconds for agent to ack a call before being logged off.
struct agent_cfg * cfg
unsigned int wrapup_time
Time after a call in ms before the agent can get a new call.
Structure representing an agent.
struct timeval last_disconnect
void ast_bridge_channel_leave_bridge(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state, int cause)
Set bridge channel state to leave bridge (if not leaving already).
unsigned int override_wrapup_time
unsigned int override_auto_logoff
#define LOGIN_WAIT_TIMEOUT_TIME
time_t probation_start
static void agent_devstate_changed(const char *agent_id)

◆ bridge_agent_hold_new()

static struct ast_bridge* bridge_agent_hold_new ( void  )
static

Definition at line 1396 of file app_agent_pool.c.

References AST_BRIDGE_CAPABILITY_HOLDING, AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM, AST_BRIDGE_FLAG_MERGE_INHIBIT_TO, AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM, AST_BRIDGE_FLAG_TRANSFER_PROHIBITED, bridge_agent_hold_v_table, bridge_alloc(), bridge_base_init(), bridge_register(), and NULL.

Referenced by bridge_agent_hold_deferred_create().

1397 {
1398  struct ast_bridge *bridge;
1399 
1400  bridge = bridge_alloc(sizeof(struct ast_bridge), &bridge_agent_hold_v_table);
1404  "AgentPool", NULL, NULL);
1405  bridge = bridge_register(bridge);
1406  return bridge;
1407 }
struct ast_bridge * bridge_register(struct ast_bridge *bridge)
Register the new bridge with the system.
Definition: bridge.c:709
#define NULL
Definition: resample.c:96
struct ast_bridge * bridge_alloc(size_t size, const struct ast_bridge_methods *v_table)
Definition: bridge.c:724
struct ast_bridge * bridge_base_init(struct ast_bridge *self, uint32_t capabilities, unsigned int flags, const char *creator, const char *name, const char *id)
Initialize the base class of the bridge.
Definition: bridge.c:760
Structure that contains information about a bridge.
Definition: bridge.h:357
static struct ast_bridge_methods bridge_agent_hold_v_table

◆ bridge_agent_hold_pull()

static void bridge_agent_hold_pull ( struct ast_bridge self,
struct ast_bridge_channel bridge_channel 
)
static

Definition at line 1369 of file app_agent_pool.c.

References ast_bridge_base_v_table, ast_channel_remove_bridge_role(), ast_bridge_channel::chan, and ast_bridge_methods::pull.

Referenced by bridge_init_agent_hold().

1370 {
1371  ast_channel_remove_bridge_role(bridge_channel->chan, "holding_participant");
1372  ast_bridge_base_v_table.pull(self, bridge_channel);
1373 }
void ast_channel_remove_bridge_role(struct ast_channel *chan, const char *role_name)
Removes a bridge role from a channel.
Definition: bridge_roles.c:336
struct ast_bridge_methods ast_bridge_base_v_table
Bridge base class virtual method table.
Definition: bridge.c:949
struct ast_channel * chan
ast_bridge_pull_channel_fn pull
Definition: bridge.h:275

◆ bridge_agent_hold_push()

static int bridge_agent_hold_push ( struct ast_bridge self,
struct ast_bridge_channel bridge_channel,
struct ast_bridge_channel swap 
)
static
Todo:
XXX the login probation time should be only if it is needed.

Need to determine if there are any local channels that can optimize and wait until they actually do before leaving the AGENT_STATE_PROBATION_WAIT state. For now, the blind timer of LOGIN_WAIT_TIMEOUT_TIME will do.

Definition at line 1196 of file app_agent_pool.c.

References __ao2_cleanup(), agent_devstate_changed(), AGENT_FLAG_ACK_CALL, AGENT_FLAG_DTMF_ACCEPT, AGENT_FLAG_WRAPUP_TIME, agent_lock, AGENT_STATE_CALL_PRESENT, AGENT_STATE_CALL_WAIT_ACK, AGENT_STATE_CALL_WRAPUP, AGENT_STATE_LOGGED_OUT, AGENT_STATE_ON_CALL, AGENT_STATE_PROBATION_WAIT, AGENT_STATE_READY_FOR_CALL, agent_unlock, ao2_cleanup, ao2_find, ao2_ref, ast_assert, ast_bridge_base_v_table, ast_bridge_channel_leave_bridge(), ast_bridge_dtmf_hook(), AST_BRIDGE_HOOK_REMOVE_ON_PULL, ast_bridge_interval_hook(), ast_bridge_set_after_callback(), AST_CAUSE_NORMAL_CLEARING, ast_channel_add_bridge_role(), ast_channel_ref, ast_channel_remove_bridge_role(), ast_channel_set_bridge_role_option(), ast_channel_unref, ast_copy_string(), ast_debug, AST_DEVICE_NOT_INUSE, AST_FEATURE_MAX_LEN, ast_strdupa, ast_strlen_zero, ast_test_flag, bridge_agent_hold_ack(), bridge_agent_hold_heartbeat(), BRIDGE_CHANNEL_STATE_END, ast_bridge_channel::chan, agent_cfg::dtmf_accept, ast_bridge_channel::features, NULL, ast_bridge_methods::push, RAII_VAR, and agent_cfg::wrapup_time.

Referenced by bridge_init_agent_hold().

1197 {
1198  int res = 0;
1199  unsigned int wrapup_time;
1200  char dtmf[AST_FEATURE_MAX_LEN];
1201  struct ast_channel *chan;
1202  const char *moh_class;
1203  RAII_VAR(struct agent_pvt *, agent, NULL, ao2_cleanup);
1204 
1205  chan = bridge_channel->chan;
1206 
1207  agent = ao2_find(agents, swap ? swap->chan : chan, 0);
1208  if (!agent) {
1209  /* Could not find the agent. */
1210  return -1;
1211  }
1212 
1213  /* Setup agent entertainment */
1214  agent_lock(agent);
1215  moh_class = ast_strdupa(agent->cfg->moh);
1216  agent_unlock(agent);
1217  res |= ast_channel_add_bridge_role(chan, "holding_participant");
1218  res |= ast_channel_set_bridge_role_option(chan, "holding_participant", "idle_mode", "musiconhold");
1219  res |= ast_channel_set_bridge_role_option(chan, "holding_participant", "moh_class", moh_class);
1220 
1221  /* Add DTMF acknowledge hook. */
1222  dtmf[0] = '\0';
1223  agent_lock(agent);
1225  ? agent->override_ack_call : agent->cfg->ack_call) {
1226  const char *dtmf_accept;
1227 
1228  dtmf_accept = ast_test_flag(agent, AGENT_FLAG_DTMF_ACCEPT)
1229  ? agent->override_dtmf_accept : agent->cfg->dtmf_accept;
1230  ast_copy_string(dtmf, dtmf_accept, sizeof(dtmf));
1231  }
1232  agent_unlock(agent);
1233  if (!ast_strlen_zero(dtmf)) {
1234  ao2_ref(agent, +1);
1235  if (ast_bridge_dtmf_hook(bridge_channel->features, dtmf, bridge_agent_hold_ack,
1237  ao2_ref(agent, -1);
1238  res = -1;
1239  }
1240  }
1241 
1242  /* Add heartbeat interval hook. */
1243  ao2_ref(agent, +1);
1244  if (ast_bridge_interval_hook(bridge_channel->features, 0, 1000,
1246  ao2_ref(agent, -1);
1247  res = -1;
1248  }
1249 
1250  res |= ast_bridge_base_v_table.push(self, bridge_channel, swap);
1251  if (res) {
1252  ast_channel_remove_bridge_role(chan, "holding_participant");
1253  return -1;
1254  }
1255 
1256  if (swap) {
1259  if (res) {
1260  ast_channel_remove_bridge_role(chan, "holding_participant");
1261  return -1;
1262  }
1263 
1264  agent_lock(agent);
1265  ast_channel_unref(agent->logged);
1266  agent->logged = ast_channel_ref(chan);
1267  agent_unlock(agent);
1268 
1269  /*
1270  * Kick the channel out so it can come back in fully controlled.
1271  * Otherwise, the after bridge callback will linger and the
1272  * agent will have some slightly different behavior in corner
1273  * cases.
1274  */
1277  return 0;
1278  }
1279 
1280  agent_lock(agent);
1281  switch (agent->state) {
1283  /*!
1284  * \todo XXX the login probation time should be only if it is needed.
1285  *
1286  * Need to determine if there are any local channels that can
1287  * optimize and wait until they actually do before leaving the
1288  * AGENT_STATE_PROBATION_WAIT state. For now, the blind
1289  * timer of LOGIN_WAIT_TIMEOUT_TIME will do.
1290  */
1291  /*
1292  * Start the login probation timer.
1293  *
1294  * We cannot handle an agent local channel optimization when the
1295  * agent is on a call. The optimization may kick the agent
1296  * channel we know about out of the call without our being able
1297  * to switch to the replacement channel. Get any agent local
1298  * channel optimization out of the way while the agent is in the
1299  * holding bridge.
1300  */
1301  time(&agent->probation_start);
1302  agent->state = AGENT_STATE_PROBATION_WAIT;
1303  agent_unlock(agent);
1304  break;
1306  /* Restart the probation timer. */
1307  time(&agent->probation_start);
1308  agent_unlock(agent);
1309  break;
1311  /*
1312  * Likely someone manually kicked us out of the holding bridge
1313  * and we came right back in.
1314  */
1315  agent_unlock(agent);
1316  break;
1317  default:
1318  /* Unexpected agent state. */
1319  ast_assert(0);
1320  /* Fall through */
1323  agent->state = AGENT_STATE_READY_FOR_CALL;
1324  agent->devstate = AST_DEVICE_NOT_INUSE;
1325  agent_unlock(agent);
1326  ast_debug(1, "Agent %s: Call abort recovery complete.\n", agent->username);
1327  agent_devstate_changed(agent->username);
1328  break;
1329  case AGENT_STATE_ON_CALL:
1331  wrapup_time = agent->cfg->wrapup_time;
1332  if (ast_test_flag(agent, AGENT_FLAG_WRAPUP_TIME)) {
1333  wrapup_time = agent->override_wrapup_time;
1334  }
1335  if (wrapup_time) {
1336  agent->state = AGENT_STATE_CALL_WRAPUP;
1337  } else {
1338  agent->state = AGENT_STATE_READY_FOR_CALL;
1339  agent->devstate = AST_DEVICE_NOT_INUSE;
1340  }
1341  agent_unlock(agent);
1342  if (!wrapup_time) {
1343  /* No wrapup time. */
1344  ast_debug(1, "Agent %s: Ready for new call.\n", agent->username);
1345  agent_devstate_changed(agent->username);
1346  }
1347  break;
1348  }
1349 
1350  return 0;
1351 }
Main Channel structure associated with a channel.
struct ast_bridge_features * features
#define agent_unlock(agent)
Unlock the agent.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
#define ast_test_flag(p, flag)
Definition: utils.h:63
void ast_channel_remove_bridge_role(struct ast_channel *chan, const char *role_name)
Removes a bridge role from a channel.
Definition: bridge_roles.c:336
static void agent_after_bridge_cb_failed(enum ast_bridge_after_cb_reason reason, void *data)
void __ao2_cleanup(void *obj)
Definition: astobj2.c:674
#define ast_assert(a)
Definition: utils.h:695
int ast_channel_add_bridge_role(struct ast_channel *chan, const char *role_name)
Adds a bridge role to a channel.
Definition: bridge_roles.c:317
#define NULL
Definition: resample.c:96
int ast_bridge_set_after_callback(struct ast_channel *chan, ast_bridge_after_cb callback, ast_bridge_after_cb_failed failed, void *data)
Setup an after bridge callback for when the channel leaves the bridging system.
Definition: bridge_after.c:259
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ast_bridge_methods ast_bridge_base_v_table
Bridge base class virtual method table.
Definition: bridge.c:949
int ast_channel_set_bridge_role_option(struct ast_channel *channel, const char *role_name, const char *option, const char *value)
Set a role option on a channel.
Definition: bridge_roles.c:379
#define agent_lock(agent)
Lock the agent.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:105
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static int bridge_agent_hold_heartbeat(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
int ast_bridge_interval_hook(struct ast_bridge_features *features, enum ast_bridge_hook_timer_option flags, unsigned int interval, ast_bridge_hook_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Attach an interval hook to a bridge features structure.
Definition: bridge.c:3382
Structure representing an agent.
void ast_bridge_channel_leave_bridge(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state, int cause)
Set bridge channel state to leave bridge (if not leaving already).
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1756
static int bridge_agent_hold_ack(struct ast_bridge_channel *bridge_channel, void *hook_pvt)
int ast_bridge_dtmf_hook(struct ast_bridge_features *features, const char *dtmf, ast_bridge_hook_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Attach a DTMF hook to a bridge features structure.
Definition: bridge.c:3245
struct ast_channel * chan
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2970
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define AST_FEATURE_MAX_LEN
ast_bridge_push_channel_fn push
Definition: bridge.h:273
static void agent_devstate_changed(const char *agent_id)
static struct ao2_container * agents
static void agent_after_bridge_cb(struct ast_channel *chan, void *data)

◆ bridge_init_agent_hold()

static void bridge_init_agent_hold ( void  )
static

Definition at line 1409 of file app_agent_pool.c.

References ast_bridge_base_v_table, bridge_agent_hold_dissolving(), bridge_agent_hold_pull(), bridge_agent_hold_push(), bridge_agent_hold_v_table, ast_bridge_methods::dissolving, ast_bridge_methods::name, ast_bridge_methods::pull, and ast_bridge_methods::push.

Referenced by load_module().

1410 {
1411  /* Setup bridge agent_hold subclass v_table. */
1413  bridge_agent_hold_v_table.name = "agent_hold";
1417 }
const char * name
Definition: bridge.h:267
ast_bridge_dissolving_fn dissolving
Definition: bridge.h:271
struct ast_bridge_methods ast_bridge_base_v_table
Bridge base class virtual method table.
Definition: bridge.c:949
static void bridge_agent_hold_pull(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel)
static void bridge_agent_hold_dissolving(struct ast_bridge *self)
The bridge is being dissolved.
ast_bridge_pull_channel_fn pull
Definition: bridge.h:275
ast_bridge_push_channel_fn push
Definition: bridge.h:273
static struct ast_bridge_methods bridge_agent_hold_v_table
static int bridge_agent_hold_push(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)

◆ caller_abort_agent()

static void caller_abort_agent ( struct agent_pvt agent)
static

Definition at line 1696 of file app_agent_pool.c.

References agent_bridge_channel_get_lock(), agent_lock, agent_unlock, ast_bridge_channel_leave_bridge_nolock(), ast_bridge_channel_unlock, ast_bridge_destroy(), AST_CAUSE_NORMAL_CLEARING, ast_debug, BRIDGE_CHANNEL_STATE_END, agent_pvt::caller_bridge, NULL, and agent_pvt::username.

Referenced by agent_request_exec(), caller_joined_bridge(), and caller_safety_timeout().

1697 {
1698  struct ast_bridge_channel *logged;
1699 
1700  logged = agent_bridge_channel_get_lock(agent);
1701  if (!logged) {
1702  struct ast_bridge *caller_bridge;
1703 
1704  ast_debug(1, "Agent '%s' no longer logged in.\n", agent->username);
1705 
1706  agent_lock(agent);
1707  caller_bridge = agent->caller_bridge;
1708  agent->caller_bridge = NULL;
1709  agent_unlock(agent);
1710  if (caller_bridge) {
1711  ast_bridge_destroy(caller_bridge, 0);
1712  }
1713  return;
1714  }
1715 
1716  /* Kick the agent out of the holding bridge to reset it. */
1719  ast_bridge_channel_unlock(logged);
1720 }
#define agent_unlock(agent)
Unlock the agent.
void ast_bridge_channel_leave_bridge_nolock(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state, int cause)
Set bridge channel state to leave bridge (if not leaving already).
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:970
#define NULL
Definition: resample.c:96
struct ast_bridge * caller_bridge
#define agent_lock(agent)
Lock the agent.
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:105
const ast_string_field username
#define ast_bridge_channel_unlock(bridge_channel)
Unlock the bridge_channel.
Structure that contains information about a bridge.
Definition: bridge.h:357
Structure that contains information regarding a channel in a bridge.
static struct ast_bridge_channel * agent_bridge_channel_get_lock(struct agent_pvt *agent)

◆ caller_joined_bridge()

static int caller_joined_bridge ( struct ast_bridge_channel bridge_channel,
void *  hook_pvt 
)
static

Definition at line 1847 of file app_agent_pool.c.

References agent_bridge_channel_get_lock(), ao2_ref, ast_bridge_channel_leave_bridge(), ast_bridge_channel_unlock, AST_CONTROL_RINGING, ast_indicate(), ast_verb, BRIDGE_CHANNEL_STATE_END, caller_abort_agent(), ast_bridge_channel::chan, pbx_builtin_setvar_helper(), send_alert_to_agent(), and agent_pvt::username.

Referenced by agent_request_exec().

1848 {
1849  struct agent_pvt *agent = hook_pvt;
1850  struct ast_bridge_channel *logged;
1851  int res;
1852 
1853  logged = agent_bridge_channel_get_lock(agent);
1854  if (!logged) {
1855  ast_verb(3, "Agent '%s' not logged in.\n", agent->username);
1856  pbx_builtin_setvar_helper(bridge_channel->chan, "AGENT_STATUS", "NOT_LOGGED_IN");
1857 
1859  caller_abort_agent(agent);
1860  return -1;
1861  }
1862 
1863  res = send_alert_to_agent(logged, agent->username);
1864  ast_bridge_channel_unlock(logged);
1865  ao2_ref(logged, -1);
1866  if (res) {
1867  ast_verb(3, "Agent '%s': Failed to alert the agent.\n", agent->username);
1868  pbx_builtin_setvar_helper(bridge_channel->chan, "AGENT_STATUS", "ERROR");
1869 
1871  caller_abort_agent(agent);
1872  return -1;
1873  }
1874 
1875  pbx_builtin_setvar_helper(bridge_channel->chan, "AGENT_STATUS", "NOT_CONNECTED");
1876  ast_indicate(bridge_channel->chan, AST_CONTROL_RINGING);
1877  return -1;
1878 }
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4322
#define ast_verb(level,...)
Definition: logger.h:463
const ast_string_field username
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_bridge_channel_unlock(bridge_channel)
Unlock the bridge_channel.
Structure representing an agent.
static void caller_abort_agent(struct agent_pvt *agent)
void ast_bridge_channel_leave_bridge(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state, int cause)
Set bridge channel state to leave bridge (if not leaving already).
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
struct ast_channel * chan
Structure that contains information regarding a channel in a bridge.
static struct ast_bridge_channel * agent_bridge_channel_get_lock(struct agent_pvt *agent)
static int send_alert_to_agent(struct ast_bridge_channel *bridge_channel, const char *agent_id)

◆ caller_safety_timeout()

static int caller_safety_timeout ( struct ast_bridge_channel bridge_channel,
void *  hook_pvt 
)
static

Definition at line 1722 of file app_agent_pool.c.

References AGENT_STATE_CALL_PRESENT, ast_bridge_channel_leave_bridge(), ast_log, BRIDGE_CHANNEL_STATE_END, caller_abort_agent(), ast_bridge_channel::chan, LOG_WARNING, pbx_builtin_setvar_helper(), agent_pvt::state, and agent_pvt::username.

Referenced by agent_request_exec().

1723 {
1724  struct agent_pvt *agent = hook_pvt;
1725 
1726  if (agent->state == AGENT_STATE_CALL_PRESENT) {
1727  ast_log(LOG_WARNING, "Agent '%s' process did not respond. Safety timeout.\n",
1728  agent->username);
1729  pbx_builtin_setvar_helper(bridge_channel->chan, "AGENT_STATUS", "ERROR");
1730 
1732  caller_abort_agent(agent);
1733  }
1734 
1735  return -1;
1736 }
enum agent_state state
#define LOG_WARNING
Definition: logger.h:274
#define ast_log
Definition: astobj2.c:42
const ast_string_field username
Structure representing an agent.
static void caller_abort_agent(struct agent_pvt *agent)
void ast_bridge_channel_leave_bridge(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state, int cause)
Set bridge channel state to leave bridge (if not leaving already).
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
struct ast_channel * chan

◆ clear_agent_status()

static void clear_agent_status ( struct ast_bridge_channel bridge_channel,
const void *  payload,
size_t  payload_size 
)
static

Definition at line 1017 of file app_agent_pool.c.

References ast_bridge_channel::chan, NULL, and pbx_builtin_setvar_helper().

Referenced by agent_connect_caller().

1018 {
1019  pbx_builtin_setvar_helper(bridge_channel->chan, "AGENT_STATUS", NULL);
1020 }
#define NULL
Definition: resample.c:96
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
struct ast_channel * chan

◆ complete_agent()

static char* complete_agent ( const char *  word,
int  state 
)
static

Definition at line 2277 of file app_agent_pool.c.

References ao2_callback_data, ao2_ref, ast_strdup, ast_strlen_zero, complete_agent_search(), NULL, OBJ_PARTIAL_KEY, state, agent_complete::state, and agent_pvt::username.

Referenced by agent_handle_show_specific().

2278 {
2279  char *ret;
2280  struct agent_pvt *agent;
2281  struct agent_complete search = {
2282  .state = state,
2283  };
2284 
2286  complete_agent_search, (char *) word, &search);
2287  if (!agent) {
2288  return NULL;
2289  }
2290  ret = ast_strdup(agent->username);
2291  ao2_ref(agent, -1);
2292  return ret;
2293 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
#define OBJ_PARTIAL_KEY
Definition: astobj2.h:1156
#define ast_strlen_zero(foo)
Definition: strings.h:52
const ast_string_field username
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Structure representing an agent.
#define ao2_callback_data(container, flags, cb_fn, arg, data)
Definition: astobj2.h:1743
static int complete_agent_search(void *obj, void *arg, void *data, int flags)
short word
static struct ao2_container * agents

◆ complete_agent_logoff()

static char* complete_agent_logoff ( const char *  word,
int  state 
)
static

Definition at line 2309 of file app_agent_pool.c.

References ao2_callback_data, ao2_ref, ast_strdup, ast_strlen_zero, complete_agent_logoff_search(), NULL, OBJ_PARTIAL_KEY, state, agent_complete::state, and agent_pvt::username.

Referenced by agent_handle_logoff_cmd().

2310 {
2311  char *ret;
2312  struct agent_pvt *agent;
2313  struct agent_complete search = {
2314  .state = state,
2315  };
2316 
2318  complete_agent_logoff_search, (char *) word, &search);
2319  if (!agent) {
2320  return NULL;
2321  }
2322  ret = ast_strdup(agent->username);
2323  ao2_ref(agent, -1);
2324  return ret;
2325 }
enum sip_cc_notify_state state
Definition: chan_sip.c:959
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
#define OBJ_PARTIAL_KEY
Definition: astobj2.h:1156
#define ast_strlen_zero(foo)
Definition: strings.h:52
const ast_string_field username
#define ao2_ref(o, delta)
Definition: astobj2.h:464
Structure representing an agent.
#define ao2_callback_data(container, flags, cb_fn, arg, data)
Definition: astobj2.h:1743
static int complete_agent_logoff_search(void *obj, void *arg, void *data, int flags)
short word
static struct ao2_container * agents

◆ complete_agent_logoff_search()

static int complete_agent_logoff_search ( void *  obj,
void *  arg,
void *  data,
int  flags 
)
static

Definition at line 2295 of file app_agent_pool.c.

References CMP_MATCH, agent_pvt::logged, agent_complete::state, and agent_complete::which.

Referenced by complete_agent_logoff().

2296 {
2297  struct agent_pvt *agent = obj;
2298  struct agent_complete *search = data;
2299 
2300  if (!agent->logged) {
2301  return 0;
2302  }
2303  if (++search->which > search->state) {
2304  return CMP_MATCH;
2305  }
2306  return 0;
2307 }
struct ast_channel * logged
Structure representing an agent.

◆ complete_agent_search()

static int complete_agent_search ( void *  obj,
void *  arg,
void *  data,
int  flags 
)
static

Definition at line 2267 of file app_agent_pool.c.

References CMP_MATCH, agent_complete::state, and agent_complete::which.

Referenced by complete_agent().

2268 {
2269  struct agent_complete *search = data;
2270 
2271  if (++search->which > search->state) {
2272  return CMP_MATCH;
2273  }
2274  return 0;
2275 }

◆ CONFIG_INFO_STANDARD()

CONFIG_INFO_STANDARD ( cfg_info  ,
cfg_handle  ,
agents_cfg_alloc  ,
files = ACO_FILES(&agents_conf),
post_apply_config = agents_post_apply_config 
)

Referenced by agents_cfg_alloc().

◆ destroy_config()

static void destroy_config ( void  )
static

Definition at line 537 of file app_agent_pool.c.

References aco_info_destroy(), ao2_global_obj_release, and cfg_handle.

Referenced by unload_module().

538 {
540  aco_info_destroy(&cfg_info);
541 }
void aco_info_destroy(struct aco_info *info)
Destroy an initialized aco_info struct.
#define ao2_global_obj_release(holder)
Definition: astobj2.h:865
static corosync_cfg_handle_t cfg_handle
Definition: res_corosync.c:284

◆ load_config()

static int load_config ( void  )
static

Definition at line 543 of file app_agent_pool.c.

References agent_cfg::ack_call, ACO_EXACT, aco_info_init(), aco_option_register, aco_process_config(), ACO_PROCESS_ERROR, agent_cfg::auto_logoff, agent_cfg::beep_sound, agent_cfg::dtmf_accept, FLDSET, agent_cfg::full_name, agent_cfg::moh, NULL, OPT_BOOL_T, OPT_STRINGFIELD_T, OPT_UINT_T, agent_cfg::record_agent_calls, STRFLDSET, and agent_cfg::wrapup_time.

Referenced by load_module(), and load_values_config().

544 {
545  if (aco_info_init(&cfg_info)) {
546  return -1;
547  }
548 
549  /* Agent options */
550  aco_option_register(&cfg_info, "ackcall", ACO_EXACT, agent_types, "no", OPT_BOOL_T, 1, FLDSET(struct agent_cfg, ack_call));
551  aco_option_register(&cfg_info, "acceptdtmf", ACO_EXACT, agent_types, "#", OPT_STRINGFIELD_T, 1, STRFLDSET(struct agent_cfg, dtmf_accept));
552  aco_option_register(&cfg_info, "autologoff", ACO_EXACT, agent_types, "0", OPT_UINT_T, 0, FLDSET(struct agent_cfg, auto_logoff));
553  aco_option_register(&cfg_info, "wrapuptime", ACO_EXACT, agent_types, "0", OPT_UINT_T, 0, FLDSET(struct agent_cfg, wrapup_time));
554  aco_option_register(&cfg_info, "musiconhold", ACO_EXACT, agent_types, "default", OPT_STRINGFIELD_T, 0, STRFLDSET(struct agent_cfg, moh));
555  aco_option_register(&cfg_info, "recordagentcalls", ACO_EXACT, agent_types, "no", OPT_BOOL_T, 1, FLDSET(struct agent_cfg, record_agent_calls));
556  aco_option_register(&cfg_info, "custom_beep", ACO_EXACT, agent_types, "beep", OPT_STRINGFIELD_T, 0, STRFLDSET(struct agent_cfg, beep_sound));
557  aco_option_register(&cfg_info, "fullname", ACO_EXACT, agent_types, NULL, OPT_STRINGFIELD_T, 0, STRFLDSET(struct agent_cfg, full_name));
558 
559  if (aco_process_config(&cfg_info, 0) == ACO_PROCESS_ERROR) {
560  return -1;
561  }
562 
563  return 0;
564 }
#define aco_option_register(info, name, matchtype, types, default_val, opt_type, flags,...)
Register a config option.
enum aco_process_status aco_process_config(struct aco_info *info, int reload)
Process a config info via the options registered with an aco_info.
#define NULL
Definition: resample.c:96
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
int aco_info_init(struct aco_info *info)
Initialize an aco_info structure.
Type for default option handler for unsigned integers.
Their was an error and no changes were applied.
Type for default option handler for bools (ast_true/ast_false)
#define STRFLDSET(type,...)
Convert a struct and a list of stringfield fields to an argument list of field offsets.
Type for default option handler for stringfields.
static struct aco_type * agent_types[]

◆ load_module()

static int load_module ( void  )
static

Definition at line 2656 of file app_agent_pool.c.

References action_agent_logoff(), action_agents(), agent_login_exec(), agent_pvt_cmp(), agent_pvt_devstate_get(), agent_pvt_sort_cmp(), agent_request_exec(), AO2_ALLOC_OPT_LOCK_MUTEX, AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, ao2_container_alloc_rbtree, app_agent_login, app_agent_request, ARRAY_LEN, ast_cli_register_multiple, ast_custom_function_register, ast_devstate_prov_add(), ast_log, ast_manager_register_xml, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_register_application_xml, bridge_init_agent_hold(), EVENT_FLAG_AGENT, load_config(), LOG_ERROR, and unload_module().

Referenced by reload().

2657 {
2658  int res = 0;
2659 
2662  if (!agents) {
2663  return AST_MODULE_LOAD_DECLINE;
2664  }
2665 
2666  /* Init agent holding bridge v_table. */
2668 
2669  /* Setup to provide Agent:agent-id device state. */
2671 
2672  /* CLI Commands */
2674 
2675  /* Manager commands */
2678 
2679  /* Dialplan Functions */
2681 
2682  /* Dialplan applications */
2685 
2686  if (res) {
2687  ast_log(LOG_ERROR, "Unable to register application. Not loading module.\n");
2688  unload_module();
2689  return AST_MODULE_LOAD_DECLINE;
2690  }
2691 
2692  if (load_config()) {
2693  ast_log(LOG_ERROR, "Unable to load config. Not loading module.\n");
2694  unload_module();
2695  return AST_MODULE_LOAD_DECLINE;
2696  }
2697 
2698  return AST_MODULE_LOAD_SUCCESS;
2699 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static int load_config(void)
static struct ast_cli_entry cli_agents[]
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
int ast_devstate_prov_add(const char *label, ast_devstate_prov_cb_type callback)
Add device state provider.
Definition: devicestate.c:391
static int agent_pvt_sort_cmp(const void *obj_left, const void *obj_right, int flags)
#define ast_log
Definition: astobj2.c:42
static int agent_request_exec(struct ast_channel *chan, const char *data)
Dialplan AgentRequest application to locate an agent to talk with.
static int agent_pvt_cmp(void *obj, void *arg, int flags)
#define LOG_ERROR
Definition: logger.h:285
static int unload_module(void)
#define EVENT_FLAG_AGENT
Definition: manager.h:76
static int action_agents(struct mansession *s, const struct message *m)
static int agent_login_exec(struct ast_channel *chan, const char *data)
Dialplan AgentLogin application to log in an agent.
static void bridge_init_agent_hold(void)
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static const char app_agent_request[]
Replace objects with duplicate keys in container.
Definition: astobj2.h:1215
static const char app_agent_login[]
static struct ast_custom_function agent_function
static int action_agent_logoff(struct mansession *s, const struct message *m)
#define ao2_container_alloc_rbtree(ao2_options, container_options, sort_fn, cmp_fn)
Definition: astobj2.h:1358
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:186
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1508
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626
static enum ast_device_state agent_pvt_devstate_get(const char *agent_id)
static struct ao2_container * agents

◆ reload()

static int reload ( void  )
static

Definition at line 2701 of file app_agent_pool.c.

References aco_process_config(), ACO_PROCESS_ERROR, AST_MODFLAG_LOAD_ORDER, AST_MODPRI_DEVSTATE_PROVIDER, AST_MODULE_INFO(), AST_MODULE_SUPPORT_CORE, ASTERISK_GPL_KEY, load_module(), and unload_module().

2702 {
2703  if (aco_process_config(&cfg_info, 1) == ACO_PROCESS_ERROR) {
2704  /* Just keep the config we already have in place. */
2705  return -1;
2706  }
2707  return 0;
2708 }
enum aco_process_status aco_process_config(struct aco_info *info, int reload)
Process a config info via the options registered with an aco_info.
Their was an error and no changes were applied.

◆ send_agent_login()

static void send_agent_login ( struct ast_channel chan,
const char *  agent 
)
static

Definition at line 1439 of file app_agent_pool.c.

References ast_assert, ast_channel_agent_login_type(), ast_channel_publish_blob(), ast_json_pack(), ast_json_unref(), NULL, and RAII_VAR.

Referenced by agent_login_exec().

1440 {
1441  RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
1442 
1443  ast_assert(agent != NULL);
1444 
1445  blob = ast_json_pack("{s: s}",
1446  "agent", agent);
1447  if (!blob) {
1448  return;
1449  }
1450 
1452 }
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
struct stasis_message_type * ast_channel_agent_login_type(void)
Message type for agent login on a channel.
Abstract JSON element (object, array, string, int, ...).
void ast_channel_publish_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Publish a channel blob message.

◆ send_agent_logoff()

static void send_agent_logoff ( struct ast_channel chan,
const char *  agent,
long  logintime 
)
static

Definition at line 1454 of file app_agent_pool.c.

References ast_assert, ast_channel_agent_logoff_type(), ast_channel_publish_blob(), ast_json_pack(), ast_json_unref(), NULL, and RAII_VAR.

Referenced by agent_logout().

1455 {
1456  RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
1457 
1458  ast_assert(agent != NULL);
1459 
1460  blob = ast_json_pack("{s: s, s: I}",
1461  "agent", agent,
1462  "logintime", (ast_json_int_t)logintime);
1463  if (!blob) {
1464  return;
1465  }
1466 
1468 }
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:591
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
AST_JSON_INT_T ast_json_int_t
Primarily used to cast when packing to an "I" type.
Definition: json.h:87
#define ast_assert(a)
Definition: utils.h:695
#define NULL
Definition: resample.c:96
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
struct stasis_message_type * ast_channel_agent_logoff_type(void)
Message type for agent logoff on a channel.
Abstract JSON element (object, array, string, int, ...).
void ast_channel_publish_blob(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob)
Publish a channel blob message.

◆ send_alert_to_agent()

static int send_alert_to_agent ( struct ast_bridge_channel bridge_channel,
const char *  agent_id 
)
static

Definition at line 1812 of file app_agent_pool.c.

References agent_alert(), AST_BRIDGE_CHANNEL_CB_OPTION_MEDIA, and ast_bridge_channel_queue_callback().

Referenced by caller_joined_bridge().

1813 {
1814  return ast_bridge_channel_queue_callback(bridge_channel,
1815  AST_BRIDGE_CHANNEL_CB_OPTION_MEDIA, agent_alert, agent_id, strlen(agent_id) + 1);
1816 }
static void agent_alert(struct ast_bridge_channel *bridge_channel, const void *payload, size_t payload_size)
int ast_bridge_channel_queue_callback(struct ast_bridge_channel *bridge_channel, enum ast_bridge_channel_custom_callback_option flags, ast_bridge_custom_callback_fn callback, const void *payload, size_t payload_size)
Queue a bridge action custom callback frame onto the bridge channel.

◆ send_colp_to_agent()

static int send_colp_to_agent ( struct ast_bridge_channel bridge_channel,
struct ast_party_connected_line connected 
)
static

Definition at line 1818 of file app_agent_pool.c.

References ast_bridge_channel_queue_control_data(), ast_connected_line_build_data(), AST_CONTROL_CONNECTED_LINE, ast_set_party_connected_line::id, and ast_set_party_id::name.

Referenced by agent_request_exec().

1819 {
1821  .id.name = 1,
1822  .id.number = 1,
1823  .id.subaddress = 1,
1824  };
1825  unsigned char data[1024]; /* This should be large enough */
1826  size_t datalen;
1827 
1828  datalen = ast_connected_line_build_data(data, sizeof(data), connected, &update);
1829  if (datalen == (size_t) -1) {
1830  return 0;
1831  }
1832 
1833  return ast_bridge_channel_queue_control_data(bridge_channel,
1834  AST_CONTROL_CONNECTED_LINE, data, datalen);
1835 }
int ast_connected_line_build_data(unsigned char *data, size_t datalen, const struct ast_party_connected_line *connected, const struct ast_set_party_connected_line *update)
Build the connected line information data frame.
Definition: channel.c:8793
static void update(int code_size, int y, int wi, int fi, int dq, int sr, int dqsez, struct g726_state *state_ptr)
Definition: codec_g726.c:367
Indicate what information in ast_party_connected_line should be set.
Definition: channel.h:490
int ast_bridge_channel_queue_control_data(struct ast_bridge_channel *bridge_channel, enum ast_control_frame_type control, const void *data, size_t datalen)
Queue a control frame onto the bridge channel with data.

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 2624 of file app_agent_pool.c.

References ao2_cleanup, ao2_global_obj_replace, app_agent_login, app_agent_request, ARRAY_LEN, ast_bridge_destroy(), ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_devstate_prov_del(), ast_manager_unregister(), ast_unregister_application(), destroy_config(), and NULL.

Referenced by load_module(), and reload().

2625 {
2626  struct ast_bridge *holding;
2627 
2628  /* Unregister dialplan applications */
2631 
2632  /* Unregister dialplan functions */
2634 
2635  /* Unregister manager command */
2636  ast_manager_unregister("Agents");
2637  ast_manager_unregister("AgentLogoff");
2638 
2639  /* Unregister CLI commands */
2641 
2642  ast_devstate_prov_del("Agent");
2643 
2644  /* Destroy agent holding bridge. */
2645  holding = ao2_global_obj_replace(agent_holding, NULL);
2646  if (holding) {
2647  ast_bridge_destroy(holding, 0);
2648  }
2649 
2650  destroy_config();
2652  agents = NULL;
2653  return 0;
2654 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
static struct ast_cli_entry cli_agents[]
int ast_devstate_prov_del(const char *label)
Remove device state provider.
Definition: devicestate.c:418
int ast_bridge_destroy(struct ast_bridge *bridge, int cause)
Destroy a bridge.
Definition: bridge.c:970
#define NULL
Definition: resample.c:96
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7258
Structure that contains information about a bridge.
Definition: bridge.h:357
static void destroy_config(void)
static const char app_agent_request[]
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static const char app_agent_login[]
static struct ast_custom_function agent_function
#define ao2_global_obj_replace(holder, obj)
Definition: astobj2.h:885
static struct ao2_container * agents

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Call center agent pool applications" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_DEVSTATE_PROVIDER, }
static

Definition at line 2716 of file app_agent_pool.c.

◆ agent_function

struct ast_custom_function agent_function
static
Initial value:
= {
.name = "AGENT",
}
static int agent_function_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)

Definition at line 2255 of file app_agent_pool.c.

◆ agent_holding_lock

ast_mutex_t agent_holding_lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, {1, 0} }
static

Agent holding bridge deferred creation lock.

Definition at line 1003 of file app_agent_pool.c.

Referenced by bridge_agent_hold_deferred_create().

◆ agent_login_opts

const struct ast_app_option agent_login_opts[128] = { [ 's' ] = { .flag = OPT_SILENT }, }
static

Definition at line 2101 of file app_agent_pool.c.

Referenced by agent_login_exec().

◆ agent_type

struct aco_type agent_type
static

Definition at line 465 of file app_agent_pool.c.

◆ agent_type_blacklist

const char* agent_type_blacklist[]
static
Initial value:
= {
"general",
"agents",
}
#define NULL
Definition: resample.c:96

Definition at line 459 of file app_agent_pool.c.

◆ agent_types

struct aco_type* agent_types[] = ACO_TYPES(&agent_type)
static

Definition at line 475 of file app_agent_pool.c.

◆ agents

struct ao2_container* agents
static

Container of defined agents.

Definition at line 649 of file app_agent_pool.c.

◆ agents_conf

struct aco_file agents_conf
static
Initial value:
= {
.filename = "agents.conf",
}
static struct aco_type agent_type
#define ACO_TYPES(...)
A helper macro to ensure that aco_info types always have a sentinel.
static struct aco_type general_type

Definition at line 485 of file app_agent_pool.c.

◆ app_agent_login

const char app_agent_login[] = "AgentLogin"
static

Definition at line 344 of file app_agent_pool.c.

Referenced by load_module(), and unload_module().

◆ app_agent_request

const char app_agent_request[] = "AgentRequest"
static

Definition at line 345 of file app_agent_pool.c.

Referenced by load_module(), and unload_module().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 2716 of file app_agent_pool.c.

◆ bridge_agent_hold_v_table

struct ast_bridge_methods bridge_agent_hold_v_table
static

Definition at line 1394 of file app_agent_pool.c.

Referenced by bridge_agent_hold_new(), and bridge_init_agent_hold().

◆ cli_agents

struct ast_cli_entry cli_agents[]
static

Definition at line 2520 of file app_agent_pool.c.

◆ general_type

struct aco_type general_type
static

Definition at line 478 of file app_agent_pool.c.