Index: app_dial.c =================================================================== RCS file: /usr/cvsroot/asterisk/apps/app_dial.c,v retrieving revision 1.149 diff -u -r1.149 app_dial.c --- app_dial.c 21 Apr 2005 06:02:43 -0000 1.149 +++ app_dial.c 26 Apr 2005 15:57:06 -0000 @@ -75,6 +75,9 @@ " 'o' -- Original (inbound) Caller*ID should be placed on the outbound leg of the call\n" " instead of using the destination extension (old style asterisk behavior)\n" " 'r' -- indicate ringing to the calling party, pass no audio until answered.\n" +" 'R(secs)' -- timeout to apply once ringing/call progress commences.\n" +" 'V(ms)' -- Drops call if ringing answered before ms milliseconds (ie. by eager voicemail);\n" +" DIALSTATUS is set to ANSWEREDTOOFAST. Requires use of timeout or R().\n" " 'm[(class)]' -- provide hold music to the calling party until answered (optionally\n" " with the specified class.\n" " 'M(x[^arg])' -- Executes the macro (x with ^ delim arg list) upon connect of the call.\n" @@ -259,7 +262,7 @@ dst->uniqueid); } -static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, struct ast_flags *peerflags, int *sentringing, char *status, size_t statussize, int busystart, int nochanstart, int congestionstart, int nojump, int *result) +static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, struct ast_flags *peerflags, int *sentringing, char *status, size_t statussize, int busystart, int nochanstart, int congestionstart, int nojump, int *result, int *ringingtimeout) { struct localuser *o; int found; @@ -269,6 +272,7 @@ int numnochan = nochanstart; int prestart = busystart + congestionstart + nochanstart; int cause; + int gotring = 0, gotprogress = 0; int orig = *to; struct ast_frame *f; struct ast_channel *peer = NULL; @@ -475,12 +479,21 @@ ast_indicate(in, AST_CONTROL_RINGING); (*sentringing)++; } + /* Ring timeout specified? Use it, now that there's ringing. */ + if (!gotring && ringingtimeout && *ringingtimeout >= 0) + orig = *to = *ringingtimeout; + gotring++; break; case AST_CONTROL_PROGRESS: if (option_verbose > 2) ast_verbose ( VERBOSE_PREFIX_3 "%s is making progress passing it to %s\n", o->chan->name,in->name); if (!ast_test_flag(outgoing, DIAL_RINGBACKONLY)) ast_indicate(in, AST_CONTROL_PROGRESS); + /* Call progress is sometimes all that indicates ringing. Note */ + /* if an actual ring indicator is received, the timer restarts */ + if (!gotprogress && ringingtimeout && *ringingtimeout >= 0) + orig = *to = *ringingtimeout; + gotprogress++; break; case AST_CONTROL_HOLD: if (option_verbose > 2) @@ -589,6 +602,10 @@ ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig); } + /* Call answered. Store millisecs line spent ringing/in progress */ + *ringingtimeout = orig; + if (*to != -1) + *ringingtimeout -= *to; return peer; } @@ -630,6 +647,7 @@ char *end_sound=NULL; char *start_sound=NULL; char *limitptr; + char *ptr; char limitdata[256]; char *sdtmfptr; char *dtmfcalled=NULL, *dtmfcalling=NULL; @@ -639,6 +657,7 @@ char toast[80]; int play_to_caller=0,play_to_callee=0; int playargs=0, sentringing=0, moh=0; + int ringingtimeout = -1, ringingminimum = -1; char *mohclass = NULL; char *outbound_group = NULL; char *macro_result = NULL, *macro_transfer_dest = NULL; @@ -701,6 +720,21 @@ ast_verbose(VERBOSE_PREFIX_3 "Setting call duration limit to %i seconds.\n",calldurationlimit); } + /* Extract ringing timeout */ + if ((ptr = strstr(transfer, "R("))) { + ringingtimeout=atoi(ptr+2); + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "Setting ringing limit to %i seconds.\n",ringingtimeout); + ringingtimeout *= 1000; + } + + /* Extract ringing minimum */ + if ((ptr = strstr(transfer, "V("))) { + ringingminimum=atoi(ptr+2); + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "Setting ring minimum to %i ms.\n",ringingminimum); + } + /* Extract DTMF strings to send upon successfull connect */ if ((sdtmfptr = strstr(transfer, "D("))) { dtmfcalled = ast_strdupa(sdtmfptr + 2); @@ -1119,8 +1153,8 @@ strncpy(status, "CHANUNAVAIL", sizeof(status) - 1); time(&start_time); - peer = wait_for_answer(chan, outgoing, &to, peerflags, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion, nojump, &result); - + peer = wait_for_answer(chan, outgoing, &to, peerflags, &sentringing, status, sizeof(status), numbusy, numnochan, numcongestion, nojump, &result, &ringingtimeout); + if (!peer) { if (result) { res = result; @@ -1139,7 +1173,21 @@ #ifdef OSP_SUPPORT /* Once call is answered, ditch the OSP Handle */ pbx_builtin_setvar_helper(chan, "_OSPHANDLE", ""); -#endif +#endif + + /* ringingtimeout now contains number of ms spent ringing */ + if (ringingtimeout < ringingminimum) { + if (ringingtimeout != -1) { + if (option_verbose > 2) + ast_verbose( VERBOSE_PREFIX_3 "ring time of %i beneath minimum of %i\n", + ringingtimeout, ringingminimum); + strncpy(status, "ANSWEREDTOOFAST", sizeof(status) - 1); + res = 0; + goto out; + } + + ast_log(LOG_WARNING, "V() option used without R() or timeout - ignoring\n"); + } strncpy(status, "ANSWER", sizeof(status) - 1); /* Ah ha! Someone answered within the desired timeframe. Of course after this we will always return with -1 so that it is hung up properly after the