diff --git a/channels/chan_agent.c b/channels/chan_agent.c index 768e159842f64d2091dc35f8b466749d7232f193..534b0ee75090bb15478f6eec922dd1bb519742e2 100644 --- a/channels/chan_agent.c +++ b/channels/chan_agent.c @@ -158,6 +158,7 @@ static int autologoff; static int wrapuptime; static int ackcall; static int multiplelogin = 1; +static int autologoffunavail = 0; static int maxlogintries = 3; static char agentgoodbye[AST_MAX_FILENAME_LEN] = "vm-goodbye"; @@ -255,6 +256,7 @@ static int agent_sendtext(struct ast_channel *ast, const char *text); static int agent_indicate(struct ast_channel *ast, int condition); static int agent_fixup(struct ast_channel *oldchan, struct ast_channel *newchan); static struct ast_channel *agent_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge); +static void set_agentbycallerid(const char *callerid, const char *agent); static const struct ast_channel_tech agent_tech = { .type = channeltype, @@ -464,6 +466,7 @@ static struct ast_frame *agent_read(struct ast_channel *ast) struct ast_frame *f = NULL; static struct ast_frame null_frame = { AST_FRAME_NULL, }; static struct ast_frame answer_frame = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER }; + const char *status; ast_mutex_lock(&p->lock); CHECK_FORMATS(ast, p); if (p->chan) { @@ -484,6 +487,26 @@ static struct ast_frame *agent_read(struct ast_channel *ast) if (!ast_strlen_zero(p->loginchan)) { if (p->chan) ast_log(LOG_DEBUG, "Bridge on '%s' being cleared (2)\n", p->chan->name); + + status = pbx_builtin_getvar_helper(p->chan, "CHANLOCALSTATUS"); + if (autologoffunavail && status && !strcasecmp(status, "CHANUNAVAIL")) { + char agent[AST_MAX_AGENT] = ""; + long logintime = time(NULL) - p->loginstart; + p->loginstart = 0; + ast_log(LOG_NOTICE, "Agent read: '%s' is not available now, auto logoff\n", p->name); + manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogoff", + "Agent: %s\r\n" + "Loginchan: %s\r\n" + "Logintime: %ld\r\n" + "Reason: Chanunavail\r\n" + "Uniqueid: %s\r\n", + p->agent, p->loginchan, logintime, ast->uniqueid); + snprintf(agent, sizeof(agent), "Agent/%s", p->agent); + ast_queue_log("NONE", ast->uniqueid, agent, "AGENTCALLBACKLOGOFF", "%s|%ld|%s", p->loginchan, logintime, "Chanunavail"); + set_agentbycallerid(p->logincallerid, NULL); + p->loginchan[0] = '\0'; + p->logincallerid[0] = '\0'; + } ast_hangup(p->chan); if (p->wrapuptime && p->acknowledged) p->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000)); @@ -732,6 +755,7 @@ static int agent_hangup(struct ast_channel *ast) { struct agent_pvt *p = ast->tech_pvt; int howlong = 0; + const char *status; ast_mutex_lock(&p->lock); p->owner = NULL; ast->tech_pvt = NULL; @@ -767,6 +791,25 @@ static int agent_hangup(struct ast_channel *ast) else p->lastdisc = ast_tv(0,0); if (p->chan) { + status = pbx_builtin_getvar_helper(p->chan, "CHANLOCALSTATUS"); + if (autologoffunavail && status && !strcasecmp(status, "CHANUNAVAIL")) { + char agent[AST_MAX_AGENT] = ""; + long logintime = time(NULL) - p->loginstart; + p->loginstart = 0; + ast_log(LOG_NOTICE, "Agent hangup: '%s' is not available now, auto logoff\n", p->name); + manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogoff", + "Agent: %s\r\n" + "Loginchan: %s\r\n" + "Logintime: %ld\r\n" + "Reason: Chanunavail\r\n" + "Uniqueid: %s\r\n", + p->agent, p->loginchan, logintime, ast->uniqueid); + snprintf(agent, sizeof(agent), "Agent/%s", p->agent); + ast_queue_log("NONE", ast->uniqueid, agent, "AGENTCALLBACKLOGOFF", "%s|%ld|%s", p->loginchan, logintime, "Chanunavail"); + set_agentbycallerid(p->logincallerid, NULL); + p->loginchan[0] = '\0'; + p->logincallerid[0] = '\0'; + } /* Recognize the hangup and pass it along immediately */ ast_hangup(p->chan); p->chan = NULL; @@ -1086,6 +1129,11 @@ static int read_agent_config(void) updatecdr = 1; else updatecdr = 0; + } else if (!strcasecmp(v->name, "autologoffunavail")) { + if (ast_true(v->value)) + autologoffunavail = 1; + else + autologoffunavail = 0; } else if (!strcasecmp(v->name, "recordagentcalls")) { recordagentcalls = ast_true(v->value); } else if (!strcasecmp(v->name, "recordformat")) { diff --git a/channels/chan_local.c b/channels/chan_local.c index 44103de50dda12a594e03a8a0df8718efd8abe05..612e28c8b2d1c81395335eb624254e5d8b567c7c 100644 --- a/channels/chan_local.c +++ b/channels/chan_local.c @@ -390,10 +390,14 @@ static int local_hangup(struct ast_channel *ast) struct local_pvt *cur, *prev=NULL; struct ast_channel *ochan = NULL; int glaredetect; + char *status; ast_mutex_lock(&p->lock); isoutbound = IS_OUTBOUND(ast, p); if (isoutbound) { + status = pbx_builtin_getvar_helper(p->chan, "DIALSTATUS"); + if(status) + pbx_builtin_setvar_helper(p->owner, "CHANLOCALSTATUS", status); p->chan = NULL; p->launchedpbx = 0; } else diff --git a/configs/agents.conf.sample b/configs/agents.conf.sample index fd631b431b934f247068393079be4c03c9a29662..5d9761cda7df70a7f9a2b1313a5bd13d922f1d4b 100644 --- a/configs/agents.conf.sample +++ b/configs/agents.conf.sample @@ -22,6 +22,13 @@ persistentagents=yes ; ;autologoff=15 ; +; Define autologoffunavail to have agents automatically logged +; out when the extension that they are at returns a CHANUNAVAIL +; status when a call is attempted to be sent there. +; Default is "no". +; +;autologoffunavail=yes +; ; Define ackcall to require an acknowledgement by '#' when ; an agent logs in using agentcallbacklogin. Default is "no". ; diff --git a/doc/manager.txt b/doc/manager.txt index bd5df8077d833ec4eaf586e5adea6be0635ec83a..065d70a2146ff680409f18f213420c0eb212e515 100644 --- a/doc/manager.txt +++ b/doc/manager.txt @@ -252,6 +252,7 @@ Some standard AMI headers: Position: <num> -- Position in Queue Queue: -- Queue name Reason: -- "Autologoff" + Reason: -- "Chanunavail" Response: <response> -- response code, like "200 OK" "Success", "Error", "Follows" Restart: -- "True", "False" diff --git a/doc/queuelog.txt b/doc/queuelog.txt index a11812eef1a856d5e909456bbc9ae2565145a727..374b7a488bb2123b1953f4a9ab17bb89b28753ac 100644 --- a/doc/queuelog.txt +++ b/doc/queuelog.txt @@ -32,7 +32,8 @@ the agent was logged in. AGENTCALLBACKLOGOFF(exten@context|logintime|reason) The callback agent logged off. The last login extension and context is recorded, along with the total time the agent was logged in, and the -reason for the logoff if it was not a normal logoff (e.g., Autologoff) +reason for the logoff if it was not a normal logoff +(e.g., Autologoff, Chanunavail) COMPLETEAGENT(holdtime|calltime|origposition) The caller was connected to an agent, and the call was terminated normally