[asterisk-commits] rmudgett: branch rmudgett/bch_shift_v1.4 r311484 - /team/rmudgett/bch_shift_v...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Mar 21 12:57:21 CDT 2011


Author: rmudgett
Date: Mon Mar 21 12:57:17 2011
New Revision: 311484

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=311484
Log:
Initial work before testing.

Modified:
    team/rmudgett/bch_shift_v1.4/channels/chan_dahdi.c

Modified: team/rmudgett/bch_shift_v1.4/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bch_shift_v1.4/channels/chan_dahdi.c?view=diff&rev=311484&r1=311483&r2=311484
==============================================================================
--- team/rmudgett/bch_shift_v1.4/channels/chan_dahdi.c (original)
+++ team/rmudgett/bch_shift_v1.4/channels/chan_dahdi.c Mon Mar 21 12:57:17 2011
@@ -5389,14 +5389,27 @@
 
 static struct ast_frame  *dahdi_read(struct ast_channel *ast)
 {
-	struct dahdi_pvt *p = ast->tech_pvt;
+	struct dahdi_pvt *p;
 	int res;
 	int index;
 	void *readbuf;
 	struct ast_frame *f;
 
+	/*
+	 * For analog channels, we must do deadlock avoidance because
+	 * analog ports can have more than one Asterisk channel using
+	 * the same private structure.
+	 */
+	p = ast->tech_pvt;
 	while (ast_mutex_trylock(&p->lock)) {
 		DEADLOCK_AVOIDANCE(&ast->lock);
+
+		/*
+		 * For PRI channels, we must refresh the private pointer because
+		 * the call could move to another B channel while the Asterisk
+		 * channel is unlocked.
+		 */
+		p = ast->tech_pvt;
 	}
 
 	index = dahdi_get_index(ast, p, 0);
@@ -9016,7 +9029,7 @@
  * \brief Obtain the DAHDI owner channel lock if the owner exists.
  * \since 1.8
  *
- * \param pri DAHDI PRI control structure.
+ * \param pri PRI span control structure.
  * \param chanpos Channel position in the span.
  *
  * \note Assumes the pri->lock is already obtained.
@@ -9046,9 +9059,126 @@
 #if defined(HAVE_PRI)
 /*!
  * \internal
+ * \brief Queue the given frame onto the owner channel.
+ * \since 1.8
+ *
+ * \param pri PRI span control structure.
+ * \param chanpos Channel position in the span.
+ * \param frame Frame to queue onto the owner channel.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ * \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained.
+ *
+ * \return Nothing
+ */
+static void pri_queue_frame(struct dahdi_pri *pri, int chanpos, struct ast_frame *frame)
+{
+	sig_pri_lock_owner(pri, chanpos);
+	if (pri->pvts[chanpos]->owner) {
+		ast_queue_frame(pri->pvts[chanpos]->owner, frame);
+		ast_channel_unlock(pri->pvts[chanpos]->owner);
+	}
+}
+#endif	/* defined(HAVE_PRI) */
+
+#if defined(HAVE_PRI)
+/*!
+ * \internal
+ * \brief Queue a control frame of the specified subclass onto the owner channel.
+ * \since 1.8
+ *
+ * \param pri PRI span control structure.
+ * \param chanpos Channel position in the span.
+ * \param subclass Control frame subclass to queue onto the owner channel.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ * \note Assumes the sig_pri_lock_private(pri->pvts[chanpos]) is already obtained.
+ *
+ * \return Nothing
+ */
+static void pri_queue_control(struct dahdi_pri *pri, int chanpos, int subclass)
+{
+	struct ast_frame f = {AST_FRAME_CONTROL, };
+
+	f.subclass = subclass;
+	pri_queue_frame(pri, chanpos, &f);
+}
+#endif	/* defined(HAVE_PRI) */
+
+#if defined(HAVE_PRI)
+/*!
+ * \internal
+ * \brief Find the channel associated with the libpri call.
+ * \since 1.10
+ *
+ * \param pri PRI span control structure.
+ * \param call LibPRI opaque call pointer to find.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ *
+ * \retval array-index into private pointer array on success.
+ * \retval -1 on error.
+ */
+static int pri_find_principle_by_call(struct dahdi_pri *pri, q931_call *call)
+{
+	int idx;
+
+	if (!call) {
+		/* Cannot find a call without a call. */
+		return -1;
+	}
+	for (idx = 0; idx < pri->numchans; ++idx) {
+		if (pri->pvts[idx] && pri->pvts[idx]->call == call) {
+			/* Found the principle */
+			return idx;
+		}
+	}
+	return -1;
+}
+#endif	/* defined(HAVE_PRI) */
+
+#if defined(HAVE_PRI)
+/*!
+ * \internal
+ * \brief Kill the call.
+ * \since 1.10
+ *
+ * \param pri PRI span control structure.
+ * \param call LibPRI opaque call pointer to find.
+ * \param cause Reason call was killed.
+ *
+ * \note Assumes the pvt->pri->lock is already obtained.
+ *
+ * \return Nothing
+ */
+static void sig_pri_kill_call(struct dahdi_pri *pri, q931_call *call, int cause)
+{
+	int chanpos;
+
+	chanpos = pri_find_principle_by_call(pri, call);
+	if (chanpos < 0) {
+		pri_hangup(pri->pri, call, cause);
+		return;
+	}
+	ast_mutex_lock(&pri->pvts[chanpos]->lock);
+	if (!pri->pvts[chanpos]->owner) {
+		pri_hangup(pri->pri, call, cause);
+		pri->pvts[chanpos]->call = NULL;
+		ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+		return;
+	}
+	pri->pvts[chanpos]->owner->hangupcause = cause;
+	pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
+	ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+}
+#endif	/* defined(HAVE_PRI) */
+
+#if defined(HAVE_PRI)
+/*!
+ * \internal
  * \brief Find the private structure for the libpri call.
  *
- * \param pri Span controller structure.
+ * \param pri PRI span control structure.
  * \param channel LibPRI encoded channel ID.
  *
  * \note Assumes the pri->lock is already obtained.
@@ -9090,7 +9220,7 @@
  * \internal
  * \brief Fixup the private structure associated with the libpri call.
  *
- * \param pri Span controller structure.
+ * \param pri PRI span control structure.
  * \param principle Array-index into private array to move call to if not already there.
  * \param c LibPRI opaque call pointer to find if need to move call.
  *
@@ -9217,6 +9347,54 @@
 	}
 	ast_log(LOG_WARNING, "Call specified, but not found?\n");
 	return -1;
+}
+#endif	/* defined(HAVE_PRI) */
+
+#if defined(HAVE_PRI)
+/*!
+ * \internal
+ * \brief Find and fixup the private structure associated with the libpri call.
+ *
+ * \param pri PRI span control structure.
+ * \param channel LibPRI encoded channel ID.
+ * \param call LibPRI opaque call pointer.
+ *
+ * \details
+ * This is a combination of pri_find_principle() and pri_fixup_principle()
+ * to reduce code redundancy and to make handling several PRI_EVENT_xxx's
+ * consistent for the current architecture.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ *
+ * \retval array-index into private pointer array on success.
+ * \retval -1 on error.
+ */
+static int pri_find_fixup_principle(struct dahdi_pri *pri, int channel, q931_call *call)
+{
+	int chanpos;
+
+	chanpos = pri_find_principle(pri, channel);
+	if (chanpos < 0) {
+		ast_log(LOG_WARNING, "Span %d: PRI requested channel %d/%d is unconfigured.\n",
+			pri->span, PRI_SPAN(channel), PRI_CHANNEL(channel));
+		sig_pri_kill_call(pri, call, PRI_CAUSE_IDENTIFIED_CHANNEL_NOTEXIST);
+		return -1;
+	}
+	chanpos = pri_fixup_principle(pri, chanpos, call);
+	if (chanpos < 0) {
+		ast_log(LOG_WARNING, "Span %d: PRI requested channel %d/%d is not available.\n",
+			pri->span, PRI_SPAN(channel), PRI_CHANNEL(channel));
+		/*
+		 * Using Q.931 section 5.2.3.1 b) as the reason for picking
+		 * PRI_CAUSE_CHANNEL_UNACCEPTABLE.  Receiving a
+		 * PRI_CAUSE_REQUESTED_CHAN_UNAVAIL would cause us to restart
+		 * that channel (which is not specified by Q.931) and kill some
+		 * other call which would be bad.
+		 */
+		sig_pri_kill_call(pri, call, PRI_CAUSE_CHANNEL_UNACCEPTABLE);
+		return -1;
+	}
+	return chanpos;
 }
 #endif	/* defined(HAVE_PRI) */
 
@@ -9489,7 +9667,8 @@
 	char plancallingnum[256];
 	char plancallingani[256];
 	char calledtonstr[10];
-	
+	unsigned int len;
+
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
 
 	gettimeofday(&lastidle, NULL);
@@ -9775,66 +9954,74 @@
 				}
 				break;
 			case PRI_EVENT_KEYPAD_DIGIT:
-				chanpos = pri_find_principle(pri, e->digit.channel);
+				chanpos = pri_find_principle_by_call(pri, e->digit.call);
 				if (chanpos < 0) {
-					ast_log(LOG_WARNING, "KEYPAD_DIGITs received on unconfigured channel %d/%d span %d\n", 
-						PRI_SPAN(e->digit.channel), PRI_CHANNEL(e->digit.channel), pri->span);
-				} else {
-					chanpos = pri_fixup_principle(pri, chanpos, e->digit.call);
-					if (chanpos > -1) {
-						ast_mutex_lock(&pri->pvts[chanpos]->lock);
-						/* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
-						if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
-							/* how to do that */
-							int digitlen = strlen(e->digit.digits);
-							char digit;
-							int i;					
-							for (i = 0; i < digitlen; i++) {	
-								digit = e->digit.digits[i];
-								{
-									struct ast_frame f = { AST_FRAME_DTMF, digit, };
-									dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
-								}
-							}
+					ast_log(LOG_WARNING,
+						"Span %d: Received keypad digits for unknown call.\n", pri->span);
+					break;
+				}
+				ast_mutex_lock(&pri->pvts[chanpos]->lock);
+				/* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
+				if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
+					&& pri->pvts[chanpos]->owner) {
+					/* how to do that */
+					int digitlen = strlen(e->digit.digits);
+					char digit;
+					int i;
+					for (i = 0; i < digitlen; i++) {
+						digit = e->digit.digits[i];
+						{
+							struct ast_frame f = { AST_FRAME_DTMF, digit, };
+							dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
 						}
-						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
 					}
 				}
+				ast_mutex_unlock(&pri->pvts[chanpos]->lock);
 				break;
 				
 			case PRI_EVENT_INFO_RECEIVED:
-				chanpos = pri_find_principle(pri, e->ring.channel);
+				chanpos = pri_find_principle_by_call(pri, e->ring.call);
 				if (chanpos < 0) {
-					ast_log(LOG_WARNING, "INFO received on unconfigured channel %d/%d span %d\n", 
-						PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
-				} else {
-					chanpos = pri_fixup_principle(pri, chanpos, e->ring.call);
-					if (chanpos > -1) {
-						ast_mutex_lock(&pri->pvts[chanpos]->lock);
-						/* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
-						if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->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, };
-									dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
-								}
-							}
+					ast_log(LOG_WARNING,
+						"Span %d: Received INFORMATION for unknown call.\n", pri->span);
+					break;
+				}
+				ast_mutex_lock(&pri->pvts[chanpos]->lock);
+				/* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
+				if ((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
+					&& pri->pvts[chanpos]->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, };
+							dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
 						}
-						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
 					}
 				}
+				ast_mutex_unlock(&pri->pvts[chanpos]->lock);
 				break;
 			case PRI_EVENT_RING:
 				crv = NULL;
-				if (e->ring.channel == -1)
+				if (e->ring.channel == -1) {
 					chanpos = pri_find_empty_chan(pri, 1);
-				else
+				} else {
 					chanpos = pri_find_principle(pri, e->ring.channel);
+/*!
+ * Define to make always pick a channel if allowed.  Useful for
+ * testing channel shifting.
+ */
+//#define ALWAYS_PICK_CHANNEL	1
+#define ALWAYS_PICK_CHANNEL	1	//BUGBUG
+#if defined(ALWAYS_PICK_CHANNEL)
+					if (e->ring.flexible) {
+						chanpos = pri_find_empty_chan(pri, 1);
+					}
+#endif	/* defined(ALWAYS_PICK_CHANNEL) */
+				}
 				/* if no channel specified find one empty */
 				if (chanpos < 0) {
 					ast_log(LOG_WARNING, "Ring requested on unconfigured channel %d/%d span %d\n", 
@@ -10113,410 +10300,394 @@
 				}
 				break;
 			case PRI_EVENT_RINGING:
-				chanpos = pri_find_principle(pri, e->ringing.channel);
+				chanpos = pri_find_fixup_principle(pri, e->ringing.channel,
+					e->ringing.call);
 				if (chanpos < 0) {
-					ast_log(LOG_WARNING, "Ringing requested on unconfigured channel %d/%d span %d\n", 
-						PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
-				} else {
-					chanpos = pri_fixup_principle(pri, chanpos, e->ringing.call);
-					if (chanpos < 0) {
-						ast_log(LOG_WARNING, "Ringing requested on channel %d/%d not in use on span %d\n", 
-							PRI_SPAN(e->ringing.channel), PRI_CHANNEL(e->ringing.channel), pri->span);
-					} else {
-						ast_mutex_lock(&pri->pvts[chanpos]->lock);
-						if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
-							dahdi_enable_ec(pri->pvts[chanpos]);
-							pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
-							if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_ALERTING) {
-								pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_ALERTING;
-							}
-						} else
-							ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
+					break;
+				}
+				ast_mutex_lock(&pri->pvts[chanpos]->lock);
+				if (ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
+					dahdi_enable_ec(pri->pvts[chanpos]);
+					pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
+					if (pri->pvts[chanpos]->call_level < DAHDI_CALL_LEVEL_ALERTING) {
+						pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_ALERTING;
+					}
+				} else
+					ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
+				if (
 #ifdef PRI_PROGRESS_MASK
-						if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
+					e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE
 #else
-						if (e->ringing.progress == 8) {
+					e->ringing.progress == 8
 #endif
-							/* Now we can do call progress detection */
-							if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
-								/* RINGING detection isn't required because we got ALERTING signal */
-								ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
-								pri->pvts[chanpos]->dsp_features = 0;
+					) {
+					/* Now we can do call progress detection */
+					if (pri->pvts[chanpos]->dsp && pri->pvts[chanpos]->dsp_features) {
+						/* RINGING detection isn't required because we got ALERTING signal */
+						ast_dsp_set_features(pri->pvts[chanpos]->dsp, pri->pvts[chanpos]->dsp_features & ~DSP_PROGRESS_RINGING);
+						pri->pvts[chanpos]->dsp_features = 0;
+					}
+				}
+
+#ifdef SUPPORT_USERUSER
+				if (!ast_strlen_zero(e->ringing.useruserinfo)) {
+					struct ast_channel *owner = pri->pvts[chanpos]->owner;
+					ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+					pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
+					ast_mutex_lock(&pri->pvts[chanpos]->lock);
+				}
+#endif
+
+				ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+				break;
+			case PRI_EVENT_PROGRESS:
+				chanpos = pri_find_fixup_principle(pri, e->proceeding.channel,
+					e->proceeding.call);
+				if (chanpos < 0) {
+					break;
+				}
+				if ((!pri->pvts[chanpos]->progress)
+#ifdef PRI_PROGRESS_MASK
+					|| (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
+#else
+					|| (e->proceeding.progress == 8)
+#endif
+					) {
+					struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
+
+					if (e->proceeding.cause > -1) {
+						if (option_verbose > 2)
+							ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
+
+						/* Work around broken, out of spec USER_BUSY cause in a progress message */
+						if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
+							if (pri->pvts[chanpos]->owner) {
+								if (option_verbose > 2)
+									ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
+
+								pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
+								f.subclass = AST_CONTROL_BUSY;
 							}
 						}
-
-#ifdef SUPPORT_USERUSER
-						if (!ast_strlen_zero(e->ringing.useruserinfo)) {
-							struct ast_channel *owner = pri->pvts[chanpos]->owner;
-							ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-							pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->ringing.useruserinfo);
-							ast_mutex_lock(&pri->pvts[chanpos]->lock);
-						}
+					}
+
+					ast_mutex_lock(&pri->pvts[chanpos]->lock);
+					ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS 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);
+					if (
+#ifdef PRI_PROGRESS_MASK
+						e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
+#else
+						e->proceeding.progress == 8
 #endif
-
-						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-					}
-				}
-				break;
-			case PRI_EVENT_PROGRESS:
-				/* Get chan value if e->e is not PRI_EVNT_RINGING */
-				chanpos = pri_find_principle(pri, e->proceeding.channel);
-				if (chanpos > -1) {
-#ifdef PRI_PROGRESS_MASK
-					if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)) {
-#else
-					if ((!pri->pvts[chanpos]->progress) || (e->proceeding.progress == 8)) {
-#endif
-						struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
-
-						if (e->proceeding.cause > -1) {
-							if (option_verbose > 2)
-								ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with cause code %d received\n", e->proceeding.cause);
-
-							/* Work around broken, out of spec USER_BUSY cause in a progress message */
-							if (e->proceeding.cause == AST_CAUSE_USER_BUSY) {
-								if (pri->pvts[chanpos]->owner) {
-									if (option_verbose > 2)
-										ast_verbose(VERBOSE_PREFIX_3 "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
-
-									pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
-									f.subclass = AST_CONTROL_BUSY;
-								}
-							}
-						}
-						
-						ast_mutex_lock(&pri->pvts[chanpos]->lock);
-						ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS 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);
-#ifdef PRI_PROGRESS_MASK
-						if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
-#else
-						if (e->proceeding.progress == 8) {
-#endif
-							/* Now we can do call progress detection */
-							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;
-							}
-							/* Bring voice path up */
-							f.subclass = AST_CONTROL_PROGRESS;
-							dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
-						}
-						pri->pvts[chanpos]->progress = 1;
-						pri->pvts[chanpos]->dialing = 0;
-						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-					}
-				}
-				break;
-			case PRI_EVENT_PROCEEDING:
-				chanpos = pri_find_principle(pri, e->proceeding.channel);
-				if (chanpos > -1) {
-					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, };
-
-						pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
-						ast_log(LOG_DEBUG, "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);
-#ifdef PRI_PROGRESS_MASK
-						if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
-#else
-						if (e->proceeding.progress == 8) {
-#endif
-							/* Now we can do call progress detection */
-							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;
-							}
-							/* Bring voice path up */
-							f.subclass = AST_CONTROL_PROGRESS;
-							dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
-						}
-						pri->pvts[chanpos]->dialing = 0;
-					}
-					ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-				}
-				break;
-			case PRI_EVENT_FACNAME:
-				chanpos = pri_find_principle(pri, e->facname.channel);
-				if (chanpos < 0) {
-					ast_log(LOG_WARNING, "Facility Name requested on unconfigured channel %d/%d span %d\n", 
-						PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
-				} else {
-					chanpos = pri_fixup_principle(pri, chanpos, e->facname.call);
-					if (chanpos < 0) {
-						ast_log(LOG_WARNING, "Facility Name requested on channel %d/%d not in use on span %d\n", 
-							PRI_SPAN(e->facname.channel), PRI_CHANNEL(e->facname.channel), pri->span);
-					} else if (pri->pvts[chanpos]->use_callerid) {
-						/* Re-use *69 field for PRI */
-						ast_mutex_lock(&pri->pvts[chanpos]->lock);
-						ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
-						ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
-						pri->pvts[chanpos]->subs[SUB_REAL].needcallerid = 1;
-						dahdi_enable_ec(pri->pvts[chanpos]);
-						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-					}
-				}
-				break;				
-			case PRI_EVENT_ANSWER:
-				chanpos = pri_find_principle(pri, e->answer.channel);
-				if (chanpos < 0) {
-					ast_log(LOG_WARNING, "Answer on unconfigured channel %d/%d span %d\n", 
-						PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
-				} else {
-					chanpos = pri_fixup_principle(pri, chanpos, e->answer.call);
-					if (chanpos < 0) {
-						ast_log(LOG_WARNING, "Answer requested on channel %d/%d not in use on span %d\n", 
-							PRI_SPAN(e->answer.channel), PRI_CHANNEL(e->answer.channel), pri->span);
-					} else {
-						ast_mutex_lock(&pri->pvts[chanpos]->lock);
+						) {
 						/* Now we can do call progress detection */
-
-						/* We changed this so it turns on the DSP no matter what... progress or no progress.
-						 * By this time, we need DTMF detection and other features that were previously disabled
-						 * -- Matt F */
 						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;
 						}
-						if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
-							ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
-							x = DAHDI_START;
-							res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
-							if (res < 0) {
-								if (errno != EINPROGRESS) {
-									ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
-								}
-							}
-						} else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
-							pri->pvts[chanpos]->dialing = 1;
-							/* Send any "w" waited stuff */
-							res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
-							if (res < 0) {
-								ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
-								pri->pvts[chanpos]->dop.dialstr[0] = '\0';
-							} else 
-								ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
-							pri->pvts[chanpos]->dop.dialstr[0] = '\0';
-						} else if (pri->pvts[chanpos]->confirmanswer) {
-							ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
-						} else {
-							pri->pvts[chanpos]->dialing = 0;
-							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]);
+						/* Bring voice path up */
+						f.subclass = AST_CONTROL_PROGRESS;
+						dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
+					}
+					pri->pvts[chanpos]->progress = 1;
+					pri->pvts[chanpos]->dialing = 0;
+					ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+				}
+				break;
+			case PRI_EVENT_PROCEEDING:
+				chanpos = pri_find_fixup_principle(pri, e->proceeding.channel,
+					e->proceeding.call);
+				if (chanpos < 0) {
+					break;
+				}
+				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, };
+
+					pri->pvts[chanpos]->call_level = DAHDI_CALL_LEVEL_PROCEEDING;
+					ast_log(LOG_DEBUG, "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);
+					if (
+#ifdef PRI_PROGRESS_MASK
+						e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE
+#else
+						e->proceeding.progress == 8
+#endif
+						) {
+						/* Now we can do call progress detection */
+						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;
 						}
+						/* Bring voice path up */
+						f.subclass = AST_CONTROL_PROGRESS;
+						dahdi_queue_frame(pri->pvts[chanpos], &f, pri);
+					}
+					pri->pvts[chanpos]->dialing = 0;
+				}
+				ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+				break;
+			case PRI_EVENT_FACNAME:
+				chanpos = pri_find_principle_by_call(pri, e->facname.call);
+				if (chanpos < 0) {
+					ast_log(LOG_WARNING, "Span %d: Received facility for unknown call.\n",
+						pri->span);
+					break;
+				}
+				if (pri->pvts[chanpos]->use_callerid) {
+					/* Re-use *69 field for PRI */
+					ast_mutex_lock(&pri->pvts[chanpos]->lock);
+					ast_copy_string(pri->pvts[chanpos]->lastcid_num, e->facname.callingnum, sizeof(pri->pvts[chanpos]->lastcid_num));
+					ast_copy_string(pri->pvts[chanpos]->lastcid_name, e->facname.callingname, sizeof(pri->pvts[chanpos]->lastcid_name));
+					pri->pvts[chanpos]->subs[SUB_REAL].needcallerid = 1;
+					dahdi_enable_ec(pri->pvts[chanpos]);
+					ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+				}
+				break;				
+			case PRI_EVENT_ANSWER:
+				chanpos = pri_find_fixup_principle(pri, e->answer.channel, e->answer.call);
+				if (chanpos < 0) {
+					break;
+				}
+				ast_mutex_lock(&pri->pvts[chanpos]->lock);
+				/* Now we can do call progress detection */
+
+				/* We changed this so it turns on the DSP no matter what... progress or no progress.
+				 * By this time, we need DTMF detection and other features that were previously disabled
+				 * -- Matt F */
+				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;
+				}
+				if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
+					ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
+					x = DAHDI_START;
+					res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
+					if (res < 0) {
+						if (errno != EINPROGRESS) {
+							ast_log(LOG_WARNING, "Unable to start channel: %s\n", strerror(errno));
+						}
+					}
+				} else if (!ast_strlen_zero(pri->pvts[chanpos]->dop.dialstr)) {
+					pri->pvts[chanpos]->dialing = 1;
+					/* Send any "w" waited stuff */
+					res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_DIAL, &pri->pvts[chanpos]->dop);
+					if (res < 0) {
+						ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", pri->pvts[chanpos]->channel, strerror(errno));
+						pri->pvts[chanpos]->dop.dialstr[0] = '\0';
+					} else
+						ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
+					pri->pvts[chanpos]->dop.dialstr[0] = '\0';
+				} else if (pri->pvts[chanpos]->confirmanswer) {
+					ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
+				} else {
+					pri->pvts[chanpos]->dialing = 0;
+					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]);
+				}
 
 #ifdef SUPPORT_USERUSER
-						if (!ast_strlen_zero(e->answer.useruserinfo)) {
-							struct ast_channel *owner = pri->pvts[chanpos]->owner;
-							ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-							pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
-							ast_mutex_lock(&pri->pvts[chanpos]->lock);
-						}
+				if (!ast_strlen_zero(e->answer.useruserinfo)) {
+					struct ast_channel *owner = pri->pvts[chanpos]->owner;
+					ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+					pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->answer.useruserinfo);
+					ast_mutex_lock(&pri->pvts[chanpos]->lock);
+				}
 #endif
 
-						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-					}
-				}
+				ast_mutex_unlock(&pri->pvts[chanpos]->lock);
 				break;				
 			case PRI_EVENT_HANGUP:
-				chanpos = pri_find_principle(pri, e->hangup.channel);
+				chanpos = pri_find_principle_by_call(pri, e->hangup.call);
 				if (chanpos < 0) {
-					ast_log(LOG_WARNING, "Hangup requested on unconfigured channel %d/%d span %d\n", 
-						PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
+					/*
+					 * Continue hanging up the call even though
+					 * we do not remember it (if we ever did).
+					 */
+					pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
+					break;
+				}
+				ast_mutex_lock(&pri->pvts[chanpos]->lock);
+				if (!pri->pvts[chanpos]->alreadyhungup) {
+					/* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
+					pri->pvts[chanpos]->alreadyhungup = 1;
+					if (pri->pvts[chanpos]->realcall)
+						pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
+					else if (pri->pvts[chanpos]->owner) {
+						/* Queue a BUSY instead of a hangup if our cause is appropriate */
+						pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
+						switch (pri->pvts[chanpos]->owner->_state) {
+						case AST_STATE_BUSY:
+						case AST_STATE_UP:
+							pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+							break;
+						default:
+							if (!pri->pvts[chanpos]->outgoing) {
+								/*
+								 * The incoming call leg hung up before getting
+								 * connected so just hangup the call.
+								 */
+								pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+								break;
+							}
+							switch (e->hangup.cause) {
+							case PRI_CAUSE_USER_BUSY:
+								pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
+								break;
+							case PRI_CAUSE_CALL_REJECTED:
+							case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
+							case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
+							case PRI_CAUSE_SWITCH_CONGESTION:
+							case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
+							case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
+								pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
+								break;
+							default:
+								pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+								break;
+							}
+							break;
+						}
+					}
+					if (option_verbose > 2) 
+						ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n", 
+							pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
 				} else {
-					chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
-					if (chanpos > -1) {
-						ast_mutex_lock(&pri->pvts[chanpos]->lock);
-						if (!pri->pvts[chanpos]->alreadyhungup) {
-							/* we're calling here dahdi_hangup so once we get there we need to clear p->call after calling pri_hangup */
-							pri->pvts[chanpos]->alreadyhungup = 1;
-							if (pri->pvts[chanpos]->realcall) 
-								pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
-							else if (pri->pvts[chanpos]->owner) {
-								/* Queue a BUSY instead of a hangup if our cause is appropriate */
-								pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
-								switch (pri->pvts[chanpos]->owner->_state) {
-								case AST_STATE_BUSY:
-								case AST_STATE_UP:
-									pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-									break;
-								default:
-									if (!pri->pvts[chanpos]->outgoing) {
-										/*
-										 * The incoming call leg hung up before getting
-										 * connected so just hangup the call.
-										 */
-										pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-										break;
-									}
-									switch (e->hangup.cause) {
-										case PRI_CAUSE_USER_BUSY:
-											pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
-											break;
-										case PRI_CAUSE_CALL_REJECTED:
-										case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
-										case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
-										case PRI_CAUSE_SWITCH_CONGESTION:
-										case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
-										case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
-											pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
-											break;
-										default:
-											pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-									}
-									break;
-								}
-							}
-							if (option_verbose > 2) 
-								ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n", 
-									pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
-						} else {
-							pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
-							pri->pvts[chanpos]->call = NULL;
-						}
-						if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
-							if (option_verbose > 2)
-								ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 
-									PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-							pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
-							pri->pvts[chanpos]->resetting = 1;
-						}
-						if (e->hangup.aoc_units > -1)
-							if (option_verbose > 2)
-								ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
-									pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
+					pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
+					pri->pvts[chanpos]->call = NULL;
+				}
+				if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL) {
+					if (option_verbose > 2)
+						ast_verbose(VERBOSE_PREFIX_3 "Forcing restart of channel %d/%d on span %d since channel reported in use\n", 
+							PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
+					pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos]));
+					pri->pvts[chanpos]->resetting = 1;
+				}
+				if (e->hangup.aoc_units > -1)
+					if (option_verbose > 2)
+						ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
+							pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
 
 #ifdef SUPPORT_USERUSER
-						if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
-							struct ast_channel *owner = pri->pvts[chanpos]->owner;
-							ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-							pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
-							ast_mutex_lock(&pri->pvts[chanpos]->lock);
-						}
+				if (pri->pvts[chanpos]->owner && !ast_strlen_zero(e->hangup.useruserinfo)) {
+					struct ast_channel *owner = pri->pvts[chanpos]->owner;
+					ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+					pbx_builtin_setvar_helper(owner, "USERUSERINFO", e->hangup.useruserinfo);
+					ast_mutex_lock(&pri->pvts[chanpos]->lock);
+				}
 #endif
 
-						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-					} else {
-						ast_log(LOG_WARNING, "Hangup on bad channel %d/%d on span %d\n", 
-							PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
-					}
-				} 
+				ast_mutex_unlock(&pri->pvts[chanpos]->lock);
 				break;
 #ifndef PRI_EVENT_HANGUP_REQ
 #error please update libpri
 #endif
 			case PRI_EVENT_HANGUP_REQ:
-				chanpos = pri_find_principle(pri, e->hangup.channel);
+				chanpos = pri_find_principle_by_call(pri, e->hangup.call);
 				if (chanpos < 0) {
-					ast_log(LOG_WARNING, "Hangup REQ requested on unconfigured channel %d/%d span %d\n", 
-						PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
+					/*
+					 * Continue hanging up the call even though
+					 * we do not remember it (if we ever did).
+					 */
+					pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
+					break;
+				}
+				ast_mutex_lock(&pri->pvts[chanpos]->lock);
+				if (pri->pvts[chanpos]->realcall)
+					pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
+				else if (pri->pvts[chanpos]->owner) {
+					pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
+					switch (pri->pvts[chanpos]->owner->_state) {
+					case AST_STATE_BUSY:
+					case AST_STATE_UP:
+						pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+						break;
+					default:
+						if (!pri->pvts[chanpos]->outgoing) {
+							/*
+							 * The incoming call leg hung up before getting
+							 * connected so just hangup the call.
+							 */
+							pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+							break;
+						}
+						switch (e->hangup.cause) {
+						case PRI_CAUSE_USER_BUSY:
+							pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
+							break;
+						case PRI_CAUSE_CALL_REJECTED:
+						case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
+						case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
+						case PRI_CAUSE_SWITCH_CONGESTION:
+						case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
+						case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
+							pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
+							break;
+						default:
+							pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+							break;
+						}
+						break;
+					}
+					if (option_verbose > 2) 
+						ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause);
+					if (e->hangup.aoc_units > -1)
+						if (option_verbose > 2)
+							ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
+								pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s");
 				} else {
-					chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
-					if (chanpos > -1) {
-						ast_mutex_lock(&pri->pvts[chanpos]->lock);
-						if (pri->pvts[chanpos]->realcall) 
-							pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
-						else if (pri->pvts[chanpos]->owner) {

[... 229 lines stripped ...]



More information about the asterisk-commits mailing list