diff options
author | Mark Spencer <markster@digium.com> | 2004-05-02 03:39:17 +0000 |
---|---|---|
committer | Mark Spencer <markster@digium.com> | 2004-05-02 03:39:17 +0000 |
commit | cb59df7bed336fbb374fd81a36bdd0c555cb128d (patch) | |
tree | 69807ce788ac5ccc2a7cb1cb0e277d5435defa96 /channels | |
parent | 70d5cd021014a6e4837e325f61748ccb1f1d96ca (diff) |
Make overlap dial be interpreted in the same way an FXS would be (bugs #1080 and #1452)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@2854 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels')
-rwxr-xr-x | channels/chan_zap.c | 230 |
1 files changed, 140 insertions, 90 deletions
diff --git a/channels/chan_zap.c b/channels/chan_zap.c index d68847f56..9f445a127 100755 --- a/channels/chan_zap.c +++ b/channels/chan_zap.c @@ -590,6 +590,8 @@ static int hangup_cause2pri(int cause) switch(cause) { case AST_CAUSE_BUSY: return PRI_CAUSE_USER_BUSY; + case AST_CAUSE_UNALLOCATED: + return PRI_CAUSE_UNALLOCATED; case AST_CAUSE_NORMAL: default: return PRI_CAUSE_NORMAL_CLEARING; @@ -4232,6 +4234,43 @@ static void *ss_thread(void *data) if (p->dsp) ast_dsp_digitreset(p->dsp); switch(p->sig) { +#ifdef ZAPATA_PRI + case SIG_PRI: + /* Now loop looking for an extension */ + strncpy(exten, p->exten, sizeof(exten) - 1); + len = strlen(exten); + res = 0; + while((len < AST_MAX_EXTENSION-1) && ast_matchmore_extension(chan, chan->context, exten, 1, p->callerid)) { + if (ast_exists_extension(chan, chan->context, exten, 1, p->callerid)) + timeout = matchdigittimeout; + else + timeout = gendigittimeout; + res = ast_waitfordigit(chan, timeout); + if (res < 0) { + ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n"); + ast_hangup(chan); + return NULL; + } else if (res) { + exten[len++] = res; + } else + break; + } + if (ast_exists_extension(chan, chan->context, exten, 1, p->callerid)) { + /* Start the real PBX */ + strncpy(chan->exten, exten, sizeof(chan->exten)); + ast_dsp_digitreset(p->dsp); + res = ast_pbx_run(chan); + if (res) { + ast_log(LOG_WARNING, "PBX exited non-zero!\n"); + } + } else { + ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context); + chan->hangupcause = AST_CAUSE_UNALLOCATED; + ast_hangup(chan); + } + return NULL; + break; +#endif case SIG_FEATD: case SIG_FEATDMF: case SIG_E911: @@ -6112,6 +6151,8 @@ static void *pri_dchannel(void *vpri) pthread_t p; time_t t; int i; + pthread_t threadid; + pthread_attr_t attr; gettimeofday(&lastidle, NULL); if (strlen(pri->idledial) && strlen(pri->idleext)) { /* Need to do idle dialing, check to be sure though */ @@ -6332,44 +6373,68 @@ static void *pri_dchannel(void *vpri) } break; case PRI_EVENT_INFO_RECEIVED: + chan = e->ring.channel; + if ((chan < 1) || (chan > pri->channels)) { + ast_log(LOG_WARNING, "INFO received on odd channel number %d span %d\n", chan, pri->span); + chan = 0; + } else if (!pri->pvt[chan]) { + ast_log(LOG_WARNING, "INFO received on unconfigured channel %d span %d\n", chan, pri->span); + chan = 0; + } + if (chan) { + chan = pri_fixup(pri, chan, e->ring.call); + if (chan) { + /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */ + if (pri->overlapdial && pri->pvt[chan]->call==e->ring.call && pri->pvt[chan]->owner) { + /* how to do that */ + int digitlen = strlen(e->ring.callednum); + char digit; + int i; + for (i=0; i<digitlen; i++) { + digit = e->ring.callednum[i]; + { + struct ast_frame f = { AST_FRAME_DTMF, digit, }; + ast_queue_frame(pri->pvt[chan]->owner, &f); + } + } + } + } + } + break; case PRI_EVENT_RING: chan = e->ring.channel; - if (e->e==PRI_EVENT_RING) { - /* if no channel specified find one empty */ - if (chan == -1) - chan = pri_find_empty_chan(pri); - if ((chan < 1) || (chan > pri->channels)) { - ast_log(LOG_WARNING, "Ring requested on odd channel number %d span %d\n", chan, pri->span); - chan = 0; - } else if (!pri->pvt[chan]) { - ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d span %d\n", chan, pri->span); + /* if no channel specified find one empty */ + if (chan == -1) + chan = pri_find_empty_chan(pri); + if ((chan < 1) || (chan > pri->channels)) { + ast_log(LOG_WARNING, "Ring requested on odd channel number %d span %d\n", chan, pri->span); + chan = 0; + } else if (!pri->pvt[chan]) { + ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d span %d\n", chan, pri->span); + chan = 0; + } else if (pri->pvt[chan]->owner) { + if (pri->pvt[chan]->call == e->ring.call) { + ast_log(LOG_WARNING, "Duplicate setup requested on channel %d already in use on span %d\n", chan, pri->span); + break; + } else { + ast_log(LOG_WARNING, "Ring requested on channel %d already in use on span %d. Hanging up owner.\n", chan, pri->span); + pri->pvt[chan]->owner->_softhangup |= AST_SOFTHANGUP_DEV; chan = 0; - } else if (pri->pvt[chan]->owner) { - if (pri->pvt[chan]->call == e->ring.call) { - ast_log(LOG_WARNING, "Duplicate setup requested on channel %d already in use on span %d\n", chan, pri->span); - break; - } else { - ast_log(LOG_WARNING, "Ring requested on channel %d already in use on span %d. Hanging up owner.\n", chan, pri->span); - pri->pvt[chan]->owner->_softhangup |= AST_SOFTHANGUP_DEV; - chan = 0; - } } - if (!chan && (e->ring.flexible)) - chan = pri_find_empty_chan(pri); } + if (!chan && (e->ring.flexible)) + chan = pri_find_empty_chan(pri); if (chan) { - if (e->e==PRI_EVENT_RING) { - pri->pvt[chan]->call = e->ring.call; - /* Get caller ID */ - if (pri->pvt[chan]->use_callerid) { - if (strlen(e->ring.callingname)) { - snprintf(pri->pvt[chan]->callerid, sizeof(pri->pvt[chan]->callerid), "\"%s\" <%s>", e->ring.callingname, e->ring.callingnum); - } else - strncpy(pri->pvt[chan]->callerid, e->ring.callingnum, sizeof(pri->pvt[chan]->callerid)-1); + pri->pvt[chan]->call = e->ring.call; + /* Get caller ID */ + if (pri->pvt[chan]->use_callerid) { + if (strlen(e->ring.callingname)) { + snprintf(pri->pvt[chan]->callerid, sizeof(pri->pvt[chan]->callerid), "\"%s\" <%s>", e->ring.callingname, e->ring.callingnum); } else - strcpy(pri->pvt[chan]->callerid, ""); - strncpy(pri->pvt[chan]->rdnis, e->ring.redirectingnum, sizeof(pri->pvt[chan]->rdnis)); - } + strncpy(pri->pvt[chan]->callerid, e->ring.callingnum, sizeof(pri->pvt[chan]->callerid)-1); + } else + strcpy(pri->pvt[chan]->callerid, ""); + strncpy(pri->pvt[chan]->rdnis, e->ring.redirectingnum, sizeof(pri->pvt[chan]->rdnis)); /* If immediate=yes go to s|1 */ if (pri->pvt[chan]->immediate) { if (option_verbose > 2) @@ -6378,20 +6443,9 @@ static void *pri_dchannel(void *vpri) } /* Get called number */ else if (strlen(e->ring.callednum)) { -#ifndef PRI_COPY_DIGITS_CALLED_NUMBER -#error Please update the libpri package -#endif - if (e->e==PRI_EVENT_RING) - strncpy(pri->pvt[chan]->exten, e->ring.callednum, sizeof(pri->pvt[chan]->exten)-1); - else - strncat(pri->pvt[chan]->exten, e->ring.callednum, sizeof(pri->pvt[chan]->exten)-1); + strncpy(pri->pvt[chan]->exten, e->ring.callednum, sizeof(pri->pvt[chan]->exten)-1); strncpy(pri->pvt[chan]->dnid, e->ring.callednum, sizeof(pri->pvt[chan]->dnid)); - } -#if 0 - else - strcpy(pri->pvt[chan]->exten, "s"); -#endif - else + } else strcpy(pri->pvt[chan]->exten, ""); /* No number yet, but received "sending complete"? */ if (e->ring.complete && (!strlen(e->ring.callednum))) { @@ -6399,30 +6453,12 @@ static void *pri_dchannel(void *vpri) ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n"); strcpy(pri->pvt[chan]->exten, "s"); } - /* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */ - if (pri->overlapdial && pri->pvt[chan]->call==e->ring.call && pri->pvt[chan]->owner) { - /* how to do that */ - int digitlen = strlen(e->ring.callednum); - char digit; - int i; - /* make sure that we store the right number in CDR */ - if (pri->pvt[chan]->owner->cdr) - strncat(pri->pvt[chan]->owner->cdr->dst,e->ring.callednum,digitlen); - - for (i=0; i<digitlen; i++) { - digit = e->ring.callednum[i]; - { - struct ast_frame f = { AST_FRAME_DTMF, digit, }; - ast_queue_frame(pri->pvt[chan]->owner, &f); - } - } - } - /* Make sure extension exists */ - /* If extensions is empty then make sure we send later on SETUP_ACKNOWLEDGE to get digits in overlap mode */ - else if (strlen(pri->pvt[chan]->exten) && ast_exists_extension(NULL, pri->pvt[chan]->context, pri->pvt[chan]->exten, 1, pri->pvt[chan]->callerid)) { + /* Make sure extension exists (or in overlap dial mode, can exist) */ + if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvt[chan]->context, pri->pvt[chan]->exten, 1, pri->pvt[chan]->callerid)) || + ast_exists_extension(NULL, pri->pvt[chan]->context, pri->pvt[chan]->exten, 1, pri->pvt[chan]->callerid)) { /* Setup law */ int law; - /* Set to audio mode at this poitn mode */ + /* Set to audio mode at this point */ law = 1; if (ioctl(pri->pvt[chan]->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &law) == -1) ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d\n", pri->pvt[chan]->channel, law); @@ -6438,43 +6474,57 @@ static void *pri_dchannel(void *vpri) ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvt[chan]->channel); if (e->ring.complete || !pri->overlapdial) { pri_acknowledge(pri->pri, e->ring.call, chan, 1); - } else if (e->e==PRI_EVENT_RING) { - /* If we got here directly and didn't send the SETUP_ACKNOWLEDGE we need to send it otherwise we don't sent anything */ + } else { pri_need_more_info(pri->pri, e->ring.call, chan, 1); } /* Get the use_callingpres state */ pri->pvt[chan]->callingpres = e->ring.callingpres; /* Start PBX */ - c = zt_new(pri->pvt[chan], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype); - if (c) { - if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d, span %d\n", - e->ring.callingnum, pri->pvt[chan]->exten, chan, pri->span); - zt_enable_ec(pri->pvt[chan]); - } else { - ast_log(LOG_WARNING, "Unable to start PBX on channel %d, span %d\n", chan, pri->span); + if (pri->overlapdial && ast_matchmore_extension(NULL, pri->pvt[chan]->context, pri->pvt[chan]->exten, 1, pri->pvt[chan]->callerid)) { + c = zt_new(pri->pvt[chan], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype); + if (c && !pthread_create(&threadid, &attr, ss_thread, c)) { + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d, span %d\n", + e->ring.callingnum, strlen(pri->pvt[chan]->exten) ? pri->pvt[chan]->exten : "<unspecified>", chan, pri->span); + } else { + ast_log(LOG_WARNING, "Unable to start PBX on channel %d, span %d\n", chan, pri->span); + if (c) + ast_hangup(c); + else { #if NEW_PRI_HANGUP - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); #else - pri_release(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); + pri_release(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); #endif - pri->pvt[chan]->call = NULL; + pri->pvt[chan]->call = NULL; + } + } + } else { + c = zt_new(pri->pvt[chan], AST_STATE_RING, 1, SUB_REAL, law, e->ring.ctype); + if (c) { + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d, span %d\n", + e->ring.callingnum, pri->pvt[chan]->exten, chan, pri->span); + zt_enable_ec(pri->pvt[chan]); + } else { + ast_log(LOG_WARNING, "Unable to start PBX on channel %d, span %d\n", chan, pri->span); +#if NEW_PRI_HANGUP + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); +#else + pri_release(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION); +#endif + pri->pvt[chan]->call = NULL; + } } } else { - if ((!strlen(pri->pvt[chan]->exten) || ast_matchmore_extension(NULL, pri->pvt[chan]->context, pri->pvt[chan]->exten, 1, pri->pvt[chan]->callerid)) && !e->ring.complete) - { - /* Send SETUP_ACKNOWLEDGE only when we receive SETUP, don't send if we got INFORMATION */ - if (e->e==PRI_EVENT_RING) pri_need_more_info(pri->pri, e->ring.call, chan, 1); - } else { - if (option_verbose > 2) - ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d, span %d\n",pri->pvt[chan]->exten, pri->pvt[chan]->context, pri->pvt[chan]->callerid, chan, pri->span); + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist. Rejecting call on channel %d, span %d\n",pri->pvt[chan]->exten, pri->pvt[chan]->context, pri->pvt[chan]->callerid, chan, pri->span); #ifdef NEW_PRI_HANGUP - pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED); + pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED); #else - pri_release(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED); + pri_release(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED); #endif - pri->pvt[chan]->call = NULL; - } + pri->pvt[chan]->call = NULL; } } else #ifdef NEW_PRI_HANGUP |