Index: channels/chan_agent.c =================================================================== RCS file: /usr/cvsroot/asterisk/channels/chan_agent.c,v retrieving revision 1.133 diff -u -r1.133 chan_agent.c --- channels/chan_agent.c 21 Apr 2005 06:02:43 -0000 1.133 +++ channels/chan_agent.c 9 May 2005 22:37:12 -0000 @@ -133,6 +133,10 @@ static int updatecdr = 0; static char beep[AST_MAX_BUF] = "beep"; +static int anydtmfdisconnects = 0; +static int longwrapuptime = 0; +static char longwrapupdtmf[2] = ""; + #define GETAGENTBYCALLERID "AGENTBYCALLERID" static struct agent_pvt { @@ -146,6 +150,7 @@ time_t start; /* When call started */ struct timeval lastdisc; /* When last disconnected */ int wrapuptime; /* Wrapup time in ms */ + int lastwrapuptime; /* Last wrapup time in ms (used when we allow long wrap up times so we can keep state of the original wrap up time) */ ast_group_t group; /* Group memberships */ int acknowledged; /* Acknowledged */ char moh[80]; /* Which music on hold */ @@ -318,6 +323,7 @@ } } p->wrapuptime = wrapuptime; + p->lastwrapuptime = wrapuptime; if (pending) p->dead = 1; @@ -391,6 +397,7 @@ 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 }; + char tmpdtmf[2] = ""; ast_mutex_lock(&p->lock); CHECK_FORMATS(ast, p); if (p->chan) { @@ -451,6 +458,15 @@ p->acknowledged = 1; ast_frfree(f); f = &answer_frame; + } else if (anydtmfdisconnects) { + /* any DTMF (besides #) terminates call */ + if (p->owner && ast_bridged_channel(p->owner)) { + tmpdtmf[0] = f->subclass; + ast_cdr_setuserfield(ast_bridged_channel(p->owner), tmpdtmf); + pbx_builtin_setvar_helper(p->chan, "DTMF_DISCO", tmpdtmf); + } + ast_frfree(f); + f = NULL; } else if (f->subclass == '*') { /* terminates call */ ast_frfree(f); @@ -644,6 +660,8 @@ { struct agent_pvt *p = ast->tech_pvt; int howlong = 0; + char *dtmfdisco = NULL; + long logintime; ast_mutex_lock(&p->lock); p->owner = NULL; ast->tech_pvt = NULL; @@ -671,10 +689,36 @@ p->start = 0; if (p->chan) { p->chan->_bridge = NULL; + /* If any DTMF can disconnect, let's see what it was */ + if (anydtmfdisconnects) { + if ((dtmfdisco = pbx_builtin_getvar_helper(p->chan, "DTMF_DISCO"))) { + if (!ast_strlen_zero(dtmfdisco)) { + logintime = time(NULL) - p->loginstart; + ast_log(LOG_DEBUG, "Agent hungup with DTMF '%s'\n", dtmfdisco); + manager_event(EVENT_FLAG_AGENT, "AgentDisconnect", + "Agent: %s\r\n" + "Loginchan: %s\r\n" + "Logintime: %ld\r\n" + "Dtmf: %s\r\n" + "Uniqueid: %s\r\n", + p->agent, p->loginchan, logintime, dtmfdisco, ast->uniqueid); + } + } + } /* If they're dead, go ahead and hang up on the agent now */ if (!ast_strlen_zero(p->loginchan)) { /* Store last disconnect time */ if (p->wrapuptime && p->acknowledged) { + /* Check if we got the special DTMF disconnect */ + if (strchr(longwrapupdtmf, dtmfdisco[0])) { + /* Change the wrap up time to be a little longer */ + p->lastwrapuptime = p->wrapuptime; + p->wrapuptime = longwrapuptime; + } else { + /* Change the wrap up time back to the original */ + if (p->lastwrapuptime) + p->wrapuptime = p->lastwrapuptime; + } gettimeofday(&p->lastdisc, NULL); p->lastdisc.tv_usec += (p->wrapuptime % 1000) * 1000; if (p->lastdisc.tv_usec >= 1000000) { @@ -752,8 +796,27 @@ if (p->chan) { /* Not dead -- check availability now */ ast_mutex_lock(&p->lock); - /* Store last disconnect time */ - gettimeofday(&p->lastdisc, NULL); + /* Store last disconnect time, depending on DTMF disconnect */ + if (!ast_strlen_zero(longwrapupdtmf) && p->wrapuptime && anydtmfdisconnects) { + /* Check if we got the special DTMF disconnect */ + if (strchr(longwrapupdtmf, dtmfdisco[0])) { + /* Change the wrap up time to be a little longer */ + p->lastwrapuptime = p->wrapuptime; + p->wrapuptime = longwrapuptime; + } else { + /* Change the wrap up time back to the original */ + if (p->lastwrapuptime) + p->wrapuptime = p->lastwrapuptime; + } + gettimeofday(&p->lastdisc, NULL); + p->lastdisc.tv_usec += (p->wrapuptime % 1000) * 1000; + if (p->lastdisc.tv_usec >= 1000000) { + p->lastdisc.tv_usec -= 1000000; + p->lastdisc.tv_sec++; + } + p->lastdisc.tv_sec += (p->wrapuptime / 1000); + } else + gettimeofday(&p->lastdisc, NULL); ast_mutex_unlock(&p->lock); } /* Release ownership of the agent to other threads (presumably running the login app). */ @@ -950,6 +1013,9 @@ autologoff = 0; wrapuptime = 0; ackcall = 0; + anydtmfdisconnects = 0; + longwrapuptime = 0; + longwrapupdtmf[0] = '\0'; cfg = ast_config_load(config); if (!cfg) { ast_log(LOG_NOTICE, "No agent configuration found -- agent support disabled\n"); @@ -1033,6 +1099,14 @@ strncat(savecallsin, "/", sizeof(savecallsin) - strlen(savecallsin) - 1); } else if (!strcasecmp(v->name, "custom_beep")) { strncpy(beep, v->value, sizeof(beep) - 1); + } else if (!strcasecmp(v->name, "anydtmfdisconnects")) { + anydtmfdisconnects = ast_true(v->value); + } else if (!strcasecmp(v->name, "longwrapupdtmf")) { + strncpy(longwrapupdtmf, v->value, sizeof(longwrapupdtmf) - 1); + } else if (!strcasecmp(v->name, "longwrapuptime")) { + longwrapuptime = atoi(v->value); + if (longwrapuptime < 0) + longwrapuptime = 0; } v = v->next; } Index: configs/agents.conf.sample =================================================================== RCS file: /usr/cvsroot/asterisk/configs/agents.conf.sample,v retrieving revision 1.15 diff -u -r1.15 agents.conf.sample --- configs/agents.conf.sample 14 Feb 2005 23:20:01 -0000 1.15 +++ configs/agents.conf.sample 9 May 2005 22:37:12 -0000 @@ -28,6 +28,21 @@ ; ;wrapuptime=5000 ; +; Define if any DTMF tone sent by the agent will disconnect a call. +; By default, only '*' will allow an agent to disconnect a call. +; Default is "no". +; +;anydtmfdisconnects=no +; +; Define a different wrapuptime if any DTMF tone is allowed to +; disconnect the call. anydtmfdisconnects must be set to "yes" +; for this to work, and then receipt of the longwrapupdtmf will +; temporarily change the wrapuptime (after that call only) to +; the value of longwrapuptime. +; +;longwrapupdtmf=5 +;longwrapuptime=30000 +; ; Define the default musiconhold for agents ; musiconhold => music_class ;