[svn-commits] rmudgett: branch rmudgett/bch_shift_v1.4 r311736 - in /team/rmudgett/bch_shif...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Mon Mar 28 11:55:25 CDT 2011


Author: rmudgett
Date: Mon Mar 28 11:55:21 2011
New Revision: 311736

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=311736
Log:
Merged revisions 311684 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/team/rmudgett/bch_shift_v1.6.2

................
  r311684 | rmudgett | 2011-03-25 15:03:46 -0500 (Fri, 25 Mar 2011) | 9 lines
  
  Merged revisions 311500 via svnmerge from 
  https://origsvn.digium.com/svn/asterisk/team/rmudgett/bch_shift_v1.8
  
  ........
    r311500 | rmudgett | 2011-03-22 10:42:37 -0500 (Tue, 22 Mar 2011) | 2 lines
    
    Fix deadlock and internal B channel allocation race between in/out going calls.
  ........
................

Modified:
    team/rmudgett/bch_shift_v1.4/   (props changed)
    team/rmudgett/bch_shift_v1.4/channels/chan_dahdi.c

Propchange: team/rmudgett/bch_shift_v1.4/
------------------------------------------------------------------------------
--- bch_shift_v1.6.2-integrated (original)
+++ bch_shift_v1.6.2-integrated Mon Mar 28 11:55:21 2011
@@ -1,1 +1,1 @@
-/team/rmudgett/bch_shift_v1.6.2:1-311681
+/team/rmudgett/bch_shift_v1.6.2:1-311681,311684

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=311736&r1=311735&r2=311736
==============================================================================
--- team/rmudgett/bch_shift_v1.4/channels/chan_dahdi.c (original)
+++ team/rmudgett/bch_shift_v1.4/channels/chan_dahdi.c Mon Mar 28 11:55:21 2011
@@ -257,6 +257,9 @@
 static enum ast_bridge_result dahdi_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms);
 
 static int dahdi_sendtext(struct ast_channel *c, const char *text);
+
+#define SIG_PRI_LIB_HANDLE_CASES	\
+	SIG_PRI
 
 /*! \brief Avoid the silly dahdi_getevent which ignores a bunch of events */
 static inline int dahdi_get_event(int fd)
@@ -592,6 +595,19 @@
 	unsigned int unknown_alarm:1;
 	/*! \brief TRUE if TDD in MATE mode */
 	unsigned int mate:1;
+#if defined(HAVE_PRI)
+	/*!
+	 * \brief TRUE when this channel is allocated.
+	 *
+	 * \details
+	 * Needed to hold an outgoing channel allocation before the
+	 * owner pointer is created.
+	 *
+	 * \note This is one of several items to check to see if a
+	 * channel is available for use.
+	 */
+	unsigned int allocated:1;
+#endif	/* defined(HAVE_PRI) */
 	/*! \brief TRUE if we originated the call leg. */
 	unsigned int outgoing:1;
 	/* unsigned int overlapdial:1; 			unused and potentially confusing */
@@ -3071,6 +3087,7 @@
 		p->pulsedial = 0;
 		p->onhooktime = time(NULL);
 #ifdef HAVE_PRI
+		p->allocated = 0;
 		p->dialing = 0;
 		p->progress = 0;
 		p->call_level = DAHDI_CALL_LEVEL_IDLE;
@@ -8595,6 +8612,86 @@
 	return tmp;
 }
 
+#if defined(HAVE_PRI)
+/*!
+ * \internal
+ * \brief Determine if a private channel structure is in use.
+ * \since 1.8
+ *
+ * \param pvt Channel to determine if in use.
+ *
+ * \return TRUE if the channel is in use.
+ */
+static int sig_pri_is_chan_in_use(struct dahdi_pvt *pvt)
+{
+	return pvt->owner || pvt->call || pvt->allocated || pvt->resetting || pvt->inalarm;
+}
+#endif	/* defined(HAVE_PRI) */
+
+#if defined(HAVE_PRI)
+/*!
+ * \internal
+ * \brief Determine if a private channel structure is available.
+ * \since 1.8
+ *
+ * \param pvt Channel to determine if available.
+ *
+ * \return TRUE if the channel is available.
+ */
+static int sig_pri_is_chan_available(struct dahdi_pvt *pvt)
+{
+	return !sig_pri_is_chan_in_use(pvt);
+}
+#endif	/* defined(HAVE_PRI) */
+
+#if defined(HAVE_PRI)
+/*!
+ * \internal
+ * \brief Simple check if the channel is available to use.
+ * \since 1.8
+ *
+ * \param pvt Private channel control structure.
+ *
+ * \retval 0 Interface not available.
+ * \retval 1 Interface is available.
+ */
+static int sig_pri_available_check(struct dahdi_pvt *pvt)
+{
+	/*
+	 * If interface is available for use
+	 * then the channel is available.
+	 */
+	if (sig_pri_is_chan_available(pvt)) {
+		return 1;
+	}
+	return 0;
+}
+#endif	/* defined(HAVE_PRI) */
+
+#if defined(HAVE_PRI)
+static int sig_pri_available(struct dahdi_pvt *pvt)
+{
+	struct dahdi_pvt *p = pvt;
+	struct dahdi_pri *pri;
+
+	if (!p->pri) {
+		/* Something is wrong here.  A PRI channel without the pri pointer? */
+		return 0;
+	}
+	pri = p->pri;
+
+	ast_mutex_lock(&pri->lock);
+	if (sig_pri_available_check(p)) {
+		p->allocated = 1;
+		ast_mutex_unlock(&pri->lock);
+		return 1;
+	}
+
+	ast_mutex_unlock(&pri->lock);
+	return 0;
+}
+#endif	/* defined(HAVE_PRI) */
+
 static inline int available(struct dahdi_pvt *p, int channelmatch, ast_group_t groupmatch, int *busy, int *channelmatched, int *groupmatched)
 {
 	int res;
@@ -8612,6 +8709,16 @@
 			return 0;
 		*channelmatched = 1;
 	}
+
+#if defined(HAVE_PRI)
+	switch (p->sig) {
+	case SIG_PRI_LIB_HANDLE_CASES:
+		return sig_pri_available(p);
+	default:
+		break;
+	}
+#endif	/* defined(HAVE_PRI) */
+
 	/* We're at least busy at this point */
 	if (busy) {
 		if ((p->sig == SIG_FXOKS) || (p->sig == SIG_FXOLS) || (p->sig == SIG_FXOGS))
@@ -8629,10 +8736,8 @@
 #ifdef HAVE_PRI
 		/* Trust PRI */
 		if (p->pri) {
-			if (p->resetting || p->call)
-				return 0;
-			else
-				return 1;
+			/* Likely only GR-303 gets here. */
+			return sig_pri_available(p);
 		}
 #endif
 		if (!(p->radio || (p->oprmode < 0)))
@@ -8739,6 +8844,18 @@
 	
 
 #ifdef HAVE_PRI
+/*!
+ * \internal
+ * \brief Find an empty B-channel interface to use.
+ *
+ * \param pri PRI span control structure.
+ * \param backwards TRUE if the search starts from higher channels.
+ *
+ * \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_empty_chan(struct dahdi_pri *pri, int backwards)
 {
 	int x;
@@ -8751,7 +8868,8 @@
 			break;
 		if (!backwards && (x >= pri->numchans))
 			break;
-		if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
+		if (pri->pvts[x]
+			&& sig_pri_is_chan_available(pri->pvts[x])) {
 			ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n", 
 				pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
 			return x;
@@ -8946,6 +9064,19 @@
 			tmp = dahdi_new(p, AST_STATE_RESERVED, 0, p->owner ? SUB_CALLWAIT : SUB_REAL, 0, 0);
 			if (!tmp) {
 				p->outgoing = 0;
+#if defined(HAVE_PRI)
+				switch (p->sig) {
+				case SIG_PRI_LIB_HANDLE_CASES:
+					/*
+					 * This should be the last thing to clear when we are done with
+					 * the channel.
+					 */
+					p->allocated = 0;
+					break;
+				default:
+					break;
+				}
+#endif	/* defined(HAVE_PRI) */
 			}
 #ifdef HAVE_PRI
 			if (p->bearer) {
@@ -9263,7 +9394,7 @@
 						old->owner ? old->owner->name : "",
 						old->channel, new->channel);
 				}
-				if (new->owner) {
+				if (!sig_pri_is_chan_available(new)) {
 					ast_log(LOG_WARNING,
 						"Can't move call (%s) from channel %d to %d.  It is already in use.\n",
 						old->owner ? old->owner->name : "",
@@ -9300,11 +9431,13 @@
 				new->alreadyhungup = old->alreadyhungup;
 				new->isidlecall = old->isidlecall;
 				new->progress = old->progress;
+				new->allocated = old->allocated;
 				new->outgoing = old->outgoing;
 				new->digital = old->digital;
 				old->alreadyhungup = 0;
 				old->isidlecall = 0;
 				old->progress = 0;
+				old->allocated = 0;
 				old->outgoing = 0;
 				old->digital = 0;
 
@@ -9538,14 +9671,25 @@
 	ast_mutex_unlock(&pridebugfdlock);
 }
 
-static int pri_check_restart(struct dahdi_pri *pri)
-{
-	do {
-		pri->resetpos++;
-	} while ((pri->resetpos < pri->numchans) &&
-		 (!pri->pvts[pri->resetpos] ||
-		  pri->pvts[pri->resetpos]->call ||
-		  pri->pvts[pri->resetpos]->resetting));
+/*!
+ * \internal
+ * \brief Restart the next channel we think is idle on the span.
+ *
+ * \param pri PRI span control structure.
+ *
+ * \note Assumes the pri->lock is already obtained.
+ *
+ * \return Nothing
+ */
+static void pri_check_restart(struct dahdi_pri *pri)
+{
+	for (++pri->resetpos; pri->resetpos < pri->numchans; ++pri->resetpos) {
+		if (!pri->pvts[pri->resetpos]
+			|| sig_pri_is_chan_in_use(pri->pvts[pri->resetpos])) {
+			continue;
+		}
+		break;
+	}
 	if (pri->resetpos < pri->numchans) {
 		/* Mark the channel as resetting and restart it */
 		pri->pvts[pri->resetpos]->resetting = 1;
@@ -9554,7 +9698,6 @@
 		pri->resetting = 0;
 		time(&pri->lastreset);
 	}
-	return 0;
 }
 
 static int pri_hangup_all(struct dahdi_pvt *p, struct dahdi_pri *pri)
@@ -9702,8 +9845,9 @@
 		ast_mutex_lock(&pri->lock);
 		if (pri->switchtype != PRI_SWITCH_GR303_TMC && (pri->resetinterval > 0)) {
 			if (pri->resetting && pri_is_up(pri)) {
-				if (pri->resetpos < 0)
+				if (pri->resetpos < 0) {
 					pri_check_restart(pri);
+				}
 			} else {
 				if (!pri->resetting	&& (t - pri->lastreset) >= pri->resetinterval) {
 					pri->resetting = 1;
@@ -9717,30 +9861,39 @@
 			haveidles = 0;
 			activeidles = 0;
 			for (x = pri->numchans; x >= 0; x--) {
-				if (pri->pvts[x] && !pri->pvts[x]->owner && 
-				    !pri->pvts[x]->call) {
-					if (haveidles < pri->minunused) {
-						haveidles++;
-					} else if (!pri->pvts[x]->resetting) {
-						nextidle = x;
-						break;
+				if (pri->pvts[x]) {
+					if (sig_pri_is_chan_available(pri->pvts[x])) {
+						if (haveidles < pri->minunused) {
+							haveidles++;
+						} else {
+							nextidle = x;
+							break;
+						}
+					} else if (pri->pvts[x]->owner && pri->pvts[x]->isidlecall) {
+						activeidles++;
 					}
-				} else if (pri->pvts[x] && pri->pvts[x]->owner && pri->pvts[x]->isidlecall)
-					activeidles++;
+				}
 			}
 			if (nextidle > -1) {
 				if (ast_tvdiff_ms(ast_tvnow(), lastidle) > 1000) {
 					/* Don't create a new idle call more than once per second */
 					snprintf(idlen, sizeof(idlen), "%d/%s", pri->pvts[nextidle]->channel, pri->idledial);
+					/*
+					 * Release the PRI lock while we create the channel so other
+					 * threads can send D channel messages.
+					 */
+					ast_mutex_unlock(&pri->lock);
 					idle = dahdi_request(dahdi_chan_name, AST_FORMAT_ULAW, idlen, &cause);
+					ast_mutex_lock(&pri->lock);
 					if (idle) {
 						pri->pvts[nextidle]->isidlecall = 1;
 						if (ast_pthread_create_background(&p, NULL, do_idle_thread, idle)) {
 							ast_log(LOG_WARNING, "Unable to start new thread for idle channel '%s'\n", idle->name);
-							dahdi_hangup(idle);
+							ast_hangup(idle);
 						}
-					} else
+					} else {
 						ast_log(LOG_WARNING, "Unable to request channel 'DAHDI/%s' for idle call\n", idlen);
+					}
 					gettimeofday(&lastidle, NULL);
 				}
 			} else if ((haveidles < pri->minunused) &&
@@ -10006,10 +10159,40 @@
 				break;
 			case PRI_EVENT_RING:
 				crv = NULL;
-				if (e->ring.channel == -1) {
+				if (e->ring.channel == -1 || PRI_CHANNEL(e->ring.channel) == 0xFF) {
+					/* Any channel requested. */
 					chanpos = pri_find_empty_chan(pri, 1);
+				} else if (PRI_CHANNEL(e->ring.channel) == 0x00) {
+					/* No channel specified. */
+					{
+						/* We will not accept incoming call waiting calls. */
+						pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INCOMPATIBLE_DESTINATION);
+						break;
+					}
 				} else {
+					/* A channel is specified. */
 					chanpos = pri_find_principle(pri, e->ring.channel);
+					if (chanpos < 0) {
+						ast_log(LOG_WARNING,
+							"Span %d: SETUP on unconfigured channel %d/%d\n",
+							pri->span, PRI_SPAN(e->ring.channel),
+							PRI_CHANNEL(e->ring.channel));
+					} else if (!sig_pri_is_chan_available(pri->pvts[chanpos])) {
+						/* Libpri has already filtered out duplicate SETUPs anyway. */
+						if (pri->pvts[chanpos]->call == e->ring.call) {
+							ast_log(LOG_WARNING,
+								"Span %d: Ignoring duplicate SETUP on channel %d/%d\n",
+								pri->span, PRI_SPAN(e->ring.channel),
+								PRI_CHANNEL(e->ring.channel));
+							break;
+						}
+						/* This is where we handle initial glare */
+						ast_log(LOG_DEBUG,
+							"Span %d: SETUP requested unavailable channel %d/%d.  Attempting to renegotiate.\n",
+							pri->span, PRI_SPAN(e->ring.channel),
+							PRI_CHANNEL(e->ring.channel));
+						chanpos = -1;
+					}
 /*!
  * Define to make always pick a channel if allowed.  Useful for
  * testing channel shifting.
@@ -10018,286 +10201,288 @@
 #define ALWAYS_PICK_CHANNEL	1	//BUGBUG
 #if defined(ALWAYS_PICK_CHANNEL)
 					if (e->ring.flexible) {
+						chanpos = -1;
+					}
+#endif	/* defined(ALWAYS_PICK_CHANNEL) */
+					if (chanpos < 0 && e->ring.flexible) {
+						/* We can try to pick another channel. */
 						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", 
-						PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
+					if (e->ring.flexible) {
+						pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
+					} else {
+						pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
+					}
+					break;
+				}
+
+				ast_mutex_lock(&pri->pvts[chanpos]->lock);
+				if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
+					/* Should be safe to lock CRV AFAIK while bearer is still locked */
+					crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
+					if (crv)
+						ast_mutex_lock(&crv->lock);
+					if (!crv || crv->owner) {
+						pri->pvts[chanpos]->call = NULL;
+						if (crv) {
+							if (crv->owner)
+								crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+							ast_log(LOG_WARNING, "Call received for busy CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
+						} else
+							ast_log(LOG_NOTICE, "Call received for unconfigured CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
+						pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
+						if (crv)
+							ast_mutex_unlock(&crv->lock);
+						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+						break;
+					}
+				}
+
+				/* Mark channel as in use so noone else will steal it. */
+				pri->pvts[chanpos]->call = e->ring.call;
+
+				apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
+				if (pri->pvts[chanpos]->use_callerid) {
+					ast_shrink_phone_number(plancallingnum);
+					ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
+#ifdef PRI_ANI
+					if (!ast_strlen_zero(e->ring.callingani)) {
+						apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
+						ast_shrink_phone_number(plancallingani);
+						ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
+					} else {
+						pri->pvts[chanpos]->cid_ani[0] = '\0';
+					}
+#endif
+					ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
+					pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
 				} else {
-					ast_mutex_lock(&pri->pvts[chanpos]->lock);
-					if (pri->pvts[chanpos]->owner) {
-						if (pri->pvts[chanpos]->call == e->ring.call) {
-							ast_log(LOG_WARNING, "Duplicate setup requested on channel %d/%d already in use on span %d\n", 
-								PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
-							ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-							break;
+					pri->pvts[chanpos]->cid_num[0] = '\0';
+					pri->pvts[chanpos]->cid_ani[0] = '\0';
+					pri->pvts[chanpos]->cid_name[0] = '\0';
+					pri->pvts[chanpos]->cid_ton = 0;
+				}
+				apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
+							 e->ring.redirectingnum, e->ring.callingplanrdnis);
+
+				/* Set DNID on all incoming calls -- even immediate */
+				ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
+
+				/* If immediate=yes go to s|1 */
+				if (pri->pvts[chanpos]->immediate) {
+					if (option_verbose > 2)
+						ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
+					pri->pvts[chanpos]->exten[0] = 's';
+					pri->pvts[chanpos]->exten[1] = '\0';
+				}
+				/* Get called number */
+				else if (!ast_strlen_zero(e->ring.callednum)) {
+					ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
+				} else if (pri->overlapdial)
+					pri->pvts[chanpos]->exten[0] = '\0';
+				else {
+					/* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
+					pri->pvts[chanpos]->exten[0] = 's';
+					pri->pvts[chanpos]->exten[1] = '\0';
+				}
+				/* No number yet, but received "sending complete"? */
+				if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
+					if (option_verbose > 2)
+						ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
+					pri->pvts[chanpos]->exten[0] = 's';
+					pri->pvts[chanpos]->exten[1] = '\0';
+				}
+
+				/* Make sure extension exists (or in overlap dial mode, can exist) */
+				if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
+					ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
+					/* Setup law */
+					int law;
+					if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
+						/* Set to audio mode at this point */
+						law = 1;
+						if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
+							ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
+					}
+					if (e->ring.layer1 == PRI_LAYER_1_ALAW)
+						law = DAHDI_LAW_ALAW;
+					else
+						law = DAHDI_LAW_MULAW;
+					res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
+					if (res < 0) 
+						ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
+					res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
+					if (res < 0)
+						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]->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 {
+						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;
+				
+					/* Start PBX */
+					if (!e->ring.complete
+						&& (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
+						&& ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
+						/*
+						 * Release the PRI lock while we create the channel so other
+						 * threads can send D channel messages.  We must also release
+						 * the private lock to prevent deadlock while creating the
+						 * channel.
+						 */
+						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+						ast_mutex_unlock(&pri->lock);
+						if (crv) {
+							/* Set bearer and such */
+							pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
+							c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
+							pri->pvts[chanpos]->owner = &inuse;
+							ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
 						} else {
-							/* This is where we handle initial glare */
-							ast_log(LOG_DEBUG, "Ring requested on channel %d/%d already in use or previously requested on span %d.  Attempting to renegotiating channel.\n", 
-							PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
-							ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-							chanpos = -1;
+							c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
+						}
+						ast_mutex_lock(&pri->lock);
+						ast_mutex_lock(&pri->pvts[chanpos]->lock);
+						if (c) {
+							if (!ast_strlen_zero(e->ring.callingsubaddr)) {
+								pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
+							}
+							if (e->ring.ani2 >= 0) {
+								snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
+								pbx_builtin_setvar_helper(c, "ANI2", ani2str);
+							}
+
+#ifdef SUPPORT_USERUSER
+							if (!ast_strlen_zero(e->ring.useruserinfo)) {
+								pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
+							}
+#endif
+
+							snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
+							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. */
+								pri_progress(pri->pri, e->ring.call,
+									PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
+							}
+						}
+
+						pthread_attr_init(&attr);
+						pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+						if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
+							if (option_verbose > 2)
+								ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
+									plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
+									pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
+						} else {
+							ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
+								pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
+							if (c) {
+								/* Avoid deadlock while destroying channel */
+								ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+								ast_mutex_unlock(&pri->lock);
+								ast_hangup(c);
+								ast_mutex_lock(&pri->lock);
+								ast_mutex_lock(&pri->pvts[chanpos]->lock);
+							} else {
+								pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
+								pri->pvts[chanpos]->call = NULL;
+							}
+						}
+						pthread_attr_destroy(&attr);
+					} else {
+						/*
+						 * Release the PRI lock while we create the channel so other
+						 * threads can send D channel messages.  We must also release
+						 * the private lock to prevent deadlock while creating the
+						 * channel.
+						 */
+						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+						ast_mutex_unlock(&pri->lock);
+						c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
+						ast_mutex_lock(&pri->lock);
+						ast_mutex_lock(&pri->pvts[chanpos]->lock);
+						if (c) {
+							/*
+							 * It is reasonably safe to set the following
+							 * channel variables while the PRI and DAHDI private
+							 * structures are locked.  The PBX has not been
+							 * started yet and it is unlikely that any other task
+							 * will do anything with the channel we have just
+							 * created.
+							 */
+							if (!ast_strlen_zero(e->ring.callingsubaddr)) {
+								pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
+							}
+							if (e->ring.ani2 >= 0) {
+								snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
+								pbx_builtin_setvar_helper(c, "ANI2", ani2str);
+							}
+
+#ifdef SUPPORT_USERUSER
+							if (!ast_strlen_zero(e->ring.useruserinfo)) {
+								pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
+							}
+#endif
+
+							if (e->ring.redirectingreason >= 0)
+								pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
+
+							snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
+							pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
+						}
+						if (c && !ast_pbx_start(c)) {
+							if (option_verbose > 2)
+								ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
+									plancallingnum, pri->pvts[chanpos]->exten,
+									pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
+
+							dahdi_enable_ec(pri->pvts[chanpos]);
+						} else {
+							ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
+								pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
+							if (c) {
+								/* Avoid deadlock while destroying channel */
+								ast_mutex_unlock(&pri->pvts[chanpos]->lock);
+								ast_mutex_unlock(&pri->lock);
+								ast_hangup(c);
+								ast_mutex_lock(&pri->lock);
+								ast_mutex_lock(&pri->pvts[chanpos]->lock);
+							} else {
+								pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
+								pri->pvts[chanpos]->call = NULL;
+							}
 						}
 					}
-					if (chanpos > -1)
-						ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-				}
-				if ((chanpos < 0) && (e->ring.flexible))
-					chanpos = pri_find_empty_chan(pri, 1);
-				if (chanpos > -1) {
-					ast_mutex_lock(&pri->pvts[chanpos]->lock);
-					if (pri->switchtype == PRI_SWITCH_GR303_TMC) {
-						/* Should be safe to lock CRV AFAIK while bearer is still locked */
-						crv = pri_find_crv(pri, pri_get_crv(pri->pri, e->ring.call, NULL));
-						if (crv)
-							ast_mutex_lock(&crv->lock);
-						if (!crv || crv->owner) {
-							pri->pvts[chanpos]->call = NULL;
-							if (crv) {
-								if (crv->owner)
-									crv->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-								ast_log(LOG_WARNING, "Call received for busy CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
-							} else
-								ast_log(LOG_NOTICE, "Call received for unconfigured CRV %d on span %d\n", pri_get_crv(pri->pri, e->ring.call, NULL), pri->span);
-							pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_INVALID_CALL_REFERENCE);
-							if (crv)
-								ast_mutex_unlock(&crv->lock);
-							ast_mutex_unlock(&pri->pvts[chanpos]->lock);
-							break;
-						}
-					}
-					pri->pvts[chanpos]->call = e->ring.call;
-					apply_plan_to_number(plancallingnum, sizeof(plancallingnum), pri, e->ring.callingnum, e->ring.callingplan);
-					if (pri->pvts[chanpos]->use_callerid) {
-						ast_shrink_phone_number(plancallingnum);
-						ast_copy_string(pri->pvts[chanpos]->cid_num, plancallingnum, sizeof(pri->pvts[chanpos]->cid_num));
-#ifdef PRI_ANI
-						if (!ast_strlen_zero(e->ring.callingani)) {
-							apply_plan_to_number(plancallingani, sizeof(plancallingani), pri, e->ring.callingani, e->ring.callingplanani);
-							ast_shrink_phone_number(plancallingani);
-							ast_copy_string(pri->pvts[chanpos]->cid_ani, plancallingani, sizeof(pri->pvts[chanpos]->cid_ani));
-						} else {
-							pri->pvts[chanpos]->cid_ani[0] = '\0';
-						}
-#endif
-						ast_copy_string(pri->pvts[chanpos]->cid_name, e->ring.callingname, sizeof(pri->pvts[chanpos]->cid_name));
-						pri->pvts[chanpos]->cid_ton = e->ring.callingplan; /* this is the callingplan (TON/NPI), e->ring.callingplan>>4 would be the TON */
-					} else {
-						pri->pvts[chanpos]->cid_num[0] = '\0';
-						pri->pvts[chanpos]->cid_ani[0] = '\0';
-						pri->pvts[chanpos]->cid_name[0] = '\0';
-						pri->pvts[chanpos]->cid_ton = 0;
-					}
-					apply_plan_to_number(pri->pvts[chanpos]->rdnis, sizeof(pri->pvts[chanpos]->rdnis), pri,
-							     e->ring.redirectingnum, e->ring.callingplanrdnis);
-
-					/* Set DNID on all incoming calls -- even immediate */
-					ast_copy_string(pri->pvts[chanpos]->dnid, e->ring.callednum, sizeof(pri->pvts[chanpos]->dnid));
-
-					/* If immediate=yes go to s|1 */
-					if (pri->pvts[chanpos]->immediate) {
-						if (option_verbose > 2)
-							ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of immediate=yes\n");
-						pri->pvts[chanpos]->exten[0] = 's';
-						pri->pvts[chanpos]->exten[1] = '\0';
-					}
-					/* Get called number */
-					else if (!ast_strlen_zero(e->ring.callednum)) {
-						ast_copy_string(pri->pvts[chanpos]->exten, e->ring.callednum, sizeof(pri->pvts[chanpos]->exten));
-					} else if (pri->overlapdial)
-						pri->pvts[chanpos]->exten[0] = '\0';
-					else {
-						/* Some PRI circuits are set up to send _no_ digits.  Handle them as 's'. */
-						pri->pvts[chanpos]->exten[0] = 's';
-						pri->pvts[chanpos]->exten[1] = '\0';
-					}
-					/* No number yet, but received "sending complete"? */
-					if (e->ring.complete && (ast_strlen_zero(e->ring.callednum))) {
-						if (option_verbose > 2)
-							ast_verbose(VERBOSE_PREFIX_3 "Going to extension s|1 because of Complete received\n");
-						pri->pvts[chanpos]->exten[0] = 's';
-						pri->pvts[chanpos]->exten[1] = '\0';
-					}
-
-					/* Make sure extension exists (or in overlap dial mode, can exist) */
-					if (((pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
-						ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
-						/* Setup law */
-						int law;
-						if (pri->switchtype != PRI_SWITCH_GR303_TMC) {
-							/* Set to audio mode at this point */
-							law = 1;
-							if (ioctl(pri->pvts[chanpos]->subs[SUB_REAL].dfd, DAHDI_AUDIOMODE, &law) == -1)
-								ast_log(LOG_WARNING, "Unable to set audio mode on channel %d to %d: %s\n", pri->pvts[chanpos]->channel, law, strerror(errno));
-						}
-						if (e->ring.layer1 == PRI_LAYER_1_ALAW)
-							law = DAHDI_LAW_ALAW;
-						else
-							law = DAHDI_LAW_MULAW;
-						res = dahdi_setlaw(pri->pvts[chanpos]->subs[SUB_REAL].dfd, law);
-						if (res < 0) 
-							ast_log(LOG_WARNING, "Unable to set law on channel %d\n", pri->pvts[chanpos]->channel);
-						res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].dfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
-						if (res < 0)
-							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]->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 {
-							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;
-					
-						/* Start PBX */
-						if (!e->ring.complete
-							&& (pri->overlapdial & DAHDI_OVERLAPDIAL_INCOMING)
-							&& ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
-							/*
-							 * Release the PRI lock while we create the channel
-							 * so other threads can send D channel messages.
-							 */
-							ast_mutex_unlock(&pri->lock);
-							if (crv) {
-								/* Set bearer and such */
-								pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
-								c = dahdi_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
-								pri->pvts[chanpos]->owner = &inuse;
-								ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
-							} else {
-								c = dahdi_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
-							}
-							ast_mutex_lock(&pri->lock);
-							if (c) {
-								if (!ast_strlen_zero(e->ring.callingsubaddr)) {
-									pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
-								}
-								if (e->ring.ani2 >= 0) {
-									snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
-									pbx_builtin_setvar_helper(c, "ANI2", ani2str);
-								}
-
-#ifdef SUPPORT_USERUSER
-								if (!ast_strlen_zero(e->ring.useruserinfo)) {
-									pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
-								}
-#endif
-
-								snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
-								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. */
-									pri_progress(pri->pri, e->ring.call,
-										PVT_TO_CHANNEL(pri->pvts[chanpos]), 1);
-								}
-							}
-
-							pthread_attr_init(&attr);
-							pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-							if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
-								if (option_verbose > 2)
-									ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
-										plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
-										pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
-							} else {
-								ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
-									pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
-								if (c)
-									ast_hangup(c);
-								else {
-									pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
-									pri->pvts[chanpos]->call = NULL;
-								}
-							}
-							pthread_attr_destroy(&attr);
-						} else {
-							/*
-							 * Release the PRI lock while we create the channel
-							 * so other threads can send D channel messages.
-							 */
-							ast_mutex_unlock(&pri->lock);
-							c = dahdi_new(pri->pvts[chanpos], AST_STATE_RING, 0, SUB_REAL, law, e->ring.ctype);
-							ast_mutex_lock(&pri->lock);
-							if (c) {
-								/*
-								 * It is reasonably safe to set the following
-								 * channel variables while the PRI and DAHDI private
-								 * structures are locked.  The PBX has not been
-								 * started yet and it is unlikely that any other task
-								 * will do anything with the channel we have just
-								 * created.
-								 */
-								if (!ast_strlen_zero(e->ring.callingsubaddr)) {
-									pbx_builtin_setvar_helper(c, "CALLINGSUBADDR", e->ring.callingsubaddr);
-								}
-								if (e->ring.ani2 >= 0) {
-									snprintf(ani2str, sizeof(ani2str), "%d", e->ring.ani2);
-									pbx_builtin_setvar_helper(c, "ANI2", ani2str);
-								}
-
-#ifdef SUPPORT_USERUSER
-								if (!ast_strlen_zero(e->ring.useruserinfo)) {
-									pbx_builtin_setvar_helper(c, "USERUSERINFO", e->ring.useruserinfo);
-								}
-#endif
-
-								if (e->ring.redirectingreason >= 0)
-									pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
-
-								snprintf(calledtonstr, sizeof(calledtonstr), "%d", e->ring.calledplan);
-								pbx_builtin_setvar_helper(c, "CALLEDTON", calledtonstr);
-							}
-							if (c && !ast_pbx_start(c)) {
-								if (option_verbose > 2)
-									ast_verbose(VERBOSE_PREFIX_3 "Accepting call from '%s' to '%s' on channel %d/%d, span %d\n",
-										plancallingnum, pri->pvts[chanpos]->exten,
-										pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
-
-								dahdi_enable_ec(pri->pvts[chanpos]);
-							} else {
-								ast_log(LOG_WARNING, "Unable to start PBX on channel %d/%d, span %d\n",
-									pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
-								if (c) {
-									ast_hangup(c);
-								} else {
-									pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_SWITCH_CONGESTION);
-									pri->pvts[chanpos]->call = NULL;
-								}
-							}
-						}
-					} else {
-						if (option_verbose > 2)
-							ast_verbose(VERBOSE_PREFIX_3 "Extension '%s' in context '%s' from '%s' does not exist.  Rejecting call on channel %d/%d, span %d\n",
-								pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context, pri->pvts[chanpos]->cid_num, pri->pvts[chanpos]->logicalspan, 
-									pri->pvts[chanpos]->prioffset, pri->span);
-						pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
-						pri->pvts[chanpos]->call = NULL;
-						pri->pvts[chanpos]->exten[0] = '\0';
-					}
-					if (crv)
-						ast_mutex_unlock(&crv->lock);
-					ast_mutex_unlock(&pri->pvts[chanpos]->lock);
 				} else {
-					if (e->ring.flexible)
-						pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
-					else
-						pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
-				}
+					if (option_verbose > 2)
+						ast_verbose(VERBOSE_PREFIX_3 "Span %d: Extension %s@%s does not exist.  Rejecting call from '%s'.\n",
+							pri->span, pri->pvts[chanpos]->exten, pri->pvts[chanpos]->context,
+							pri->pvts[chanpos]->cid_num);
+					pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_UNALLOCATED);
+					pri->pvts[chanpos]->call = NULL;
+					pri->pvts[chanpos]->exten[0] = '\0';
+				}
+				if (crv)
+					ast_mutex_unlock(&crv->lock);
+				ast_mutex_unlock(&pri->pvts[chanpos]->lock);
 				break;
 			case PRI_EVENT_RINGING:
 				chanpos = pri_find_fixup_principle(pri, e->ringing.channel,
@@ -10555,11 +10740,19 @@
 							}
 							break;
 						}
+					} 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;
 					}
 					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 {
+					/* Continue hanging up the call. */
 					pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
 					pri->pvts[chanpos]->call = NULL;
 				}
@@ -10643,6 +10836,10 @@
 							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 {
+					/*
+					 * 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;
 				}




More information about the svn-commits mailing list