[svn-commits] rmudgett: branch rmudgett/t312 r2219 - /team/rmudgett/t312/q931.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri Feb 25 14:24:49 CST 2011


Author: rmudgett
Date: Fri Feb 25 14:24:45 2011
New Revision: 2219

URL: http://svnview.digium.com/svn/libpri?view=rev&rev=2219
Log:
Reworked T312 to better isolate the master call state machine.

Modified:
    team/rmudgett/t312/q931.c

Modified: team/rmudgett/t312/q931.c
URL: http://svnview.digium.com/svn/libpri/team/rmudgett/t312/q931.c?view=diff&rev=2219&r1=2218&r2=2219
==============================================================================
--- team/rmudgett/t312/q931.c (original)
+++ team/rmudgett/t312/q931.c Fri Feb 25 14:24:45 2011
@@ -4209,7 +4209,19 @@
 	free(cur);
 }
 
-static void pri_create_fake_clearing(struct pri *ctrl, struct q931_call *master);
+int q931_get_subcall_count(struct q931_call *master)
+{
+	int count = 0;
+	int idx;
+
+	for (idx = 0; idx < ARRAY_LEN(master->subcalls); ++idx) {
+		if (master->subcalls[idx]) {
+			++count;
+		}
+	}
+
+	return count;
+}
 
 static void t312_expiry(void *data)
 {
@@ -4224,8 +4236,13 @@
 	master->t312_timer = 0;
 	switch (master->ourcallstate) {
 	case Q931_CALL_STATE_CALL_ABORT:
-		/* The upper layer has already disconnected. */
-		q931_destroycall(master->pri, master);
+		if (!q931_get_subcall_count(master)) {
+			/*
+			 * T312 has expired and no slaves are left so we can
+			 * destroy the master.
+			 */
+			q931_destroycall(ctrl, master);
+		}
 		break;
 	default:
 		break;
@@ -4261,6 +4278,10 @@
 			master->subcalls[idx], master, idx);
 	}
 	cleanup_and_free_call(master->subcalls[idx]);
+	if (master->pri_winner == idx) {
+		/* This was the winning subcall. */
+		master->pri_winner = -1;
+	}
 	master->subcalls[idx] = NULL;
 }
 
@@ -4311,21 +4332,7 @@
 					return;
 				}
 
-				if (cur->pri_winner < 0) {
-					/*
-					 * Let the upper layer know about the call clearing.
-					 * The master will get destroyed as a result.
-					 */
-					UPDATE_OURCALLSTATE(ctrl, cur, Q931_CALL_STATE_NULL);
-					cur->peercallstate = Q931_CALL_STATE_NULL;
-					pri_create_fake_clearing(ctrl, cur);
-					return;
-				}
 				/* No slaves left.  We can safely destroy the master. */
-				if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
-					pri_message(ctrl,
-						"Since we already had a winner, we should be able to destroy the master.\n");
-				}
 			} else {
 				/* Destroy any slaves that may be present as well. */
 				for (i = 0; i < ARRAY_LEN(cur->subcalls); ++i) {
@@ -5714,7 +5721,34 @@
 		call);
 }
 
-static void pri_fake_clearing(void *data);
+static int pri_internal_clear(struct q931_call *c);
+
+/* Fake RELEASE for NT-PTMP initiated SETUPs w/o response */
+static void pri_fake_clearing(void *data)
+{
+	struct q931_call *c = data;/* Call is not a subcall call record. */
+	struct pri *ctrl;
+
+	ctrl = c->pri;
+	if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
+		pri_message(ctrl, "Fake clearing.  cref:%d\n", c->cr);
+	}
+	/*
+	 * We cannot clear the retranstimer id because we are called by t303_expiry also.
+	 * Fortunately, it doesn't matter because pri_internal_clear() will stop it if
+	 * it was actually running.
+	 */
+	//c->retranstimer = 0;
+	if (pri_internal_clear(c) == Q931_RES_HAVEEVENT) {
+		ctrl->schedev = 1;
+	}
+}
+
+static void pri_create_fake_clearing(struct pri *ctrl, struct q931_call *master)
+{
+	pri_schedule_del(ctrl, master->retranstimer);
+	master->retranstimer = pri_schedule_event(ctrl, 0, pri_fake_clearing, master);
+}
 
 static void t303_expiry(void *data)
 {
@@ -5768,6 +5802,11 @@
 			start_t312(c);
 		}
 	} else {
+		/*
+		 * We never got any response for a normal call or an
+		 * establishment response from any TEI for a master/subcall
+		 * call.
+		 */
 		c->cause = PRI_CAUSE_NO_USER_RESPONSE;
 		if (c->outboundbroadcast) {
 			UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_CALL_ABORT);
@@ -6431,58 +6470,22 @@
 	return q931_send_retrieve_rej_msg(ctrl, winner, cause);
 }
 
-static int pri_internal_clear(struct q931_call *c);
-
-/* Fake RELEASE for NT-PTMP initiated SETUPs w/o response */
-static void pri_fake_clearing(void *data)
-{
-	struct q931_call *c = data;/* Call is not a subcall call record. */
-
-	/*
-	 * We cannot clear the retranstimer id because we are called by t303_expiry also.
-	 * Fortunately, it doesn't matter because pri_internal_clear() will stop it if
-	 * it was actually running.
-	 */
-	//c->retranstimer = 0;
-	if (pri_internal_clear(c) == Q931_RES_HAVEEVENT) {
-		c->pri->schedev = 1;
-	}
-}
-
-static void pri_create_fake_clearing(struct pri *ctrl, struct q931_call *master)
-{
-	pri_schedule_del(ctrl, master->retranstimer);
-	master->retranstimer = pri_schedule_event(ctrl, 0, pri_fake_clearing, master);
-}
-
-int q931_get_subcall_count(struct q931_call *master)
-{
-	int count = 0;
-	int idx;
-
-	for (idx = 0; idx < ARRAY_LEN(master->subcalls); ++idx) {
-		if (master->subcalls[idx]) {
-			++count;
-		}
-	}
-
-	return count;
-}
-
 static int __q931_hangup(struct pri *ctrl, q931_call *c, int cause)
 {
 	int disconnect = 1;
 	int release_compl = 0;
-	int t303_was_running = c->master_call->t303_timer;
-
-	if (ctrl->debug & PRI_DEBUG_Q931_STATE)
+
+	if (!ctrl || !c) {
+		return -1;
+	}
+	if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
 		pri_message(ctrl,
 			DBGHEAD "ourstate %s, peerstate %s, hold-state %s\n", DBGINFO,
 			q931_call_state_str(c->ourcallstate),
 			q931_call_state_str(c->peercallstate),
 			q931_hold_state_str(c->master_call->hold_state));
-	if (!ctrl || !c)
-		return -1;
+	}
+
 	/* If mandatory IE was missing, insist upon that cause code */
 	if (c->cause == PRI_CAUSE_MANDATORY_IE_MISSING)
 		cause = c->cause;
@@ -6557,18 +6560,6 @@
 			q931_release_complete(ctrl,c,cause);
 		break;
 	case Q931_CALL_STATE_CALL_INITIATED:
-		if (c->outboundbroadcast && c->master_call == c && t303_was_running) {
-			//c->fakeclearing = 1;
-			//c->alive = 0;
-			/* We need to fake a received clearing sequence in this case... */
-			if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
-				pri_message(ctrl, "Faking clearing\n");
-			}
-			UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_CALL_ABORT);
-			pri_create_fake_clearing(ctrl, c);
-			/* This means that we never got a response from a TEI */
-			return 0;
-		}
 		/* we sent SETUP */
 	case Q931_CALL_STATE_OVERLAP_SENDING:
 		/* received SETUP_ACKNOWLEDGE */
@@ -6673,6 +6664,15 @@
 				pri_message(ctrl, DBGHEAD "Hangup master cref:%d\n", DBGINFO, call->cr);
 			}
 
+			UPDATE_OURCALLSTATE(ctrl, call, Q931_CALL_STATE_CALL_ABORT);
+			if (call->pri_winner < 0 && call->alive) {
+				/*
+				 * Fake clearing if we have no winner to get rid of the upper
+				 * layer.
+				 */
+				pri_create_fake_clearing(ctrl, call);
+			}
+
 			/* Initiate hangup of slaves */
 			call->master_hanging_up = 1;
 			for (i = 0; i < ARRAY_LEN(call->subcalls); ++i) {
@@ -6695,15 +6695,12 @@
 				pri_message(ctrl, DBGHEAD "Remaining slaves %d\n", DBGINFO, slaves);
 			}
 
-/* BUGBUG T312 active, winning subcall exists, master call state rank */
-			if (call->t303_timer) {
-				/* Abort master call. */
-				__q931_hangup(ctrl, call, cause);
-			} else if (call->t312_timer || slaves) {
-				/* Make sure that the master call is aborting. */
-				UPDATE_OURCALLSTATE(ctrl, call, Q931_CALL_STATE_CALL_ABORT);
-			} else {
-				/* No slaves left so we can safely destroy the master. */
+			stop_t303(call);
+			if (!call->t312_timer && !slaves) {
+				/*
+				 * T312 has expired and no slaves are left so we can safely
+				 * destroy the master.
+				 */
 				q931_destroycall(ctrl, call);
 			}
 			return 0;
@@ -7519,7 +7516,6 @@
 	struct q931_call *winner = q931_get_subcall_winner(master);
 	enum Q931_RANKED_CALL_STATE master_rank;
 	enum Q931_RANKED_CALL_STATE subcall_rank;
-	enum Q931_CALL_STATE newstate;
 
 	/* For broadcast calls, we default to not allowing events to keep events received to a minimum
 	 * and to allow post processing, since that is where hangup and subcall state handling and other processing is done */
@@ -7573,12 +7569,8 @@
 		}
 		break;
 	case Q931_DISCONNECT:
-		newstate = Q931_CALL_STATE_DISCONNECT_INDICATION;
-		goto process_hangup;
 	case Q931_RELEASE:
 	case Q931_RELEASE_COMPLETE:
-		newstate = Q931_CALL_STATE_NULL;
-process_hangup:
 		if (!winner) {
 			int master_priority;
 			int slave_priority;
@@ -7623,9 +7615,7 @@
 			if (subcall == winner) {
 				/* .. and we're it: */
 				*allow_event = 1;
-				if (master_rank != Q931_RANKED_CALL_STATE_ABORT) {
-					UPDATE_OURCALLSTATE(ctrl, master, newstate);
-				}
+				UPDATE_OURCALLSTATE(ctrl, master, Q931_CALL_STATE_CALL_ABORT);
 			}
 		}
 		break;
@@ -8085,8 +8075,6 @@
 	struct q931_call *master;
 	int cause;
 
-/* BUGBUG more conditions are needed to correctly determine which cause to use. */
-/* BUGBUG T312 active, winning subcall exists, master call state rank */
 	cause = PRI_CAUSE_INVALID_CALL_REFERENCE;
 	master = call->master_call;
 	if (master != call && master->t312_timer) {




More information about the svn-commits mailing list