aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
authorrmudgett <rmudgett@f38db490-d61c-443f-a65b-d21fe96a405b>2011-01-25 17:42:42 +0000
committerrmudgett <rmudgett@f38db490-d61c-443f-a65b-d21fe96a405b>2011-01-25 17:42:42 +0000
commit0013388425c43990cc5c06b5d803ab6519f8aa97 (patch)
tree4109cb1d14a2e3dc1bf2f4ab20e111b2360d105e /channels
parent75ca086244174231a7f3e80c0e04e7397005ab04 (diff)
Merged revisions 303765 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4 ........ r303765 | rmudgett | 2011-01-25 11:36:50 -0600 (Tue, 25 Jan 2011) | 40 lines Sending out unnecessary PROCEEDING messages breaks overlap dialing. Issue #16789 was a good idea. Unfortunately, it breaks overlap dialing through Asterisk. There is not enough information available at this point to know if dialing is complete. The ast_exists_extension(), ast_matchmore_extension(), and ast_canmatch_extension() calls are not adequate to detect a dial through extension pattern of "_9!". Workaround is to use the dialplan Proceeding() application early in non-dial through extensions. * Effectively revert issue #16789. * Allow outgoing overlap dialing to hear dialtone and other early media. A PROGRESS "inband-information is now available" message is now sent after the SETUP_ACKNOWLEDGE message for non-digital calls. An AST_CONTROL_PROGRESS is now generated for incoming SETUP_ACKNOWLEDGE messages for non-digital calls. * Handling of the AST_CONTROL_CONGESTION in chan_dahdi/sig_pri was inconsistent with the cause codes. * Added better protection from sending out of sequence messages by combining several flags into a single enum value representing call progress level. * Added diagnostic messages for deferred overlap digits handling corner cases. (closes issue #17085) Reported by: shawkris (closes issue #18509) Reported by: wimpy Patches: issue18509_early_media_v1.8_v3.patch uploaded by rmudgett (license 664) Expanded upon issue18509_early_media_v1.8_v3.patch to include analog and SS7 because of backporting requirements. Tested by: wimpy, rmudgett ........ git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.6.2@303769 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_dahdi.c451
1 files changed, 301 insertions, 150 deletions
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index da01d595a..4048afea0 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -505,6 +505,22 @@ static int r2links_count = 0;
#define PRI_SPAN(p) (((p) >> 8) & 0xff)
#define PRI_EXPLICIT(p) (((p) >> 16) & 0x01)
+/*! Call establishment life cycle level for simple comparisons. */
+enum dahdi_call_level {
+ /*! Call does not exist. */
+ DAHDI_CALL_LEVEL_IDLE,
+ /*! Call is present but has no response yet. (SETUP) */
+ DAHDI_CALL_LEVEL_SETUP,
+ /*! Call is collecting digits for overlap dialing. (SETUP ACKNOWLEDGE) */
+ DAHDI_CALL_LEVEL_OVERLAP,
+ /*! Call routing is happening. (PROCEEDING) */
+ DAHDI_CALL_LEVEL_PROCEEDING,
+ /*! Called party is being alerted of the call. (ALERTING) */
+ DAHDI_CALL_LEVEL_ALERTING,
+ /*! Call is connected/answered. (CONNECT) */
+ DAHDI_CALL_LEVEL_CONNECT,
+};
+
struct dahdi_pri {
pthread_t master; /*!< Thread of master */
ast_mutex_t lock; /*!< Mutex */
@@ -918,14 +934,17 @@ static struct dahdi_pvt {
* \note Applies to SS7 channels.
*/
unsigned int remotelyblocked:1;
+ /*!
+ * \brief TRUE if SMDI (Simplified Message Desk Interface) is enabled
+ * \note Set from the "usesmdi" value read in from chan_dahdi.conf
+ */
+ unsigned int use_smdi:1;
#if defined(HAVE_PRI) || defined(HAVE_SS7)
/*!
* \brief XXX BOOLEAN Purpose???
* \note Applies to SS7 channels.
*/
unsigned int rlt:1;
- /*! \brief TRUE if channel is alerting/ringing */
- unsigned int alerting:1;
/*! \brief TRUE if the call has already gone/hungup */
unsigned int alreadyhungup:1;
/*!
@@ -933,29 +952,17 @@ static struct dahdi_pvt {
* \note Applies to PRI channels.
*/
unsigned int isidlecall:1;
- /*!
- * \brief TRUE if call is in a proceeding state.
- * The call has started working its way through the network.
- */
- unsigned int proceeding:1;
- /*! \brief TRUE if the call has seen progress through the network. */
+ /*! \brief TRUE if the call has seen inband-information progress through the network. */
unsigned int progress:1;
/*!
* \brief TRUE if this channel is being reset/restarted
* \note Applies to PRI channels.
*/
unsigned int resetting:1;
- /*!
- * \brief TRUE if this channel has received a SETUP_ACKNOWLEDGE
- * \note Applies to PRI channels.
- */
- unsigned int setup_ack:1;
+
+ /*! Call establishment life cycle level for simple comparisons. */
+ enum dahdi_call_level call_level;
#endif
- /*!
- * \brief TRUE if SMDI (Simplified Message Desk Interface) is enabled
- * \note Set from the "usesmdi" value read in from chan_dahdi.conf
- */
- unsigned int use_smdi:1;
struct mwisend_info mwisend_data;
/*! \brief The serial port to listen for SMDI data on */
struct ast_smdi_interface *smdi_iface;
@@ -2298,21 +2305,37 @@ static int dahdi_digit_begin(struct ast_channel *chan, char digit)
#ifdef HAVE_PRI
if (((pvt->sig == SIG_PRI) || (pvt->sig == SIG_BRI) || (pvt->sig == SIG_BRI_PTMP))
- && (chan->_state == AST_STATE_DIALING) && !pvt->proceeding) {
- if (pvt->setup_ack) {
+ && chan->_state == AST_STATE_DIALING) {
+ if (pvt->call_level < DAHDI_CALL_LEVEL_OVERLAP) {
+ unsigned int len;
+
+ len = strlen(pvt->dialdest);
+ if (len < sizeof(pvt->dialdest) - 1) {
+ ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n",
+ digit);
+ pvt->dialdest[len++] = digit;
+ pvt->dialdest[len] = '\0';
+ } else {
+ ast_log(LOG_WARNING,
+ "Span %d: Deferred digit buffer overflow for digit '%c'.\n",
+ pvt->span, digit);
+ }
+ goto out;
+ }
+ if (pvt->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
if (!pri_grab(pvt, pvt->pri)) {
pri_information(pvt->pri->pri, pvt->call, digit);
pri_rel(pvt->pri);
- } else
+ } else {
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
- } else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
- int res;
- ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit);
- res = strlen(pvt->dialdest);
- pvt->dialdest[res++] = digit;
- pvt->dialdest[res] = '\0';
+ }
+ goto out;
+ }
+ if (pvt->call_level < DAHDI_CALL_LEVEL_CONNECT) {
+ ast_log(LOG_WARNING,
+ "Span %d: Digit '%c' may be ignored by peer. (Call level:%d)\n",
+ pvt->span, digit, pvt->call_level);
}
- goto out;
}
#endif
if ((dtmf = digit_to_dtmfindex(digit)) == -1)
@@ -3582,6 +3605,7 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
ast_channel_unlock(ast);
+ p->call_level = DAHDI_CALL_LEVEL_SETUP;
isup_iam(p->ss7->ss7, p->ss7call);
ast_setstate(ast, AST_STATE_DIALING);
ss7_rel(p->ss7);
@@ -3897,11 +3921,14 @@ static int dahdi_call(struct ast_channel *ast, char *rdest, int timeout)
if (pri_setup(p->pri->pri, p->call, sr)) {
ast_log(LOG_WARNING, "Unable to setup call to %s (using %s)\n",
c + p->stripmsd + dp_strip, dialplan2str(p->pri->dialplan));
+ pri_destroycall(p->pri->pri, p->call);
+ p->call = NULL;
pri_rel(p->pri);
ast_mutex_unlock(&p->lock);
pri_sr_free(sr);
return -1;
}
+ p->call_level = DAHDI_CALL_LEVEL_SETUP;
pri_sr_free(sr);
ast_setstate(ast, AST_STATE_DIALING);
pri_rel(p->pri);
@@ -4570,12 +4597,10 @@ static int dahdi_hangup(struct ast_channel *ast)
p->pulsedial = 0;
p->onhooktime = time(NULL);
#if defined(HAVE_PRI) || defined(HAVE_SS7)
- p->proceeding = 0;
p->dialing = 0;
p->progress = 0;
- p->alerting = 0;
- p->setup_ack = 0;
p->rlt = 0;
+ p->call_level = DAHDI_CALL_LEVEL_IDLE;
#endif
if (p->dsp) {
ast_dsp_free(p->dsp);
@@ -4879,7 +4904,9 @@ static int dahdi_answer(struct ast_channel *ast)
case SIG_PRI:
/* Send a pri acknowledge */
if (!pri_grab(p, p->pri)) {
- p->proceeding = 1;
+ if (p->call_level < DAHDI_CALL_LEVEL_CONNECT) {
+ p->call_level = DAHDI_CALL_LEVEL_CONNECT;
+ }
p->dialing = 0;
res = pri_answer(p->pri->pri, p->call, 0, !p->digital);
pri_rel(p->pri);
@@ -4892,7 +4919,9 @@ static int dahdi_answer(struct ast_channel *ast)
#ifdef HAVE_SS7
case SIG_SS7:
if (!ss7_grab(p, p->ss7)) {
- p->proceeding = 1;
+ if (p->call_level < DAHDI_CALL_LEVEL_CONNECT) {
+ p->call_level = DAHDI_CALL_LEVEL_CONNECT;
+ }
res = isup_anm(p->ss7->ss7, p->ss7call);
ss7_rel(p->ss7);
} else {
@@ -5966,7 +5995,10 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
p->pulsedial = (res & DAHDI_EVENT_PULSEDIGIT) ? 1 : 0;
ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
#if defined(HAVE_PRI)
- if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
+ if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
+ && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING
+ && p->pri
+ && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
/* absorb event */
} else
#endif /* defined(HAVE_PRI) */
@@ -5983,7 +6015,10 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
if (res & DAHDI_EVENT_DTMFDOWN) {
ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
#if defined(HAVE_PRI)
- if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
+ if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
+ && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING
+ && p->pri
+ && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
/* absorb event */
} else
#endif /* defined(HAVE_PRI) */
@@ -7309,9 +7344,11 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast)
} else if (f->frametype == AST_FRAME_DTMF_BEGIN
|| f->frametype == AST_FRAME_DTMF_END) {
#ifdef HAVE_PRI
- if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) && p->pri &&
- ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) ||
- (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
+ if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
+ && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING
+ && p->pri
+ && ((!p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING))
+ || (p->outgoing && (p->pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)))) {
/* Don't accept in-band DTMF when in overlap dial mode */
ast_debug(1, "Absorbing inband %s DTMF digit: 0x%02X '%c' on %s\n",
f->frametype == AST_FRAME_DTMF_BEGIN ? "begin" : "end",
@@ -7422,22 +7459,6 @@ static int dahdi_write(struct ast_channel *ast, struct ast_frame *frame)
return -1;
}
-#if 0
-#ifdef HAVE_PRI
- ast_mutex_lock(&p->lock);
- if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
- if (p->pri->pri) {
- if (!pri_grab(p, p->pri)) {
- pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
- pri_rel(p->pri);
- } else
- ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
- }
- p->proceeding=1;
- }
- ast_mutex_unlock(&p->lock);
-#endif
-#endif
/* Write a frame of (presumably voice) data */
if (frame->frametype != AST_FRAME_VOICE) {
if (frame->frametype != AST_FRAME_IMAGE)
@@ -7513,57 +7534,60 @@ static int dahdi_indicate(struct ast_channel *chan, int condition, const void *d
switch (condition) {
case AST_CONTROL_BUSY:
#ifdef HAVE_PRI
- if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
- chan->hangupcause = AST_CAUSE_USER_BUSY;
- chan->_softhangup |= AST_SOFTHANGUP_DEV;
- res = 0;
- } else if (!p->progress &&
- ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
- && p->pri && !p->outgoing) {
- if (p->pri->pri) {
- if (!pri_grab(p, p->pri)) {
+ if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
+ if (p->priindication_oob) {
+ chan->hangupcause = AST_CAUSE_USER_BUSY;
+ chan->_softhangup |= AST_SOFTHANGUP_DEV;
+ res = 0;
+ break;
+ }
+ res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
+ if (p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
+ chan->hangupcause = AST_CAUSE_USER_BUSY;
+ p->progress = 1;/* No need to send plain PROGRESS after this. */
+ if (p->pri && p->pri->pri) {
+ if (!pri_grab(p, p->pri)) {
#ifdef HAVE_PRI_PROG_W_CAUSE
- pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_USER_BUSY); /* cause = 17 */
+ pri_progress_with_cause(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1, chan->hangupcause);
#else
- pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
+ pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
#endif
- pri_rel(p->pri);
+ pri_rel(p->pri);
+ } else {
+ ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
+ }
}
- else
- ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
}
- p->progress = 1;
- res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
- } else
+ break;
+ }
#endif
- res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
+ res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
break;
case AST_CONTROL_RINGING:
#ifdef HAVE_PRI
- if ((!p->alerting) && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
- && p->pri && !p->outgoing && (chan->_state != AST_STATE_UP)) {
- if (p->pri->pri) {
+ if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
+ && p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
+ p->call_level = DAHDI_CALL_LEVEL_ALERTING;
+ if (p->pri && p->pri->pri) {
if (!pri_grab(p, p->pri)) {
pri_acknowledge(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
pri_rel(p->pri);
- }
- else
+ } else {
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
+ }
}
- p->alerting = 1;
}
-
#endif
#ifdef HAVE_SS7
- if ((!p->alerting) && (p->sig == SIG_SS7) && p->ss7 && !p->outgoing && (chan->_state != AST_STATE_UP)) {
- if (p->ss7->ss7) {
+ if (p->sig == SIG_SS7
+ && p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
+ p->call_level = DAHDI_CALL_LEVEL_ALERTING;
+ if (p->ss7 && p->ss7->ss7) {
ss7_grab(p, p->ss7);
-
if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
p->rlt = 1;
if (p->rlt != 1) /* No need to send CPG if call will be RELEASE */
isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_ALERTING);
- p->alerting = 1;
ss7_rel(p->ss7);
}
}
@@ -7582,34 +7606,35 @@ static int dahdi_indicate(struct ast_channel *chan, int condition, const void *d
case AST_CONTROL_PROCEEDING:
ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
#ifdef HAVE_PRI
- if (!p->proceeding && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
- && p->pri && !p->outgoing) {
- if (p->pri->pri) {
+ if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
+ && p->call_level < DAHDI_CALL_LEVEL_PROCEEDING && !p->outgoing) {
+ p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
+ if (p->pri && p->pri->pri) {
if (!pri_grab(p, p->pri)) {
pri_proceeding(p->pri->pri,p->call, PVT_TO_CHANNEL(p), !p->digital);
pri_rel(p->pri);
- }
- else
+ } else {
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
+ }
}
- p->proceeding = 1;
p->dialing = 0;
}
#endif
#ifdef HAVE_SS7
- /* This IF sends the FAR for an answered ALEG call */
- if (chan->_state == AST_STATE_UP && (p->rlt != 1) && (p->sig == SIG_SS7)){
- if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
- p->rlt = 1;
- }
-
- if (!p->proceeding && p->sig == SIG_SS7 && p->ss7 && !p->outgoing) {
- if (p->ss7->ss7) {
- ss7_grab(p, p->ss7);
- isup_acm(p->ss7->ss7, p->ss7call);
- p->proceeding = 1;
- ss7_rel(p->ss7);
+ if (p->sig == SIG_SS7) {
+ /* This IF sends the FAR for an answered ALEG call */
+ if (chan->_state == AST_STATE_UP && (p->rlt != 1)){
+ if ((isup_far(p->ss7->ss7, p->ss7call)) != -1)
+ p->rlt = 1;
+ }
+ if (p->call_level < DAHDI_CALL_LEVEL_PROCEEDING && !p->outgoing) {
+ p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
+ if (p->ss7 && p->ss7->ss7) {
+ ss7_grab(p, p->ss7);
+ isup_acm(p->ss7->ss7, p->ss7call);
+ ss7_rel(p->ss7);
+ }
}
}
#endif
@@ -7620,9 +7645,11 @@ static int dahdi_indicate(struct ast_channel *chan, int condition, const void *d
ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
#ifdef HAVE_PRI
p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */
- if (!p->progress && !p->alerting && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
- && p->pri && !p->outgoing) {
- if (p->pri->pri) {
+ if (((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
+ && !p->progress && p->call_level < DAHDI_CALL_LEVEL_ALERTING
+ && !p->outgoing) {
+ p->progress = 1;/* No need to send plain PROGRESS again. */
+ if (p->pri && p->pri->pri) {
if (!pri_grab(p, p->pri)) {
#ifdef HAVE_PRI_PROG_W_CAUSE
pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, -1); /* no cause at all */
@@ -7630,23 +7657,23 @@ static int dahdi_indicate(struct ast_channel *chan, int condition, const void *d
pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
#endif
pri_rel(p->pri);
- }
- else
+ } else {
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
+ }
}
- p->progress = 1;
}
#endif
#ifdef HAVE_SS7
- if (!p->progress && p->sig==SIG_SS7 && p->ss7 && !p->outgoing) {
- if (p->ss7->ss7) {
+ if (p->sig == SIG_SS7
+ && !p->progress && p->call_level < DAHDI_CALL_LEVEL_ALERTING
+ && !p->outgoing) {
+ p->progress = 1;/* No need to send inband-information progress again. */
+ if (p->ss7 && p->ss7->ss7) {
ss7_grab(p, p->ss7);
isup_cpg(p->ss7->ss7, p->ss7call, CPG_EVENT_INBANDINFO);
- p->progress = 1;
ss7_rel(p->ss7);
/* enable echo canceler here on SS7 calls */
dahdi_enable_ec(p);
-
}
}
#endif
@@ -7654,30 +7681,66 @@ static int dahdi_indicate(struct ast_channel *chan, int condition, const void *d
res = 0;
break;
case AST_CONTROL_CONGESTION:
- chan->hangupcause = AST_CAUSE_CONGESTION;
#ifdef HAVE_PRI
- if (p->priindication_oob && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))) {
- chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
- chan->_softhangup |= AST_SOFTHANGUP_DEV;
- res = 0;
- } else if (!p->progress && ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP))
- && p->pri && !p->outgoing) {
- if (p->pri) {
- if (!pri_grab(p, p->pri)) {
+ if ((p->sig == SIG_PRI) || (p->sig == SIG_BRI) || (p->sig == SIG_BRI_PTMP)) {
+ if (p->priindication_oob) {
+ /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
+ switch (chan->hangupcause) {
+ case AST_CAUSE_USER_BUSY:
+ case AST_CAUSE_NORMAL_CLEARING:
+ case 0:/* Cause has not been set. */
+ /* Supply a more appropriate cause. */
+ chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
+ break;
+ default:
+ break;
+ }
+ chan->_softhangup |= AST_SOFTHANGUP_DEV;
+ res = 0;
+ break;
+ }
+ res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
+ if (p->call_level < DAHDI_CALL_LEVEL_ALERTING && !p->outgoing) {
+ /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
+ switch (chan->hangupcause) {
+ case AST_CAUSE_USER_BUSY:
+ case AST_CAUSE_NORMAL_CLEARING:
+ case 0:/* Cause has not been set. */
+ /* Supply a more appropriate cause. */
+ chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
+ break;
+ default:
+ break;
+ }
+ p->progress = 1;/* No need to send plain PROGRESS after this. */
+ if (p->pri && p->pri->pri) {
+ if (!pri_grab(p, p->pri)) {
#ifdef HAVE_PRI_PROG_W_CAUSE
- pri_progress_with_cause(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1, PRI_CAUSE_SWITCH_CONGESTION); /* cause = 42 */
+ pri_progress_with_cause(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 1, chan->hangupcause);
#else
- pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
+ pri_progress(p->pri->pri,p->call, PVT_TO_CHANNEL(p), 1);
#endif
- pri_rel(p->pri);
- } else
- ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
+ pri_rel(p->pri);
+ } else {
+ ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
+ }
+ }
}
- p->progress = 1;
- res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
- } else
+ break;
+ }
#endif
- res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
+ /* There are many cause codes that generate an AST_CONTROL_CONGESTION. */
+ switch (chan->hangupcause) {
+ case AST_CAUSE_USER_BUSY:
+ case AST_CAUSE_NORMAL_CLEARING:
+ case 0:/* Cause has not been set. */
+ /* Supply a more appropriate cause. */
+ chan->hangupcause = AST_CAUSE_CONGESTION;
+ break;
+ default:
+ break;
+ }
+ res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
break;
case AST_CONTROL_HOLD:
#ifdef HAVE_PRI
@@ -8085,12 +8148,28 @@ static void *ss_thread(void *data)
if (p->dsp) {
ast_dsp_digitreset(p->dsp);
}
- if (p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) {
+#if defined(ISSUE_16789)
+ /*
+ * Conditionaled out this code to effectively revert the Mantis
+ * issue 16789 change. It breaks overlap dialing through
+ * Asterisk. There is not enough information available at this
+ * point to know if dialing is complete. The
+ * ast_exists_extension(), ast_matchmore_extension(), and
+ * ast_canmatch_extension() calls are not adequate to detect a
+ * dial through extension pattern of "_9!".
+ *
+ * Workaround is to use the dialplan Proceeding() application
+ * early on non-dial through extensions.
+ */
+ if ((p->pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
+ && !ast_matchmore_extension(chan, chan->context, exten, 1, p->cid_num)) {
ast_mutex_lock(&p->lock);
- if (p->pri->pri) {
+ if (p->pri->pri) {
if (!pri_grab(p, p->pri)) {
+ if (p->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
+ p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
+ }
pri_proceeding(p->pri->pri, p->call, PVT_TO_CHANNEL(p), 0);
- p->proceeding = 1;
pri_rel(p->pri);
} else {
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", p->span);
@@ -8098,6 +8177,8 @@ static void *ss_thread(void *data)
}
ast_mutex_unlock(&p->lock);
}
+#endif /* defined(ISSUE_16789) */
+
dahdi_enable_ec(p);
ast_setstate(chan, AST_STATE_RING);
res = ast_pbx_run(chan);
@@ -11618,17 +11699,19 @@ static void ss7_start_call(struct dahdi_pvt *p, struct dahdi_ss7 *linkset)
ast_log(LOG_WARNING, "Unable to set law on channel %d\n", p->channel);
if (!(linkset->flags & LINKSET_FLAG_EXPLICITACM)) {
- p->proceeding = 1;
+ p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
isup_acm(ss7, p->ss7call);
+ } else {
+ p->call_level = DAHDI_CALL_LEVEL_SETUP;
}
ast_mutex_unlock(&linkset->lock);
c = dahdi_new(p, AST_STATE_RING, 1, SUB_REAL, law, 0);
-
if (!c) {
ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
/* Holding this lock is assumed entering the function */
ast_mutex_lock(&linkset->lock);
+ p->call_level = DAHDI_CALL_LEVEL_IDLE;
return;
} else
ast_verb(3, "Accepting call to '%s' on CIC %d\n", p->exten, p->cic);
@@ -11883,7 +11966,9 @@ static void *ss7_linkset(void *data)
ast_mutex_lock(&p->lock);
switch (e->cpg.event) {
case CPG_EVENT_ALERTING:
- p->alerting = 1;
+ if (p->call_level < DAHDI_CALL_LEVEL_ALERTING) {
+ p->call_level = DAHDI_CALL_LEVEL_ALERTING;
+ }
p->subs[SUB_REAL].needringing = 1;
break;
case CPG_EVENT_PROGRESS:
@@ -12123,11 +12208,15 @@ static void *ss7_linkset(void *data)
ast_mutex_lock(&p->lock);
dahdi_queue_frame(p, &f, linkset);
- p->proceeding = 1;
+ if (p->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
+ p->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
+ }
p->dialing = 0;
/* Send alerting if subscriber is free */
if (e->acm.called_party_status_ind == 1) {
- p->alerting = 1;
+ if (p->call_level < DAHDI_CALL_LEVEL_ALERTING) {
+ p->call_level = DAHDI_CALL_LEVEL_ALERTING;
+ }
p->subs[SUB_REAL].needringing = 1;
}
ast_mutex_unlock(&p->lock);
@@ -12231,6 +12320,9 @@ static void *ss7_linkset(void *data)
} else {
p = linkset->pvts[chanpos];
ast_mutex_lock(&p->lock);
+ if (p->call_level < DAHDI_CALL_LEVEL_CONNECT) {
+ p->call_level = DAHDI_CALL_LEVEL_CONNECT;
+ }
p->subs[SUB_REAL].needanswer = 1;
if (p->dsp && p->dsp_features) {
ast_dsp_set_features(p->dsp, p->dsp_features);
@@ -12490,6 +12582,22 @@ static int pri_fixup_principle(struct dahdi_pri *pri, int principle, q931_call *
new->dsp_features = old->dsp_features;
old->dsp = NULL;
old->dsp_features = 0;
+
+ /* Transfer flags from the old channel. */
+ new->alreadyhungup = old->alreadyhungup;
+ new->isidlecall = old->isidlecall;
+ new->progress = old->progress;
+ new->outgoing = old->outgoing;
+ new->digital = old->digital;
+ old->alreadyhungup = 0;
+ old->isidlecall = 0;
+ old->progress = 0;
+ old->outgoing = 0;
+ old->digital = 0;
+
+ /* More stuff to transfer to the new channel. */
+ new->call_level = old->call_level;
+ old->call_level = DAHDI_CALL_LEVEL_IDLE;
}
return principle;
}
@@ -13266,13 +13374,14 @@ static void *pri_dchannel(void *vpri)
ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
if (e->ring.complete || !(pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)) {
/* Just announce proceeding */
- pri->pvts[chanpos]->proceeding = 1;
+ pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
+ } else if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
+ pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_CONNECT;
+ pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
} else {
- if (pri->switchtype != PRI_SWITCH_GR303_TMC)
- pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
- else
- pri_answer(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
+ pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_OVERLAP;
+ pri_need_more_info(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
}
/* Get the use_callingpres state */
pri->pvts[chanpos]->callingpres = e->ring.callingpres;
@@ -13316,6 +13425,21 @@ static void *pri_dchannel(void *vpri)
pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
if (e->ring.redirectingreason >= 0)
pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
+
+ if (!pri->pvts[chanpos]->digital) {
+ /*
+ * Call has a channel.
+ * Indicate that we are providing dialtone.
+ */
+ pri->pvts[chanpos]->progress = 1;/* No need to send plain PROGRESS again. */
+#ifdef HAVE_PRI_PROG_W_CAUSE
+ pri_progress_with_cause(pri->pri, e->ring.call,
+ PVT_TO_CHANNEL(pri->pvts[chanpos]), 1, -1);/* no cause at all */
+#else
+ pri_progress(pri->pri, e->ring.call,
+ PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
+#endif
+ }
}
if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
ast_verb(3, "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
@@ -13419,7 +13543,9 @@ static void *pri_dchannel(void *vpri)
if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
dahdi_enable_ec(pri->pvts[chanpos]);
pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
- pri->pvts[chanpos]->alerting = 1;
+ if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_ALERTING) {
+ pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_ALERTING;
+ }
} else
ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
@@ -13507,10 +13633,11 @@ static void *pri_dchannel(void *vpri)
case PRI_EVENT_PROCEEDING:
chanpos = pri_find_principle(pri, e->proceeding.channel);
if (chanpos > -1) {
- if (!pri->pvts[chanpos]->proceeding) {
+ ast_mutex_lock(&pri->pvts[chanpos]->lock);
+ if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_PROCEEDING) {
struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
- ast_mutex_lock(&pri->pvts[chanpos]->lock);
+ pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
@@ -13530,10 +13657,9 @@ static void *pri_dchannel(void *vpri)
f.subclass = AST_CONTROL_PROGRESS;
dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
}
- pri->pvts[chanpos]->proceeding = 1;
pri->pvts[chanpos]->dialing = 0;
- ast_mutex_unlock(&pri->pvts[chanpos]->lock);
}
+ ast_mutex_unlock(&pri->pvts[chanpos]->lock);
}
break;
case PRI_EVENT_FACNAME:
@@ -13602,7 +13728,9 @@ static void *pri_dchannel(void *vpri)
ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
} else {
pri->pvts[chanpos]->dialing = 0;
- pri->pvts[chanpos]->proceeding = 1;
+ if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_CONNECT) {
+ pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_CONNECT;
+ }
pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
/* Enable echo cancellation if it's not on already */
dahdi_enable_ec(pri->pvts[chanpos]);
@@ -13871,14 +13999,37 @@ static void *pri_dchannel(void *vpri)
} else {
chanpos = pri_fixup_principle(pri, chanpos, e->setup_ack.call);
if (chanpos > -1) {
+ unsigned int len;
+
ast_mutex_lock(&pri->pvts[chanpos]->lock);
- pri->pvts[chanpos]->setup_ack = 1;
+ if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_OVERLAP) {
+ pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_OVERLAP;
+ }
+
/* Send any queued digits */
- for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
+ len = strlen(pri->pvts[chanpos]->dialdest);
+ for (x = 0; x < len; ++x) {
ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
pri_information(pri->pri, pri->pvts[chanpos]->call,
pri->pvts[chanpos]->dialdest[x]);
}
+
+ if (!pri->pvts[chanpos]->progress
+ && (pri->overlapdial & DAHDI_OVERLAPDIAL_OUTGOING)
+ && !pri->pvts[chanpos]->digital) {
+ /*
+ * Call has a channel.
+ * Indicate for overlap dialing that dialtone may be present.
+ */
+ struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
+ dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
+ pri->pvts[chanpos]->progress = 1;/* Claim to have seen inband-information */
+ pri->pvts[chanpos]->dialing = 0;
+ if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
+ ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features);
+ pri->pvts[chanpos]->dsp_features = 0;
+ }
+ }
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
} else
ast_log(LOG_WARNING, "Unable to move channel %d!\n", e->setup_ack.channel);