Agent documentation changes to agents and verbose / debug fixes (bug #3158)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4618 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Mark Spencer
2004-12-31 00:58:44 +00:00
parent 658000cc9a
commit a66d310f8d
2 changed files with 184 additions and 122 deletions

View File

@@ -45,7 +45,7 @@
#include <sys/signal.h>
static char *desc = "Agent Proxy Channel";
static char *type = "Agent";
static char *channeltype = "Agent";
static char *tdesc = "Call Agent Proxy Channel";
static char *config = "agents.conf";
@@ -78,10 +78,21 @@ static char *descrip2 =
static char *descrip3 =
" AgentMonitorOutgoing([options]):\n"
"Tries to figure out the id of the agent who is placing outgoing call based on comparision of the callerid of the current interface and the global variable placed by the AgentCallbackLogin application. That's why it should be used only with the AgentCallbackLogin app. Uses the monitoring functions in chan_agent instead of Monitor application. That have to be configured in the agents.conf file. Normally the app returns 0 unless the options are passed. Also if the callerid or the agentid are not specified it'll look for n+101 priority. The options are:\n"
" 'd' - make the app return -1 if there is an error condition and there is no extension n+101\n"
"Tries to figure out the id of the agent who is placing outgoing call based on\n"
"comparision of the callerid of the current interface and the global variable \n"
"placed by the AgentCallbackLogin application. That's why it should be used only\n"
"with the AgentCallbackLogin app. Uses the monitoring functions in chan_agent \n"
"instead of Monitor application. That have to be configured in the agents.conf file.\n"
"\nReturn value:\n"
"Normally the app returns 0 unless the options are passed. Also if the callerid or\n"
"the agentid are not specified it'll look for n+101 priority.\n"
"\nOptions:\n"
" 'd' - make the app return -1 if there is an error condition and there is\n"
" no extension n+101\n"
" 'c' - change the CDR so that the source of the call is 'Agent/agent_id'\n"
" 'n' - don't generate the warnings when there is no callerid or the agentid is not known. It's handy if you want to have one context for agent and non-agent calls.\n";
" 'n' - don't generate the warnings when there is no callerid or the\n"
" agentid is not known.\n"
" It's handy if you want to have one context for agent and non-agent calls.\n";
static char mandescr_agents[] =
"Description: Will list info about all possible agents.\n"
@@ -106,7 +117,7 @@ static char agentgoodbye[AST_MAX_FILENAME_LEN] = "vm-goodbye";
static int usecnt =0;
AST_MUTEX_DEFINE_STATIC(usecnt_lock);
/* Protect the interface list (of sip_pvt's) */
/* Protect the interface list (of pvt's) */
AST_MUTEX_DEFINE_STATIC(agentlock);
static int recordagentcalls = 0;
@@ -742,6 +753,7 @@ static struct ast_channel *agent_bridgedchannel(struct ast_channel *chan, struct
return NULL;
}
/*--- agent_new: Create new agent channel ---*/
static struct ast_channel *agent_new(struct agent_pvt *p, int state)
{
struct ast_channel *tmp;
@@ -774,7 +786,7 @@ static struct ast_channel *agent_new(struct agent_pvt *p, int state)
snprintf(tmp->name, sizeof(tmp->name), "Agent/P%s-%d", p->agent, rand() & 0xffff);
else
snprintf(tmp->name, sizeof(tmp->name), "Agent/%s", p->agent);
tmp->type = type;
tmp->type = channeltype;
ast_setstate(tmp, state);
tmp->pvt->pvt = p;
tmp->pvt->send_digit = agent_digit;
@@ -831,16 +843,18 @@ static struct ast_channel *agent_new(struct agent_pvt *p, int state)
ast_moh_stop(p->chan);
}
} else
ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
ast_log(LOG_WARNING, "Unable to allocate agent channel structure\n");
return tmp;
}
/*--- read_agent_config: Read configuration data (agents.conf) ---*/
static int read_agent_config(void)
{
struct ast_config *cfg;
struct ast_variable *v;
struct agent_pvt *p, *pl, *pn;
group = 0;
autologoff = 0;
wrapuptime = 0;
@@ -961,6 +975,8 @@ static int check_availability(struct agent_pvt *newlyavailable, int needlock)
struct ast_channel *chan=NULL, *parent=NULL;
struct agent_pvt *p;
int res;
if (option_debug)
ast_log(LOG_DEBUG, "Checking availability of '%s'\n", newlyavailable->agent);
if (needlock)
ast_mutex_lock(&agentlock);
@@ -972,6 +988,7 @@ static int check_availability(struct agent_pvt *newlyavailable, int needlock)
}
ast_mutex_lock(&p->lock);
if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) {
if (option_debug)
ast_log(LOG_DEBUG, "Call '%s' looks like a winner for agent '%s'\n", p->owner->name, newlyavailable->agent);
/* We found a pending call, time to merge */
chan = agent_new(newlyavailable, AST_STATE_DOWN);
@@ -990,8 +1007,10 @@ static int check_availability(struct agent_pvt *newlyavailable, int needlock)
/* Don't do beep here */
res = 0;
} else {
if (option_debug > 2)
ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", newlyavailable->chan->language);
res = ast_streamfile(newlyavailable->chan, beep, newlyavailable->chan->language);
if (option_debug > 2)
ast_log( LOG_DEBUG, "Played beep, result '%d'\n", res);
if (!res) {
res = ast_waitstream(newlyavailable->chan, "");
@@ -1013,10 +1032,12 @@ static int check_availability(struct agent_pvt *newlyavailable, int needlock)
ast_mutex_unlock(&parent->lock);
p->abouttograb = 0;
} else {
if (option_debug)
ast_log(LOG_DEBUG, "Sneaky, parent disappeared in the mean time...\n");
agent_cleanup(newlyavailable);
}
} else {
if (option_debug)
ast_log(LOG_DEBUG, "Ugh... Agent hung up at exactly the wrong time\n");
agent_cleanup(newlyavailable);
}
@@ -1028,6 +1049,7 @@ static int check_beep(struct agent_pvt *newlyavailable, int needlock)
{
struct agent_pvt *p;
int res=0;
ast_log(LOG_DEBUG, "Checking beep availability of '%s'\n", newlyavailable->agent);
if (needlock)
ast_mutex_lock(&agentlock);
@@ -1039,6 +1061,7 @@ static int check_beep(struct agent_pvt *newlyavailable, int needlock)
}
ast_mutex_lock(&p->lock);
if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) {
if (option_debug)
ast_log(LOG_DEBUG, "Call '%s' looks like a would-be winner for agent '%s'\n", p->owner->name, newlyavailable->agent);
ast_mutex_unlock(&p->lock);
break;
@@ -1050,11 +1073,14 @@ static int check_beep(struct agent_pvt *newlyavailable, int needlock)
ast_mutex_unlock(&agentlock);
if (p) {
ast_mutex_unlock(&newlyavailable->lock);
if (option_debug > 2)
ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", newlyavailable->chan->language);
res = ast_streamfile(newlyavailable->chan, beep, newlyavailable->chan->language);
if (option_debug > 2)
ast_log( LOG_DEBUG, "Played beep, result '%d'\n", res);
if (!res) {
res = ast_waitstream(newlyavailable->chan, "");
if (option_debug)
ast_log( LOG_DEBUG, "Waited for stream, result '%d'\n", res);
}
ast_mutex_lock(&newlyavailable->lock);
@@ -1062,6 +1088,7 @@ static int check_beep(struct agent_pvt *newlyavailable, int needlock)
return res;
}
/*--- agent_request: Part of the Asterisk PBX interface ---*/
static struct ast_channel *agent_request(const char *type, int format, void *data, int *cause)
{
struct agent_pvt *p;
@@ -1071,6 +1098,7 @@ static struct ast_channel *agent_request(const char *type, int format, void *dat
int waitforagent=0;
int hasagent = 0;
struct timeval tv;
s = data;
if ((s[0] == '@') && (sscanf(s + 1, "%d", &groupmatch) == 1)) {
groupmatch = (1 << groupmatch);
@@ -1143,6 +1171,7 @@ static struct ast_channel *agent_request(const char *type, int format, void *dat
/* No agent available -- but we're requesting to wait for one.
Allocate a place holder */
if (hasagent) {
if (option_debug)
ast_log(LOG_DEBUG, "Creating place holder for '%s'\n", s);
p = add_agent(data, 1);
p->group = groupmatch;
@@ -1177,12 +1206,14 @@ static int action_agents(struct mansession *s, struct message *m)
char *loginChan = NULL;
char *talkingtoChan = NULL;
char *status = NULL;
ast_mutex_lock(&agentlock);
p = agents;
while(p) {
ast_mutex_lock(&p->lock);
/* Status Values: AGENT_LOGGEDOFF - Agent isn't logged in
/* Status Values:
AGENT_LOGGEDOFF - Agent isn't logged in
AGENT_IDLE - Agent is logged in, and waiting for call
AGENT_ONCALL - Agent is logged in, and on a call
AGENT_UNKNOWN - Don't know anything about agent. Shouldn't ever get this. */
@@ -1235,6 +1266,7 @@ static int action_agents(struct mansession *s, struct message *m)
}
/*--- agents_show: Show agents in cli ---*/
static int agents_show(int fd, int argc, char **argv)
{
struct agent_pvt *p;
@@ -1298,6 +1330,7 @@ static struct ast_cli_entry cli_show_agents = {
STANDARD_LOCAL_USER;
LOCAL_USER_DECL;
/*--- __login_exec: Log in agent application ---*/
static int __login_exec(struct ast_channel *chan, void *data, int callbackmode)
{
int res=0;
@@ -1337,19 +1370,22 @@ static int __login_exec(struct ast_channel *chan, void *data, int callbackmode)
if (max_login_tries < 0)
max_login_tries = 0;
tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTMAXLOGINTRIES");
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTMAXLOGINTRIES=%s, setting max_login_tries to: %d on Channel '%s'.\n",tmpoptions,max_login_tries,chan->name);
}
if (pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR") && strlen(pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR"))) {
if (pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR") && !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR"))) {
if (ast_true(pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR")))
update_cdr = 1;
else
update_cdr = 0;
tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR");
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTUPDATECDR=%s, setting update_cdr to: %d on Channel '%s'.\n",tmpoptions,update_cdr,chan->name);
}
if (pbx_builtin_getvar_helper(chan, "AGENTGOODBYE") && strlen(pbx_builtin_getvar_helper(chan, "AGENTGOODBYE"))) {
if (pbx_builtin_getvar_helper(chan, "AGENTGOODBYE") && !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTGOODBYE"))) {
strcpy(agent_goodbye, pbx_builtin_getvar_helper(chan, "AGENTGOODBYE"));
tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTGOODBYE");
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTGOODBYE=%s, setting agent_goodbye to: %s on Channel '%s'.\n",tmpoptions,agent_goodbye,chan->name);
}
/* End Channel Specific Login Overrides */
@@ -1385,6 +1421,7 @@ static int __login_exec(struct ast_channel *chan, void *data, int callbackmode)
badoption[0] = option;
badoption[1] = '\0';
tmpoptions=badoption;
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Warning: option %s is unknown.\n",tmpoptions);
}
options++;
@@ -1441,6 +1478,7 @@ static int __login_exec(struct ast_channel *chan, void *data, int callbackmode)
else
p->ackcall = 0;
tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTACKCALL");
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTACKCALL=%s, setting ackcall to: %d for Agent '%s'.\n",tmpoptions,p->ackcall,p->agent);
}
if (pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF") && strlen(pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF"))) {
@@ -1448,6 +1486,7 @@ static int __login_exec(struct ast_channel *chan, void *data, int callbackmode)
if (p->autologoff < 0)
p->autologoff = 0;
tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF");
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTAUTOLOGOFF=%s, setting autologff to: %d for Agent '%s'.\n",tmpoptions,p->autologoff,p->agent);
}
if (pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME") && strlen(pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME"))) {
@@ -1455,6 +1494,7 @@ static int __login_exec(struct ast_channel *chan, void *data, int callbackmode)
if (p->wrapuptime < 0)
p->wrapuptime = 0;
tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME");
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTWRAPUPTIME=%s, setting wrapuptime to: %d for Agent '%s'.\n",tmpoptions,p->wrapuptime,p->agent);
}
/* End Channel Specific Agent Overides */
@@ -1557,8 +1597,8 @@ static int __login_exec(struct ast_channel *chan, void *data, int callbackmode)
"Uniqueid: %s\r\n",
p->agent, p->loginchan, chan->uniqueid);
ast_queue_log("NONE", chan->uniqueid, agent, "AGENTCALLBACKLOGIN", "%s", p->loginchan);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Callback Agent '%s' logged in on %s\n", p->agent, p->loginchan);
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "Callback Agent '%s' logged in on %s\n", p->agent, p->loginchan);
ast_device_state_changed("Agent/%s", p->agent);
} else {
logintime = time(NULL) - p->loginstart;
@@ -1570,8 +1610,8 @@ static int __login_exec(struct ast_channel *chan, void *data, int callbackmode)
"Uniqueid: %s\r\n",
p->agent, last_loginchan, logintime, chan->uniqueid);
ast_queue_log("NONE", chan->uniqueid, agent, "AGENTCALLBACKLOGOFF", "%s|%ld|", last_loginchan, logintime);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Callback Agent '%s' logged out\n", p->agent);
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "Callback Agent '%s' logged out\n", p->agent);
ast_device_state_changed("Agent/%s", p->agent);
}
ast_mutex_unlock(&agentlock);
@@ -1595,8 +1635,8 @@ static int __login_exec(struct ast_channel *chan, void *data, int callbackmode)
if (update_cdr && chan->cdr)
snprintf(chan->cdr->channel, sizeof(chan->cdr->channel), "Agent/%s", p->agent);
ast_queue_log("NONE", chan->uniqueid, agent, "AGENTLOGIN", "%s", chan->name);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Agent '%s' logged in (format %s/%s)\n", p->agent,
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "Agent '%s' logged in (format %s/%s)\n", p->agent,
ast_getformatname(chan->readformat), ast_getformatname(chan->writeformat));
/* Login this channel and wait for it to
go away */
@@ -1624,7 +1664,8 @@ static int __login_exec(struct ast_channel *chan, void *data, int callbackmode)
gettimeofday(&tv, NULL);
if ((tv.tv_sec - p->lastdisc.tv_sec) * 1000 +
(tv.tv_usec - p->lastdisc.tv_usec) / 1000 > p->wrapuptime) {
ast_log(LOG_DEBUG, "Wrapup time expired!\n");
if (option_debug)
ast_log(LOG_DEBUG, "Wrapup time for %s expired!\n", p->agent);
memset(&p->lastdisc, 0, sizeof(p->lastdisc));
if (p->ackcall > 1)
check_beep(p, 0);
@@ -1671,8 +1712,8 @@ static int __login_exec(struct ast_channel *chan, void *data, int callbackmode)
"Uniqueid: %s\r\n",
p->agent, logintime, chan->uniqueid);
ast_queue_log("NONE", chan->uniqueid, agent, "AGENTLOGOFF", "%s|%ld", chan->name, logintime);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Agent '%s' logged out\n", p->agent);
if (option_verbose > 1)
ast_verbose(VERBOSE_PREFIX_2 "Agent '%s' logged out\n", p->agent);
/* If there is no owner, go ahead and kill it now */
ast_device_state_changed("Agent/%s", p->agent);
if (p->dead && !p->owner) {
@@ -1761,6 +1802,7 @@ static int agentmonitoroutgoing_exec(struct ast_channel *chan, void *data)
int changeoutgoing = 0;
int res = 0;
char agent[AST_MAX_AGENT], *tmp;
if (data) {
if (strchr(data, 'd'))
exitifnoagentid = 1;
@@ -1800,6 +1842,7 @@ static int agentmonitoroutgoing_exec(struct ast_channel *chan, void *data)
if (res) {
if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num)) {
chan->priority+=100;
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Going to %d priority because there is no callerid or the agentid cannot be found.\n",chan->priority);
}
else if (exitifnoagentid)
@@ -1808,7 +1851,7 @@ static int agentmonitoroutgoing_exec(struct ast_channel *chan, void *data)
return 0;
}
/*--- sip_devicestate: Part of PBX channel interface ---*/
/*--- agent_devicestate: Part of PBX channel interface ---*/
static int agent_devicestate(void *data)
{
struct agent_pvt *p;
@@ -1857,17 +1900,21 @@ static int agent_devicestate(void *data)
return res;
}
/*--- load_module: Initialize channel module ---*/
int load_module()
{
/* Make sure we can register our sip channel type */
if (ast_channel_register_ex(type, tdesc, capability, agent_request, agent_devicestate)) {
ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
/* Make sure we can register our agent channel type */
if (ast_channel_register_ex(channeltype, tdesc, capability, agent_request, agent_devicestate)) {
ast_log(LOG_ERROR, "Unable to register channel class %s\n", channeltype);
return -1;
}
/* Dialplan applications */
ast_register_application(app, login_exec, synopsis, descrip);
ast_register_application(app2, callback_exec, synopsis2, descrip2);
ast_register_application(app3, agentmonitoroutgoing_exec, synopsis3, descrip3);
/* Manager command */
ast_manager_register2("Agents", 0, action_agents, "Agents", mandescr_agents);
/* CLI Application */
ast_cli_register(&cli_show_agents);
/* Read in the config */
read_agent_config();
@@ -1884,12 +1931,16 @@ int unload_module()
{
struct agent_pvt *p;
/* First, take us out of the channel loop */
/* Unregister CLI application */
ast_cli_unregister(&cli_show_agents);
/* Unregister dialplan applications */
ast_unregister_application(app);
ast_unregister_application(app2);
ast_unregister_application(app3);
ast_channel_unregister(type);
/* Unregister manager command */
ast_manager_unregister("Agents");
/* Unregister channel */
ast_channel_unregister(channeltype);
if (!ast_mutex_lock(&agentlock)) {
/* Hangup all interfaces if they have an owner */
p = agents;

View File

@@ -38,13 +38,13 @@ They are stored in the respective channel structure.
To set a variable to a particular value, do :
;exten => 1,2,SetVar,varname=value
exten => 1,2,SetVar,varname=value
You can substitute the value of a variable everywhere using ${variablename}.
For example, to stringwise append $lala to $blabla and store result in $koko,
do:
;exten => 1,2,SetVar,koko=${blabla}${lala}
exten => 1,2,SetVar,koko=${blabla}${lala}
There are also the following special variables:
@@ -85,6 +85,17 @@ ${ANSWEREDTIME} Time from dial to answer (seconds)
${DIALSTATUS} Status of the call, one of:
CHANUNAVAIL | CONGESTION | BUSY | NOANSWER | ANSWER | CANCEL
The agent channel uses the following variables:
${AGENTMAXLOGINTRIES} Set the maximum number of failed logins
${AGENTUPDATECDR} Whether to update the CDR record with Agent channel data
${AGENTGOODBYE} Sound file to use for "Good Bye" when agent logs out
${AGENTACKCALL} Whether the agent should acknowledge the incoming call
${AGENTAUTOLOGOFF} Auto logging off for an agent
${AGENTWRAPUPTIME} Setting the time for wrapup between incoming calls
${AGENTNUMBER} Agent number (username) set at login
${AGENTSTATUS} Status of login ( fail | on | off )
${AGENTEXTEN} Extension for logged in agent
There are two reference modes - reference by value and reference by name.
To refer to a variable with its name (as an argument to a function that
requires a variable), just write the name. To refer to the variable's value,