[asterisk-commits] rmudgett: branch rmudgett/bch_shift_trunk r311678 - in /team/rmudgett/bch_shi...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Mar 25 11:03:38 CDT 2011


Author: rmudgett
Date: Fri Mar 25 11:03:33 2011
New Revision: 311678

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=311678
Log:
Merged revisions 311486,311490,311499 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/team/rmudgett/bch_shift_v1.8

........
  r311486 | rmudgett | 2011-03-21 12:57:42 -0500 (Mon, 21 Mar 2011) | 1 line
  
  Initial work before testing.
........
  r311490 | rmudgett | 2011-03-21 14:41:16 -0500 (Mon, 21 Mar 2011) | 1 line
  
  Add warning comment.
........
  r311499 | rmudgett | 2011-03-22 10:28:57 -0500 (Tue, 22 Mar 2011) | 1 line
  
  Turn off automerge for now.
........

Modified:
    team/rmudgett/bch_shift_trunk/   (props changed)
    team/rmudgett/bch_shift_trunk/channels/chan_dahdi.c
    team/rmudgett/bch_shift_trunk/channels/sig_pri.c

Propchange: team/rmudgett/bch_shift_trunk/
------------------------------------------------------------------------------
--- bch_shift_v1.8-integrated (original)
+++ bch_shift_v1.8-integrated Fri Mar 25 11:03:33 2011
@@ -1,1 +1,1 @@
-/team/rmudgett/bch_shift_v1.8:1-311481
+/team/rmudgett/bch_shift_v1.8:1-311499

Modified: team/rmudgett/bch_shift_trunk/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bch_shift_trunk/channels/chan_dahdi.c?view=diff&rev=311678&r1=311677&r2=311678
==============================================================================
--- team/rmudgett/bch_shift_trunk/channels/chan_dahdi.c (original)
+++ team/rmudgett/bch_shift_trunk/channels/chan_dahdi.c Fri Mar 25 11:03:33 2011
@@ -8776,14 +8776,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 idx;
 	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)) {
 		CHANNEL_DEADLOCK_AVOIDANCE(ast);
+
+		/*
+		 * 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;
 	}
 
 	idx = dahdi_get_index(ast, p, 0);

Modified: team/rmudgett/bch_shift_trunk/channels/sig_pri.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bch_shift_trunk/channels/sig_pri.c?view=diff&rev=311678&r1=311677&r2=311678
==============================================================================
--- team/rmudgett/bch_shift_trunk/channels/sig_pri.c (original)
+++ team/rmudgett/bch_shift_trunk/channels/sig_pri.c Fri Mar 25 11:03:33 2011
@@ -1150,6 +1150,40 @@
 
 /*!
  * \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 sig_pri_span *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;
+	}
+	sig_pri_lock_private(pri->pvts[chanpos]);
+	if (!pri->pvts[chanpos]->owner) {
+		pri_hangup(pri->pri, call, cause);
+		pri->pvts[chanpos]->call = NULL;
+		sig_pri_unlock_private(pri->pvts[chanpos]);
+		return;
+	}
+	pri->pvts[chanpos]->owner->hangupcause = cause;
+	pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
+	sig_pri_unlock_private(pri->pvts[chanpos]);
+}
+
+/*!
+ * \internal
  * \brief Find the private structure for the libpri call.
  *
  * \param pri PRI span control structure.
@@ -1365,6 +1399,52 @@
 	}
 	ast_verb(3, "Call specified, but not found.\n");
 	return -1;
+}
+
+/*!
+ * \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 sig_pri_span *pri, int channel, q931_call *call)
+{
+	int chanpos;
+
+	chanpos = pri_find_principle(pri, channel, call);
+	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;
 }
 
 static char * redirectingreason2str(int redirectingreason)
@@ -4183,42 +4263,6 @@
 	}
 }
 
-#if defined(HAVE_PRI_CALL_HOLD)
-/*!
- * \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 sig_pri_span *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;
-	}
-	sig_pri_lock_private(pri->pvts[chanpos]);
-	if (!pri->pvts[chanpos]->owner) {
-		pri_hangup(pri->pri, call, cause);
-		pri->pvts[chanpos]->call = NULL;
-		sig_pri_unlock_private(pri->pvts[chanpos]);
-		return;
-	}
-	pri->pvts[chanpos]->owner->hangupcause = cause;
-	pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
-	sig_pri_unlock_private(pri->pvts[chanpos]);
-}
-#endif	/* defined(HAVE_PRI_CALL_HOLD) */
-
 /*!
  * \internal
  * \brief Convert the MOH state to string.
@@ -4899,11 +4943,9 @@
 	struct ast_channel *bridged;
 	struct ast_channel *owner;
 
-	chanpos_old = pri_find_principle(pri, ev->hold.channel, ev->hold.call);
+	chanpos_old = pri_find_principle_by_call(pri, ev->hold.call);
 	if (chanpos_old < 0) {
-		ast_log(LOG_WARNING,
-			"Received HOLD on unconfigured channel %d/%d span %d\n",
-			PRI_SPAN(ev->hold.channel), PRI_CHANNEL(ev->hold.channel), pri->span);
+		ast_log(LOG_WARNING, "Span %d: Received HOLD for unknown call.\n", pri->span);
 		return -1;
 	}
 	if (pri->pvts[chanpos_old]->no_b_channel) {
@@ -5020,6 +5062,7 @@
 	if (chanpos < 0) {
 		ast_log(LOG_WARNING, "Span %d: Could not find principle for HOLD_REJECT\n",
 			pri->span);
+		sig_pri_kill_call(pri, ev->hold_rej.call, PRI_CAUSE_NORMAL_TEMPORARY_FAILURE);
 		return;
 	}
 	chanpos = pri_fixup_principle(pri, chanpos, ev->hold_rej.call);
@@ -5058,9 +5101,14 @@
 {
 	int chanpos;
 
-	if (!(ev->retrieve.channel & PRI_HELD_CALL)
-		|| pri_find_principle(pri, ev->retrieve.channel, ev->retrieve.call) < 0) {
+	if (!(ev->retrieve.channel & PRI_HELD_CALL)) {
 		/* The call is not currently held. */
+		pri_retrieve_rej(pri->pri, ev->retrieve.call,
+			PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED);
+		return;
+	}
+	if (pri_find_principle_by_call(pri, ev->retrieve.call) < 0) {
+		ast_log(LOG_WARNING, "Span %d: Received RETRIEVE for unknown call.\n", pri->span);
 		pri_retrieve_rej(pri->pri, ev->retrieve.call,
 			PRI_CAUSE_RESOURCE_UNAVAIL_UNSPECIFIED);
 		return;
@@ -5071,7 +5119,7 @@
 		chanpos = pri_find_principle(pri,
 			ev->retrieve.channel & ~PRI_HELD_CALL, ev->retrieve.call);
 		if (ev->retrieve.flexible
-			&& (chanpos < 0 || pri->pvts[chanpos]->owner)) {
+			&& (chanpos < 0 || pri->pvts[chanpos]->owner || pri->pvts[chanpos]->call)) {
 			/*
 			 * Channel selection is flexible and the requested channel
 			 * is bad or already in use.  Pick another channel.
@@ -5127,16 +5175,9 @@
 {
 	int chanpos;
 
-	chanpos = pri_find_principle(pri, ev->retrieve_ack.channel, ev->retrieve_ack.call);
+	chanpos = pri_find_fixup_principle(pri, ev->retrieve_ack.channel,
+		ev->retrieve_ack.call);
 	if (chanpos < 0) {
-		ast_log(LOG_WARNING,
-			"Span %d: Could not find principle for RETRIEVE_ACKNOWLEDGE\n", pri->span);
-		return;
-	}
-	chanpos = pri_fixup_principle(pri, chanpos, ev->retrieve_ack.call);
-	if (chanpos < 0) {
-		/* Very bad news.  The channel is already in use. */
-		sig_pri_kill_call(pri, ev->retrieve_ack.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
 		return;
 	}
 
@@ -5170,6 +5211,7 @@
 	if (chanpos < 0) {
 		ast_log(LOG_WARNING, "Span %d: Could not find principle for RETRIEVE_REJECT\n",
 			pri->span);
+		sig_pri_kill_call(pri, ev->retrieve_rej.call, PRI_CAUSE_NORMAL_TEMPORARY_FAILURE);
 		return;
 	}
 	chanpos = pri_fixup_principle(pri, chanpos, ev->retrieve_rej.call);
@@ -5218,6 +5260,7 @@
 	int nextidle = -1;
 	int haveidles;
 	int activeidles;
+	unsigned int len;
 
 	gettimeofday(&lastidle, NULL);
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
@@ -5511,33 +5554,29 @@
 						e->digit.call);
 					break;
 				}
-				chanpos = pri_find_principle(pri, e->digit.channel, e->digit.call);
+				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) {
-						sig_pri_lock_private(pri->pvts[chanpos]);
-						sig_pri_handle_subcmds(pri, chanpos, e->e, e->digit.channel,
-							e->digit.subcmds, e->digit.call);
-						/* 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);
-							int i;
-
-							for (i = 0; i < digitlen; i++) {
-								struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = e->digit.digits[i], };
-
-								pri_queue_frame(pri, chanpos, &f);
-							}
-						}
-						sig_pri_unlock_private(pri->pvts[chanpos]);
+					ast_log(LOG_WARNING,
+						"Span %d: Received keypad digits for unknown call.\n", pri->span);
+					break;
+				}
+				sig_pri_lock_private(pri->pvts[chanpos]);
+				sig_pri_handle_subcmds(pri, chanpos, e->e, e->digit.channel,
+					e->digit.subcmds, e->digit.call);
+				/* 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);
+					int i;
+
+					for (i = 0; i < digitlen; i++) {
+						struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = e->digit.digits[i], };
+
+						pri_queue_frame(pri, chanpos, &f);
 					}
 				}
+				sig_pri_unlock_private(pri->pvts[chanpos]);
 				break;
 
 			case PRI_EVENT_INFO_RECEIVED:
@@ -5546,33 +5585,29 @@
 						e->ring.call);
 					break;
 				}
-				chanpos = pri_find_principle(pri, e->ring.channel, e->ring.call);
+				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) {
-						sig_pri_lock_private(pri->pvts[chanpos]);
-						sig_pri_handle_subcmds(pri, chanpos, e->e, e->ring.channel,
-							e->ring.subcmds, e->ring.call);
-						/* 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);
-							int i;
-
-							for (i = 0; i < digitlen; i++) {
-								struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = e->ring.callednum[i], };
-
-								pri_queue_frame(pri, chanpos, &f);
-							}
-						}
-						sig_pri_unlock_private(pri->pvts[chanpos]);
+					ast_log(LOG_WARNING,
+						"Span %d: Received INFORMATION for unknown call.\n", pri->span);
+					break;
+				}
+				sig_pri_lock_private(pri->pvts[chanpos]);
+				sig_pri_handle_subcmds(pri, chanpos, e->e, e->ring.channel,
+					e->ring.subcmds, e->ring.call);
+				/* 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);
+					int i;
+
+					for (i = 0; i < digitlen; i++) {
+						struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = e->ring.callednum[i], };
+
+						pri_queue_frame(pri, chanpos, &f);
 					}
 				}
+				sig_pri_unlock_private(pri->pvts[chanpos]);
 				break;
 #if defined(HAVE_PRI_SERVICE_MESSAGES)
 			case PRI_EVENT_SERVICE:
@@ -5671,6 +5706,17 @@
 				} else {
 					/* A channel is specified. */
 					chanpos = pri_find_principle(pri, e->ring.channel, e->ring.call);
+/*!
+ * 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) {
@@ -6045,55 +6091,47 @@
 						e->ringing.call);
 					break;
 				}
-				chanpos = pri_find_principle(pri, e->ringing.channel, e->ringing.call);
+				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 {
-						sig_pri_lock_private(pri->pvts[chanpos]);
-
-						sig_pri_handle_subcmds(pri, chanpos, e->e, e->ringing.channel,
-							e->ringing.subcmds, e->ringing.call);
-						sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCNR);
-						sig_pri_set_echocanceller(pri->pvts[chanpos], 1);
-						pri_queue_control(pri, chanpos, AST_CONTROL_RINGING);
-						if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_ALERTING) {
-							pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_ALERTING;
-						}
-
-						if (
+					break;
+				}
+				sig_pri_lock_private(pri->pvts[chanpos]);
+
+				sig_pri_handle_subcmds(pri, chanpos, e->e, e->ringing.channel,
+					e->ringing.subcmds, e->ringing.call);
+				sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCNR);
+				sig_pri_set_echocanceller(pri->pvts[chanpos], 1);
+				pri_queue_control(pri, chanpos, AST_CONTROL_RINGING);
+				if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_ALERTING) {
+					pri->pvts[chanpos]->call_level = SIG_PRI_CALL_LEVEL_ALERTING;
+				}
+
+				if (
 #ifdef PRI_PROGRESS_MASK
-							e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE
+					e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE
 #else
-							e->ringing.progress == 8
+					e->ringing.progress == 8
 #endif
-							) {
-							sig_pri_open_media(pri->pvts[chanpos]);
-						}
-
+					) {
+					sig_pri_open_media(pri->pvts[chanpos]);
+				}
 
 #ifdef SUPPORT_USERUSER
-						if (!ast_strlen_zero(e->ringing.useruserinfo)) {
-							struct ast_channel *owner;
-
-							sig_pri_lock_owner(pri, chanpos);
-							owner = pri->pvts[chanpos]->owner;
-							if (owner) {
-								pbx_builtin_setvar_helper(owner, "USERUSERINFO",
-									e->ringing.useruserinfo);
-								ast_channel_unlock(owner);
-							}
-						}
+				if (!ast_strlen_zero(e->ringing.useruserinfo)) {
+					struct ast_channel *owner;
+
+					sig_pri_lock_owner(pri, chanpos);
+					owner = pri->pvts[chanpos]->owner;
+					if (owner) {
+						pbx_builtin_setvar_helper(owner, "USERUSERINFO",
+							e->ringing.useruserinfo);
+						ast_channel_unlock(owner);
+					}
+				}
 #endif
 
-						sig_pri_unlock_private(pri->pvts[chanpos]);
-					}
-				}
+				sig_pri_unlock_private(pri->pvts[chanpos]);
 				break;
 			case PRI_EVENT_PROGRESS:
 				if (sig_pri_is_cis_call(e->proceeding.channel)) {
@@ -6101,44 +6139,48 @@
 						e->proceeding.call);
 					break;
 				}
-				chanpos = pri_find_principle(pri, e->proceeding.channel, e->proceeding.call);
-				if (chanpos > -1) {
-					sig_pri_lock_private(pri->pvts[chanpos]);
-					sig_pri_handle_subcmds(pri, chanpos, e->e, e->proceeding.channel,
-						e->proceeding.subcmds, e->proceeding.call);
-
-					if (e->proceeding.cause > -1) {
-						ast_verb(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) {
-								ast_verb(3, "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
-
-								pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
-								pri_queue_control(pri, chanpos, AST_CONTROL_BUSY);
-							}
+				chanpos = pri_find_fixup_principle(pri, e->proceeding.channel,
+					e->proceeding.call);
+				if (chanpos < 0) {
+					break;
+				}
+				sig_pri_lock_private(pri->pvts[chanpos]);
+				sig_pri_handle_subcmds(pri, chanpos, e->e, e->proceeding.channel,
+					e->proceeding.subcmds, e->proceeding.call);
+
+				if (e->proceeding.cause > -1) {
+					ast_verb(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) {
+							ast_verb(3, "PROGRESS with 'user busy' received, signaling AST_CONTROL_BUSY instead of AST_CONTROL_PROGRESS\n");
+
+							pri->pvts[chanpos]->owner->hangupcause = e->proceeding.cause;
+							pri_queue_control(pri, chanpos, AST_CONTROL_BUSY);
 						}
 					}
-
-					if (!pri->pvts[chanpos]->progress
-						&& !pri->pvts[chanpos]->no_b_channel
+				}
+
+				if (!pri->pvts[chanpos]->progress
+					&& !pri->pvts[chanpos]->no_b_channel
 #ifdef PRI_PROGRESS_MASK
-						&& (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
+					&& (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
 #else
-						&& e->proceeding.progress == 8
+					&& e->proceeding.progress == 8
 #endif
-						) {
-						/* Bring voice path up */
-						ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
-							pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
-						pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
-						pri->pvts[chanpos]->progress = 1;
-						sig_pri_set_dialing(pri->pvts[chanpos], 0);
-						sig_pri_open_media(pri->pvts[chanpos]);
-					}
-					sig_pri_unlock_private(pri->pvts[chanpos]);
-				}
+					) {
+					/* Bring voice path up */
+					ast_debug(1,
+						"Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
+						pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,
+						pri->span);
+					pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
+					pri->pvts[chanpos]->progress = 1;
+					sig_pri_set_dialing(pri->pvts[chanpos], 0);
+					sig_pri_open_media(pri->pvts[chanpos]);
+				}
+				sig_pri_unlock_private(pri->pvts[chanpos]);
 				break;
 			case PRI_EVENT_PROCEEDING:
 				if (sig_pri_is_cis_call(e->proceeding.channel)) {
@@ -6146,33 +6188,37 @@
 						e->proceeding.call);
 					break;
 				}
-				chanpos = pri_find_principle(pri, e->proceeding.channel, e->proceeding.call);
-				if (chanpos > -1) {
-					sig_pri_lock_private(pri->pvts[chanpos]);
-					sig_pri_handle_subcmds(pri, chanpos, e->e, e->proceeding.channel,
-						e->proceeding.subcmds, e->proceeding.call);
-					if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING) {
-						pri->pvts[chanpos]->call_level = SIG_PRI_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);
-						pri_queue_control(pri, chanpos, AST_CONTROL_PROCEEDING);
-					}
-					if (!pri->pvts[chanpos]->progress
-						&& !pri->pvts[chanpos]->no_b_channel
+				chanpos = pri_find_fixup_principle(pri, e->proceeding.channel,
+					e->proceeding.call);
+				if (chanpos < 0) {
+					break;
+				}
+				sig_pri_lock_private(pri->pvts[chanpos]);
+				sig_pri_handle_subcmds(pri, chanpos, e->e, e->proceeding.channel,
+					e->proceeding.subcmds, e->proceeding.call);
+				if (pri->pvts[chanpos]->call_level < SIG_PRI_CALL_LEVEL_PROCEEDING) {
+					pri->pvts[chanpos]->call_level = SIG_PRI_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);
+					pri_queue_control(pri, chanpos, AST_CONTROL_PROCEEDING);
+				}
+				if (!pri->pvts[chanpos]->progress
+					&& !pri->pvts[chanpos]->no_b_channel
 #ifdef PRI_PROGRESS_MASK
-						&& (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
+					&& (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE)
 #else
-						&& e->proceeding.progress == 8
+					&& e->proceeding.progress == 8
 #endif
-						) {
-						/* Bring voice path up */
-						pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
-						pri->pvts[chanpos]->progress = 1;
-						sig_pri_set_dialing(pri->pvts[chanpos], 0);
-						sig_pri_open_media(pri->pvts[chanpos]);
-					}
-					sig_pri_unlock_private(pri->pvts[chanpos]);
-				}
+					) {
+					/* Bring voice path up */
+					pri_queue_control(pri, chanpos, AST_CONTROL_PROGRESS);
+					pri->pvts[chanpos]->progress = 1;
+					sig_pri_set_dialing(pri->pvts[chanpos], 0);
+					sig_pri_open_media(pri->pvts[chanpos]);
+				}
+				sig_pri_unlock_private(pri->pvts[chanpos]);
 				break;
 			case PRI_EVENT_FACILITY:
 				if (!e->facility.call || sig_pri_is_cis_call(e->facility.channel)) {
@@ -6186,27 +6232,21 @@
 #endif	/* !defined(HAVE_PRI_CALL_REROUTING) */
 					break;
 				}
-				chanpos = pri_find_principle(pri, e->facility.channel, e->facility.call);
+				chanpos = pri_find_principle_by_call(pri, e->facility.call);
 				if (chanpos < 0) {
-					ast_log(LOG_WARNING, "Facility requested on unconfigured channel %d/%d span %d\n",
-						PRI_SPAN(e->facility.channel), PRI_CHANNEL(e->facility.channel), pri->span);
-				} else {
-					chanpos = pri_fixup_principle(pri, chanpos, e->facility.call);
-					if (chanpos < 0) {
-						ast_log(LOG_WARNING, "Facility requested on channel %d/%d not in use on span %d\n",
-							PRI_SPAN(e->facility.channel), PRI_CHANNEL(e->facility.channel), pri->span);
-					} else {
-						sig_pri_lock_private(pri->pvts[chanpos]);
+					ast_log(LOG_WARNING, "Span %d: Received facility for unknown call.\n",
+						pri->span);
+					break;
+				}
+				sig_pri_lock_private(pri->pvts[chanpos]);
 #if defined(HAVE_PRI_CALL_REROUTING)
-						sig_pri_handle_subcmds(pri, chanpos, e->e, e->facility.channel,
-							e->facility.subcmds, e->facility.subcall);
+				sig_pri_handle_subcmds(pri, chanpos, e->e, e->facility.channel,
+					e->facility.subcmds, e->facility.subcall);
 #else
-						sig_pri_handle_subcmds(pri, chanpos, e->e, e->facility.channel,
-							e->facility.subcmds, e->facility.call);
+				sig_pri_handle_subcmds(pri, chanpos, e->e, e->facility.channel,
+					e->facility.subcmds, e->facility.call);
 #endif	/* !defined(HAVE_PRI_CALL_REROUTING) */
-						sig_pri_unlock_private(pri->pvts[chanpos]);
-					}
-				}
+				sig_pri_unlock_private(pri->pvts[chanpos]);
 				break;
 			case PRI_EVENT_ANSWER:
 				if (sig_pri_is_cis_call(e->answer.channel)) {
@@ -6218,16 +6258,8 @@
 						e->answer.call);
 					break;
 				}
-				chanpos = pri_find_principle(pri, e->answer.channel, e->answer.call);
+				chanpos = pri_find_fixup_principle(pri, e->answer.channel, e->answer.call);
 				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);
-					break;
-				}
-				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);
 					break;
 				}
 #if defined(HAVE_PRI_CALL_WAITING)
@@ -6240,11 +6272,23 @@
 						 * kill the call with PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION.
 						 */
 						new_chanpos = pri_find_empty_chan(pri, 1);
+						if (0 <= new_chanpos) {
+							new_chanpos = pri_fixup_principle(pri, new_chanpos,
+								e->answer.call);
+						}
 						if (new_chanpos < 0) {
+							/*
+							 * Either no channel was available or someone stole
+							 * the channel!
+							 */
+							ast_verb(3,
+								"Span %d: Channel not available for call waiting call.\n",
+								pri->span);
 							sig_pri_lock_private(pri->pvts[chanpos]);
 							sig_pri_handle_subcmds(pri, chanpos, e->e, e->answer.channel,
 								e->answer.subcmds, e->answer.call);
 							sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCBS);
+							sig_pri_lock_owner(pri, chanpos);
 							if (pri->pvts[chanpos]->owner) {
 								pri->pvts[chanpos]->owner->hangupcause = PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION;
 								switch (pri->pvts[chanpos]->owner->_state) {
@@ -6256,6 +6300,7 @@
 									pri_queue_control(pri, chanpos, AST_CONTROL_CONGESTION);
 									break;
 								}
+								ast_channel_unlock(pri->pvts[chanpos]->owner);
 							} else {
 								pri->pvts[chanpos]->is_call_waiting = 0;
 								ast_atomic_fetchadd_int(&pri->num_call_waiting_calls, -1);
@@ -6265,13 +6310,7 @@
 							sig_pri_unlock_private(pri->pvts[chanpos]);
 							break;
 						}
-						chanpos = pri_fixup_principle(pri, new_chanpos, e->answer.call);
-						if (chanpos < 0) {
-							ast_log(LOG_WARNING,
-								"Unable to move call waiting call channel on span %d\n",
-								pri->span);
-							break;
-						}
+						chanpos = new_chanpos;
 					}
 					pri_connect_ack(pri->pri, e->answer.call, PVT_TO_CHANNEL(pri->pvts[chanpos]));
 				} else {
@@ -6322,19 +6361,9 @@
 						e->connect_ack.call);
 					break;
 				}
-				chanpos = pri_find_principle(pri, e->connect_ack.channel,
+				chanpos = pri_find_fixup_principle(pri, e->connect_ack.channel,
 					e->connect_ack.call);
 				if (chanpos < 0) {
-					ast_log(LOG_WARNING, "Connect ACK on unconfigured channel %d/%d span %d\n",
-						PRI_SPAN(e->connect_ack.channel),
-						PRI_CHANNEL(e->connect_ack.channel), pri->span);
-					break;
-				}
-				chanpos = pri_fixup_principle(pri, chanpos, e->connect_ack.call);
-				if (chanpos < 0) {
-					ast_log(LOG_WARNING, "Connect ACK requested on channel %d/%d not in use on span %d\n",
-						PRI_SPAN(e->connect_ack.channel),
-						PRI_CHANNEL(e->connect_ack.channel), pri->span);
 					break;
 				}
 
@@ -6353,130 +6382,119 @@
 					pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
 					break;
 				}
-				chanpos = pri_find_principle(pri, e->hangup.channel, e->hangup.call);
+				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
-					 * it is on an unconfigured channel.
+					 * we do not remember it (if we ever did).
 					 */
 					pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
-				} else {
-					chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
-					if (chanpos > -1) {
-						sig_pri_lock_private(pri->pvts[chanpos]);
-						sig_pri_handle_subcmds(pri, chanpos, e->e, e->hangup.channel,
-							e->hangup.subcmds, e->hangup.call);
-						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;
+					break;
+				}
+				sig_pri_lock_private(pri->pvts[chanpos]);
+				sig_pri_handle_subcmds(pri, chanpos, e->e, e->hangup.channel,
+					e->hangup.subcmds, e->hangup.call);
+				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;
+					switch (e->hangup.cause) {
+					case PRI_CAUSE_USER_BUSY:
+					case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
+						sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCBS);
+						break;
+					default:
+						break;
+					}
+					if (pri->pvts[chanpos]->owner) {
+						int do_hangup = 0;
+						/* 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:
+							do_hangup = 1;
+							break;
+						default:
+							if (!pri->pvts[chanpos]->outgoing) {
+								/*
+								 * The incoming call leg hung up before getting
+								 * connected so just hangup the call.
+								 */
+								do_hangup = 1;
+								break;
+							}
 							switch (e->hangup.cause) {
 							case PRI_CAUSE_USER_BUSY:
+								pri_queue_control(pri, chanpos, AST_CONTROL_BUSY);
+								break;
+							case PRI_CAUSE_CALL_REJECTED:
+							case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
 							case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
-								sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCBS);
+							case PRI_CAUSE_SWITCH_CONGESTION:
+							case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
+							case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
+								pri_queue_control(pri, chanpos, AST_CONTROL_CONGESTION);
 								break;
 							default:
+								do_hangup = 1;
 								break;
 							}
-							if (pri->pvts[chanpos]->owner) {
-								int do_hangup = 0;
-								/* 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:
-									do_hangup = 1;
-									break;
-								default:
-									if (!pri->pvts[chanpos]->outgoing) {
-										/*
-										 * The incoming call leg hung up before getting
-										 * connected so just hangup the call.
-										 */
-										do_hangup = 1;
-										break;
-									}
-									switch (e->hangup.cause) {
-									case PRI_CAUSE_USER_BUSY:
-										pri_queue_control(pri, chanpos, AST_CONTROL_BUSY);
-										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_queue_control(pri, chanpos, AST_CONTROL_CONGESTION);
-										break;
-									default:
-										do_hangup = 1;
-										break;
-									}
-									break;
-								}
-
-								if (do_hangup) {
+							break;
+						}
+
+						if (do_hangup) {
 #if defined(HAVE_PRI_AOC_EVENTS)
-									if (detect_aoc_e_subcmd(e->hangup.subcmds)) {
-										/* If a AOC-E msg was sent during the release, we must use a
-										 * AST_CONTROL_HANGUP frame to guarantee that frame gets read before hangup */
-										pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
-									} else {
-										pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-									}
+							if (detect_aoc_e_subcmd(e->hangup.subcmds)) {
+								/* If a AOC-E msg was sent during the release, we must use a
+								 * AST_CONTROL_HANGUP frame to guarantee that frame gets read before hangup */
+								pri_queue_control(pri, chanpos, AST_CONTROL_HANGUP);
+							} else {
+								pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+							}
 #else
-									pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+							pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
 #endif	/* defined(HAVE_PRI_AOC_EVENTS) */
-								}
-							} else {
-								/*
-								 * Continue hanging up the call even though
-								 * we do not have an owner.
-								 */
-								pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
-								pri->pvts[chanpos]->call = NULL;
-							}
-							ast_verb(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 {
-							/* Continue hanging up the call. */
-							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) {
-							ast_verb(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)
-							ast_verb(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 (!ast_strlen_zero(e->hangup.useruserinfo)) {
-							struct ast_channel *owner;
-
-							sig_pri_lock_owner(pri, chanpos);
-							owner = pri->pvts[chanpos]->owner;
-							if (owner) {
-								pbx_builtin_setvar_helper(owner, "USERUSERINFO",
-									e->hangup.useruserinfo);
-								ast_channel_unlock(owner);
-							}
-						}
-#endif
-
-						sig_pri_unlock_private(pri->pvts[chanpos]);
 					} else {
 						/*
 						 * Continue hanging up the call even though
-						 * we do not remember it (if we ever did).
+						 * we do not have an owner.
 						 */
-						pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
+						pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
+						pri->pvts[chanpos]->call = NULL;
 					}
-				}
+					ast_verb(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 {
+					/* Continue hanging up the call. */
+					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) {
+					ast_verb(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)
+					ast_verb(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 (!ast_strlen_zero(e->hangup.useruserinfo)) {
+					struct ast_channel *owner;
+
+					sig_pri_lock_owner(pri, chanpos);
+					owner = pri->pvts[chanpos]->owner;
+					if (owner) {
+						pbx_builtin_setvar_helper(owner, "USERUSERINFO",
+							e->hangup.useruserinfo);
+						ast_channel_unlock(owner);
+					}
+				}
+#endif
+
+				sig_pri_unlock_private(pri->pvts[chanpos]);
 				break;
 			case PRI_EVENT_HANGUP_REQ:
 				if (sig_pri_is_cis_call(e->hangup.channel)) {
@@ -6485,136 +6503,125 @@
 					pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
 					break;
 				}
-				chanpos = pri_find_principle(pri, e->hangup.channel, e->hangup.call);
+				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
-					 * it is on an unconfigured channel.
+					 * we do not remember it (if we ever did).
 					 */
 					pri_hangup(pri->pri, e->hangup.call, e->hangup.cause);
-				} else {
-					chanpos = pri_fixup_principle(pri, chanpos, e->hangup.call);
-					if (chanpos > -1) {
-						sig_pri_lock_private(pri->pvts[chanpos]);
-						sig_pri_handle_subcmds(pri, chanpos, e->e, e->hangup.channel,
-							e->hangup.subcmds, e->hangup.call);
+					break;
+				}
+				sig_pri_lock_private(pri->pvts[chanpos]);
+				sig_pri_handle_subcmds(pri, chanpos, e->e, e->hangup.channel,
+					e->hangup.subcmds, e->hangup.call);
 #if defined(HAVE_PRI_CALL_HOLD)
-						if (e->hangup.call_active && e->hangup.call_held
-							&& pri->hold_disconnect_transfer) {
-							/* We are to transfer the call instead of simply hanging up. */
-							sig_pri_unlock_private(pri->pvts[chanpos]);
-							if (!sig_pri_attempt_transfer(pri, e->hangup.call_held, 1,
-								e->hangup.call_active, 0, NULL, NULL)) {
-								break;
-							}
-							sig_pri_lock_private(pri->pvts[chanpos]);
+				if (e->hangup.call_active && e->hangup.call_held
+					&& pri->hold_disconnect_transfer) {
+					/* We are to transfer the call instead of simply hanging up. */
+					sig_pri_unlock_private(pri->pvts[chanpos]);
+					if (!sig_pri_attempt_transfer(pri, e->hangup.call_held, 1,
+						e->hangup.call_active, 0, NULL, NULL)) {
+						break;
+					}
+					sig_pri_lock_private(pri->pvts[chanpos]);
+				}
+#endif	/* defined(HAVE_PRI_CALL_HOLD) */
+				switch (e->hangup.cause) {
+				case PRI_CAUSE_USER_BUSY:
+				case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
+					sig_pri_cc_generic_check(pri, chanpos, AST_CC_CCBS);
+					break;
+				default:
+					break;
+				}
+				if (pri->pvts[chanpos]->owner) {
+					int do_hangup = 0;
+
+					pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
+					switch (pri->pvts[chanpos]->owner->_state) {
+					case AST_STATE_BUSY:
+					case AST_STATE_UP:
+						do_hangup = 1;
+						break;
+					default:
+						if (!pri->pvts[chanpos]->outgoing) {
+							/*
+							 * The incoming call leg hung up before getting
+							 * connected so just hangup the call.
+							 */
+							do_hangup = 1;
+							break;
 						}
-#endif	/* defined(HAVE_PRI_CALL_HOLD) */
 						switch (e->hangup.cause) {
 						case PRI_CAUSE_USER_BUSY:
+							pri_queue_control(pri, chanpos, AST_CONTROL_BUSY);
+							break;

[... 364 lines stripped ...]



More information about the asterisk-commits mailing list