diff --git a/apps/app_dial.c b/apps/app_dial.c index b0a21fb8584bfc8e7f99409bebe6b64998519767..3a963f9f3e74f6116c163c9c2c5b1e5ebfc6fe1b 100755 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -122,12 +122,14 @@ static void hanguptree(struct localuser *outgoing, struct ast_channel *exception #define AST_MAX_WATCHERS 256 -static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect, int *sentringing) +static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect, int *sentringing, char *status) { struct localuser *o; int found; int numlines; - int numbusies = 0; + int numbusy = 0; + int numcongestion = 0; + int numnochan = 0; int orig = *to; struct ast_frame *f; struct ast_channel *peer = NULL; @@ -162,9 +164,15 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu numlines++; } if (found < 0) { - if (numlines == numbusies) { + if (numlines == (numbusy + numcongestion + numnochan)) { if (option_verbose > 2) - ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy at this time\n"); + ast_verbose( VERBOSE_PREFIX_2 "Everyone is busy/congested at this time\n"); + if (numbusy) + strcpy(status, "BUSY"); + else if (numcongestion) + strcpy(status, "CONGESTION"); + else if (numnochan) + strcpy(status, "CHANUNAVAIL"); /* See if there is a special busy message */ if (ast_exists_extension(in, in->context, in->exten, in->priority + 101, in->callerid)) in->priority+=100; @@ -211,7 +219,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu if (!o->chan) { ast_log(LOG_NOTICE, "Unable to create local channel for call forward to '%s/%s'\n", tech, stuff); o->stillgoing = 0; - numbusies++; + numnochan++; } else { if (o->chan->callerid) free(o->chan->callerid); @@ -255,7 +263,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu o->stillgoing = 0; ast_hangup(o->chan); o->chan = NULL; - numbusies++; + numnochan++; } } continue; @@ -284,7 +292,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu o->stillgoing = 0; if (in->cdr) ast_cdr_busy(in->cdr); - numbusies++; + numbusy++; break; case AST_CONTROL_CONGESTION: if (option_verbose > 2) @@ -295,7 +303,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu o->stillgoing = 0; if (in->cdr) ast_cdr_busy(in->cdr); - numbusies++; + numcongestion++; break; case AST_CONTROL_RINGING: if (option_verbose > 2) @@ -418,6 +426,7 @@ static int dial_exec(struct ast_channel *chan, void *data) char *sdtmfptr; char sdtmfdata[256] = ""; char *stack,*var; + char status[256]; int play_to_caller=0,play_to_callee=0; int playargs=0, sentringing=0, moh=0; int digit = 0; @@ -816,6 +825,8 @@ static int dial_exec(struct ast_channel *chan, void *data) to = -1; if (outgoing) { + /* Our status will at least be NOANSWER */ + strcpy(status, "NOANSWER"); if (outgoing->musiconhold) { moh=1; ast_moh_start(chan, NULL); @@ -823,9 +834,10 @@ static int dial_exec(struct ast_channel *chan, void *data) ast_indicate(chan, AST_CONTROL_RINGING); sentringing++; } - } + } else + strcpy(status, "CHANUNAVAIL"); - peer = wait_for_answer(chan, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect, &sentringing); + peer = wait_for_answer(chan, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect, &sentringing, status); if (!peer) { if (to) @@ -838,6 +850,7 @@ static int dial_exec(struct ast_channel *chan, void *data) goto out; } if (peer) { + strcpy(status, "ANSWER"); /* 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 conversation. */ @@ -929,6 +942,8 @@ out: ast_indicate(chan, -1); } hanguptree(outgoing, NULL); + pbx_builtin_setvar_helper(chan, "DIALSTATUS", status); + LOCAL_USER_REMOVE(u); if((go_on>0) && (!chan->_softhangup)) diff --git a/channels/chan_zap.c b/channels/chan_zap.c index 4682617ea3693e1e1fd422892abadd267a9b6cd7..0125adee476d3fea4f1e76aeb5d1925f001e6b50 100755 --- a/channels/chan_zap.c +++ b/channels/chan_zap.c @@ -1448,6 +1448,14 @@ static int zt_call(struct ast_channel *ast, char *rdest, int timeout) ast_mutex_lock(&p->lock); strncpy(dest, rdest, sizeof(dest) - 1); strncpy(p->dialdest, rdest, sizeof(dest) - 1); + if ((ast->_state == AST_STATE_BUSY)) { + struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_BUSY }; + /* If this is a placeholder frame for a busy channel, + return busy state immediately */ + zap_queue_frame(p, &f); + ast_mutex_unlock(&p->lock); + return 0; + } if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) { ast_log(LOG_WARNING, "zt_call called on %s, neither down nor reserved\n", ast->name); ast_mutex_unlock(&p->lock); @@ -6136,7 +6144,7 @@ static struct zt_pvt *mkintf(int channel, int signalling, int radio, struct zt_p return tmp; } -static inline int available(struct zt_pvt *p, int channelmatch, int groupmatch) +static inline int available(struct zt_pvt *p, int channelmatch, int groupmatch, int *busy) { int res; ZT_PARAMS par; @@ -6146,6 +6154,11 @@ static inline int available(struct zt_pvt *p, int channelmatch, int groupmatch) /* Check to see if we have a channel match */ if ((channelmatch > 0) && (p->channel != channelmatch)) return 0; + /* We're at least busy at this point */ + if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS)) { + if (busy) + *busy = 1; + } /* If do not distrub, definitely not */ if (p->dnd) return 0; @@ -6293,6 +6306,7 @@ static struct ast_channel *zt_request(char *type, int format, void *data) int channelmatch = -1; int roundrobin = 0; int callwait = 0; + int busy = 0; struct zt_pvt *p; struct ast_channel *tmp = NULL; char *dest=NULL; @@ -6405,7 +6419,7 @@ static struct ast_channel *zt_request(char *type, int format, void *data) #if 0 ast_verbose("name = %s, %d\n",p->owner->name,p->channel); #endif - if (p && available(p, channelmatch, groupmatch)) { + if (p && available(p, channelmatch, groupmatch, &busy)) { if (option_debug) ast_log(LOG_DEBUG, "Using channel %d\n", p->channel); if (p->inalarm) @@ -6483,6 +6497,19 @@ next: } ast_mutex_unlock(lock); restart_monitor(); + if (!tmp) { + if (busy) { + tmp = zt_request("Zap", format, "pseudo"); + if (tmp) { + char newname[80]; + ast_mutex_lock(&tmp->lock); + snprintf(newname, sizeof(newname), "Zap/%s-busy-%d", (char *)data, rand()); + ast_change_name(tmp, newname); + ast_setstate(tmp, AST_STATE_BUSY); + ast_mutex_unlock(&tmp->lock); + } + } + } return tmp; } diff --git a/configs/extensions.conf.sample b/configs/extensions.conf.sample index b500f0252edcd3c8283daa64c9adadaa479e06fb..3fcf312629d20e884c7e42c044dc6b0932928f5e 100755 --- a/configs/extensions.conf.sample +++ b/configs/extensions.conf.sample @@ -181,10 +181,16 @@ include => iaxprovider ; ${ARG2} - Device(s) to ring ; exten => s,1,Dial(${ARG2},20) ; Ring the interface, 20 seconds maximum -exten => s,2,Voicemail(u${ARG1}) ; If unavailable, send to voicemail w/ unavail announce -exten => s,3,Goto(default,s,1) ; If they press #, return to start -exten => s,102,Voicemail(b${ARG1}) ; If busy, send to voicemail w/ busy announce -exten => s,103,Goto(default,s,1) ; If they press #, return to start +exten => s,2,Goto(s-${DIALSTATUS}) ; Jump based on status (NOANSWER,BUSY,CHANUNAVAIL,CONGESTION,ANSWER) + +exten => s-NOANSWER,1,Voicemail(u${ARG1}) ; If unavailable, send to voicemail w/ unavail announce +exten => s-NOANSWER,2,Goto(default,s,1) ; If they press #, return to start + +exten => s-BUSY,1,Voicemail(b${ARG1}) ; If busy, send to voicemail w/ busy announce +exten => s-BUSY,2,Goto(default,s,1) ; If they press #, return to start + +exten => s-.,1,Goto(s-NOANSWER,1) ; Treat anything else as no answer + exten => a,1,VoicemailMain(${ARG1}) ; If they press *, send the user into VoicemailMain [demo]