Index: channels/chan_agent.c =================================================================== RCS file: /usr/cvsroot/asterisk/channels/chan_agent.c,v retrieving revision 1.119 diff -u -r1.119 chan_agent.c --- channels/chan_agent.c 1 Mar 2005 06:24:43 -0000 1.119 +++ channels/chan_agent.c 3 Mar 2005 13:47:48 -0000 @@ -137,6 +137,12 @@ static char savecallsin[AST_MAX_BUF] = ""; static int updatecdr = 0; static char beep[AST_MAX_BUF] = "beep"; +static int anydtmfdisconnects = 0; +static int longwrapuptime = 0; +/* This has to be -1 because that's not a valid DTMF */ +static int longwrapupdtmf = -1; +/* This has to be 1 because that's legacy behaviour */ +static int splatdisconnects = 1; #define GETAGENTBYCALLERID "AGENTBYCALLERID" @@ -151,6 +157,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 */ @@ -270,6 +277,7 @@ p->ackcall = ackcall; p->autologoff = autologoff; p->wrapuptime = wrapuptime; + p->lastwrapuptime = wrapuptime; if (pending) p->dead = 1; else @@ -342,6 +350,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[3] = ""; ast_mutex_lock(&p->lock); CHECK_FORMATS(ast, p); if (p->chan) { @@ -392,22 +401,38 @@ f = &answer_frame; } } - if (f && (f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) { - if (!p->acknowledged) { - if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "%s acknowledged\n", p->chan->name); - p->acknowledged = 1; + if (f && (f->frametype == AST_FRAME_DTMF)) { + if (f->subclass == '#') { + if (!p->acknowledged) { + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "%s acknowledged\n", p->chan->name); + p->acknowledged = 1; + ast_frfree(f); + f = &answer_frame; + } + } else if (anydtmfdisconnects) { + /* any DTMF (besides #) terminates call */ + snprintf(tmpdtmf, 2, "%c", f->subclass); + if (p->owner && ast_bridged_channel(p->owner)) { + if (!ast_bridged_channel(p->owner)->cdr) + ast_bridged_channel(p->owner)->cdr = ast_cdr_alloc(); + ast_cdr_setuserfield(ast_bridged_channel(p->owner), tmpdtmf); + pbx_builtin_setvar_helper(p->chan, "DTMF_DISCO", tmpdtmf); + } ast_frfree(f); - f = &answer_frame; + f = NULL; + } else if (splatdisconnects && f->subclass == '*') { + /* * terminates call */ + ast_frfree(f); + f = NULL; + } else { + /* we dont care about this DTMF */ + ast_verbose(VERBOSE_PREFIX_3 "ignored DTMF %d on %s\n", f->subclass, p->chan->name); } } - if (f && (f->frametype == AST_FRAME_DTMF) && (f->subclass == '*')) { - /* * terminates call */ - ast_frfree(f); - f = NULL; - } if (f && (f->frametype == AST_FRAME_VOICE) && !p->acknowledged) { /* Don't pass along agent audio until call is acknowledged */ + ast_verbose(VERBOSE_PREFIX_3 "WTF WTF WTF\n"); ast_frfree(f); f = &null_frame; } @@ -588,6 +613,7 @@ { struct agent_pvt *p = ast->pvt->pvt; int howlong = 0; + int dtmfdisco = -1; ast_mutex_lock(&p->lock); p->owner = NULL; ast->pvt->pvt = NULL; @@ -614,10 +640,26 @@ } else p->start = 0; if (p->chan) { + /* If any DTMF can disconnect, let's see what it was */ + if (anydtmfdisconnects) { + if (pbx_builtin_getvar_helper(p->chan, "DTMF_DISCO") && strlen(pbx_builtin_getvar_helper(p->chan, "DTMF_DISCO"))) { + dtmfdisco = atoi(pbx_builtin_getvar_helper(p->chan, "DTMF_DISCO")); + } + } /* 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) { + /* Check if we got the special DTMF disconnect */ + if (dtmfdisco == longwrapupdtmf) { + /* 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) { @@ -694,8 +736,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 (longwrapupdtmf > 0 && p->wrapuptime && anydtmfdisconnects) { + /* Check if we got the special DTMF disconnect */ + if (dtmfdisco == longwrapupdtmf) { + /* 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). */ @@ -902,6 +963,10 @@ autologoff = 0; wrapuptime = 0; ackcall = 0; + anydtmfdisconnects = 0; + longwrapuptime = 0; + longwrapupdtmf = -1; + splatdisconnects = 1; cfg = ast_config_load(config); if (!cfg) { ast_log(LOG_NOTICE, "No agent configuration found -- agent support disabled\n"); @@ -985,6 +1050,16 @@ 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")) { + longwrapupdtmf = atoi(v->value); + } else if (!strcasecmp(v->name, "longwrapuptime")) { + longwrapuptime = atoi(v->value); + if (longwrapuptime < 0) + longwrapuptime = 0; + } else if (!strcasecmp(v->name, "splatdisconnects")) { + splatdisconnects = ast_true(v->value); } 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 3 Mar 2005 13:47:49 -0000 @@ -28,6 +28,23 @@ ; ;wrapuptime=5000 ; +; Define a different wrapuptime if any DTMF tone is allowed to +; disconnect the call. anydtmfdisconnects must be set to "yes" +; for this to work, then the longwraupdtmf will temporarily +; change the wrapuptime (after that call only) to the value of +; longwrapuptime. +; +; anydtmfdisconnects=no +; longwrapupdtmf=5 +; longwrapuptime=30000 +; +; Define splatdisconnects to allow '*' to terminate a call. +; If you have both this and anydtmfdisconnects set to "yes", +; then anydtmfdisconnects will take priority. +; Default is "yes". (legacy behaviour) +; +; splatdisconnects=yes +; ; Define the default musiconhold for agents ; musiconhold => music_class ;