[asterisk-commits] rmudgett: branch 1.6.2 r303769 - in /branches/1.6.2: ./ channels/chan_dahdi.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Jan 25 11:42:49 CST 2011


Author: rmudgett
Date: Tue Jan 25 11:42:42 2011
New Revision: 303769

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=303769
Log:
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
........

Modified:
    branches/1.6.2/   (props changed)
    branches/1.6.2/channels/chan_dahdi.c

Propchange: branches/1.6.2/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.

Modified: branches/1.6.2/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.6.2/channels/chan_dahdi.c?view=diff&rev=303769&r1=303768&r2=303769
==============================================================================
--- branches/1.6.2/channels/chan_dahdi.c (original)
+++ branches/1.6.2/channels/chan_dahdi.c Tue Jan 25 11:42:42 2011
@@ -504,6 +504,22 @@
 #define PRI_CHANNEL(p) ((p) & 0xff)
 #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 */
@@ -918,14 +934,17 @@
 	 * \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 @@
 	 * \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;
-#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;
+
+	/*! Call establishment life cycle level for simple comparisons. */
+	enum dahdi_call_level call_level;
+#endif
 	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 @@
 
 #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;
+			}
+			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);
+		}
 	}
 #endif
 	if ((dtmf = digit_to_dtmfindex(digit)) == -1)
@@ -3582,6 +3605,7 @@
 
 		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 @@
 		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 @@
 		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 @@
 	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 @@
 #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 @@
 		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 @@
 	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 @@
 			} 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 @@
 		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 @@
 		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);
-#endif
-						pri_rel(p->pri);
+							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);
+						}
 					}
-					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
-#endif
-				res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_BUSY);
+				}
+				break;
+			}
+#endif
+			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 {
+						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->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 @@
 		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 {
+						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->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 @@
 			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 @@
 						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);
 					}
-					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 @@
 			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);
-#endif
-						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
-#endif
-				res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
+							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);
+						}
+					}
+				}
+				break;
+			}
+#endif
+			/* 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 @@
 			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 @@
 				}
 				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 @@
 		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 @@
 				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 @@
 
 					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 @@
 				} 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 @@
 				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 @@
 							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 @@
 								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 @@
 						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 @@
 			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 @@
 							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 @@
 							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,13 +13999,36 @@
 				} 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




More information about the asterisk-commits mailing list