Wed Jan 8 2020 09:49:59

Asterisk developer's documentation


chan_agent.c File Reference

Implementation of Agents (proxy channel) More...

#include "asterisk.h"
#include <sys/socket.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/signal.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/file.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/musiconhold.h"
#include "asterisk/manager.h"
#include "asterisk/features.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/astdb.h"
#include "asterisk/devicestate.h"
#include "asterisk/monitor.h"
#include "asterisk/stringfields.h"
#include "asterisk/event.h"
#include "asterisk/data.h"

Go to the source code of this file.

Data Structures

struct  agent_pvt
 Structure representing an agent. More...
 
struct  agents
 

Macros

#define AST_MAX_AGENT   80
 
#define AST_MAX_BUF   256
 
#define AST_MAX_FILENAME_LEN   256
 
#define CHECK_FORMATS(ast, p)
 
#define CLEANUP(ast, p)
 Cleanup moves all the relevant FD's from the 2nd to the first, but retains things properly for a timingfd XXX This might need more work if agents were logged in as agents or other totally impractical combinations XXX. More...
 
#define DATA_EXPORT_AGENT(MEMBER)
 
#define DEFAULT_ACCEPTDTMF   '#'
 
#define DEFAULT_ENDDTMF   '*'
 
#define GETAGENTBYCALLERID   "AGENTBYCALLERID"
 
#define PA_MAX_LEN   2048
 

Enumerations

enum  {
  AGENT_FLAG_ACKCALL = (1 << 0), AGENT_FLAG_AUTOLOGOFF = (1 << 1), AGENT_FLAG_WRAPUPTIME = (1 << 2), AGENT_FLAG_ACCEPTDTMF = (1 << 3),
  AGENT_FLAG_ENDDTMF = (1 << 4)
}
 

Functions

static int __agent_start_monitoring (struct ast_channel *ast, struct agent_pvt *p, int needlock)
 
static void __reg_module (void)
 
static void __unreg_module (void)
 
static int action_agent_logoff (struct mansession *s, const struct message *m)
 
static int action_agents (struct mansession *s, const struct message *m)
 
static struct agent_pvtadd_agent (const char *agent, int pending)
 
static int agent_ack_sleep (struct agent_pvt *p)
 
static int agent_answer (struct ast_channel *ast)
 
static struct ast_channelagent_bridgedchannel (struct ast_channel *chan, struct ast_channel *bridge)
 
static int agent_call (struct ast_channel *ast, char *dest, int timeout)
 
static int agent_cleanup (struct agent_pvt *p)
 
static int agent_cont_sleep (void *data)
 
static int agent_devicestate (void *data)
 Part of PBX channel interface. More...
 
static int agent_digit_begin (struct ast_channel *ast, char digit)
 
static int agent_digit_end (struct ast_channel *ast, char digit, unsigned int duration)
 
static int agent_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
 
static struct ast_channelagent_get_base_channel (struct ast_channel *chan)
 return the channel or base channel if one exists. This function assumes the channel it is called on is already locked More...
 
static int agent_hangup (struct ast_channel *ast)
 
static int agent_indicate (struct ast_channel *ast, int condition, const void *data, size_t datalen)
 
static struct ast_channelagent_lock_owner (struct agent_pvt *pvt)
 Locks the owning channel for a LOCKED pvt while obeying locking order. The pvt must enter this function locked and will be returned locked, but this function will unlock the pvt for a short time, so it can't be used while expecting the pvt to remain static. If function returns a non NULL channel, it will need to be unlocked and unrefed once it is no longer needed. More...
 
static int agent_logoff (const char *agent, int soft)
 
static char * agent_logoff_cmd (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static struct ast_channelagent_new (struct agent_pvt *p, int state, const char *linkedid)
 Create new agent channel. More...
 
static void agent_pvt_destroy (struct agent_pvt *doomed)
 
static struct ast_frameagent_read (struct ast_channel *ast)
 
static struct ast_channelagent_request (const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
 Part of the Asterisk PBX interface. More...
 
static int agent_sendhtml (struct ast_channel *ast, int subclass, const char *data, int datalen)
 
static int agent_sendtext (struct ast_channel *ast, const char *text)
 
static int agent_start_monitoring (struct ast_channel *ast, int needlock)
 
static int agent_write (struct ast_channel *ast, struct ast_frame *f)
 
static int agentmonitoroutgoing_exec (struct ast_channel *chan, const char *data)
 Called by the AgentMonitorOutgoing application (from the dial plan). More...
 
static int agents_data_provider_get (const struct ast_data_search *search, struct ast_data *data_root)
 
static char * agents_show (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * agents_show_online (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
 AST_DATA_STRUCTURE (agent_pvt, DATA_EXPORT_AGENT)
 
static int check_availability (struct agent_pvt *newlyavailable, int needlock)
 
static int check_beep (struct agent_pvt *newlyavailable, int needlock)
 
static char * complete_agent_logoff_cmd (const char *line, const char *word, int pos, int state)
 
static struct agent_pvtfind_agent (char *agentid)
 
static int function_agent (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 
static int load_module (void)
 Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other things it registers applications, cli commands and reads the cofiguration file. More...
 
static int login_exec (struct ast_channel *chan, const char *data)
 Log in agent application. More...
 
static force_inline int powerof (unsigned int d)
 
static int read_agent_config (int reload)
 
static int reload (void)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Agent Proxy Channel" , .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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .nonoptreq = "res_monitor,chan_local", }
 
static char acceptdtmf = DEFAULT_ACCEPTDTMF
 
static int ackcall
 
static struct ast_custom_function agent_function
 
static const char agent_logoff_usage []
 
static struct ast_channel_tech agent_tech
 Channel interface description for PBX integration. More...
 
static char agentgoodbye [AST_MAX_FILENAME_LEN] = "vm-goodbye"
 
static struct agents agents = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } , }
 
static struct ast_data_handler agents_data_provider
 
static struct ast_data_entry agents_data_providers []
 
static const char app [] = "AgentLogin"
 
static const char app3 [] = "AgentMonitorOutgoing"
 
static struct ast_module_infoast_module_info = &__mod_info
 
static int autologoff
 
static int autologoffunavail = 0
 
static char beep [AST_MAX_BUF] = "beep"
 
static struct ast_cli_entry cli_agents []
 
static const char config [] = "agents.conf"
 
static int endcall
 
static char enddtmf = DEFAULT_ENDDTMF
 
static ast_group_t group
 
static int maxlogintries = 3
 
static char moh [80] = "default"
 
static const char pa_family [] = "Agents"
 
static int recordagentcalls = 0
 
static char recordformat [AST_MAX_BUF] = ""
 
static char recordformatext [AST_MAX_BUF] = ""
 
static char savecallsin [AST_MAX_BUF] = ""
 
static const char tdesc [] = "Call Agent Proxy Channel"
 
static int updatecdr = 0
 
static char urlprefix [AST_MAX_BUF] = ""
 
static int wrapuptime
 

Detailed Description

Implementation of Agents (proxy channel)

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

This file is the implementation of Agents modules. It is a dynamic module that is loaded by Asterisk.

See also

Definition in file chan_agent.c.

Macro Definition Documentation

#define AST_MAX_AGENT   80

Agent ID or Password max length

Definition at line 211 of file chan_agent.c.

Referenced by agentmonitoroutgoing_exec(), complete_agent_logoff_cmd(), and login_exec().

#define AST_MAX_BUF   256
#define AST_MAX_FILENAME_LEN   256

Definition at line 213 of file chan_agent.c.

Referenced by login_exec().

#define CHECK_FORMATS (   ast,
 
)

Definition at line 296 of file chan_agent.c.

Referenced by agent_read(), and agent_write().

#define CLEANUP (   ast,
 
)

Cleanup moves all the relevant FD's from the 2nd to the first, but retains things properly for a timingfd XXX This might need more work if agents were logged in as agents or other totally impractical combinations XXX.

Definition at line 318 of file chan_agent.c.

Referenced by agent_call(), agent_read(), and agent_write().

#define DATA_EXPORT_AGENT (   MEMBER)

Definition at line 282 of file chan_agent.c.

#define DEFAULT_ACCEPTDTMF   '#'

Definition at line 218 of file chan_agent.c.

#define DEFAULT_ENDDTMF   '*'

Definition at line 219 of file chan_agent.c.

#define GETAGENTBYCALLERID   "AGENTBYCALLERID"

Definition at line 241 of file chan_agent.c.

Referenced by agentmonitoroutgoing_exec().

#define PA_MAX_LEN   2048

The maximum length of each persistent member agent database entry

Definition at line 216 of file chan_agent.c.

Enumeration Type Documentation

anonymous enum
Enumerator
AGENT_FLAG_ACKCALL 
AGENT_FLAG_AUTOLOGOFF 
AGENT_FLAG_WRAPUPTIME 
AGENT_FLAG_ACCEPTDTMF 
AGENT_FLAG_ENDDTMF 

Definition at line 243 of file chan_agent.c.

Function Documentation

static int __agent_start_monitoring ( struct ast_channel ast,
struct agent_pvt p,
int  needlock 
)
static

Definition at line 574 of file chan_agent.c.

References agent_pvt::agent, ast_cdr_alloc(), ast_cdr_setuserfield(), ast_log(), AST_MAX_BUF, ast_monitor_setjoinfiles(), ast_monitor_start(), ast_verbose(), ast_channel::cdr, LOG_ERROR, ast_channel::monitor, ast_channel::uniqueid, X_REC_IN, and X_REC_OUT.

Referenced by agent_start_monitoring(), and agentmonitoroutgoing_exec().

575 {
576  char tmp[AST_MAX_BUF],tmp2[AST_MAX_BUF], *pointer;
577  char filename[AST_MAX_BUF];
578  int res = -1;
579  if (!p)
580  return -1;
581  if (!ast->monitor) {
582  snprintf(filename, sizeof(filename), "agent-%s-%s",p->agent, ast->uniqueid);
583  /* substitute . for - */
584  if ((pointer = strchr(filename, '.')))
585  *pointer = '-';
586  snprintf(tmp, sizeof(tmp), "%s%s", savecallsin, filename);
587  ast_monitor_start(ast, recordformat, tmp, needlock, X_REC_IN | X_REC_OUT);
588  ast_monitor_setjoinfiles(ast, 1);
589  snprintf(tmp2, sizeof(tmp2), "%s%s.%s", urlprefix, filename, recordformatext);
590 #if 0
591  ast_verbose("name is %s, link is %s\n",tmp, tmp2);
592 #endif
593  if (!ast->cdr)
594  ast->cdr = ast_cdr_alloc();
595  ast_cdr_setuserfield(ast, tmp2);
596  res = 0;
597  } else
598  ast_log(LOG_ERROR, "Recording already started on that call.\n");
599  return res;
600 }
#define X_REC_IN
Definition: monitor.h:35
const ast_string_field uniqueid
Definition: channel.h:787
void ast_verbose(const char *fmt,...)
Definition: logger.c:1568
static char recordformatext[AST_MAX_BUF]
Definition: chan_agent.c:235
static char recordformat[AST_MAX_BUF]
Definition: chan_agent.c:234
struct ast_cdr * cdr
Definition: channel.h:766
void ast_monitor_setjoinfiles(struct ast_channel *chan, int turnon)
Definition: res_monitor.c:867
static char urlprefix[AST_MAX_BUF]
Definition: chan_agent.c:236
#define AST_MAX_BUF
Definition: chan_agent.c:212
#define X_REC_OUT
Definition: monitor.h:36
int ast_cdr_setuserfield(struct ast_channel *chan, const char *userfield)
Set CDR user field for channel (stored in CDR)
Definition: cdr.c:1057
int ast_monitor_start(struct ast_channel *chan, const char *format_spec, const char *fname_base, int need_lock, int stream_action)
Start monitoring a channel.
Definition: res_monitor.c:290
#define LOG_ERROR
Definition: logger.h:155
char agent[AST_MAX_AGENT]
Definition: chan_agent.c:269
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static char savecallsin[AST_MAX_BUF]
Definition: chan_agent.c:237
struct ast_channel_monitor * monitor
Definition: channel.h:769
struct ast_cdr * ast_cdr_alloc(void)
Allocate a CDR record.
Definition: cdr.c:499
static void __reg_module ( void  )
static

Definition at line 2541 of file chan_agent.c.

static void __unreg_module ( void  )
static

Definition at line 2541 of file chan_agent.c.

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

Sets an agent as no longer logged in in the Manager API. It is registered on load_module() and it gets called by the manager backend.

Parameters
s
m
Returns
See Also
action_agents(), load_module().

Definition at line 1653 of file chan_agent.c.

References agent_pvt::agent, agent_logoff(), ast_strlen_zero(), ast_true(), astman_get_header(), astman_send_ack(), and astman_send_error().

Referenced by load_module().

1654 {
1655  const char *agent = astman_get_header(m, "Agent");
1656  const char *soft_s = astman_get_header(m, "Soft"); /* "true" is don't hangup */
1657  int soft;
1658  int ret; /* return value of agent_logoff */
1659 
1660  if (ast_strlen_zero(agent)) {
1661  astman_send_error(s, m, "No agent specified");
1662  return 0;
1663  }
1664 
1665  soft = ast_true(soft_s) ? 1 : 0;
1666  ret = agent_logoff(agent, soft);
1667  if (ret == 0)
1668  astman_send_ack(s, m, "Agent logged out");
1669  else
1670  astman_send_error(s, m, "No such agent");
1671 
1672  return 0;
1673 }
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2135
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:1860
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static int agent_logoff(const char *agent, int soft)
Definition: chan_agent.c:1574
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:2130
static int action_agents ( struct mansession s,
const struct message m 
)
static

Lists agents and their status to the Manager API. It is registered on load_module() and it gets called by the manager backend. This function locks both the pvt and the channel that owns it for a while, but does not keep these locks.

Parameters
s
m
Returns
See Also
action_agent_logoff(), load_module().

Definition at line 1494 of file chan_agent.c.

References ast_channel::_bridge, agent_pvt::agent, agent_lock_owner(), ast_bridged_channel(), ast_channel_unlock, ast_channel_unref, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock, ast_mutex_unlock, ast_strdupa, ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_ack(), ast_channel::bridge, ast_channel::caller, agent_pvt::chan, ast_party_caller::id, agent_pvt::lock, agent_pvt::loginstart, agent_pvt::name, ast_channel::name, ast_party_id::number, agent_pvt::owner, S_COR, S_OR, status, ast_party_number::str, and ast_party_number::valid.

Referenced by load_module().

1495 {
1496  const char *id = astman_get_header(m,"ActionID");
1497  char idText[256] = "";
1498  struct agent_pvt *p;
1499  char *username = NULL;
1500  char *loginChan = NULL;
1501  char *talkingto = NULL;
1502  char *talkingtoChan = NULL;
1503  char *status = NULL;
1504  struct ast_channel *bridge;
1505 
1506  if (!ast_strlen_zero(id))
1507  snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id);
1508  astman_send_ack(s, m, "Agents will follow");
1510  AST_LIST_TRAVERSE(&agents, p, list) {
1511  struct ast_channel *owner;
1512  ast_mutex_lock(&p->lock);
1513  owner = agent_lock_owner(p);
1514 
1515  /* Status Values:
1516  AGENT_LOGGEDOFF - Agent isn't logged in
1517  AGENT_IDLE - Agent is logged in, and waiting for call
1518  AGENT_ONCALL - Agent is logged in, and on a call
1519  AGENT_UNKNOWN - Don't know anything about agent. Shouldn't ever get this. */
1520 
1521  username = S_OR(p->name, "None");
1522 
1523  /* Set a default status. It 'should' get changed. */
1524  status = "AGENT_UNKNOWN";
1525 
1526  if (p->chan) {
1527  loginChan = ast_strdupa(p->chan->name);
1528  if (owner && owner->_bridge) {
1529  talkingto = S_COR(p->chan->caller.id.number.valid,
1530  p->chan->caller.id.number.str, "n/a");
1531  if ((bridge = ast_bridged_channel(owner))) {
1532  talkingtoChan = ast_strdupa(bridge->name);
1533  } else {
1534  talkingtoChan = "n/a";
1535  }
1536  status = "AGENT_ONCALL";
1537  } else {
1538  talkingto = "n/a";
1539  talkingtoChan = "n/a";
1540  status = "AGENT_IDLE";
1541  }
1542  } else {
1543  loginChan = "n/a";
1544  talkingto = "n/a";
1545  talkingtoChan = "n/a";
1546  status = "AGENT_LOGGEDOFF";
1547  }
1548 
1549  if (owner) {
1550  ast_channel_unlock(owner);
1551  owner = ast_channel_unref(owner);
1552  }
1553 
1554  astman_append(s, "Event: Agents\r\n"
1555  "Agent: %s\r\n"
1556  "Name: %s\r\n"
1557  "Status: %s\r\n"
1558  "LoggedInChan: %s\r\n"
1559  "LoggedInTime: %d\r\n"
1560  "TalkingTo: %s\r\n"
1561  "TalkingToChan: %s\r\n"
1562  "%s"
1563  "\r\n",
1564  p->agent, username, status, loginChan, (int)p->loginstart, talkingto, talkingtoChan, idText);
1565  ast_mutex_unlock(&p->lock);
1566  }
1568  astman_append(s, "Event: AgentsComplete\r\n"
1569  "%s"
1570  "\r\n",idText);
1571  return 0;
1572 }
Main Channel structure associated with a channel.
Definition: channel.h:742
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
ast_mutex_t lock
Definition: chan_agent.c:253
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:2068
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define ast_mutex_lock(a)
Definition: lock.h:155
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2135
static struct ast_channel * agent_lock_owner(struct agent_pvt *pvt)
Locks the owning channel for a LOCKED pvt while obeying locking order. The pvt must enter this functi...
Definition: chan_agent.c:382
char name[AST_MAX_AGENT]
Definition: chan_agent.c:271
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:1860
struct ast_channel * chan
Definition: chan_agent.c:277
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
time_t loginstart
Definition: chan_agent.c:262
struct ast_channel * _bridge
Definition: channel.h:748
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
Structure representing an agent.
Definition: chan_agent.c:252
char agent[AST_MAX_AGENT]
Definition: chan_agent.c:269
struct ast_channel * ast_bridged_channel(struct ast_channel *chan)
Find bridged channel.
Definition: channel.c:7160
const ast_string_field name
Definition: channel.h:787
struct ast_bridge * bridge
Definition: channel.h:865
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
jack_status_t status
Definition: app_jack.c:143
#define ast_mutex_unlock(a)
Definition: lock.h:156
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static struct agent_pvt* add_agent ( const char *  agent,
int  pending 
)
static

Adds an agent to the global list of agents.

Parameters
agentA string with the username, password and real name of an agent. As defined in agents.conf. Example: "13,169,John Smith"
pendingIf it is pending or not.
Returns
The just created agent.
See Also
agent_pvt, agents.

Definition at line 433 of file chan_agent.c.

References agent_pvt::acceptdtmf, agent_pvt::ackcall, agent_pvt::agent, AGENT_FLAG_ACCEPTDTMF, AGENT_FLAG_ACKCALL, AGENT_FLAG_AUTOLOGOFF, AGENT_FLAG_ENDDTMF, AGENT_FLAG_WRAPUPTIME, agent_pvt::app_complete_cond, agent_pvt::app_lock_flag, agent_pvt::app_sleep_cond, args, AST_APP_ARG, ast_calloc, ast_cond_init, ast_copy_string(), AST_DECLARE_APP_ARGS, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_log(), ast_mutex_init, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_tvnow(), agent_pvt::autologoff, agent_pvt::dead, agent_pvt::enddtmf, agent_pvt::group, agent_pvt::lastdisc, agent_pvt::lock, LOG_WARNING, agent_pvt::login_wait_cond, agent_pvt::moh, agent_pvt::name, parse(), agent_pvt::password, agent_pvt::pending, and agent_pvt::wrapuptime.

Referenced by agent_request(), and read_agent_config().

434 {
435  char *parse;
437  AST_APP_ARG(agt);
438  AST_APP_ARG(password);
439  AST_APP_ARG(name);
440  );
441  char *password = NULL;
442  char *name = NULL;
443  char *agt = NULL;
444  struct agent_pvt *p;
445 
446  parse = ast_strdupa(agent);
447 
448  /* Extract username (agt), password and name from agent (args). */
449  AST_STANDARD_APP_ARGS(args, parse);
450 
451  if(args.argc == 0) {
452  ast_log(LOG_WARNING, "A blank agent line!\n");
453  return NULL;
454  }
455 
456  if(ast_strlen_zero(args.agt) ) {
457  ast_log(LOG_WARNING, "An agent line with no agentid!\n");
458  return NULL;
459  } else
460  agt = args.agt;
461 
462  if(!ast_strlen_zero(args.password)) {
463  password = args.password;
464  while (*password && *password < 33) password++;
465  }
466  if(!ast_strlen_zero(args.name)) {
467  name = args.name;
468  while (*name && *name < 33) name++;
469  }
470 
471  if (!pending) {
472  /* Are we searching for the agent here ? To see if it exists already ? */
474  if (!strcmp(p->agent, agt)) {
475  break;
476  }
477  }
478  } else {
479  p = NULL;
480  }
481  if (!p) {
482  // Build the agent.
483  if (!(p = ast_calloc(1, sizeof(*p))))
484  return NULL;
485  ast_copy_string(p->agent, agt, sizeof(p->agent));
486  ast_mutex_init(&p->lock);
487  ast_cond_init(&p->app_complete_cond, NULL);
488  ast_cond_init(&p->login_wait_cond, NULL);
489  p->app_lock_flag = 0;
490  p->app_sleep_cond = 1;
491  p->group = group;
492  p->pending = pending;
494  }
495 
496  ast_copy_string(p->password, password ? password : "", sizeof(p->password));
497  ast_copy_string(p->name, name ? name : "", sizeof(p->name));
498  ast_copy_string(p->moh, moh, sizeof(p->moh));
500  p->ackcall = ackcall;
501  }
503  p->autologoff = autologoff;
504  }
506  p->acceptdtmf = acceptdtmf;
507  }
509  p->enddtmf = enddtmf;
510  }
511 
512  /* If someone reduces the wrapuptime and reloads, we want it
513  * to change the wrapuptime immediately on all calls */
515  struct timeval now = ast_tvnow();
516  /* XXX check what is this exactly */
517 
518  /* We won't be pedantic and check the tv_usec val */
519  if (p->lastdisc.tv_sec > (now.tv_sec + wrapuptime/1000)) {
520  p->lastdisc.tv_sec = now.tv_sec + wrapuptime/1000;
521  p->lastdisc.tv_usec = now.tv_usec;
522  }
523  }
524  p->wrapuptime = wrapuptime;
525 
526  if (pending)
527  p->dead = 1;
528  else
529  p->dead = 0;
530  return p;
531 }
char password[AST_MAX_AGENT]
Definition: chan_agent.c:270
char acceptdtmf
Definition: chan_agent.c:260
ast_mutex_t lock
Definition: chan_agent.c:253
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define LOG_WARNING
Definition: logger.h:144
static int ackcall
Definition: chan_agent.c:224
int wrapuptime
Definition: chan_agent.c:265
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
static int wrapuptime
Definition: chan_agent.c:223
int pending
Definition: chan_agent.c:255
#define ast_cond_init(cond, attr)
Definition: lock.h:167
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
char moh[80]
Definition: chan_agent.c:268
ast_cond_t login_wait_cond
Definition: chan_agent.c:274
char name[AST_MAX_AGENT]
Definition: chan_agent.c:271
int ackcall
Definition: chan_agent.c:258
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static char enddtmf
Definition: chan_agent.c:228
ast_cond_t app_complete_cond
Definition: chan_agent.c:273
ast_group_t group
Definition: chan_agent.c:266
static char moh[80]
Definition: chan_agent.c:209
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
int app_sleep_cond
Definition: chan_agent.c:275
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
Structure representing an agent.
Definition: chan_agent.c:252
static struct @350 args
char agent[AST_MAX_AGENT]
Definition: chan_agent.c:269
struct agent_pvt::@78 list
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
static const char name[]
static int autologoff
Definition: chan_agent.c:222
static char acceptdtmf
Definition: chan_agent.c:227
struct timeval lastdisc
Definition: chan_agent.c:264
int app_lock_flag
Definition: chan_agent.c:272
#define ast_calloc(a, b)
Definition: astmm.h:82
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
char enddtmf
Definition: chan_agent.c:261
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define ast_mutex_init(pmutex)
Definition: lock.h:152
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
int autologoff
Definition: chan_agent.c:257
static ast_group_t group
Definition: chan_agent.c:221
static int agent_ack_sleep ( struct agent_pvt p)
static

Definition at line 999 of file chan_agent.c.

References agent_pvt::acceptdtmf, agent_pvt::app_sleep_cond, AST_FRAME_DTMF, ast_frfree, ast_mutex_lock, ast_mutex_unlock, ast_read(), ast_remaining_ms(), ast_tvdiff_ms(), ast_tvnow(), ast_waitfor(), agent_pvt::chan, f, ast_frame::frametype, ast_frame_subclass::integer, agent_pvt::lastdisc, agent_pvt::lock, and ast_frame::subclass.

Referenced by login_exec().

1000 {
1001  int digit;
1002  int to = 1000;
1003  struct ast_frame *f;
1004  struct timeval start = ast_tvnow();
1005  int ms;
1006 
1007  /* Wait a second and look for something */
1008  while ((ms = ast_remaining_ms(start, to))) {
1009  ms = ast_waitfor(p->chan, ms);
1010  if (ms < 0) {
1011  return -1;
1012  }
1013  if (ms == 0) {
1014  return 0;
1015  }
1016  f = ast_read(p->chan);
1017  if (!f) {
1018  return -1;
1019  }
1020  if (f->frametype == AST_FRAME_DTMF) {
1021  digit = f->subclass.integer;
1022  } else {
1023  digit = 0;
1024  }
1025  ast_frfree(f);
1026  ast_mutex_lock(&p->lock);
1027  if (!p->app_sleep_cond) {
1028  ast_mutex_unlock(&p->lock);
1029  return 0;
1030  }
1031  if (digit == p->acceptdtmf) {
1032  ast_mutex_unlock(&p->lock);
1033  return 1;
1034  }
1035  if (p->lastdisc.tv_sec) {
1036  if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > 0) {
1037  ast_mutex_unlock(&p->lock);
1038  return 0;
1039  }
1040  }
1041  ast_mutex_unlock(&p->lock);
1042  }
1043  return 0;
1044 }
union ast_frame_subclass subclass
Definition: frame.h:146
char acceptdtmf
Definition: chan_agent.c:260
ast_mutex_t lock
Definition: chan_agent.c:253
#define AST_FRAME_DTMF
Definition: frame.h:128
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
#define ast_mutex_lock(a)
Definition: lock.h:155
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:90
struct ast_channel * chan
Definition: chan_agent.c:277
int app_sleep_cond
Definition: chan_agent.c:275
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: utils.c:1615
static struct ast_format f[]
Definition: format_g726.c:181
struct timeval lastdisc
Definition: chan_agent.c:264
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
Data structure associated with a single frame of data.
Definition: frame.h:142
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
#define ast_mutex_unlock(a)
Definition: lock.h:156
static int agent_answer ( struct ast_channel ast)
static

Definition at line 568 of file chan_agent.c.

References ast_log(), and LOG_WARNING.

569 {
570  ast_log(LOG_WARNING, "Huh? Agent is being asked to answer?\n");
571  return -1;
572 }
#define LOG_WARNING
Definition: logger.h:144
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static struct ast_channel * agent_bridgedchannel ( struct ast_channel chan,
struct ast_channel bridge 
)
static

Definition at line 1046 of file chan_agent.c.

References ast_channel::_bridge, ast_debug, agent_pvt::chan, ast_channel::name, and ast_channel::tech_pvt.

1047 {
1048  struct agent_pvt *p = bridge->tech_pvt;
1049  struct ast_channel *ret = NULL;
1050 
1051  if (p) {
1052  if (chan == p->chan)
1053  ret = bridge->_bridge;
1054  else if (chan == bridge->_bridge)
1055  ret = p->chan;
1056  }
1057 
1058  ast_debug(1, "Asked for bridged channel on '%s'/'%s', returning '%s'\n", chan->name, bridge->name, ret ? ret->name : "<none>");
1059  return ret;
1060 }
Main Channel structure associated with a channel.
Definition: channel.h:742
void * tech_pvt
Definition: channel.h:744
struct ast_channel * chan
Definition: chan_agent.c:277
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
struct ast_channel * _bridge
Definition: channel.h:748
Structure representing an agent.
Definition: chan_agent.c:252
const ast_string_field name
Definition: channel.h:787
static int agent_call ( struct ast_channel ast,
char *  dest,
int  timeout 
)
static

Definition at line 829 of file chan_agent.c.

References agent_pvt::ackcall, agent_pvt::acknowledged, agent_pvt::agent, agent_start_monitoring(), ast_assert, ast_best_codec(), ast_debug, ast_getformatname(), ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_set_read_format(), ast_set_write_format(), ast_setstate(), AST_STATE_DIALING, AST_STATE_RINGING, AST_STATE_UP, ast_streamfile(), ast_verb, ast_waitstream(), agent_pvt::chan, CLEANUP, ast_channel::language, agent_pvt::lock, LOG_DEBUG, LOG_WARNING, ast_channel::name, ast_channel::nativeformats, agent_pvt::pending, and ast_channel::tech_pvt.

830 {
831  struct agent_pvt *p = ast->tech_pvt;
832  int res;
833  int newstate=0;
834 
835  ast_mutex_lock(&p->lock);
836  p->acknowledged = 0;
837 
838  if (p->pending) {
839  ast_log(LOG_DEBUG, "Pretending to dial on pending agent\n");
840  ast_mutex_unlock(&p->lock);
842  return 0;
843  }
844 
845  ast_assert(p->chan != NULL);
846  ast_verb(3, "agent_call, call to agent '%s' call on '%s'\n", p->agent, p->chan->name);
847  ast_debug(3, "Playing beep, lang '%s'\n", p->chan->language);
848 
849  ast_mutex_unlock(&p->lock);
850 
851  res = ast_streamfile(p->chan, beep, p->chan->language);
852  ast_debug(3, "Played beep, result '%d'\n", res);
853  if (!res) {
854  res = ast_waitstream(p->chan, "");
855  ast_debug(3, "Waited for stream, result '%d'\n", res);
856  }
857 
858  ast_mutex_lock(&p->lock);
859 
860  if (!res) {
862  ast_debug(3, "Set read format, result '%d'\n", res);
863  if (res)
864  ast_log(LOG_WARNING, "Unable to set read format to %s\n", ast_getformatname(ast_best_codec(p->chan->nativeformats)));
865  }
866 
867  if (!res) {
869  ast_debug(3, "Set write format, result '%d'\n", res);
870  if (res)
871  ast_log(LOG_WARNING, "Unable to set write format to %s\n", ast_getformatname(ast_best_codec(p->chan->nativeformats)));
872  }
873  if(!res) {
874  /* Call is immediately up, or might need ack */
875  if (p->ackcall) {
876  newstate = AST_STATE_RINGING;
877  } else {
878  newstate = AST_STATE_UP;
879  if (recordagentcalls)
880  agent_start_monitoring(ast, 0);
881  p->acknowledged = 1;
882  }
883  }
884  CLEANUP(ast, p);
885  ast_mutex_unlock(&p->lock);
886  if (newstate)
887  ast_setstate(ast, newstate);
888  return res ? -1 : 0;
889 }
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:946
ast_mutex_t lock
Definition: chan_agent.c:253
void * tech_pvt
Definition: channel.h:744
#define LOG_WARNING
Definition: logger.h:144
int acknowledged
Definition: chan_agent.c:267
int pending
Definition: chan_agent.c:255
format_t ast_best_codec(format_t fmts)
Pick the best audio codec.
Definition: channel.c:1062
#define ast_assert(a)
Definition: utils.h:738
#define ast_mutex_lock(a)
Definition: lock.h:155
format_t nativeformats
Definition: channel.h:852
#define LOG_DEBUG
Definition: logger.h:122
static int recordagentcalls
Definition: chan_agent.c:233
#define ast_verb(level,...)
Definition: logger.h:243
int ackcall
Definition: chan_agent.c:258
struct ast_channel * chan
Definition: chan_agent.c:277
static char beep[AST_MAX_BUF]
Definition: chan_agent.c:239
int ast_set_write_format(struct ast_channel *chan, format_t format)
Sets write format on channel chan Set write format for channel to whichever component of &quot;format&quot; is ...
Definition: channel.c:5307
int ast_set_read_format(struct ast_channel *chan, format_t format)
Sets read format on channel chan Set read format for channel to whichever component of &quot;format&quot; is be...
Definition: channel.c:5301
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
char * ast_getformatname(format_t format)
Get the name of a format.
Definition: frame.c:578
#define CLEANUP(ast, p)
Cleanup moves all the relevant FD&#39;s from the 2nd to the first, but retains things properly for a timi...
Definition: chan_agent.c:318
Structure representing an agent.
Definition: chan_agent.c:252
char agent[AST_MAX_AGENT]
Definition: chan_agent.c:269
const ast_string_field name
Definition: channel.h:787
static int agent_start_monitoring(struct ast_channel *ast, int needlock)
Definition: chan_agent.c:602
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1343
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7119
const ast_string_field language
Definition: channel.h:787
#define ast_mutex_unlock(a)
Definition: lock.h:156
static int agent_cleanup ( struct agent_pvt p)
static

Deletes an agent after doing some clean up. Further documentation: How safe is this function ? What state should the agent be to be cleaned.

Warning
XXX This function seems to be very unsafe. Potential for double free and use after free among other problems.
Parameters
pAgent to be deleted.
Returns
Always 0.

Definition at line 544 of file chan_agent.c.

References agent_pvt_destroy(), agent_pvt::app_complete_cond, agent_pvt::app_lock_flag, agent_pvt::app_sleep_cond, ast_channel_release(), ast_cond_signal, ast_mutex_lock, ast_mutex_unlock, agent_pvt::chan, agent_pvt::dead, agent_pvt::lock, agent_pvt::owner, and ast_channel::tech_pvt.

Referenced by check_availability().

545 {
546  struct ast_channel *chan;
547 
548  ast_mutex_lock(&p->lock);
549  chan = p->owner;
550  p->owner = NULL;
551  /* Release ownership of the agent to other threads (presumably running the login app). */
552  p->app_sleep_cond = 1;
553  p->app_lock_flag = 0;
555  if (chan) {
556  chan->tech_pvt = NULL;
557  chan = ast_channel_release(chan);
558  }
559  if (p->dead) {
560  ast_mutex_unlock(&p->lock);
562  } else {
563  ast_mutex_unlock(&p->lock);
564  }
565  return 0;
566 }
Main Channel structure associated with a channel.
Definition: channel.h:742
ast_mutex_t lock
Definition: chan_agent.c:253
void * tech_pvt
Definition: channel.h:744
struct ast_channel * ast_channel_release(struct ast_channel *chan)
Unlink and release reference to a channel.
Definition: channel.c:1921
#define ast_mutex_lock(a)
Definition: lock.h:155
#define ast_cond_signal(cond)
Definition: lock.h:169
ast_cond_t app_complete_cond
Definition: chan_agent.c:273
struct ast_channel * owner
Definition: chan_agent.c:276
int app_sleep_cond
Definition: chan_agent.c:275
int app_lock_flag
Definition: chan_agent.c:272
static void agent_pvt_destroy(struct agent_pvt *doomed)
Definition: chan_agent.c:417
#define ast_mutex_unlock(a)
Definition: lock.h:156
static int agent_cont_sleep ( void *  data)
static

Definition at line 976 of file chan_agent.c.

References agent_pvt::app_sleep_cond, ast_debug, ast_mutex_lock, ast_mutex_unlock, ast_tvdiff_ms(), ast_tvnow(), agent_pvt::lastdisc, and agent_pvt::lock.

Referenced by login_exec().

977 {
978  struct agent_pvt *p;
979  int res;
980 
981  p = (struct agent_pvt *) data;
982 
983  ast_mutex_lock(&p->lock);
984  res = p->app_sleep_cond;
985  if (res && p->lastdisc.tv_sec) {
986  if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > 0) {
987  res = 0;
988  }
989  }
990  ast_mutex_unlock(&p->lock);
991 
992  if (!res) {
993  ast_debug(5, "agent_cont_sleep() returning %d\n", res);
994  }
995 
996  return res;
997 }
ast_mutex_t lock
Definition: chan_agent.c:253
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
#define ast_mutex_lock(a)
Definition: lock.h:155
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:90
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int app_sleep_cond
Definition: chan_agent.c:275
Structure representing an agent.
Definition: chan_agent.c:252
struct timeval lastdisc
Definition: chan_agent.c:264
#define ast_mutex_unlock(a)
Definition: lock.h:156
static int agent_devicestate ( void *  data)
static

Part of PBX channel interface.

Definition at line 2252 of file chan_agent.c.

References agent_pvt::agent, AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_UNAVAILABLE, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock, ast_mutex_unlock, agent_pvt::chan, agent_pvt::deferlogoff, agent_pvt::lastdisc, agent_pvt::lock, agent_pvt::owner, and agent_pvt::pending.

2253 {
2254  struct agent_pvt *p;
2255  const char *device = data;
2256  int res = AST_DEVICE_INVALID;
2257 
2258  if (device[0] == '@' || device[0] == ':') {
2259  /* Device state of groups not supported. */
2260  return AST_DEVICE_INVALID;
2261  }
2262 
2263  /* Want device state of a specific agent. */
2265  AST_LIST_TRAVERSE(&agents, p, list) {
2266  ast_mutex_lock(&p->lock);
2267  if (!p->pending && !strcmp(device, p->agent)) {
2268  if (p->owner) {
2269  res = AST_DEVICE_BUSY;
2270  } else if (p->chan) {
2271  if (p->lastdisc.tv_sec || p->deferlogoff) {
2272  /* Agent is in wrapup time so unavailable for another call. */
2273  res = AST_DEVICE_INUSE;
2274  } else {
2275  res = AST_DEVICE_NOT_INUSE;
2276  }
2277  } else {
2278  res = AST_DEVICE_UNAVAILABLE;
2279  }
2280  ast_mutex_unlock(&p->lock);
2281  break;
2282  }
2283  ast_mutex_unlock(&p->lock);
2284  }
2286  return res;
2287 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
ast_mutex_t lock
Definition: chan_agent.c:253
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
int pending
Definition: chan_agent.c:255
#define ast_mutex_lock(a)
Definition: lock.h:155
struct ast_channel * chan
Definition: chan_agent.c:277
int deferlogoff
Definition: chan_agent.c:259
struct ast_channel * owner
Definition: chan_agent.c:276
Structure representing an agent.
Definition: chan_agent.c:252
char agent[AST_MAX_AGENT]
Definition: chan_agent.c:269
struct agent_pvt::@78 list
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct timeval lastdisc
Definition: chan_agent.c:264
#define ast_mutex_unlock(a)
Definition: lock.h:156
static int agent_digit_begin ( struct ast_channel ast,
char  digit 
)
static

Definition at line 807 of file chan_agent.c.

References ast_mutex_lock, ast_mutex_unlock, ast_senddigit_begin(), agent_pvt::chan, agent_pvt::lock, and ast_channel::tech_pvt.

808 {
809  struct agent_pvt *p = ast->tech_pvt;
810  ast_mutex_lock(&p->lock);
811  if (p->chan) {
812  ast_senddigit_begin(p->chan, digit);
813  }
814  ast_mutex_unlock(&p->lock);
815  return 0;
816 }
ast_mutex_t lock
Definition: chan_agent.c:253
void * tech_pvt
Definition: channel.h:744
#define ast_mutex_lock(a)
Definition: lock.h:155
int ast_senddigit_begin(struct ast_channel *chan, char digit)
Send a DTMF digit to a channel.
Definition: channel.c:4705
struct ast_channel * chan
Definition: chan_agent.c:277
Structure representing an agent.
Definition: chan_agent.c:252
#define ast_mutex_unlock(a)
Definition: lock.h:156
static int agent_digit_end ( struct ast_channel ast,
char  digit,
unsigned int  duration 
)
static

Definition at line 818 of file chan_agent.c.

References ast_mutex_lock, ast_mutex_unlock, ast_senddigit_end(), agent_pvt::chan, agent_pvt::lock, and ast_channel::tech_pvt.

819 {
820  struct agent_pvt *p = ast->tech_pvt;
821  ast_mutex_lock(&p->lock);
822  if (p->chan) {
823  ast_senddigit_end(p->chan, digit, duration);
824  }
825  ast_mutex_unlock(&p->lock);
826  return 0;
827 }
ast_mutex_t lock
Definition: chan_agent.c:253
void * tech_pvt
Definition: channel.h:744
#define ast_mutex_lock(a)
Definition: lock.h:155
struct ast_channel * chan
Definition: chan_agent.c:277
int ast_senddigit_end(struct ast_channel *chan, char digit, unsigned int duration)
Send a DTMF digit to a channel.
Definition: channel.c:4755
Structure representing an agent.
Definition: chan_agent.c:252
#define ast_mutex_unlock(a)
Definition: lock.h:156
static int agent_fixup ( struct ast_channel oldchan,
struct ast_channel newchan 
)
static

Definition at line 773 of file chan_agent.c.

References ast_log(), ast_mutex_lock, ast_mutex_unlock, agent_pvt::lock, LOG_WARNING, agent_pvt::owner, and ast_channel::tech_pvt.

774 {
775  struct agent_pvt *p = newchan->tech_pvt;
776  ast_mutex_lock(&p->lock);
777  if (p->owner != oldchan) {
778  ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, p->owner);
779  ast_mutex_unlock(&p->lock);
780  return -1;
781  }
782  p->owner = newchan;
783  ast_mutex_unlock(&p->lock);
784  return 0;
785 }
ast_mutex_t lock
Definition: chan_agent.c:253
void * tech_pvt
Definition: channel.h:744
#define LOG_WARNING
Definition: logger.h:144
#define ast_mutex_lock(a)
Definition: lock.h:155
struct ast_channel * owner
Definition: chan_agent.c:276
Structure representing an agent.
Definition: chan_agent.c:252
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_mutex_unlock(a)
Definition: lock.h:156
struct ast_channel * agent_get_base_channel ( struct ast_channel chan)
static

return the channel or base channel if one exists. This function assumes the channel it is called on is already locked

Definition at line 892 of file chan_agent.c.

References ast_log(), agent_pvt::chan, LOG_ERROR, and ast_channel::tech_pvt.

893 {
894  struct agent_pvt *p;
895  struct ast_channel *base = chan;
896 
897  /* chan is locked by the calling function */
898  if (!chan || !chan->tech_pvt) {
899  ast_log(LOG_ERROR, "whoa, you need a channel (0x%ld) with a tech_pvt (0x%ld) to get a base channel.\n", (long)chan, (chan)?(long)chan->tech_pvt:(long)NULL);
900  return NULL;
901  }
902  p = chan->tech_pvt;
903  if (p->chan)
904  base = p->chan;
905  return base;
906 }
Main Channel structure associated with a channel.
Definition: channel.h:742
void * tech_pvt
Definition: channel.h:744
struct ast_channel * chan
Definition: chan_agent.c:277
#define LOG_ERROR
Definition: logger.h:155
Structure representing an agent.
Definition: chan_agent.c:252
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static int agent_hangup ( struct ast_channel ast)
static

Definition at line 908 of file chan_agent.c.

References ast_channel::_bridge, ast_channel::_state, agent_pvt::abouttograb, agent_pvt::acknowledged, agent_pvt_destroy(), agent_pvt::app_complete_cond, agent_pvt::app_lock_flag, agent_pvt::app_sleep_cond, ast_channel_ref, ast_channel_unref, ast_cond_signal, AST_CONTROL_HOLD, ast_debug, ast_indicate_data(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_mutex_lock, ast_mutex_unlock, ast_samp2tv(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, ast_state2str(), ast_strdupa, ast_strlen_zero(), ast_tvadd(), ast_tvnow(), agent_pvt::chan, agent_pvt::dead, agent_pvt::lastdisc, agent_pvt::lock, agent_pvt::loginstart, agent_pvt::moh, agent_pvt::owner, agent_pvt::pending, S_OR, agent_pvt::start, ast_channel::tech_pvt, and agent_pvt::wrapuptime.

909 {
910  struct agent_pvt *p = ast->tech_pvt;
911  struct ast_channel *indicate_chan = NULL;
912  char *tmp_moh; /* moh buffer for indicating after unlocking p */
913 
914  if (p->pending) {
916  AST_LIST_REMOVE(&agents, p, list);
918  }
919 
920  ast_mutex_lock(&p->lock);
921  p->owner = NULL;
922  ast->tech_pvt = NULL;
923  p->acknowledged = 0;
924 
925  /* if they really are hung up then set start to 0 so the test
926  * later if we're called on an already downed channel
927  * doesn't cause an agent to be logged out like when
928  * agent_request() is followed immediately by agent_hangup()
929  * as in apps/app_chanisavail.c:chanavail_exec()
930  */
931 
932  ast_debug(1, "Hangup called for state %s\n", ast_state2str(ast->_state));
933  p->start = 0;
934  if (p->chan) {
935  p->chan->_bridge = NULL;
936  /* If they're dead, go ahead and hang up on the agent now */
937  if (p->dead) {
939  } else if (p->loginstart) {
940  indicate_chan = ast_channel_ref(p->chan);
941  tmp_moh = ast_strdupa(p->moh);
942  }
943  }
944  ast_mutex_unlock(&p->lock);
945 
946  if (indicate_chan) {
947  ast_indicate_data(indicate_chan, AST_CONTROL_HOLD,
948  S_OR(tmp_moh, NULL),
949  !ast_strlen_zero(tmp_moh) ? strlen(tmp_moh) + 1 : 0);
950  indicate_chan = ast_channel_unref(indicate_chan);
951  }
952 
953  ast_mutex_lock(&p->lock);
954  if (p->abouttograb) {
955  /* Let the "about to grab" thread know this isn't valid anymore, and let it
956  kill it later */
957  p->abouttograb = 0;
958  } else if (p->dead) {
959  ast_mutex_unlock(&p->lock);
961  return 0;
962  } else {
963  /* Store last disconnect time */
965  }
966 
967  /* Release ownership of the agent to other threads (presumably running the login app). */
968  p->app_sleep_cond = 1;
969  p->app_lock_flag = 0;
971 
972  ast_mutex_unlock(&p->lock);
973  return 0;
974 }
Main Channel structure associated with a channel.
Definition: channel.h:742
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
ast_mutex_t lock
Definition: chan_agent.c:253
time_t start
Definition: chan_agent.c:263
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
void * tech_pvt
Definition: channel.h:744
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
int acknowledged
Definition: chan_agent.c:267
int wrapuptime
Definition: chan_agent.c:265
int pending
Definition: chan_agent.c:255
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
Definition: channel.c:4447
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
int abouttograb
Definition: chan_agent.c:256
char moh[80]
Definition: chan_agent.c:268
#define ast_mutex_lock(a)
Definition: lock.h:155
const char * ast_state2str(enum ast_channel_state)
Gives the string form of a given channel state.
Definition: channel.c:1007
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:841
#define ast_cond_signal(cond)
Definition: lock.h:169
struct ast_channel * chan
Definition: chan_agent.c:277
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2746
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:191
time_t loginstart
Definition: chan_agent.c:262
struct ast_channel * _bridge
Definition: channel.h:748
ast_cond_t app_complete_cond
Definition: chan_agent.c:273
struct ast_channel * owner
Definition: chan_agent.c:276
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
int app_sleep_cond
Definition: chan_agent.c:275
Structure representing an agent.
Definition: chan_agent.c:252
enum ast_channel_state _state
Definition: channel.h:839
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: utils.c:1587
struct timeval lastdisc
Definition: chan_agent.c:264
int app_lock_flag
Definition: chan_agent.c:272
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2491
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
static void agent_pvt_destroy(struct agent_pvt *doomed)
Definition: chan_agent.c:417
#define ast_mutex_unlock(a)
Definition: lock.h:156
static int agent_indicate ( struct ast_channel ast,
int  condition,
const void *  data,
size_t  datalen 
)
static

Definition at line 787 of file chan_agent.c.

References ast_channel_lock, ast_channel_unlock, ast_check_hangup(), ast_mutex_lock, ast_mutex_unlock, agent_pvt::chan, ast_channel_tech::indicate, agent_pvt::lock, ast_channel::tech, and ast_channel::tech_pvt.

788 {
789  struct agent_pvt *p = ast->tech_pvt;
790  int res = -1;
791 
792  ast_mutex_lock(&p->lock);
793  if (p->chan && !ast_check_hangup(p->chan)) {
794  ast_channel_unlock(ast);
796  res = p->chan->tech->indicate ? p->chan->tech->indicate(p->chan, condition, data, datalen) : -1;
798  ast_mutex_unlock(&p->lock);
799  ast_channel_lock(ast);
800  } else {
801  ast_mutex_unlock(&p->lock);
802  res = 0;
803  }
804  return res;
805 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
ast_mutex_t lock
Definition: chan_agent.c:253
void * tech_pvt
Definition: channel.h:744
#define ast_mutex_lock(a)
Definition: lock.h:155
struct ast_channel * chan
Definition: chan_agent.c:277
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:806
Structure representing an agent.
Definition: chan_agent.c:252
#define ast_channel_unlock(chan)
Definition: channel.h:2467
struct ast_channel_tech * tech
Definition: channel.h:743
int(*const indicate)(struct ast_channel *c, int condition, const void *data, size_t datalen)
Indicate a particular condition (e.g. AST_CONTROL_BUSY or AST_CONTROL_RINGING or AST_CONTROL_CONGESTI...
Definition: channel.h:576
#define ast_mutex_unlock(a)
Definition: lock.h:156
static struct ast_channel* agent_lock_owner ( struct agent_pvt pvt)
static

Locks the owning channel for a LOCKED pvt while obeying locking order. The pvt must enter this function locked and will be returned locked, but this function will unlock the pvt for a short time, so it can't be used while expecting the pvt to remain static. If function returns a non NULL channel, it will need to be unlocked and unrefed once it is no longer needed.

Parameters
pvtPointer to the LOCKED agent_pvt for which the owner is needed locked channel which owns the pvt at the time of completion. NULL if not available.

Definition at line 382 of file chan_agent.c.

References ast_channel_lock, ast_channel_ref, ast_channel_unlock, ast_channel_unref, ast_mutex_lock, ast_mutex_unlock, agent_pvt::lock, and agent_pvt::owner.

Referenced by action_agents(), agent_logoff(), agent_read(), agents_data_provider_get(), agents_show(), and agents_show_online().

383 {
384  struct ast_channel *owner;
385 
386  for (;;) {
387  if (!pvt->owner) { /* No owner. Nothing to do. */
388  return NULL;
389  }
390 
391  /* If we don't ref the owner, it could be killed when we unlock the pvt. */
392  owner = ast_channel_ref(pvt->owner);
393 
394  /* Locking order requires us to lock channel, then pvt. */
395  ast_mutex_unlock(&pvt->lock);
396  ast_channel_lock(owner);
397  ast_mutex_lock(&pvt->lock);
398 
399  /* Check if owner changed during pvt unlock period */
400  if (owner != pvt->owner) { /* Channel changed. Unref and do another pass. */
401  ast_channel_unlock(owner);
402  owner = ast_channel_unref(owner);
403  } else { /* Channel stayed the same. Return it. */
404  return owner;
405  }
406  }
407 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
Main Channel structure associated with a channel.
Definition: channel.h:742
ast_mutex_t lock
Definition: chan_agent.c:253
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
#define ast_mutex_lock(a)
Definition: lock.h:155
struct ast_channel * owner
Definition: chan_agent.c:276
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#define ast_channel_ref(c)
Increase channel reference count.
Definition: channel.h:2491
#define ast_mutex_unlock(a)
Definition: lock.h:156
static int agent_logoff ( const char *  agent,
int  soft 
)
static

Definition at line 1574 of file chan_agent.c.

References agent_pvt::agent, agent_lock_owner(), ast_channel_trylock, ast_channel_unlock, ast_channel_unref, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock, ast_mutex_unlock, ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, agent_pvt::chan, DEADLOCK_AVOIDANCE, agent_pvt::deferlogoff, agent_pvt::lock, and agent_pvt::owner.

Referenced by action_agent_logoff(), and agent_logoff_cmd().

1575 {
1576  struct agent_pvt *p;
1577  int ret = -1; /* Return -1 if no agent if found */
1578 
1580  AST_LIST_TRAVERSE(&agents, p, list) {
1581  if (!strcasecmp(p->agent, agent)) {
1582  ret = 0;
1583  if (p->owner || p->chan) {
1584  if (!soft) {
1585  struct ast_channel *owner;
1586  ast_mutex_lock(&p->lock);
1587  owner = agent_lock_owner(p);
1588 
1589  if (owner) {
1591  ast_channel_unlock(owner);
1592  owner = ast_channel_unref(owner);
1593  }
1594 
1595  while (p->chan && ast_channel_trylock(p->chan)) {
1596  DEADLOCK_AVOIDANCE(&p->lock);
1597  }
1598  if (p->chan) {
1601  }
1602 
1603  ast_mutex_unlock(&p->lock);
1604  } else
1605  p->deferlogoff = 1;
1606  }
1607  break;
1608  }
1609  }
1611 
1612  return ret;
1613 }
Main Channel structure associated with a channel.
Definition: channel.h:742
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
ast_mutex_t lock
Definition: chan_agent.c:253
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
#define DEADLOCK_AVOIDANCE(lock)
Definition: lock.h:485
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define ast_mutex_lock(a)
Definition: lock.h:155
static struct ast_channel * agent_lock_owner(struct agent_pvt *pvt)
Locks the owning channel for a LOCKED pvt while obeying locking order. The pvt must enter this functi...
Definition: chan_agent.c:382
struct ast_channel * chan
Definition: chan_agent.c:277
int deferlogoff
Definition: chan_agent.c:259
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2746
struct ast_channel * owner
Definition: chan_agent.c:276
Structure representing an agent.
Definition: chan_agent.c:252
char agent[AST_MAX_AGENT]
Definition: chan_agent.c:269
struct agent_pvt::@78 list
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#define ast_channel_trylock(chan)
Definition: channel.h:2468
#define ast_mutex_unlock(a)
Definition: lock.h:156
static char* agent_logoff_cmd ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 1615 of file chan_agent.c.

References agent_pvt::agent, agent_logoff(), ast_cli_args::argc, ast_cli_args::argv, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_agent_logoff_cmd(), ast_cli_args::fd, ast_cli_args::line, ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

1616 {
1617  int ret;
1618  const char *agent;
1619 
1620  switch (cmd) {
1621  case CLI_INIT:
1622  e->command = "agent logoff";
1623  e->usage =
1624  "Usage: agent logoff <channel> [soft]\n"
1625  " Sets an agent as no longer logged in.\n"
1626  " If 'soft' is specified, do not hangup existing calls.\n";
1627  return NULL;
1628  case CLI_GENERATE:
1629  return complete_agent_logoff_cmd(a->line, a->word, a->pos, a->n);
1630  }
1631 
1632  if (a->argc < 3 || a->argc > 4)
1633  return CLI_SHOWUSAGE;
1634  if (a->argc == 4 && strcasecmp(a->argv[3], "soft"))
1635  return CLI_SHOWUSAGE;
1636 
1637  agent = a->argv[2] + 6;
1638  ret = agent_logoff(agent, a->argc == 4);
1639  if (ret == 0)
1640  ast_cli(a->fd, "Logging out %s\n", agent);
1641 
1642  return CLI_SUCCESS;
1643 }
const int argc
Definition: cli.h:154
Definition: cli.h:146
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
const char * line
Definition: cli.h:156
const int fd
Definition: cli.h:153
const int n
Definition: cli.h:159
static char * complete_agent_logoff_cmd(const char *line, const char *word, int pos, int state)
Definition: chan_agent.c:1675
const char *const * argv
Definition: cli.h:155
static int agent_logoff(const char *agent, int soft)
Definition: chan_agent.c:1574
#define CLI_SHOWUSAGE
Definition: cli.h:44
char * command
Definition: cli.h:180
const char * word
Definition: cli.h:157
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
const int pos
Definition: cli.h:158
static struct ast_channel* agent_new ( struct agent_pvt p,
int  state,
const char *  linkedid 
)
static

Create new agent channel.

Definition at line 1063 of file chan_agent.c.

References agent_pvt::agent, agent_tech, ast_channel_alloc(), ast_copy_string(), AST_FORMAT_SLINEAR, ast_log(), ast_random(), ast_string_field_set, agent_pvt::chan, ast_channel::context, ast_channel::exten, language, ast_channel::language, LOG_WARNING, ast_channel::nativeformats, agent_pvt::owner, agent_pvt::pending, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::tech, ast_channel::tech_pvt, and ast_channel::writeformat.

Referenced by agent_request(), and check_availability().

1064 {
1065  struct ast_channel *tmp;
1066 #if 0
1067  if (!p->chan) {
1068  ast_log(LOG_WARNING, "No channel? :(\n");
1069  return NULL;
1070  }
1071 #endif
1072  if (p->pending)
1073  tmp = ast_channel_alloc(0, state, 0, 0, "", p->chan ? p->chan->exten:"", p->chan ? p->chan->context:"", linkedid, 0, "Agent/P%s-%d", p->agent, (int) ast_random() & 0xffff);
1074  else
1075  tmp = ast_channel_alloc(0, state, 0, 0, "", p->chan ? p->chan->exten:"", p->chan ? p->chan->context:"", linkedid, 0, "Agent/%s", p->agent);
1076  if (!tmp) {
1077  ast_log(LOG_WARNING, "Unable to allocate agent channel structure\n");
1078  return NULL;
1079  }
1080 
1081  tmp->tech = &agent_tech;
1082  if (p->chan) {
1083  tmp->nativeformats = p->chan->nativeformats;
1084  tmp->writeformat = p->chan->writeformat;
1085  tmp->rawwriteformat = p->chan->writeformat;
1086  tmp->readformat = p->chan->readformat;
1087  tmp->rawreadformat = p->chan->readformat;
1089  ast_copy_string(tmp->context, p->chan->context, sizeof(tmp->context));
1090  ast_copy_string(tmp->exten, p->chan->exten, sizeof(tmp->exten));
1091  /* XXX Is this really all we copy form the originating channel?? */
1092  } else {
1098  }
1099  /* Safe, agentlock already held */
1100  tmp->tech_pvt = p;
1101  p->owner = tmp;
1102  tmp->priority = 1;
1103  return tmp;
1104 }
Main Channel structure associated with a channel.
Definition: channel.h:742
int priority
Definition: channel.h:841
format_t writeformat
Definition: channel.h:854
void * tech_pvt
Definition: channel.h:744
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define LOG_WARNING
Definition: logger.h:144
format_t rawwriteformat
Definition: channel.h:856
int pending
Definition: chan_agent.c:255
format_t nativeformats
Definition: channel.h:852
const ast_string_field linkedid
Definition: channel.h:787
format_t rawreadformat
Definition: channel.h:855
struct ast_channel * ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const char *linkedid, const int amaflag, const char *name_fmt,...)
Definition: channel.c:9825
struct ast_channel * chan
Definition: chan_agent.c:277
long int ast_random(void)
Definition: utils.c:1640
static char language[MAX_LANGUAGE]
Definition: chan_alsa.c:108
struct ast_channel * owner
Definition: chan_agent.c:276
char agent[AST_MAX_AGENT]
Definition: chan_agent.c:269
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
format_t readformat
Definition: channel.h:853
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
struct ast_channel_tech * tech
Definition: channel.h:743
const ast_string_field language
Definition: channel.h:787
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
static struct ast_channel_tech agent_tech
Channel interface description for PBX integration.
Definition: chan_agent.c:349
static void agent_pvt_destroy ( struct agent_pvt doomed)
static

Definition at line 417 of file chan_agent.c.

References agent_pvt::app_complete_cond, ast_cond_destroy, ast_free, ast_mutex_destroy, agent_pvt::lock, and agent_pvt::login_wait_cond.

Referenced by agent_cleanup(), agent_hangup(), agent_request(), login_exec(), and read_agent_config().

418 {
419  ast_mutex_destroy(&doomed->lock);
422  ast_free(doomed);
423 }
ast_mutex_t lock
Definition: chan_agent.c:253
ast_cond_t login_wait_cond
Definition: chan_agent.c:274
ast_cond_t app_complete_cond
Definition: chan_agent.c:273
#define ast_cond_destroy(cond)
Definition: lock.h:168
#define ast_free(a)
Definition: astmm.h:97
#define ast_mutex_destroy(a)
Definition: lock.h:154
static struct ast_frame * agent_read ( struct ast_channel ast)
static

Definition at line 607 of file chan_agent.c.

References ast_channel::_bridge, ast_channel::_state, agent_pvt::acceptdtmf, agent_pvt::ackcall, agent_pvt::acknowledged, agent_lock_owner(), agent_start_monitoring(), AST_AGENT_FD, ast_channel_trylock, ast_channel_unlock, ast_channel_unref, AST_CONTROL_ANSWER, ast_copy_flags, ast_debug, AST_FLAG_EXCEPTION, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_null_frame, ast_read(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, AST_STATE_UP, AST_TIMING_FD, ast_verb, agent_pvt::autologoff, agent_pvt::chan, CHECK_FORMATS, CLEANUP, DEADLOCK_AVOIDANCE, agent_pvt::enddtmf, f, ast_channel::fdno, ast_frame::frametype, ast_frame_subclass::integer, agent_pvt::lock, LOG_NOTICE, agent_pvt::name, ast_channel::name, agent_pvt::owner, agent_pvt::start, ast_frame::subclass, ast_channel::tech, ast_channel::tech_pvt, and ast_channel_tech::type.

608 {
609  struct agent_pvt *p = ast->tech_pvt;
610  struct ast_frame *f = NULL;
611  static struct ast_frame answer_frame = { AST_FRAME_CONTROL, { AST_CONTROL_ANSWER } };
612  int cur_time = time(NULL);
613  struct ast_channel *owner;
614 
615  ast_mutex_lock(&p->lock);
616  owner = agent_lock_owner(p);
617 
618  CHECK_FORMATS(ast, p);
619  if (!p->start) {
620  p->start = cur_time;
621  }
622  if (p->chan) {
624  p->chan->fdno = (ast->fdno == AST_AGENT_FD) ? AST_TIMING_FD : ast->fdno;
625  f = ast_read(p->chan);
626  ast->fdno = -1;
627  } else
628  f = &ast_null_frame;
629  if (f) {
630  /* if acknowledgement is not required, and the channel is up, we may have missed
631  an AST_CONTROL_ANSWER (if there was one), so mark the call acknowledged anyway */
632  if (!p->ackcall && !p->acknowledged && p->chan && (p->chan->_state == AST_STATE_UP)) {
633  p->acknowledged = 1;
634  }
635 
636  if (!p->acknowledged) {
637  int howlong = cur_time - p->start;
638  if (p->autologoff && (howlong >= p->autologoff)) {
639  ast_log(LOG_NOTICE, "Agent '%s' didn't answer/confirm within %d seconds (waited %d)\n", p->name, p->autologoff, howlong);
640  if (owner || p->chan) {
641  if (owner) {
643  ast_channel_unlock(owner);
644  owner = ast_channel_unref(owner);
645  }
646 
647  while (p->chan && ast_channel_trylock(p->chan)) {
649  }
650  if (p->chan) {
653  }
654  }
655  }
656  }
657  switch (f->frametype) {
658  case AST_FRAME_CONTROL:
659  if (f->subclass.integer == AST_CONTROL_ANSWER) {
660  if (p->ackcall) {
661  ast_verb(3, "%s answered, waiting for '%c' to acknowledge\n", p->chan->name, p->acceptdtmf);
662  /* Don't pass answer along */
663  ast_frfree(f);
664  f = &ast_null_frame;
665  } else {
666  p->acknowledged = 1;
667  /* Use the builtin answer frame for the
668  recording start check below. */
669  ast_frfree(f);
670  f = &answer_frame;
671  }
672  }
673  break;
675  /*ignore DTMF begin's as it can cause issues with queue announce files*/
676  if((!p->acknowledged && f->subclass.integer == p->acceptdtmf) || (f->subclass.integer == p->enddtmf && endcall)){
677  ast_frfree(f);
678  f = &ast_null_frame;
679  }
680  break;
681  case AST_FRAME_DTMF_END:
682  if (!p->acknowledged && (f->subclass.integer == p->acceptdtmf)) {
683  if (p->chan) {
684  ast_verb(3, "%s acknowledged\n", p->chan->name);
685  }
686  p->acknowledged = 1;
687  ast_frfree(f);
688  f = &answer_frame;
689  } else if (f->subclass.integer == p->enddtmf && endcall) {
690  /* terminates call */
691  ast_frfree(f);
692  f = NULL;
693  }
694  break;
695  case AST_FRAME_VOICE:
696  case AST_FRAME_VIDEO:
697  /* don't pass voice or video until the call is acknowledged */
698  if (!p->acknowledged) {
699  ast_frfree(f);
700  f = &ast_null_frame;
701  }
702  default:
703  /* pass everything else on through */
704  break;
705  }
706  }
707 
708  if (owner) {
709  ast_channel_unlock(owner);
710  owner = ast_channel_unref(owner);
711  }
712 
713  CLEANUP(ast,p);
714  if (p->chan && !p->chan->_bridge) {
715  if (strcasecmp(p->chan->tech->type, "Local")) {
716  p->chan->_bridge = ast;
717  ast_debug(1, "Bridge on '%s' being set to '%s' (3)\n", p->chan->name, p->chan->_bridge->name);
718  }
719  }
720  ast_mutex_unlock(&p->lock);
721  if (recordagentcalls && f == &answer_frame)
722  agent_start_monitoring(ast,0);
723  return f;
724 }
union ast_frame_subclass subclass
Definition: frame.h:146
Main Channel structure associated with a channel.
Definition: channel.h:742
char acceptdtmf
Definition: chan_agent.c:260
const char *const type
Definition: channel.h:508
ast_mutex_t lock
Definition: chan_agent.c:253
struct ast_frame ast_null_frame
Definition: frame.c:131
#define AST_AGENT_FD
Definition: channel.h:165
time_t start
Definition: chan_agent.c:263
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
void * tech_pvt
Definition: channel.h:744
#define DEADLOCK_AVOIDANCE(lock)
Definition: lock.h:485
int acknowledged
Definition: chan_agent.c:267
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
#define ast_mutex_lock(a)
Definition: lock.h:155
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84
static int recordagentcalls
Definition: chan_agent.c:233
#define ast_verb(level,...)
Definition: logger.h:243
static struct ast_channel * agent_lock_owner(struct agent_pvt *pvt)
Locks the owning channel for a LOCKED pvt while obeying locking order. The pvt must enter this functi...
Definition: chan_agent.c:382
char name[AST_MAX_AGENT]
Definition: chan_agent.c:271
int ackcall
Definition: chan_agent.c:258
struct ast_channel * chan
Definition: chan_agent.c:277
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define CHECK_FORMATS(ast, p)
Definition: chan_agent.c:296
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2746
struct ast_channel * _bridge
Definition: channel.h:748
#define CLEANUP(ast, p)
Cleanup moves all the relevant FD&#39;s from the 2nd to the first, but retains things properly for a timi...
Definition: chan_agent.c:318
Structure representing an agent.
Definition: chan_agent.c:252
#define AST_TIMING_FD
Definition: channel.h:164
enum ast_channel_state _state
Definition: channel.h:839
const ast_string_field name
Definition: channel.h:787
static int agent_start_monitoring(struct ast_channel *ast, int needlock)
Definition: chan_agent.c:602
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
int fdno
Definition: channel.h:834
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static struct ast_format f[]
Definition: format_g726.c:181
char enddtmf
Definition: chan_agent.c:261
Data structure associated with a single frame of data.
Definition: frame.h:142
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_channel_trylock(chan)
Definition: channel.h:2468
#define ast_frfree(fr)
Definition: frame.h:583
struct ast_channel_tech * tech
Definition: channel.h:743
static int endcall
Definition: chan_agent.c:225
int autologoff
Definition: chan_agent.c:257
#define ast_mutex_unlock(a)
Definition: lock.h:156
static struct ast_channel * agent_request ( const char *  type,
format_t  format,
const struct ast_channel requestor,
void *  data,
int *  cause 
)
static

Part of the Asterisk PBX interface.

Definition at line 1370 of file chan_agent.c.

References add_agent(), agent_pvt::agent, agent_new(), agent_pvt_destroy(), agent_pvt::app_lock_flag, agent_pvt::app_sleep_cond, AST_CAUSE_BUSY, AST_CAUSE_UNREGISTERED, ast_cond_wait, AST_CONTROL_UNHOLD, ast_debug, ast_hangup(), ast_indicate(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock, ast_mutex_unlock, ast_null_frame, ast_queue_frame(), AST_STATE_DOWN, ast_tv(), ast_tvdiff_ms(), ast_tvnow(), agent_pvt::chan, agent_pvt::group, agent_pvt::lastdisc, ast_channel::linkedid, agent_pvt::lock, agent_pvt::login_wait_cond, agent_pvt::loginstart, agent_pvt::owner, and agent_pvt::pending.

1371 {
1372  struct agent_pvt *p;
1373  struct ast_channel *chan = NULL;
1374  char *s;
1375  ast_group_t groupmatch;
1376  int groupoff;
1377  int waitforagent=0;
1378  int hasagent = 0;
1379  struct timeval now;
1380 
1381  s = data;
1382  if ((s[0] == '@') && (sscanf(s + 1, "%30d", &groupoff) == 1)) {
1383  groupmatch = (1 << groupoff);
1384  } else if ((s[0] == ':') && (sscanf(s + 1, "%30d", &groupoff) == 1)) {
1385  groupmatch = (1 << groupoff);
1386  waitforagent = 1;
1387  } else
1388  groupmatch = 0;
1389 
1390  /* Check actual logged in agents first */
1392  AST_LIST_TRAVERSE(&agents, p, list) {
1393  ast_mutex_lock(&p->lock);
1394  if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) {
1395  if (p->chan) {
1396  hasagent++;
1397  }
1398  now = ast_tvnow();
1399  if (p->loginstart
1400  && (!p->lastdisc.tv_sec || ast_tvdiff_ms(now, p->lastdisc) > 0)) {
1401  p->lastdisc = ast_tv(0, 0);
1402  /* Agent must be registered, but not have any active call, and not be in a waiting state */
1403  if (!p->owner && p->chan) {
1404  /* Fixed agent */
1405  chan = agent_new(p, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL);
1406  }
1407  if (chan) {
1408  ast_mutex_unlock(&p->lock);
1409  break;
1410  }
1411  }
1412  }
1413  ast_mutex_unlock(&p->lock);
1414  }
1415 
1416  if (!chan && waitforagent) {
1417  /* No agent available -- but we're requesting to wait for one.
1418  Allocate a place holder */
1419  if (hasagent) {
1420  ast_debug(1, "Creating place holder for '%s'\n", s);
1421  p = add_agent(data, 1);
1422  if (p) {
1423  p->group = groupmatch;
1424  chan = agent_new(p, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL);
1425  if (!chan) {
1426  AST_LIST_REMOVE(&agents, p, list);
1427  agent_pvt_destroy(p);
1428  }
1429  }
1430  } else {
1431  ast_debug(1, "Not creating place holder for '%s' since nobody logged in\n", s);
1432  }
1433  }
1434  *cause = hasagent ? AST_CAUSE_BUSY : AST_CAUSE_UNREGISTERED;
1436 
1437  if (chan) {
1438  ast_mutex_lock(&p->lock);
1439  if (p->pending) {
1440  ast_mutex_unlock(&p->lock);
1441  return chan;
1442  }
1443 
1444  if (!p->chan) {
1445  ast_debug(1, "Agent disconnected before we could connect the call\n");
1446  ast_mutex_unlock(&p->lock);
1447  ast_hangup(chan);
1448  *cause = AST_CAUSE_UNREGISTERED;
1449  return NULL;
1450  }
1451 
1452  /* we need to take control of the channel from the login app
1453  * thread */
1454  p->app_sleep_cond = 0;
1455  p->app_lock_flag = 1;
1458 
1459  if (!p->chan) {
1460  ast_debug(1, "Agent disconnected while we were connecting the call\n");
1461  ast_mutex_unlock(&p->lock);
1462  ast_hangup(chan);
1463  *cause = AST_CAUSE_UNREGISTERED;
1464  return NULL;
1465  }
1466 
1468  ast_mutex_unlock(&p->lock);
1469  }
1470 
1471  return chan;
1472 }
unsigned long long ast_group_t
Definition: channel.h:175
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
Main Channel structure associated with a channel.
Definition: channel.h:742
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
ast_mutex_t lock
Definition: chan_agent.c:253
struct ast_frame ast_null_frame
Definition: frame.c:131
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4393
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
int pending
Definition: chan_agent.c:255
#define ast_cond_wait(cond, mutex)
Definition: lock.h:171
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
static struct agent_pvt * add_agent(const char *agent, int pending)
Definition: chan_agent.c:433
#define ast_mutex_lock(a)
Definition: lock.h:155
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:90
ast_cond_t login_wait_cond
Definition: chan_agent.c:274
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
Definition: linkedlists.h:841
const ast_string_field linkedid
Definition: channel.h:787
struct ast_channel * chan
Definition: chan_agent.c:277
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
time_t loginstart
Definition: chan_agent.c:262
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel&#39;s frame queue.
Definition: channel.c:1558
ast_group_t group
Definition: chan_agent.c:266
struct ast_channel * owner
Definition: chan_agent.c:276
int app_sleep_cond
Definition: chan_agent.c:275
Structure representing an agent.
Definition: chan_agent.c:252
char agent[AST_MAX_AGENT]
Definition: chan_agent.c:269
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_CAUSE_UNREGISTERED
Definition: causes.h:153
struct timeval lastdisc
Definition: chan_agent.c:264
int app_lock_flag
Definition: chan_agent.c:272
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:179
#define AST_CAUSE_BUSY
Definition: causes.h:148
static struct ast_channel * agent_new(struct agent_pvt *p, int state, const char *linkedid)
Create new agent channel.
Definition: chan_agent.c:1063
static void agent_pvt_destroy(struct agent_pvt *doomed)
Definition: chan_agent.c:417
#define ast_mutex_unlock(a)
Definition: lock.h:156
static int agent_sendhtml ( struct ast_channel ast,
int  subclass,
const char *  data,
int  datalen 
)
static

Definition at line 726 of file chan_agent.c.

References ast_channel_sendhtml(), ast_mutex_lock, ast_mutex_unlock, agent_pvt::chan, agent_pvt::lock, and ast_channel::tech_pvt.

727 {
728  struct agent_pvt *p = ast->tech_pvt;
729  int res = -1;
730  ast_mutex_lock(&p->lock);
731  if (p->chan)
732  res = ast_channel_sendhtml(p->chan, subclass, data, datalen);
733  ast_mutex_unlock(&p->lock);
734  return res;
735 }
ast_mutex_t lock
Definition: chan_agent.c:253
void * tech_pvt
Definition: channel.h:744
#define ast_mutex_lock(a)
Definition: lock.h:155
struct ast_channel * chan
Definition: chan_agent.c:277
Structure representing an agent.
Definition: chan_agent.c:252
int ast_channel_sendhtml(struct ast_channel *channel, int subclass, const char *data, int datalen)
Sends HTML on given channel Send HTML or URL on link.
Definition: channel.c:5907
#define ast_mutex_unlock(a)
Definition: lock.h:156
static int agent_sendtext ( struct ast_channel ast,
const char *  text 
)
static

Definition at line 737 of file chan_agent.c.

References ast_mutex_lock, ast_mutex_unlock, ast_sendtext(), agent_pvt::chan, agent_pvt::lock, and ast_channel::tech_pvt.

738 {
739  struct agent_pvt *p = ast->tech_pvt;
740  int res = -1;
741  ast_mutex_lock(&p->lock);
742  if (p->chan)
743  res = ast_sendtext(p->chan, text);
744  ast_mutex_unlock(&p->lock);
745  return res;
746 }
ast_mutex_t lock
Definition: chan_agent.c:253
void * tech_pvt
Definition: channel.h:744
#define ast_mutex_lock(a)
Definition: lock.h:155
char * text
Definition: app_queue.c:1091
struct ast_channel * chan
Definition: chan_agent.c:277
Structure representing an agent.
Definition: chan_agent.c:252
#define ast_mutex_unlock(a)
Definition: lock.h:156
int ast_sendtext(struct ast_channel *chan, const char *text)
Sends text to a channel.
Definition: channel.c:4687
static int agent_start_monitoring ( struct ast_channel ast,
int  needlock 
)
static

Definition at line 602 of file chan_agent.c.

References __agent_start_monitoring(), and ast_channel::tech_pvt.

Referenced by agent_call(), and agent_read().

603 {
604  return __agent_start_monitoring(ast, ast->tech_pvt, needlock);
605 }
void * tech_pvt
Definition: channel.h:744
static int __agent_start_monitoring(struct ast_channel *ast, struct agent_pvt *p, int needlock)
Definition: chan_agent.c:574
static int agent_write ( struct ast_channel ast,
struct ast_frame f 
)
static

Definition at line 748 of file chan_agent.c.

References ast_debug, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_mutex_lock, ast_mutex_unlock, ast_write(), agent_pvt::chan, CHECK_FORMATS, CLEANUP, ast_frame_subclass::codec, ast_frame::frametype, agent_pvt::lock, ast_channel::name, ast_frame::subclass, ast_channel::tech_pvt, and ast_channel::writeformat.

749 {
750  struct agent_pvt *p = ast->tech_pvt;
751  int res = -1;
752  CHECK_FORMATS(ast, p);
753  ast_mutex_lock(&p->lock);
754  if (!p->chan)
755  res = 0;
756  else {
757  if ((f->frametype != AST_FRAME_VOICE) ||
758  (f->frametype != AST_FRAME_VIDEO) ||
759  (f->subclass.codec == p->chan->writeformat)) {
760  res = ast_write(p->chan, f);
761  } else {
762  ast_debug(1, "Dropping one incompatible %s frame on '%s' to '%s'\n",
763  f->frametype == AST_FRAME_VOICE ? "audio" : "video",
764  ast->name, p->chan->name);
765  res = 0;
766  }
767  }
768  CLEANUP(ast, p);
769  ast_mutex_unlock(&p->lock);
770  return res;
771 }
union ast_frame_subclass subclass
Definition: frame.h:146
ast_mutex_t lock
Definition: chan_agent.c:253
format_t writeformat
Definition: channel.h:854
void * tech_pvt
Definition: channel.h:744
#define ast_mutex_lock(a)
Definition: lock.h:155
format_t codec
Definition: frame.h:137
struct ast_channel * chan
Definition: chan_agent.c:277
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
#define CHECK_FORMATS(ast, p)
Definition: chan_agent.c:296
#define CLEANUP(ast, p)
Cleanup moves all the relevant FD&#39;s from the 2nd to the first, but retains things properly for a timi...
Definition: chan_agent.c:318
Structure representing an agent.
Definition: chan_agent.c:252
const ast_string_field name
Definition: channel.h:787
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition: channel.c:4916
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_mutex_unlock(a)
Definition: lock.h:156
static int agentmonitoroutgoing_exec ( struct ast_channel chan,
const char *  data 
)
static

Called by the AgentMonitorOutgoing application (from the dial plan).

Parameters
chan
data
Returns
See Also
login_exec(), load_module().

Definition at line 2199 of file chan_agent.c.

References __agent_start_monitoring(), agent_pvt::agent, ast_copy_string(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), AST_MAX_AGENT, AST_MAX_BUF, ast_strlen_zero(), ast_channel::caller, ast_channel::cdr, ast_cdr::channel, GETAGENTBYCALLERID, ast_party_caller::id, LOG_WARNING, ast_party_id::number, pbx_builtin_getvar_helper(), ast_party_number::str, and ast_party_number::valid.

Referenced by load_module().

2200 {
2201  int exitifnoagentid = 0;
2202  int nowarnings = 0;
2203  int changeoutgoing = 0;
2204  int res = 0;
2205  char agent[AST_MAX_AGENT];
2206 
2207  if (data) {
2208  if (strchr(data, 'd'))
2209  exitifnoagentid = 1;
2210  if (strchr(data, 'n'))
2211  nowarnings = 1;
2212  if (strchr(data, 'c'))
2213  changeoutgoing = 1;
2214  }
2215  if (chan->caller.id.number.valid
2216  && !ast_strlen_zero(chan->caller.id.number.str)) {
2217  const char *tmp;
2218  char agentvar[AST_MAX_BUF];
2219  snprintf(agentvar, sizeof(agentvar), "%s_%s", GETAGENTBYCALLERID,
2220  chan->caller.id.number.str);
2221  if ((tmp = pbx_builtin_getvar_helper(NULL, agentvar))) {
2222  struct agent_pvt *p;
2223  ast_copy_string(agent, tmp, sizeof(agent));
2225  AST_LIST_TRAVERSE(&agents, p, list) {
2226  if (!strcasecmp(p->agent, tmp)) {
2227  if (changeoutgoing) snprintf(chan->cdr->channel, sizeof(chan->cdr->channel), "Agent/%s", p->agent);
2228  __agent_start_monitoring(chan, p, 1);
2229  break;
2230  }
2231  }
2233 
2234  } else {
2235  res = -1;
2236  if (!nowarnings)
2237  ast_log(LOG_WARNING, "Couldn't find the global variable %s, so I can't figure out which agent (if it's an agent) is placing outgoing call.\n", agentvar);
2238  }
2239  } else {
2240  res = -1;
2241  if (!nowarnings)
2242  ast_log(LOG_WARNING, "There is no callerid on that call, so I can't figure out which agent (if it's an agent) is placing outgoing call.\n");
2243  }
2244  if (res) {
2245  if (exitifnoagentid)
2246  return res;
2247  }
2248  return 0;
2249 }
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
#define LOG_WARNING
Definition: logger.h:144
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
struct ast_cdr * cdr
Definition: channel.h:766
#define GETAGENTBYCALLERID
Definition: chan_agent.c:241
#define AST_MAX_BUF
Definition: chan_agent.c:212
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
static int __agent_start_monitoring(struct ast_channel *ast, struct agent_pvt *p, int needlock)
Definition: chan_agent.c:574
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
char channel[AST_MAX_EXTENSION]
Definition: cdr.h:92
Structure representing an agent.
Definition: chan_agent.c:252
char agent[AST_MAX_AGENT]
Definition: chan_agent.c:269
struct agent_pvt::@78 list
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define AST_MAX_AGENT
Definition: chan_agent.c:211
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static int agents_data_provider_get ( const struct ast_data_search search,
struct ast_data data_root 
)
static

Definition at line 2383 of file chan_agent.c.

References agent_pvt::agent, agent_lock_owner(), ast_bridged_channel(), ast_channel_data_add_structure(), ast_channel_unlock, ast_channel_unref, ast_data_add_bool(), ast_data_add_node(), ast_data_add_str(), ast_data_add_structure, ast_data_remove_node(), ast_data_search_match(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock, ast_mutex_unlock, agent_pvt::chan, agent_pvt::lock, agent_pvt::moh, agent_pvt::owner, and agent_pvt::pending.

2385 {
2386  struct agent_pvt *p;
2387  struct ast_data *data_agent, *data_channel, *data_talkingto;
2388 
2390  AST_LIST_TRAVERSE(&agents, p, list) {
2391  struct ast_channel *owner;
2392 
2393  data_agent = ast_data_add_node(data_root, "agent");
2394  if (!data_agent) {
2395  continue;
2396  }
2397 
2398  ast_mutex_lock(&p->lock);
2399  owner = agent_lock_owner(p);
2400 
2401  if (!(p->pending)) {
2402  ast_data_add_str(data_agent, "id", p->agent);
2403  ast_data_add_structure(agent_pvt, data_agent, p);
2404 
2405  ast_data_add_bool(data_agent, "logged", p->chan ? 1 : 0);
2406  if (p->chan) {
2407  data_channel = ast_data_add_node(data_agent, "loggedon");
2408  if (!data_channel) {
2409  ast_mutex_unlock(&p->lock);
2410  ast_data_remove_node(data_root, data_agent);
2411  if (owner) {
2412  ast_channel_unlock(owner);
2413  owner = ast_channel_unref(owner);
2414  }
2415  continue;
2416  }
2417  ast_channel_data_add_structure(data_channel, p->chan, 0);
2418  if (owner && ast_bridged_channel(owner)) {
2419  data_talkingto = ast_data_add_node(data_agent, "talkingto");
2420  if (!data_talkingto) {
2421  ast_mutex_unlock(&p->lock);
2422  ast_data_remove_node(data_root, data_agent);
2423  if (owner) {
2424  ast_channel_unlock(owner);
2425  owner = ast_channel_unref(owner);
2426  }
2427  continue;
2428  }
2429  ast_channel_data_add_structure(data_talkingto, ast_bridged_channel(owner), 0);
2430  }
2431  } else {
2432  ast_data_add_node(data_agent, "talkingto");
2433  ast_data_add_node(data_agent, "loggedon");
2434  }
2435  ast_data_add_str(data_agent, "musiconhold", p->moh);
2436  }
2437 
2438  if (owner) {
2439  ast_channel_unlock(owner);
2440  owner = ast_channel_unref(owner);
2441  }
2442 
2443  ast_mutex_unlock(&p->lock);
2444 
2445  /* if this agent doesn't match remove the added agent. */
2446  if (!ast_data_search_match(search, data_agent)) {
2447  ast_data_remove_node(data_root, data_agent);
2448  }
2449  }
2451 
2452  return 0;
2453 }
Main Channel structure associated with a channel.
Definition: channel.h:742
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
ast_mutex_t lock
Definition: chan_agent.c:253
The data tree to be returned by the callbacks and managed by functions local to this file...
Definition: data.c:85
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
int pending
Definition: chan_agent.c:255
struct ast_data * ast_data_add_bool(struct ast_data *root, const char *childname, unsigned int boolean)
Add a boolean node type.
Definition: data.c:2344
char moh[80]
Definition: chan_agent.c:268
#define ast_mutex_lock(a)
Definition: lock.h:155
static struct ast_channel * agent_lock_owner(struct agent_pvt *pvt)
Locks the owning channel for a LOCKED pvt while obeying locking order. The pvt must enter this functi...
Definition: chan_agent.c:382
struct ast_channel * chan
Definition: chan_agent.c:277
int ast_channel_data_add_structure(struct ast_data *tree, struct ast_channel *chan, int add_bridged)
Insert into an astdata tree, the channel structure.
Definition: channel.c:357
struct ast_data * ast_data_add_node(struct ast_data *root, const char *childname)
Add a container child.
Definition: data.c:2317
#define ast_data_add_structure(structure_name, root, structure)
Definition: data.h:620
Structure representing an agent.
Definition: chan_agent.c:252
void ast_data_remove_node(struct ast_data *root, struct ast_data *child)
Remove a node that was added using ast_data_add_.
Definition: data.c:2486
char agent[AST_MAX_AGENT]
Definition: chan_agent.c:269
struct ast_channel * ast_bridged_channel(struct ast_channel *chan)
Find bridged channel.
Definition: channel.c:7160
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_channel_unlock(chan)
Definition: channel.h:2467
struct ast_data * ast_data_add_str(struct ast_data *root, const char *childname, const char *string)
Add a string node type.
Definition: data.c:2401
int ast_data_search_match(const struct ast_data_search *search, struct ast_data *data)
Check the current generated node to know if it matches the search condition.
Definition: data.c:1458
#define ast_mutex_unlock(a)
Definition: lock.h:156
static char* agents_show ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Show agents in cli.

< Number of agents configured

< Number of online agents

< Number of offline agents

Definition at line 1702 of file chan_agent.c.

References agent_pvt::agent, agent_lock_owner(), ast_cli_args::argc, ast_bridged_channel(), ast_channel_unlock, ast_channel_unref, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, AST_MAX_BUF, ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), agent_pvt::chan, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, count_agents(), ast_cli_args::fd, agent_pvt::group, agent_pvt::lock, agent_pvt::moh, agent_pvt::name, ast_channel::name, agent_pvt::owner, agent_pvt::pending, powerof(), and ast_cli_entry::usage.

1703 {
1704  struct agent_pvt *p;
1705  char username[AST_MAX_BUF];
1706  char location[AST_MAX_BUF] = "";
1707  char talkingto[AST_MAX_BUF] = "";
1708  char music[AST_MAX_BUF];
1709  int count_agents = 0; /*!< Number of agents configured */
1710  int online_agents = 0; /*!< Number of online agents */
1711  int offline_agents = 0; /*!< Number of offline agents */
1712 
1713  switch (cmd) {
1714  case CLI_INIT:
1715  e->command = "agent show";
1716  e->usage =
1717  "Usage: agent show\n"
1718  " Provides summary information on agents.\n";
1719  return NULL;
1720  case CLI_GENERATE:
1721  return NULL;
1722  }
1723 
1724  if (a->argc != 2)
1725  return CLI_SHOWUSAGE;
1726 
1728  AST_LIST_TRAVERSE(&agents, p, list) {
1729  struct ast_channel *owner;
1730  ast_mutex_lock(&p->lock);
1731  owner = agent_lock_owner(p);
1732  if (p->pending) {
1733  if (p->group)
1734  ast_cli(a->fd, "-- Pending call to group %d\n", powerof(p->group));
1735  else
1736  ast_cli(a->fd, "-- Pending call to agent %s\n", p->agent);
1737  } else {
1738  if (!ast_strlen_zero(p->name))
1739  snprintf(username, sizeof(username), "(%s) ", p->name);
1740  else
1741  username[0] = '\0';
1742  if (p->chan) {
1743  snprintf(location, sizeof(location), "logged in on %s", p->chan->name);
1744  if (owner && ast_bridged_channel(owner)) {
1745  snprintf(talkingto, sizeof(talkingto), " talking to %s", ast_bridged_channel(p->owner)->name);
1746  } else {
1747  strcpy(talkingto, " is idle");
1748  }
1749  online_agents++;
1750  } else {
1751  strcpy(location, "not logged in");
1752  talkingto[0] = '\0';
1753  offline_agents++;
1754  }
1755  if (!ast_strlen_zero(p->moh))
1756  snprintf(music, sizeof(music), " (musiconhold is '%s')", p->moh);
1757  ast_cli(a->fd, "%-12.12s %s%s%s%s\n", p->agent,
1758  username, location, talkingto, music);
1759  count_agents++;
1760  }
1761 
1762  if (owner) {
1763  ast_channel_unlock(owner);
1764  owner = ast_channel_unref(owner);
1765  }
1766  ast_mutex_unlock(&p->lock);
1767  }
1769  if ( !count_agents )
1770  ast_cli(a->fd, "No Agents are configured in %s\n",config);
1771  else
1772  ast_cli(a->fd, "%d agents configured [%d online , %d offline]\n",count_agents, online_agents, offline_agents);
1773  ast_cli(a->fd, "\n");
1774 
1775  return CLI_SUCCESS;
1776 }
Main Channel structure associated with a channel.
Definition: channel.h:742
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
ast_mutex_t lock
Definition: chan_agent.c:253
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
const int argc
Definition: cli.h:154
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Definition: cli.h:146
int pending
Definition: chan_agent.c:255
char moh[80]
Definition: chan_agent.c:268
#define ast_mutex_lock(a)
Definition: lock.h:155
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
#define AST_MAX_BUF
Definition: chan_agent.c:212
static struct ast_channel * agent_lock_owner(struct agent_pvt *pvt)
Locks the owning channel for a LOCKED pvt while obeying locking order. The pvt must enter this functi...
Definition: chan_agent.c:382
char name[AST_MAX_AGENT]
Definition: chan_agent.c:271
struct ast_channel * chan
Definition: chan_agent.c:277
const int fd
Definition: cli.h:153
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static const char config[]
Definition: chan_agent.c:204
ast_group_t group
Definition: chan_agent.c:266
struct ast_channel * owner
Definition: chan_agent.c:276
Structure representing an agent.
Definition: chan_agent.c:252
#define CLI_SHOWUSAGE
Definition: cli.h:44
char agent[AST_MAX_AGENT]
Definition: chan_agent.c:269
struct agent_pvt::@78 list
struct ast_channel * ast_bridged_channel(struct ast_channel *chan)
Find bridged channel.
Definition: channel.c:7160
const ast_string_field name
Definition: channel.h:787
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_channel_unlock(chan)
Definition: channel.h:2467
char * command
Definition: cli.h:180
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
static long count_agents(const char *const caller, const int core_id_exception)
Definition: ccss.c:2243
static force_inline int powerof(unsigned int d)
Definition: chan_agent.c:1474
#define ast_mutex_unlock(a)
Definition: lock.h:156
static char* agents_show_online ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 1779 of file chan_agent.c.

References agent_pvt::agent, agent_lock_owner(), ast_cli_args::argc, ast_bridged_channel(), ast_channel_unlock, ast_channel_unref, ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, AST_MAX_BUF, ast_mutex_lock, ast_mutex_unlock, ast_strlen_zero(), agent_pvt::chan, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, count_agents(), ast_cli_args::fd, agent_pvt::lock, agent_pvt::moh, agent_pvt::name, ast_channel::name, agent_pvt::owner, and ast_cli_entry::usage.

1780 {
1781  struct agent_pvt *p;
1782  char username[AST_MAX_BUF];
1783  char location[AST_MAX_BUF] = "";
1784  char talkingto[AST_MAX_BUF] = "";
1785  char music[AST_MAX_BUF];
1786  int count_agents = 0; /* Number of agents configured */
1787  int online_agents = 0; /* Number of online agents */
1788  int agent_status = 0; /* 0 means offline, 1 means online */
1789 
1790  switch (cmd) {
1791  case CLI_INIT:
1792  e->command = "agent show online";
1793  e->usage =
1794  "Usage: agent show online\n"
1795  " Provides a list of all online agents.\n";
1796  return NULL;
1797  case CLI_GENERATE:
1798  return NULL;
1799  }
1800 
1801  if (a->argc != 3)
1802  return CLI_SHOWUSAGE;
1803 
1805  AST_LIST_TRAVERSE(&agents, p, list) {
1806  struct ast_channel *owner;
1807 
1808  agent_status = 0; /* reset it to offline */
1809  ast_mutex_lock(&p->lock);
1810  owner = agent_lock_owner(p);
1811 
1812  if (!ast_strlen_zero(p->name))
1813  snprintf(username, sizeof(username), "(%s) ", p->name);
1814  else
1815  username[0] = '\0';
1816  if (p->chan) {
1817  snprintf(location, sizeof(location), "logged in on %s", p->chan->name);
1818  if (owner && ast_bridged_channel(owner)) {
1819  snprintf(talkingto, sizeof(talkingto), " talking to %s", ast_bridged_channel(owner)->name);
1820  } else {
1821  strcpy(talkingto, " is idle");
1822  }
1823  agent_status = 1;
1824  online_agents++;
1825  }
1826 
1827  if (owner) {
1828  ast_channel_unlock(owner);
1829  owner = ast_channel_unref(owner);
1830  }
1831 
1832  if (!ast_strlen_zero(p->moh))
1833  snprintf(music, sizeof(music), " (musiconhold is '%s')", p->moh);
1834  if (agent_status)
1835  ast_cli(a->fd, "%-12.12s %s%s%s%s\n", p->agent, username, location, talkingto, music);
1836  count_agents++;
1837  ast_mutex_unlock(&p->lock);
1838  }
1840  if (!count_agents)
1841  ast_cli(a->fd, "No Agents are configured in %s\n", config);
1842  else
1843  ast_cli(a->fd, "%d agents online\n", online_agents);
1844  ast_cli(a->fd, "\n");
1845  return CLI_SUCCESS;
1846 }
Main Channel structure associated with a channel.
Definition: channel.h:742
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
ast_mutex_t lock
Definition: chan_agent.c:253
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
const int argc
Definition: cli.h:154
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Definition: cli.h:146
char moh[80]
Definition: chan_agent.c:268
#define ast_mutex_lock(a)
Definition: lock.h:155
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
#define AST_MAX_BUF
Definition: chan_agent.c:212
static struct ast_channel * agent_lock_owner(struct agent_pvt *pvt)
Locks the owning channel for a LOCKED pvt while obeying locking order. The pvt must enter this functi...
Definition: chan_agent.c:382
char name[AST_MAX_AGENT]
Definition: chan_agent.c:271
struct ast_channel * chan
Definition: chan_agent.c:277
const int fd
Definition: cli.h:153
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static const char config[]
Definition: chan_agent.c:204
Structure representing an agent.
Definition: chan_agent.c:252
#define CLI_SHOWUSAGE
Definition: cli.h:44
char agent[AST_MAX_AGENT]
Definition: chan_agent.c:269
struct agent_pvt::@78 list
struct ast_channel * ast_bridged_channel(struct ast_channel *chan)
Find bridged channel.
Definition: channel.c:7160
const ast_string_field name
Definition: channel.h:787
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static const char name[]
char * command
Definition: cli.h:180
const char * usage
Definition: cli.h:171
#define CLI_SUCCESS
Definition: cli.h:43
static long count_agents(const char *const caller, const int core_id_exception)
Definition: ccss.c:2243
#define ast_mutex_unlock(a)
Definition: lock.h:156
AST_DATA_STRUCTURE ( agent_pvt  ,
DATA_EXPORT_AGENT   
)
static int check_availability ( struct agent_pvt newlyavailable,
int  needlock 
)
static

Definition at line 1270 of file chan_agent.c.

References agent_pvt::abouttograb, agent_pvt::ackcall, agent_pvt::acknowledged, agent_pvt::agent, agent_cleanup(), agent_new(), ast_channel_masquerade(), ast_copy_string(), ast_debug, ast_hangup(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock, ast_mutex_unlock, ast_setstate(), AST_STATE_DOWN, AST_STATE_UP, ast_streamfile(), ast_waitstream(), agent_pvt::chan, ast_channel::context, agent_pvt::group, ast_channel::language, ast_channel::linkedid, agent_pvt::lock, ast_channel::name, agent_pvt::owner, and agent_pvt::pending.

Referenced by login_exec().

1271 {
1272  struct ast_channel *chan=NULL, *parent=NULL;
1273  struct agent_pvt *p;
1274  int res;
1275 
1276  ast_debug(1, "Checking availability of '%s'\n", newlyavailable->agent);
1277  if (needlock)
1279  AST_LIST_TRAVERSE(&agents, p, list) {
1280  if (p == newlyavailable) {
1281  continue;
1282  }
1283  ast_mutex_lock(&p->lock);
1284  if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) {
1285  ast_debug(1, "Call '%s' looks like a winner for agent '%s'\n", p->owner->name, newlyavailable->agent);
1286  /* We found a pending call, time to merge */
1287  chan = agent_new(newlyavailable, AST_STATE_DOWN, p->owner ? p->owner->linkedid : NULL);
1288  parent = p->owner;
1289  p->abouttograb = 1;
1290  ast_mutex_unlock(&p->lock);
1291  break;
1292  }
1293  ast_mutex_unlock(&p->lock);
1294  }
1295  if (needlock)
1297  if (parent && chan) {
1298  if (newlyavailable->ackcall) {
1299  /* Don't do beep here */
1300  res = 0;
1301  } else {
1302  ast_debug(3, "Playing beep, lang '%s'\n", newlyavailable->chan->language);
1303  res = ast_streamfile(newlyavailable->chan, beep, newlyavailable->chan->language);
1304  ast_debug(3, "Played beep, result '%d'\n", res);
1305  if (!res) {
1306  res = ast_waitstream(newlyavailable->chan, "");
1307  ast_debug(1, "Waited for stream, result '%d'\n", res);
1308  }
1309  }
1310  if (!res) {
1311  /* Note -- parent may have disappeared */
1312  if (p->abouttograb) {
1313  newlyavailable->acknowledged = 1;
1314  /* Safe -- agent lock already held */
1315  ast_setstate(parent, AST_STATE_UP);
1316  ast_setstate(chan, AST_STATE_UP);
1317  ast_copy_string(parent->context, chan->context, sizeof(parent->context));
1318  ast_channel_masquerade(parent, chan);
1319  ast_hangup(chan);
1320  p->abouttograb = 0;
1321  } else {
1322  ast_debug(1, "Sneaky, parent disappeared in the mean time...\n");
1323  agent_cleanup(newlyavailable);
1324  }
1325  } else {
1326  ast_debug(1, "Ugh... Agent hung up at exactly the wrong time\n");
1327  agent_cleanup(newlyavailable);
1328  }
1329  }
1330  return 0;
1331 }
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
Main Channel structure associated with a channel.
Definition: channel.h:742
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:946
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
ast_mutex_t lock
Definition: chan_agent.c:253
int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone)
Weird function made for call transfers.
Definition: channel.c:6110
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
int acknowledged
Definition: chan_agent.c:267
int pending
Definition: chan_agent.c:255
int abouttograb
Definition: chan_agent.c:256
#define ast_mutex_lock(a)
Definition: lock.h:155
const ast_string_field linkedid
Definition: channel.h:787
int ackcall
Definition: chan_agent.c:258
struct ast_channel * chan
Definition: chan_agent.c:277
static char beep[AST_MAX_BUF]
Definition: chan_agent.c:239
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
ast_group_t group
Definition: chan_agent.c:266
struct ast_channel * owner
Definition: chan_agent.c:276
Structure representing an agent.
Definition: chan_agent.c:252
char agent[AST_MAX_AGENT]
Definition: chan_agent.c:269
struct agent_pvt::@78 list
const ast_string_field name
Definition: channel.h:787
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static int agent_cleanup(struct agent_pvt *p)
Definition: chan_agent.c:544
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1343
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7119
static struct ast_channel * agent_new(struct agent_pvt *p, int state, const char *linkedid)
Create new agent channel.
Definition: chan_agent.c:1063
const ast_string_field language
Definition: channel.h:787
#define ast_mutex_unlock(a)
Definition: lock.h:156
static int check_beep ( struct agent_pvt newlyavailable,
int  needlock 
)
static

Definition at line 1333 of file chan_agent.c.

References agent_pvt::abouttograb, agent_pvt::agent, ast_debug, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock, ast_mutex_unlock, ast_streamfile(), ast_waitstream(), agent_pvt::chan, agent_pvt::group, ast_channel::language, agent_pvt::lock, ast_channel::name, agent_pvt::owner, and agent_pvt::pending.

Referenced by login_exec().

1334 {
1335  struct agent_pvt *p;
1336  int res=0;
1337 
1338  ast_debug(1, "Checking beep availability of '%s'\n", newlyavailable->agent);
1339  if (needlock)
1341  AST_LIST_TRAVERSE(&agents, p, list) {
1342  if (p == newlyavailable) {
1343  continue;
1344  }
1345  ast_mutex_lock(&p->lock);
1346  if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) {
1347  ast_debug(1, "Call '%s' looks like a would-be winner for agent '%s'\n", p->owner->name, newlyavailable->agent);
1348  ast_mutex_unlock(&p->lock);
1349  break;
1350  }
1351  ast_mutex_unlock(&p->lock);
1352  }
1353  if (needlock)
1355  if (p) {
1356  ast_mutex_unlock(&newlyavailable->lock);
1357  ast_debug(3, "Playing beep, lang '%s'\n", newlyavailable->chan->language);
1358  res = ast_streamfile(newlyavailable->chan, beep, newlyavailable->chan->language);
1359  ast_debug(1, "Played beep, result '%d'\n", res);
1360  if (!res) {
1361  res = ast_waitstream(newlyavailable->chan, "");
1362  ast_debug(1, "Waited for stream, result '%d'\n", res);
1363  }
1364  ast_mutex_lock(&newlyavailable->lock);
1365  }
1366  return res;
1367 }
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:946
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
ast_mutex_t lock
Definition: chan_agent.c:253
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
int pending
Definition: chan_agent.c:255
int abouttograb
Definition: chan_agent.c:256
#define ast_mutex_lock(a)
Definition: lock.h:155
struct ast_channel * chan
Definition: chan_agent.c:277
static char beep[AST_MAX_BUF]
Definition: chan_agent.c:239
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
ast_group_t group
Definition: chan_agent.c:266
struct ast_channel * owner
Definition: chan_agent.c:276
Structure representing an agent.
Definition: chan_agent.c:252
char agent[AST_MAX_AGENT]
Definition: chan_agent.c:269
struct agent_pvt::@78 list
const ast_string_field name
Definition: channel.h:787
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1343
const ast_string_field language
Definition: channel.h:787
#define ast_mutex_unlock(a)
Definition: lock.h:156
static char * complete_agent_logoff_cmd ( const char *  line,
const char *  word,
int  pos,
int  state 
)
static

Definition at line 1675 of file chan_agent.c.

References agent_pvt::agent, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, AST_MAX_AGENT, ast_strdup, len(), agent_pvt::loginstart, and agent_pvt::name.

Referenced by agent_logoff_cmd().

1676 {
1677  char *ret = NULL;
1678 
1679  if (pos == 2) {
1680  struct agent_pvt *p;
1681  char name[AST_MAX_AGENT];
1682  int which = 0, len = strlen(word);
1683 
1685  AST_LIST_TRAVERSE(&agents, p, list) {
1686  snprintf(name, sizeof(name), "Agent/%s", p->agent);
1687  if (!strncasecmp(word, name, len) && p->loginstart && ++which > state) {
1688  ret = ast_strdup(name);
1689  break;
1690  }
1691  }
1693  } else if (pos == 3 && state == 0)
1694  return ast_strdup("soft");
1695 
1696  return ret;
1697 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define ast_strdup(a)
Definition: astmm.h:109
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
Definition: ael.tab.c:203
time_t loginstart
Definition: chan_agent.c:262
Structure representing an agent.
Definition: chan_agent.c:252
char agent[AST_MAX_AGENT]
Definition: chan_agent.c:269
struct agent_pvt::@78 list
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static const char name[]
#define AST_MAX_AGENT
Definition: chan_agent.c:211
static struct agent_pvt* find_agent ( char *  agentid)
static
Note
This function expects the agent list to be locked

Definition at line 2292 of file chan_agent.c.

References agent_pvt::agent, and AST_LIST_TRAVERSE.

Referenced by function_agent().

2293 {
2294  struct agent_pvt *cur;
2295 
2296  AST_LIST_TRAVERSE(&agents, cur, list) {
2297  if (!strcmp(cur->agent, agentid))
2298  break;
2299  }
2300 
2301  return cur;
2302 }
Structure representing an agent.
Definition: chan_agent.c:252
char agent[AST_MAX_AGENT]
Definition: chan_agent.c:269
struct agent_pvt::@78 list
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static int function_agent ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

Definition at line 2304 of file chan_agent.c.

References agent_pvt::agent, args, AST_APP_ARG, ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), AST_NONSTANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), agent_pvt::chan, find_agent(), LOG_WARNING, agent_pvt::moh, agent_pvt::name, ast_channel::name, parse(), agent_pvt::password, and status.

2305 {
2306  char *parse;
2308  AST_APP_ARG(agentid);
2309  AST_APP_ARG(item);
2310  );
2311  char *tmp;
2312  struct agent_pvt *agent;
2313 
2314  buf[0] = '\0';
2315 
2316  if (ast_strlen_zero(data)) {
2317  ast_log(LOG_WARNING, "The AGENT function requires an argument - agentid!\n");
2318  return -1;
2319  }
2320 
2321  parse = ast_strdupa(data);
2322 
2323  AST_NONSTANDARD_APP_ARGS(args, parse, ':');
2324  if (!args.item)
2325  args.item = "status";
2326 
2328 
2329  if (!(agent = find_agent(args.agentid))) {
2331  ast_log(LOG_WARNING, "Agent '%s' not found!\n", args.agentid);
2332  return -1;
2333  }
2334 
2335  if (!strcasecmp(args.item, "status")) {
2336  char *status = "LOGGEDOUT";
2337  if (agent->chan) {
2338  status = "LOGGEDIN";
2339  }
2340  ast_copy_string(buf, status, len);
2341  } else if (!strcasecmp(args.item, "password"))
2342  ast_copy_string(buf, agent->password, len);
2343  else if (!strcasecmp(args.item, "name"))
2344  ast_copy_string(buf, agent->name, len);
2345  else if (!strcasecmp(args.item, "mohclass"))
2346  ast_copy_string(buf, agent->moh, len);
2347  else if (!strcasecmp(args.item, "channel")) {
2348  if (agent->chan) {
2349  ast_channel_lock(agent->chan);
2350  ast_copy_string(buf, agent->chan->name, len);
2351  ast_channel_unlock(agent->chan);
2352  tmp = strrchr(buf, '-');
2353  if (tmp)
2354  *tmp = '\0';
2355  }
2356  } else if (!strcasecmp(args.item, "fullchannel")) {
2357  if (agent->chan) {
2358  ast_channel_lock(agent->chan);
2359  ast_copy_string(buf, agent->chan->name, len);
2360  ast_channel_unlock(agent->chan);
2361  }
2362  } else if (!strcasecmp(args.item, "exten")) {
2363  buf[0] = '\0';
2364  }
2365 
2367 
2368  return 0;
2369 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
char password[AST_MAX_AGENT]
Definition: chan_agent.c:270
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define LOG_WARNING
Definition: logger.h:144
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
char moh[80]
Definition: chan_agent.c:268
char name[AST_MAX_AGENT]
Definition: chan_agent.c:271
struct ast_channel * chan
Definition: chan_agent.c:277
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
Structure representing an agent.
Definition: chan_agent.c:252
static struct @350 args
char agent[AST_MAX_AGENT]
Definition: chan_agent.c:269
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the &#39;nonstandard&#39; argument separation process for an application.
Definition: app.h:619
static struct agent_pvt * find_agent(char *agentid)
Definition: chan_agent.c:2292
jack_status_t status
Definition: app_jack.c:143
static int load_module ( void  )
static

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other things it registers applications, cli commands and reads the cofiguration file.

Returns
int Always 0.

Definition at line 2471 of file chan_agent.c.

References action_agent_logoff(), action_agents(), agent_function, agent_tech, agentmonitoroutgoing_exec(), agents_data_providers, ARRAY_LEN, ast_channel_register(), ast_cli_register_multiple(), ast_custom_function_register, ast_data_register_multiple, ast_log(), ast_manager_register_xml, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_register_application_xml, cli_agents, EVENT_FLAG_AGENT, LOG_ERROR, login_exec(), and read_agent_config().

2472 {
2473  /* Make sure we can register our agent channel type */
2475  ast_log(LOG_ERROR, "Unable to register channel class 'Agent'\n");
2476  return AST_MODULE_LOAD_FAILURE;
2477  }
2478  /* Read in the config */
2479  if (!read_agent_config(0))
2480  return AST_MODULE_LOAD_DECLINE;
2481  /* Dialplan applications */
2484 
2485  /* data tree */
2487 
2488  /* Manager commands */
2491 
2492  /* CLI Commands */
2494 
2495  /* Dialplan Functions */
2497 
2498  return AST_MODULE_LOAD_SUCCESS;
2499 }
static int agentmonitoroutgoing_exec(struct ast_channel *chan, const char *data)
Called by the AgentMonitorOutgoing application (from the dial plan).
Definition: chan_agent.c:2199
static int read_agent_config(int reload)
Definition: chan_agent.c:1112
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static struct ast_custom_function agent_function
Definition: chan_agent.c:2371
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition: channel.c:907
#define ast_manager_register_xml(a, b, c)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:172
static struct ast_data_entry agents_data_providers[]
Definition: chan_agent.c:2460
static int login_exec(struct ast_channel *chan, const char *data)
Log in agent application.
Definition: chan_agent.c:1869
#define ast_data_register_multiple(data_entries, entries)
Definition: data.h:377
static int action_agents(struct mansession *s, const struct message *m)
Definition: chan_agent.c:1494
#define LOG_ERROR
Definition: logger.h:155
static const char app3[]
Definition: chan_agent.c:207
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define EVENT_FLAG_AGENT
Definition: manager.h:76
static struct ast_cli_entry cli_agents[]
Definition: chan_agent.c:1853
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
Definition: cli.c:2167
static const char app[]
Definition: chan_agent.c:206
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1164
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
static int action_agent_logoff(struct mansession *s, const struct message *m)
Definition: chan_agent.c:1653
static struct ast_channel_tech agent_tech
Channel interface description for PBX integration.
Definition: chan_agent.c:349
static int login_exec ( struct ast_channel chan,
const char *  data 
)
static

Log in agent application.

Called by the AgentLogin application (from the dial plan).

Parameters
chan
data
Returns
See Also
agentmonitoroutgoing_exec(), load_module().

Definition at line 1869 of file chan_agent.c.

References ast_channel::_state, agent_pvt::acceptdtmf, agent_pvt::ackcall, agent_pvt::acknowledged, agent_pvt::agent, agent_ack_sleep(), agent_cont_sleep(), AGENT_FLAG_ACCEPTDTMF, AGENT_FLAG_ACKCALL, AGENT_FLAG_AUTOLOGOFF, AGENT_FLAG_ENDDTMF, AGENT_FLAG_WRAPUPTIME, agent_pvt_destroy(), agent_pvt::app_complete_cond, agent_pvt::app_lock_flag, args, ast_answer(), AST_APP_ARG, ast_app_getdata(), ast_best_codec(), ast_channel_lock, ast_channel_unlock, ast_check_hangup(), ast_cond_signal, ast_cond_wait, AST_CONTROL_HOLD, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, ast_devstate_changed(), ast_getformatname(), ast_indicate_data(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), AST_MAX_AGENT, AST_MAX_FILENAME_LEN, ast_mutex_lock, ast_mutex_unlock, ast_queue_log(), ast_safe_sleep(), ast_safe_sleep_conditional(), ast_set_flag, ast_set_read_format(), ast_set_write_format(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_true(), ast_tv(), ast_tvdiff_ms(), ast_tvnow(), ast_verb, ast_waitstream(), agent_pvt::autologoff, ast_channel::cdr, agent_pvt::chan, ast_cdr::channel, check_availability(), check_beep(), agent_pvt::dead, agent_pvt::deferlogoff, agent_pvt::enddtmf, EVENT_FLAG_AGENT, ast_channel::language, agent_pvt::lastdisc, agent_pvt::lock, LOG_NOTICE, LOG_WARNING, agent_pvt::login_wait_cond, agent_pvt::loginstart, manager_event, maxlogintries, agent_pvt::moh, ast_channel::name, ast_channel::nativeformats, agent_pvt::owner, parse(), pass, agent_pvt::password, pbx_builtin_getvar_helper(), agent_pvt::pending, ast_channel::readformat, S_OR, ast_channel::uniqueid, update_cdr, updatecdr, agent_pvt::wrapuptime, and ast_channel::writeformat.

Referenced by load_module().

1870 {
1871  int res=0;
1872  int tries = 0;
1873  int max_login_tries = maxlogintries;
1874  struct agent_pvt *p;
1875  char user[AST_MAX_AGENT];
1876  char pass[AST_MAX_AGENT];
1877  char xpass[AST_MAX_AGENT];
1878  char *errmsg;
1879  char *parse;
1881  AST_APP_ARG(agent_id);
1882  AST_APP_ARG(options);
1884  );
1885  const char *tmpoptions = NULL;
1886  int play_announcement = 1;
1887  char agent_goodbye[AST_MAX_FILENAME_LEN];
1888  int update_cdr = updatecdr;
1889 
1890  user[0] = '\0';
1891  xpass[0] = '\0';
1892 
1893  parse = ast_strdupa(data);
1894 
1895  AST_STANDARD_APP_ARGS(args, parse);
1896 
1897  ast_copy_string(agent_goodbye, agentgoodbye, sizeof(agent_goodbye));
1898 
1899  ast_channel_lock(chan);
1900  /* Set Channel Specific Login Overrides */
1901  if (!ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTLMAXLOGINTRIES"))) {
1902  max_login_tries = atoi(pbx_builtin_getvar_helper(chan, "AGENTMAXLOGINTRIES"));
1903  if (max_login_tries < 0)
1904  max_login_tries = 0;
1905  tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTMAXLOGINTRIES");
1906  ast_verb(3, "Saw variable AGENTMAXLOGINTRIES=%s, setting max_login_tries to: %d on Channel '%s'.\n",tmpoptions,max_login_tries,chan->name);
1907  }
1908  if (!ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR"))) {
1909  if (ast_true(pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR")))
1910  update_cdr = 1;
1911  else
1912  update_cdr = 0;
1913  tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR");
1914  ast_verb(3, "Saw variable AGENTUPDATECDR=%s, setting update_cdr to: %d on Channel '%s'.\n",tmpoptions,update_cdr,chan->name);
1915  }
1916  if (!ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTGOODBYE"))) {
1917  strcpy(agent_goodbye, pbx_builtin_getvar_helper(chan, "AGENTGOODBYE"));
1918  tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTGOODBYE");
1919  ast_verb(3, "Saw variable AGENTGOODBYE=%s, setting agent_goodbye to: %s on Channel '%s'.\n",tmpoptions,agent_goodbye,chan->name);
1920  }
1921  ast_channel_unlock(chan);
1922  /* End Channel Specific Login Overrides */
1923 
1924  if (!ast_strlen_zero(args.options)) {
1925  if (strchr(args.options, 's')) {
1926  play_announcement = 0;
1927  }
1928  }
1929 
1930  if (chan->_state != AST_STATE_UP)
1931  res = ast_answer(chan);
1932  if (!res) {
1933  if (!ast_strlen_zero(args.agent_id))
1934  ast_copy_string(user, args.agent_id, AST_MAX_AGENT);
1935  else
1936  res = ast_app_getdata(chan, "agent-user", user, sizeof(user) - 1, 0);
1937  }
1938  while (!res && (max_login_tries==0 || tries < max_login_tries)) {
1939  tries++;
1940  /* Check for password */
1942  AST_LIST_TRAVERSE(&agents, p, list) {
1943  if (!strcmp(p->agent, user) && !p->pending)
1944  ast_copy_string(xpass, p->password, sizeof(xpass));
1945  }
1947  if (!res) {
1948  if (!ast_strlen_zero(xpass))
1949  res = ast_app_getdata(chan, "agent-pass", pass, sizeof(pass) - 1, 0);
1950  else
1951  pass[0] = '\0';
1952  }
1953  errmsg = "agent-incorrect";
1954 
1955 #if 0
1956  ast_log(LOG_NOTICE, "user: %s, pass: %s\n", user, pass);
1957 #endif
1958 
1959  /* Check again for accuracy */
1961  AST_LIST_TRAVERSE(&agents, p, list) {
1962  int unlock_channel = 1;
1963 
1964  ast_channel_lock(chan);
1965  ast_mutex_lock(&p->lock);
1966  if (!strcmp(p->agent, user) &&
1967  !strcmp(p->password, pass) && !p->pending) {
1968 
1969  /* Set Channel Specific Agent Overrides */
1970  if (!ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"))) {
1971  if (ast_true(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"))) {
1972  p->ackcall = 1;
1973  } else {
1974  p->ackcall = 0;
1975  }
1976  tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTACKCALL");
1977  ast_verb(3, "Saw variable AGENTACKCALL=%s, setting ackcall to: %d for Agent '%s'.\n", tmpoptions, p->ackcall, p->agent);
1979  } else {
1980  p->ackcall = ackcall;
1981  }
1982  if (!ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF"))) {
1983  p->autologoff = atoi(pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF"));
1984  if (p->autologoff < 0)
1985  p->autologoff = 0;
1986  tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF");
1987  ast_verb(3, "Saw variable AGENTAUTOLOGOFF=%s, setting autologff to: %d for Agent '%s'.\n", tmpoptions, p->autologoff, p->agent);
1989  } else {
1990  p->autologoff = autologoff;
1991  }
1992  if (!ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME"))) {
1993  p->wrapuptime = atoi(pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME"));
1994  if (p->wrapuptime < 0)
1995  p->wrapuptime = 0;
1996  tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME");
1997  ast_verb(3, "Saw variable AGENTWRAPUPTIME=%s, setting wrapuptime to: %d for Agent '%s'.\n", tmpoptions, p->wrapuptime, p->agent);
1999  } else {
2000  p->wrapuptime = wrapuptime;
2001  }
2002  tmpoptions = pbx_builtin_getvar_helper(chan, "AGENTACCEPTDTMF");
2003  if (!ast_strlen_zero(tmpoptions)) {
2004  p->acceptdtmf = *tmpoptions;
2005  ast_verb(3, "Saw variable AGENTACCEPTDTMF=%s, setting acceptdtmf to: %c for Agent '%s'.\n", tmpoptions, p->acceptdtmf, p->agent);
2007  }
2008  tmpoptions = pbx_builtin_getvar_helper(chan, "AGENTENDDTMF");
2009  if (!ast_strlen_zero(tmpoptions)) {
2010  p->enddtmf = *tmpoptions;
2011  ast_verb(3, "Saw variable AGENTENDDTMF=%s, setting enddtmf to: %c for Agent '%s'.\n", tmpoptions, p->enddtmf, p->agent);
2013  }
2014  ast_channel_unlock(chan);
2015  unlock_channel = 0;
2016  /* End Channel Specific Agent Overrides */
2017 
2018  if (!p->chan) {
2019  /* Ensure nobody else can be this agent until we're done. */
2020  p->chan = chan;
2021 
2022  p->acknowledged = 0;
2023 
2024  if (!res) {
2025  res = ast_set_read_format(chan, ast_best_codec(chan->nativeformats));
2026  if (res)
2027  ast_log(LOG_WARNING, "Unable to set read format to %s\n", ast_getformatname(ast_best_codec(chan->nativeformats)));
2028  }
2029  if (!res) {
2031  if (res)
2032  ast_log(LOG_WARNING, "Unable to set write format to %s\n", ast_getformatname(ast_best_codec(chan->nativeformats)));
2033  }
2034  if (!res && play_announcement == 1) {
2035  ast_mutex_unlock(&p->lock);
2037  res = ast_streamfile(chan, "agent-loginok", chan->language);
2038  if (!res) {
2039  ast_waitstream(chan, "");
2040  }
2042  ast_mutex_lock(&p->lock);
2043  }
2044 
2045  if (!res) {
2046  long logintime;
2047  char agent[AST_MAX_AGENT];
2048 
2049  snprintf(agent, sizeof(agent), "Agent/%s", p->agent);
2050 
2051  /* Login this channel and wait for it to go away */
2053  S_OR(p->moh, NULL),
2054  !ast_strlen_zero(p->moh) ? strlen(p->moh) + 1 : 0);
2055 
2056  /* Must be done after starting HOLD. */
2057  p->lastdisc = ast_tvnow();
2058  time(&p->loginstart);
2059 
2060  manager_event(EVENT_FLAG_AGENT, "Agentlogin",
2061  "Agent: %s\r\n"
2062  "Channel: %s\r\n"
2063  "Uniqueid: %s\r\n",
2064  p->agent, chan->name, chan->uniqueid);
2065  if (update_cdr && chan->cdr)
2066  snprintf(chan->cdr->channel, sizeof(chan->cdr->channel), "%s", agent);
2067  ast_queue_log("NONE", chan->uniqueid, agent, "AGENTLOGIN", "%s", chan->name);
2068  ast_verb(2, "Agent '%s' logged in (format %s/%s)\n", p->agent,
2070 
2071  ast_mutex_unlock(&p->lock);
2073 
2074  while (res >= 0) {
2075  ast_mutex_lock(&p->lock);
2076  if (p->deferlogoff) {
2077  p->deferlogoff = 0;
2079  ast_mutex_unlock(&p->lock);
2080  break;
2081  }
2082  ast_mutex_unlock(&p->lock);
2083 
2085  ast_mutex_lock(&p->lock);
2086  if (p->lastdisc.tv_sec) {
2087  if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > 0) {
2088  ast_debug(1, "Wrapup time for %s expired!\n", agent);
2089  p->lastdisc = ast_tv(0, 0);
2091  if (p->ackcall) {
2092  check_beep(p, 0);
2093  } else {
2094  check_availability(p, 0);
2095  }
2096  }
2097  }
2098  ast_mutex_unlock(&p->lock);
2100 
2101  /* Synchronize channel ownership between call to agent and itself. */
2102  ast_mutex_lock(&p->lock);
2103  if (p->app_lock_flag) {
2106  if (ast_check_hangup(chan)) {
2107  /* Agent hungup */
2108  ast_mutex_unlock(&p->lock);
2109  break;
2110  }
2111  }
2112  ast_mutex_unlock(&p->lock);
2113 
2114  if (p->ackcall) {
2115  res = agent_ack_sleep(p);
2116  if (res == 1) {
2118  ast_mutex_lock(&p->lock);
2119  check_availability(p, 0);
2120  ast_mutex_unlock(&p->lock);
2122  }
2123  } else {
2124  res = ast_safe_sleep_conditional( chan, 1000, agent_cont_sleep, p );
2125  }
2126  }
2127  ast_mutex_lock(&p->lock);
2128 
2129  /* Logoff this channel */
2130  p->chan = NULL;
2131  logintime = time(NULL) - p->loginstart;
2132  p->loginstart = 0;
2133 
2134  /* Synchronize channel ownership between call to agent and itself. */
2135  if (p->app_lock_flag) {
2138  }
2139 
2140  if (p->owner) {
2141  ast_log(LOG_WARNING, "Huh? We broke out when there was still an owner?\n");
2142  }
2143 
2144  p->acknowledged = 0;
2145  ast_mutex_unlock(&p->lock);
2146 
2148  manager_event(EVENT_FLAG_AGENT, "Agentlogoff",
2149  "Agent: %s\r\n"
2150  "Logintime: %ld\r\n"
2151  "Uniqueid: %s\r\n",
2152  p->agent, logintime, chan->uniqueid);
2153  ast_queue_log("NONE", chan->uniqueid, agent, "AGENTLOGOFF", "%s|%ld", chan->name, logintime);
2154  ast_verb(2, "Agent '%s' logged out\n", p->agent);
2155 
2156  /* If there is no owner, go ahead and kill it now */
2157  if (p->dead && !p->owner) {
2158  agent_pvt_destroy(p);
2159  }
2161  } else {
2162  /* Agent hung up before could be logged in. */
2163  p->chan = NULL;
2164 
2165  ast_mutex_unlock(&p->lock);
2166  }
2167  res = -1;
2168  } else {
2169  ast_mutex_unlock(&p->lock);
2170  errmsg = "agent-alreadyon";
2171  }
2172  break;
2173  }
2174  ast_mutex_unlock(&p->lock);
2175  if (unlock_channel) {
2176  ast_channel_unlock(chan);
2177  }
2178  }
2180 
2181  if (!res && (max_login_tries==0 || tries < max_login_tries))
2182  res = ast_app_getdata(chan, errmsg, user, sizeof(user) - 1, 0);
2183  }
2184 
2185  if (!res)
2186  res = ast_safe_sleep(chan, 500);
2187 
2188  return -1;
2189 }
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1916
static char pass[512]
#define ast_channel_lock(chan)
Definition: channel.h:2466
char password[AST_MAX_AGENT]
Definition: chan_agent.c:270
char acceptdtmf
Definition: chan_agent.c:260
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:946
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
ast_mutex_t lock
Definition: chan_agent.c:253
static int check_beep(struct agent_pvt *newlyavailable, int needlock)
Definition: chan_agent.c:1333
int ast_app_getdata(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout)
Plays a stream and gets DTMF data from a channel.
Definition: app.c:178
const ast_string_field uniqueid
Definition: channel.h:787
format_t writeformat
Definition: channel.h:854
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define LOG_WARNING
Definition: logger.h:144
static int ackcall
Definition: chan_agent.c:224
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
int acknowledged
Definition: chan_agent.c:267
int wrapuptime
Definition: chan_agent.c:265
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
static int wrapuptime
Definition: chan_agent.c:223
void ast_queue_log(const char *queuename, const char *callid, const char *agent, const char *event, const char *fmt,...)
Definition: logger.c:479
int pending
Definition: chan_agent.c:255
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
Definition: channel.c:4447
#define ast_cond_wait(cond, mutex)
Definition: lock.h:171
format_t ast_best_codec(format_t fmts)
Pick the best audio codec.
Definition: channel.c:1062
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
char moh[80]
Definition: chan_agent.c:268
#define ast_mutex_lock(a)
Definition: lock.h:155
struct ast_cdr * cdr
Definition: channel.h:766
format_t nativeformats
Definition: channel.h:852
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:90
ast_cond_t login_wait_cond
Definition: chan_agent.c:274
#define ast_cond_signal(cond)
Definition: lock.h:169
#define ast_verb(level,...)
Definition: logger.h:243
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
int ackcall
Definition: chan_agent.c:258
#define AST_MAX_FILENAME_LEN
Definition: chan_agent.c:213
struct ast_channel * chan
Definition: chan_agent.c:277
int ast_set_write_format(struct ast_channel *chan, format_t format)
Sets write format on channel chan Set write format for channel to whichever component of &quot;format&quot; is ...
Definition: channel.c:5307
int ast_set_read_format(struct ast_channel *chan, format_t format)
Sets read format on channel chan Set read format for channel to whichever component of &quot;format&quot; is be...
Definition: channel.c:5301
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
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:516
static int updatecdr
Definition: chan_agent.c:238
int deferlogoff
Definition: chan_agent.c:259
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2746
time_t loginstart
Definition: chan_agent.c:262
char channel[AST_MAX_EXTENSION]
Definition: cdr.h:92
ast_cond_t app_complete_cond
Definition: chan_agent.c:273
static char agentgoodbye[AST_MAX_FILENAME_LEN]
Definition: chan_agent.c:231
struct ast_channel * owner
Definition: chan_agent.c:276
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:806
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static int check_availability(struct agent_pvt *newlyavailable, int needlock)
Definition: chan_agent.c:1270
char * ast_getformatname(format_t format)
Get the name of a format.
Definition: frame.c:578
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
Structure representing an agent.
Definition: chan_agent.c:252
static struct @350 args
char agent[AST_MAX_AGENT]
Definition: chan_agent.c:269
struct agent_pvt::@78 list
enum ast_channel_state _state
Definition: channel.h:839
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define EVENT_FLAG_AGENT
Definition: manager.h:76
#define LOG_NOTICE
Definition: logger.h:133
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
static int autologoff
Definition: chan_agent.c:222
static int maxlogintries
Definition: chan_agent.c:230
structure to hold users read from users.conf
struct timeval lastdisc
Definition: chan_agent.c:264
static int agent_cont_sleep(void *data)
Definition: chan_agent.c:976
static int agent_ack_sleep(struct agent_pvt *p)
Definition: chan_agent.c:999
int app_lock_flag
Definition: chan_agent.c:272
format_t readformat
Definition: channel.h:853
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:179
char enddtmf
Definition: chan_agent.c:261
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1343
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
int ast_safe_sleep_conditional(struct ast_channel *chan, int ms, int(*cond)(void *), void *data)
Wait for a specified amount of time, looking for hangups and a condition argument.
Definition: channel.c:1845
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
#define AST_MAX_AGENT
Definition: chan_agent.c:211
static void agent_pvt_destroy(struct agent_pvt *doomed)
Definition: chan_agent.c:417
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
const ast_string_field language
Definition: channel.h:787
int autologoff
Definition: chan_agent.c:257
static int update_cdr
queues.conf [general] option
Definition: app_queue.c:1076
#define ast_mutex_unlock(a)
Definition: lock.h:156
static force_inline int powerof ( unsigned int  d)
static

Definition at line 1474 of file chan_agent.c.

Referenced by agents_show().

1475 {
1476  int x = ffs(d);
1477 
1478  if (x)
1479  return x - 1;
1480 
1481  return 0;
1482 }
static int read_agent_config ( int  reload)
static

Read configuration data. The file named agents.conf.

Returns
Always 0, or so it seems.

Definition at line 1112 of file chan_agent.c.

References add_agent(), agent_pvt_destroy(), ast_category_browse(), ast_config_destroy(), ast_config_load, ast_copy_string(), ast_get_group(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, ast_strlen_zero(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), agent_pvt::chan, CONFIG_FLAG_FILEUNCHANGED, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEUNCHANGED, agent_pvt::dead, LOG_ERROR, LOG_NOTICE, ast_variable::name, ast_variable::next, agent_pvt::owner, secret, and ast_variable::value.

Referenced by load_module(), and reload().

1113 {
1114  struct ast_config *cfg;
1115  struct ast_config *ucfg;
1116  struct ast_variable *v;
1117  struct agent_pvt *p;
1118  const char *catname;
1119  const char *hasagent;
1120  int genhasagent;
1121  struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
1122 
1123  group = 0;
1124  autologoff = 0;
1125  wrapuptime = 0;
1126  ackcall = 0;
1127  endcall = 1;
1128  cfg = ast_config_load(config, config_flags);
1129  if (!cfg) {
1130  ast_log(LOG_NOTICE, "No agent configuration found -- agent support disabled\n");
1131  return 0;
1132  } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
1133  return -1;
1134  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
1135  ast_log(LOG_ERROR, "%s contains a parsing error. Aborting\n", config);
1136  return 0;
1137  }
1138  if ((ucfg = ast_config_load("users.conf", config_flags))) {
1139  if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
1140  ucfg = NULL;
1141  } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
1142  ast_log(LOG_ERROR, "users.conf contains a parsing error. Aborting\n");
1143  return 0;
1144  }
1145  }
1146 
1148  AST_LIST_TRAVERSE(&agents, p, list) {
1149  p->dead = 1;
1150  }
1151  strcpy(moh, "default");
1152  /* set the default recording values */
1153  recordagentcalls = 0;
1154  strcpy(recordformat, "wav");
1155  strcpy(recordformatext, "wav");
1156  urlprefix[0] = '\0';
1157  savecallsin[0] = '\0';
1158 
1159  /* Read in the [agents] section */
1160  v = ast_variable_browse(cfg, "agents");
1161  while(v) {
1162  /* Create the interface list */
1163  if (!strcasecmp(v->name, "agent")) {
1164  add_agent(v->value, 0);
1165  } else if (!strcasecmp(v->name, "group")) {
1166  group = ast_get_group(v->value);
1167  } else if (!strcasecmp(v->name, "autologoff")) {
1168  autologoff = atoi(v->value);
1169  if (autologoff < 0)
1170  autologoff = 0;
1171  } else if (!strcasecmp(v->name, "ackcall")) {
1172  if (ast_true(v->value) || !strcasecmp(v->value, "always")) {
1173  ackcall = 1;
1174  }
1175  } else if (!strcasecmp(v->name, "endcall")) {
1176  endcall = ast_true(v->value);
1177  } else if (!strcasecmp(v->name, "acceptdtmf")) {
1178  acceptdtmf = *(v->value);
1179  ast_log(LOG_NOTICE, "Set acceptdtmf to %c\n", acceptdtmf);
1180  } else if (!strcasecmp(v->name, "enddtmf")) {
1181  enddtmf = *(v->value);
1182  } else if (!strcasecmp(v->name, "wrapuptime")) {
1183  wrapuptime = atoi(v->value);
1184  if (wrapuptime < 0)
1185  wrapuptime = 0;
1186  } else if (!strcasecmp(v->name, "maxlogintries") && !ast_strlen_zero(v->value)) {
1187  maxlogintries = atoi(v->value);
1188  if (maxlogintries < 0)
1189  maxlogintries = 0;
1190  } else if (!strcasecmp(v->name, "goodbye") && !ast_strlen_zero(v->value)) {
1191  strcpy(agentgoodbye,v->value);
1192  } else if (!strcasecmp(v->name, "musiconhold")) {
1193  ast_copy_string(moh, v->value, sizeof(moh));
1194  } else if (!strcasecmp(v->name, "updatecdr")) {
1195  if (ast_true(v->value))
1196  updatecdr = 1;
1197  else
1198  updatecdr = 0;
1199  } else if (!strcasecmp(v->name, "autologoffunavail")) {
1200  if (ast_true(v->value))
1201  autologoffunavail = 1;
1202  else
1203  autologoffunavail = 0;
1204  } else if (!strcasecmp(v->name, "recordagentcalls")) {
1206  } else if (!strcasecmp(v->name, "recordformat")) {
1208  if (!strcasecmp(v->value, "wav49"))
1209  strcpy(recordformatext, "WAV");
1210  else
1212  } else if (!strcasecmp(v->name, "urlprefix")) {
1213  ast_copy_string(urlprefix, v->value, sizeof(urlprefix));
1214  if (urlprefix[strlen(urlprefix) - 1] != '/')
1215  strncat(urlprefix, "/", sizeof(urlprefix) - strlen(urlprefix) - 1);
1216  } else if (!strcasecmp(v->name, "savecallsin")) {
1217  if (v->value[0] == '/')
1219  else
1220  snprintf(savecallsin, sizeof(savecallsin) - 2, "/%s", v->value);
1221  if (savecallsin[strlen(savecallsin) - 1] != '/')
1222  strncat(savecallsin, "/", sizeof(savecallsin) - strlen(savecallsin) - 1);
1223  } else if (!strcasecmp(v->name, "custom_beep")) {
1224  ast_copy_string(beep, v->value, sizeof(beep));
1225  }
1226  v = v->next;
1227  }
1228  if (ucfg) {
1229  genhasagent = ast_true(ast_variable_retrieve(ucfg, "general", "hasagent"));
1230  catname = ast_category_browse(ucfg, NULL);
1231  while(catname) {
1232  if (strcasecmp(catname, "general")) {
1233  hasagent = ast_variable_retrieve(ucfg, catname, "hasagent");
1234  if (ast_true(hasagent) || (!hasagent && genhasagent)) {
1235  char tmp[256];
1236  const char *fullname = ast_variable_retrieve(ucfg, catname, "fullname");
1237  const char *secret = ast_variable_retrieve(ucfg, catname, "secret");
1238  if (!fullname)
1239  fullname = "";
1240  if (!secret)
1241  secret = "";
1242  snprintf(tmp, sizeof(tmp), "%s,%s,%s", catname, secret,fullname);
1243  add_agent(tmp, 0);
1244  }
1245  }
1246  catname = ast_category_browse(ucfg, catname);
1247  }
1248  ast_config_destroy(ucfg);
1249  }
1251  if (p->dead) {
1253  /* Destroy if appropriate */
1254  if (!p->owner) {
1255  if (!p->chan) {
1256  agent_pvt_destroy(p);
1257  } else {
1258  /* Cause them to hang up */
1260  }
1261  }
1262  }
1263  }
1266  ast_config_destroy(cfg);
1267  return 1;
1268 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
const char * ast_variable_retrieve(const struct ast_config *config, const char *category, const char *variable)
Gets a variable.
Definition: config.c:625
static int ackcall
Definition: chan_agent.c:224
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
Definition: config.c:597
static int wrapuptime
Definition: chan_agent.c:223
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
static char recordformatext[AST_MAX_BUF]
Definition: chan_agent.c:235
static char recordformat[AST_MAX_BUF]
Definition: chan_agent.c:234
static struct agent_pvt * add_agent(const char *agent, int pending)
Definition: chan_agent.c:433
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
static int recordagentcalls
Definition: chan_agent.c:233
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
static char urlprefix[AST_MAX_BUF]
Definition: chan_agent.c:236
struct ast_channel * chan
Definition: chan_agent.c:277
static char beep[AST_MAX_BUF]
Definition: chan_agent.c:239
const char * value
Definition: config.h:79
static int updatecdr
Definition: chan_agent.c:238
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
Definition: config.c:810
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2746
static char enddtmf
Definition: chan_agent.c:228
const char * name
Definition: config.h:77
ast_group_t ast_get_group(const char *s)
Definition: channel.c:7987
static const char config[]
Definition: chan_agent.c:204
static char agentgoodbye[AST_MAX_FILENAME_LEN]
Definition: chan_agent.c:231
struct ast_channel * owner
Definition: chan_agent.c:276
static char moh[80]
Definition: chan_agent.c:209
#define LOG_ERROR
Definition: logger.h:155
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
Structure representing an agent.
Definition: chan_agent.c:252
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static char savecallsin[AST_MAX_BUF]
Definition: chan_agent.c:237
#define LOG_NOTICE
Definition: logger.h:133
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
static int autologoffunavail
Definition: chan_agent.c:226
static int autologoff
Definition: chan_agent.c:222
static char acceptdtmf
Definition: chan_agent.c:227
static int maxlogintries
Definition: chan_agent.c:230
Structure used to handle boolean flags.
Definition: utils.h:200
static int reload(void)
Definition: chan_agent.c:2501
static char secret[50]
Definition: chan_h323.c:148
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
struct ast_variable * next
Definition: config.h:82
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
static void agent_pvt_destroy(struct agent_pvt *doomed)
Definition: chan_agent.c:417
static int endcall
Definition: chan_agent.c:225
#define CONFIG_STATUS_FILEUNCHANGED
Definition: config.h:51
static int reload ( void  )
static

Definition at line 2501 of file chan_agent.c.

References read_agent_config().

2502 {
2503  return read_agent_config(1);
2504 }
static int read_agent_config(int reload)
Definition: chan_agent.c:1112
static int unload_module ( void  )
static

Definition at line 2506 of file chan_agent.c.

References agent_function, agent_tech, ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_data_unregister, ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_manager_unregister(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_unregister_application(), cli_agents, and agent_pvt::owner.

2507 {
2508  struct agent_pvt *p;
2509  /* First, take us out of the channel loop */
2511  /* Unregister dialplan functions */
2513  /* Unregister CLI commands */
2515  /* Unregister dialplan applications */
2518  /* Unregister manager command */
2519  ast_manager_unregister("Agents");
2520  ast_manager_unregister("AgentLogoff");
2521  /* Unregister the data tree */
2522  ast_data_unregister(NULL);
2523  /* Unregister channel */
2525  /* Hangup all interfaces if they have an owner */
2526  while ((p = AST_LIST_REMOVE_HEAD(&agents, list))) {
2527  if (p->owner)
2529  ast_free(p);
2530  }
2532  return 0;
2533 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#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: cli.c:2177
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:938
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
static struct ast_custom_function agent_function
Definition: chan_agent.c:2371
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
Definition: pbx.c:3814
#define ast_data_unregister(path)
Definition: data.h:394
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2746
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
struct ast_channel * owner
Definition: chan_agent.c:276
Structure representing an agent.
Definition: chan_agent.c:252
static const char app3[]
Definition: chan_agent.c:207
struct agent_pvt::@78 list
static struct ast_cli_entry cli_agents[]
Definition: chan_agent.c:1853
#define ast_free(a)
Definition: astmm.h:97
static const char app[]
Definition: chan_agent.c:206
int ast_manager_unregister(char *action)
Unregister a registered manager command.
Definition: manager.c:5355
static struct ast_channel_tech agent_tech
Channel interface description for PBX integration.
Definition: chan_agent.c:349

Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Agent Proxy Channel" , .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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, .nonoptreq = "res_monitor,chan_local", }
static

Definition at line 2541 of file chan_agent.c.

char acceptdtmf = DEFAULT_ACCEPTDTMF
static

Definition at line 227 of file chan_agent.c.

Referenced by play_record_review().

int ackcall
static

Definition at line 224 of file chan_agent.c.

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

Definition at line 2371 of file chan_agent.c.

Referenced by load_module(), and unload_module().

const char agent_logoff_usage[]
static
Initial value:
=
"Usage: agent logoff <channel> [soft]\n"
" Sets an agent as no longer logged in.\n"
" If 'soft' is specified, do not hangup existing calls.\n"

Definition at line 1848 of file chan_agent.c.

struct ast_channel_tech agent_tech
static

Channel interface description for PBX integration.

Definition at line 349 of file chan_agent.c.

Referenced by agent_new(), load_module(), and unload_module().

char agentgoodbye[AST_MAX_FILENAME_LEN] = "vm-goodbye"
static

Definition at line 231 of file chan_agent.c.

struct agents agents = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } , }
static

Holds the list of agents (loaded form agents.conf).

struct ast_data_handler agents_data_provider
static
Initial value:
= {
}
static int agents_data_provider_get(const struct ast_data_search *search, struct ast_data *data_root)
Definition: chan_agent.c:2383
#define AST_DATA_HANDLER_VERSION
The Data API structures version.
Definition: data.h:204

Definition at line 2455 of file chan_agent.c.

struct ast_data_entry agents_data_providers[]
static
Initial value:
= {
AST_DATA_ENTRY("asterisk/channel/agent/list", &agents_data_provider),
}
#define AST_DATA_ENTRY(__path, __handler)
Definition: data.h:260
static struct ast_data_handler agents_data_provider
Definition: chan_agent.c:2455

Definition at line 2460 of file chan_agent.c.

Referenced by load_module().

const char app[] = "AgentLogin"
static

Definition at line 206 of file chan_agent.c.

const char app3[] = "AgentMonitorOutgoing"
static

Definition at line 207 of file chan_agent.c.

Definition at line 2541 of file chan_agent.c.

int autologoff
static

Definition at line 222 of file chan_agent.c.

int autologoffunavail = 0
static

Definition at line 226 of file chan_agent.c.

char beep[AST_MAX_BUF] = "beep"
static

Definition at line 239 of file chan_agent.c.

struct ast_cli_entry cli_agents[]
static
Initial value:
= {
AST_CLI_DEFINE(agents_show, "Show status of agents"),
AST_CLI_DEFINE(agents_show_online, "Show all online agents"),
AST_CLI_DEFINE(agent_logoff_cmd, "Sets an agent offline"),
}
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:191
static char * agent_logoff_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_agent.c:1615
static char * agents_show_online(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_agent.c:1779
static char * agents_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_agent.c:1702

Definition at line 1853 of file chan_agent.c.

Referenced by load_module(), and unload_module().

const char config[] = "agents.conf"
static

Definition at line 204 of file chan_agent.c.

int endcall
static

Definition at line 225 of file chan_agent.c.

char enddtmf = DEFAULT_ENDDTMF
static

Definition at line 228 of file chan_agent.c.

Definition at line 221 of file chan_agent.c.

Referenced by ast_get_group(), and handle_cli_check_permissions().

int maxlogintries = 3
static

Definition at line 230 of file chan_agent.c.

Referenced by login_exec().

char moh[80] = "default"
static
const char pa_family[] = "Agents"
static

Persistent Agents astdb family

Definition at line 215 of file chan_agent.c.

int recordagentcalls = 0
static

Definition at line 233 of file chan_agent.c.

char recordformat[AST_MAX_BUF] = ""
static

Definition at line 234 of file chan_agent.c.

char recordformatext[AST_MAX_BUF] = ""
static

Definition at line 235 of file chan_agent.c.

char savecallsin[AST_MAX_BUF] = ""
static

Definition at line 237 of file chan_agent.c.

const char tdesc[] = "Call Agent Proxy Channel"
static

Definition at line 203 of file chan_agent.c.

int updatecdr = 0
static

Definition at line 238 of file chan_agent.c.

Referenced by login_exec().

char urlprefix[AST_MAX_BUF] = ""
static

Definition at line 236 of file chan_agent.c.

Referenced by start_monitor_exec().

int wrapuptime
static

Definition at line 223 of file chan_agent.c.