[svn-commits] rmudgett: branch 1.4 r2170 - in /branches/1.4: pri_internal.h q931.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Mon Dec 20 23:12:15 UTC 2010


Author: rmudgett
Date: Mon Dec 20 17:12:10 2010
New Revision: 2170

URL: http://svnview.digium.com/svn/libpri?view=rev&rev=2170
Log:
Better HOLD/RETRIEVE collision handling.

The upper layer is now initiating HOLD/RETRIEVE signaling.  These changes
are needed to help preserve the correct channel id after a collision.

Modified:
    branches/1.4/pri_internal.h
    branches/1.4/q931.c

Modified: branches/1.4/pri_internal.h
URL: http://svnview.digium.com/svn/libpri/branches/1.4/pri_internal.h?view=diff&rev=2170&r1=2169&r2=2170
==============================================================================
--- branches/1.4/pri_internal.h (original)
+++ branches/1.4/pri_internal.h Mon Dec 20 17:12:10 2010
@@ -532,9 +532,9 @@
 
 	/*! \brief Incoming call transfer state. */
 	enum INCOMING_CT_STATE incoming_ct_state;
-	/*! Call hold supplementary state. */
+	/*! Call hold supplementary state.  Valid on master call record only. */
 	enum Q931_HOLD_STATE hold_state;
-	/*! Call hold event timer */
+	/*! Call hold event timer.  Valid on master call record only. */
 	int hold_timer;
 
 	int deflection_in_progress;	/*!< CallDeflection for NT PTMP in progress. */

Modified: branches/1.4/q931.c
URL: http://svnview.digium.com/svn/libpri/branches/1.4/q931.c?view=diff&rev=2170&r1=2169&r2=2170
==============================================================================
--- branches/1.4/q931.c (original)
+++ branches/1.4/q931.c Mon Dec 20 17:12:10 2010
@@ -5572,6 +5572,7 @@
 static void q931_hold_timeout(void *data)
 {
 	struct q931_call *call = data;
+	struct q931_call *master = call->master_call;
 	struct pri *ctrl = call->pri;
 
 	if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
@@ -5579,16 +5580,23 @@
 	}
 
 	/* Ensure that the timer is deleted. */
-	pri_schedule_del(ctrl, call->hold_timer);
-	call->hold_timer = 0;
-
-	UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_IDLE);
+	pri_schedule_del(ctrl, master->hold_timer);
+	master->hold_timer = 0;
+
+	/* Don't change the hold state if there was HOLD a collision. */
+	switch (master->hold_state) {
+	case Q931_HOLD_STATE_HOLD_REQ:
+		UPDATE_HOLD_STATE(ctrl, master, Q931_HOLD_STATE_IDLE);
+		break;
+	default:
+		break;
+	}
 
 	q931_clr_subcommands(ctrl);
 	ctrl->schedev = 1;
 	ctrl->ev.e = PRI_EVENT_HOLD_REJ;
 	ctrl->ev.hold_rej.channel = q931_encode_channel(call);
-	ctrl->ev.hold_rej.call = call;
+	ctrl->ev.hold_rej.call = master;
 	ctrl->ev.hold_rej.cause = PRI_CAUSE_MESSAGE_TYPE_NONEXIST;
 	ctrl->ev.hold_rej.subcmds = &ctrl->subcmds;
 }
@@ -5662,8 +5670,8 @@
 	}
 	pri_schedule_del(ctrl, call->hold_timer);
 	call->hold_timer = pri_schedule_event(ctrl, ctrl->timers[PRI_TIMER_T_HOLD],
-		q931_hold_timeout, call);
-	if (send_message(ctrl, winner, Q931_HOLD, hold_ies)) {
+		q931_hold_timeout, winner);
+	if (!call->hold_timer || send_message(ctrl, winner, Q931_HOLD, hold_ies)) {
 		pri_schedule_del(ctrl, call->hold_timer);
 		call->hold_timer = 0;
 		return -1;
@@ -5764,33 +5772,38 @@
 static void q931_retrieve_timeout(void *data)
 {
 	struct q931_call *call = data;
+	struct q931_call *master = call->master_call;
 	struct pri *ctrl = call->pri;
-	struct q931_call *winner;
 
 	if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
 		pri_message(ctrl, "Time-out waiting for RETRIEVE response\n");
 	}
 
 	/* Ensure that the timer is deleted. */
-	pri_schedule_del(ctrl, call->hold_timer);
-	call->hold_timer = 0;
-
-	UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_CALL_HELD);
-
-	winner = q931_find_winning_call(call);
-	if (winner) {
+	pri_schedule_del(ctrl, master->hold_timer);
+	master->hold_timer = 0;
+
+	/* Don't change the hold state if there was RETRIEVE a collision. */
+	switch (master->hold_state) {
+	case Q931_HOLD_STATE_CALL_HELD:
+	case Q931_HOLD_STATE_RETRIEVE_REQ:
+		UPDATE_HOLD_STATE(ctrl, master, Q931_HOLD_STATE_CALL_HELD);
+
 		/* Call is still on hold so forget the channel. */
-		winner->channelno = 0;/* No channel */
-		winner->ds1no = 0;
-		winner->ds1explicit = 0;
-		winner->chanflags = 0;
+		call->channelno = 0;/* No channel */
+		call->ds1no = 0;
+		call->ds1explicit = 0;
+		call->chanflags = 0;
+		break;
+	default:
+		break;
 	}
 
 	q931_clr_subcommands(ctrl);
 	ctrl->schedev = 1;
 	ctrl->ev.e = PRI_EVENT_RETRIEVE_REJ;
 	ctrl->ev.retrieve_rej.channel = q931_encode_channel(call);
-	ctrl->ev.retrieve_rej.call = call;
+	ctrl->ev.retrieve_rej.call = master;
 	ctrl->ev.retrieve_rej.cause = PRI_CAUSE_MESSAGE_TYPE_NONEXIST;
 	ctrl->ev.retrieve_rej.subcmds = &ctrl->subcmds;
 }
@@ -5869,7 +5882,7 @@
 		winner->ds1no = (channel & 0xff00) >> 8;
 		winner->ds1explicit = (channel & 0x10000) >> 16;
 		winner->channelno = channel & 0xff;
-		if (ctrl->localtype == PRI_NETWORK) {
+		if (ctrl->localtype == PRI_NETWORK && winner->channelno != 0xFF) {
 			winner->chanflags = FLAG_EXCLUSIVE;
 		} else {
 			winner->chanflags = FLAG_PREFERRED;
@@ -5881,8 +5894,8 @@
 
 	pri_schedule_del(ctrl, call->hold_timer);
 	call->hold_timer = pri_schedule_event(ctrl, ctrl->timers[PRI_TIMER_T_RETRIEVE],
-		q931_retrieve_timeout, call);
-	if (send_message(ctrl, winner, Q931_RETRIEVE, retrieve_ies)) {
+		q931_retrieve_timeout, winner);
+	if (!call->hold_timer || send_message(ctrl, winner, Q931_RETRIEVE, retrieve_ies)) {
 		pri_schedule_del(ctrl, call->hold_timer);
 		call->hold_timer = 0;
 
@@ -8211,6 +8224,9 @@
 			master_call = c->master_call;
 			switch (master_call->hold_state) {
 			case Q931_HOLD_STATE_HOLD_REQ:
+				if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
+					pri_message(ctrl, "HOLD collision\n");
+				}
 				if (ctrl->localtype == PRI_NETWORK) {
 					/* The network ignores HOLD request on a hold collision. */
 					break;
@@ -8224,10 +8240,6 @@
 				res = Q931_RES_HAVEEVENT;
 
 				UPDATE_HOLD_STATE(ctrl, master_call, Q931_HOLD_STATE_HOLD_IND);
-
-				/* Stop any T-HOLD timer from possible hold collision. */
-				pri_schedule_del(ctrl, master_call->hold_timer);
-				master_call->hold_timer = 0;
 				break;
 			default:
 				q931_send_hold_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
@@ -8324,6 +8336,9 @@
 			master_call = c->master_call;
 			switch (master_call->hold_state) {
 			case Q931_HOLD_STATE_RETRIEVE_REQ:
+				if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
+					pri_message(ctrl, "RETRIEVE collision\n");
+				}
 				if (ctrl->localtype == PRI_NETWORK) {
 					/* The network ignores RETRIEVE request on a retrieve collision. */
 					break;
@@ -8338,10 +8353,6 @@
 				res = Q931_RES_HAVEEVENT;
 
 				UPDATE_HOLD_STATE(ctrl, master_call, Q931_HOLD_STATE_RETRIEVE_IND);
-
-				/* Stop any T-RETRIEVE timer from possible retrieve collision. */
-				pri_schedule_del(ctrl, master_call->hold_timer);
-				master_call->hold_timer = 0;
 				break;
 			default:
 				q931_send_retrieve_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
@@ -8383,6 +8394,8 @@
 		res = 0;
 		master_call = c->master_call;
 		switch (master_call->hold_state) {
+		case Q931_HOLD_STATE_CALL_HELD:
+			/* In this state likely because of a RETRIEVE collision. */
 		case Q931_HOLD_STATE_RETRIEVE_REQ:
 			UPDATE_HOLD_STATE(ctrl, master_call, Q931_HOLD_STATE_CALL_HELD);
 




More information about the svn-commits mailing list