[svn-commits] rmudgett: branch 1.4 r2207 - /branches/1.4/q931.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Feb 17 15:12:09 CST 2011


Author: rmudgett
Date: Thu Feb 17 15:12:04 2011
New Revision: 2207

URL: http://svnview.digium.com/svn/libpri?view=rev&rev=2207
Log:
B channel lost by incoming call in BRI NT PTMP mode.

A phone's RELEASE_COMPLETE as a response to an initial broadcast SETUP
blocks one B channel permantly when the call is cancelled.

Scenario: A call to the ISDN Bus is acknowledged (ALERTING) by one
phone/endpoint and rejected by another phone/endpoint with a
RELEASE_COMPLETE.  The call is then cancelled by the caller.  If the whole
procedure is repeated once again then any further call attempt is rejected
(WARNING[5666]: app_dial.c:1546 dial_exec_full: Unable to create channel
of type 'DAHDI' (cause 34 - Circuit/channel congestion)).  It seems that
receiving a RELEASE_COMPLETE in that state blocks one B channel
permanently when the call is cancelled by the caller.

Background: The ISDN phones (Siemens Gigaset 3035 or CX253) we use for
testing additionally contain a DECT base station, which operates as a
different endpoint on the ISDN Bus (TEI).  If the DECT base station is not
in use then there are no DECT phones registered to the base station.  The
DECT base station responds to an incoming call not directed toward it with
(RELEASE_COMPLETE, cause: no user responding).

* Made initiate_hangup_if_needed() also hangup the subcall if it is in the
NULL state.

* Simplified q931_set_subcall_winner().

JIRA ABE-2745
JIRA SWP-2954

Modified:
    branches/1.4/q931.c

Modified: branches/1.4/q931.c
URL: http://svnview.digium.com/svn/libpri/branches/1.4/q931.c?view=diff&rev=2207&r1=2206&r2=2207
==============================================================================
--- branches/1.4/q931.c (original)
+++ branches/1.4/q931.c Thu Feb 17 15:12:04 2011
@@ -6597,7 +6597,7 @@
 	return 0;
 }
 
-static void initiate_hangup_if_needed(struct pri *pri, q931_call *call, int cause);
+static void initiate_hangup_if_needed(struct pri *ctrl, struct q931_call *subcall, int cause);
 
 int q931_hangup(struct pri *ctrl, q931_call *call, int cause)
 {
@@ -6614,7 +6614,7 @@
 					if (i == call->master_call->pri_winner) {
 						__q931_hangup(call->subcalls[i]->pri, call->subcalls[i], cause);
 					} else {
-						initiate_hangup_if_needed(call->subcalls[i]->pri, call->subcalls[i], cause);
+						initiate_hangup_if_needed(ctrl, call->subcalls[i], cause);
 					}
 					if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
 						pri_message(ctrl, "%s: Hanging up %d, winner %d\n", __FUNCTION__,
@@ -6850,11 +6850,29 @@
 	}
 }
 
-static void initiate_hangup_if_needed(struct pri *pri, q931_call *call, int cause)
-{
-	if (!call->hangupinitiated) {
-		q931_hangup(pri, call, cause);
-		call->alive = 0;
+static void initiate_hangup_if_needed(struct pri *ctrl, struct q931_call *subcall, int cause)
+{
+	if (!subcall->hangupinitiated) {
+		q931_hangup(ctrl, subcall, cause);
+		subcall->alive = 0;
+	} else {
+		switch (subcall->ourcallstate) {
+		case Q931_CALL_STATE_NULL:
+			switch (subcall->peercallstate) {
+			case Q931_CALL_STATE_NULL:
+				/*
+				 * Complete the hangup of the dead subcall.  Noone else will at
+				 * this point.
+				 */
+				q931_hangup(ctrl, subcall, cause);
+				break;
+			default:
+				break;
+			}
+			break;
+		default:
+			break;
+		}
 	}
 }
 
@@ -6880,20 +6898,21 @@
 	int i;
 
 	/* Set the winner first */
-	for (i = 0; i < ARRAY_LEN(realcall->subcalls); ++i) {
-		if (realcall->subcalls[i] && realcall->subcalls[i] == subcall) {
+	for (i = 0; ; ++i) {
+		if (ARRAY_LEN(realcall->subcalls) <= i) {
+			pri_error(subcall->pri, "We should always find the winner in the list!\n");
+			return;
+		}
+		if (realcall->subcalls[i] == subcall) {
 			realcall->pri_winner = i;
-		}
-	}
-	if (realcall->pri_winner < 0) {
-		pri_error(subcall->pri, "We should always find the winner in the list!\n");
-		return;
+			break;
+		}
 	}
 
 	/* Start tear down of calls that were not chosen */
 	for (i = 0; i < ARRAY_LEN(realcall->subcalls); ++i) {
 		if (realcall->subcalls[i] && realcall->subcalls[i] != subcall) {
-			initiate_hangup_if_needed(realcall->subcalls[i]->pri, realcall->subcalls[i],
+			initiate_hangup_if_needed(realcall->pri, realcall->subcalls[i],
 				PRI_CAUSE_NONSELECTED_USER_CLEARING);
 		}
 	}




More information about the svn-commits mailing list