[svn-commits] rmudgett: branch rmudgett/ntptmp r1132 - /team/rmudgett/ntptmp/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Sep 23 15:25:54 CDT 2009


Author: rmudgett
Date: Wed Sep 23 15:25:51 2009
New Revision: 1132

URL: http://svnview.digium.com/svn/libpri?view=rev&rev=1132
Log:
Add transfer held call on disconnect picking calls code.

Modified:
    team/rmudgett/ntptmp/libpri.h
    team/rmudgett/ntptmp/q931.c

Modified: team/rmudgett/ntptmp/libpri.h
URL: http://svnview.digium.com/svn/libpri/team/rmudgett/ntptmp/libpri.h?view=diff&rev=1132&r1=1131&r2=1132
==============================================================================
--- team/rmudgett/ntptmp/libpri.h (original)
+++ team/rmudgett/ntptmp/libpri.h Wed Sep 23 15:25:51 2009
@@ -623,10 +623,22 @@
 	int channel;				/* Channel requested */
 	int cause;
 	int cref;
-	q931_call *call;			/* Opaque call pointer */
+	q931_call *call;			/* Opaque call pointer of call hanging up. */
 	long aoc_units;				/* Advise of Charge number of charged units */
 	char useruserinfo[260];		/* User->User info */
 	struct pri_subcommands *subcmds;
+	/*!
+	 * \brief Opaque held call pointer for possible transfer to active call.
+	 * \note The call_held and call_active pointers must not be NULL if
+	 * transfer held call on disconnect is available.
+	 */
+	q931_call *call_held;
+	/*!
+	 * \brief Opaque active call pointer for possible transfer with held call.
+	 * \note The call_held and call_active pointers must not be NULL if
+	 * transfer held call on disconnect is available.
+	 */
+	q931_call *call_active;
 } pri_event_hangup;
 
 typedef struct pri_event_restart_ack {

Modified: team/rmudgett/ntptmp/q931.c
URL: http://svnview.digium.com/svn/libpri/team/rmudgett/ntptmp/q931.c?view=diff&rev=1132&r1=1131&r2=1132
==============================================================================
--- team/rmudgett/ntptmp/q931.c (original)
+++ team/rmudgett/ntptmp/q931.c Wed Sep 23 15:25:51 2009
@@ -4000,6 +4000,8 @@
 	ctrl->ev.hangup.cref = c->cr;
 	ctrl->ev.hangup.call = c->master_call;
 	ctrl->ev.hangup.aoc_units = c->aoc_units;
+	ctrl->ev.hangup.call_held = NULL;
+	ctrl->ev.hangup.call_active = NULL;
 	libpri_copy_string(ctrl->ev.hangup.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.hangup.useruserinfo));
 	pri_hangup(ctrl, c, c->cause);
 }
@@ -5527,7 +5529,7 @@
 			q931_set_subcall_winner(c);
 			*allow_event = 1;
 		} else {
-			/* Call clearing occurs of non selected calls occurs in
+			/* Call clearing of non selected calls occurs in
 			 * q931_set_subcall_winner() - All we need to do is make sure
 			 * that this connect is not acknowledged */
 			*allow_posthandle = 0;
@@ -5589,6 +5591,101 @@
 
 /*!
  * \internal
+ * \brief Find the active call given the held call.
+ *
+ * \param ctrl D channel controller.
+ * \param held_call Held call to help locate a compatible active call.
+ *
+ * \retval master-active-call on success.
+ * \retval NULL on error.
+ */
+static struct q931_call *q931_find_held_active_call(struct pri *ctrl, struct q931_call *held_call)
+{
+	struct pri *master;
+	struct q931_call *cur;
+	struct q931_call *winner;
+	struct q931_call *match;
+
+	match = NULL;
+	master = PRI_MASTER(ctrl);
+	for (cur = *master->callpool; cur; cur = cur->next) {
+		if (cur->hold_state == Q931_HOLD_STATE_IDLE) {
+			/* Found an active call. */
+			winner = q931_find_winning_call(cur);
+			if (!winner || (BRI_NT_PTMP(ctrl) && winner->pri != held_call->pri)) {
+				/* There is no winner or the active call does not go to the same TEI. */
+				continue;
+			}
+			switch (winner->ourcallstate) {
+			case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
+			case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
+			case Q931_CALL_STATE_CALL_DELIVERED:
+			case Q931_CALL_STATE_CALL_RECEIVED:
+			case Q931_CALL_STATE_ACTIVE:
+				break;
+			default:
+				/* Active call not in the right state. */
+				continue;
+			}
+			if (q931_party_number_cmp(&winner->remote_id.number,
+				&held_call->remote_id.number)) {
+				/* The remote party number does not match.  This is a weak match. */
+				match = cur;
+				continue;
+			}
+			/* Found an exact match. */
+			match = cur;
+			break;
+		}
+	}
+
+	return match;
+}
+
+/*!
+ * \internal
+ * \brief Find the held call given the active call.
+ *
+ * \param ctrl D channel controller.
+ * \param active_call Active call to help locate a compatible held call.
+ *
+ * \retval master-held-call on success.
+ * \retval NULL on error.
+ */
+static struct q931_call *q931_find_held_call(struct pri *ctrl, struct q931_call *active_call)
+{
+	struct pri *master;
+	struct q931_call *cur;
+	struct q931_call *winner;
+	struct q931_call *match;
+
+	match = NULL;
+	master = PRI_MASTER(ctrl);
+	for (cur = *master->callpool; cur; cur = cur->next) {
+		if (cur->hold_state == Q931_HOLD_STATE_CALL_HELD) {
+			/* Found a held call. */
+			winner = q931_find_winning_call(cur);
+			if (!winner || (BRI_NT_PTMP(ctrl) && winner->pri != active_call->pri)) {
+				/* There is no winner or the held call does not go to the same TEI. */
+				continue;
+			}
+			if (q931_party_number_cmp(&winner->remote_id.number,
+				&active_call->remote_id.number)) {
+				/* The remote party number does not match.  This is a weak match. */
+				match = cur;
+				continue;
+			}
+			/* Found an exact match. */
+			match = cur;
+			break;
+		}
+	}
+
+	return match;
+}
+
+/*!
+ * \internal
  * \brief Process the decoded information in the Q.931 message.
  *
  * \param ctrl D channel controller.
@@ -5917,6 +6014,8 @@
 			ctrl->ev.hangup.cref = c->cr;
 			ctrl->ev.hangup.call = c->master_call;
 			ctrl->ev.hangup.aoc_units = c->aoc_units;
+			ctrl->ev.hangup.call_held = NULL;
+			ctrl->ev.hangup.call_active = NULL;
 			libpri_copy_string(ctrl->ev.hangup.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.hangup.useruserinfo));
 			/* Free resources */
 			UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_NULL);
@@ -5948,6 +6047,8 @@
 		ctrl->ev.hangup.cref = c->cr;
 		ctrl->ev.hangup.call = c->master_call;
 		ctrl->ev.hangup.aoc_units = c->aoc_units;
+		ctrl->ev.hangup.call_held = NULL;
+		ctrl->ev.hangup.call_active = NULL;
 		libpri_copy_string(ctrl->ev.hangup.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.hangup.useruserinfo));
 		c->useruserinfo[0] = '\0';
 		/* Free resources */
@@ -5986,6 +6087,8 @@
 		ctrl->ev.hangup.cref = c->cr;
 		ctrl->ev.hangup.call = c->master_call;
 		ctrl->ev.hangup.aoc_units = c->aoc_units;
+		ctrl->ev.hangup.call_held = NULL;
+		ctrl->ev.hangup.call_active = NULL;
 		libpri_copy_string(ctrl->ev.hangup.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.hangup.useruserinfo));
 		c->useruserinfo[0] = '\0';
 		/* Don't send release complete if they send us release 
@@ -6007,6 +6110,52 @@
 			q931_release_complete(ctrl,c,PRI_CAUSE_INVALID_CALL_REFERENCE);
 			break;
 		}
+
+		/*
+		 * Determine if there are any calls that can be proposed for
+		 * a transfer of held call on disconnect.
+		 */
+		if (c->master_call->hold_state == Q931_HOLD_STATE_CALL_HELD) {
+			/* Held call is being hung up first. */
+			ctrl->ev.hangup.call_held = c->master_call;
+			ctrl->ev.hangup.call_active = q931_find_held_active_call(ctrl, c);
+		} else {
+			/* Active call is being hung up first. */
+			ctrl->ev.hangup.call_held = NULL;
+			ctrl->ev.hangup.call_active = NULL;
+			if (q931_find_winning_call(c) == c) {
+				/*
+				 * Only a normal call or the winning call of a broadcast SETUP
+				 * can participate in a transfer of held call on disconnet.
+				 */
+				switch (c->ourcallstate) {
+				case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
+				case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
+				case Q931_CALL_STATE_CALL_DELIVERED:
+				case Q931_CALL_STATE_CALL_RECEIVED:
+				case Q931_CALL_STATE_ACTIVE:
+					ctrl->ev.hangup.call_active = c->master_call;
+					ctrl->ev.hangup.call_held = q931_find_held_call(ctrl, c);
+					break;
+				default:
+					break;
+				}
+			}
+		}
+		if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
+			if (ctrl->ev.hangup.call_held) {
+				pri_message(ctrl, "-- Found held call: %p cref:%d\n",
+					ctrl->ev.hangup.call_held, ctrl->ev.hangup.call_held->cr);
+			}
+			if (ctrl->ev.hangup.call_active) {
+				pri_message(ctrl, "-- Found active call: %p cref:%d\n",
+					ctrl->ev.hangup.call_active, ctrl->ev.hangup.call_active->cr);
+			}
+			if (ctrl->ev.hangup.call_held && ctrl->ev.hangup.call_active) {
+				pri_message(ctrl, "-- Transfer held call on disconnect possible.\n");
+			}
+		}
+
 		UPDATE_OURCALLSTATE(ctrl, c, Q931_CALL_STATE_DISCONNECT_INDICATION);
 		c->peercallstate = Q931_CALL_STATE_DISCONNECT_REQUEST;
 		c->sendhangupack = 1;
@@ -6435,6 +6584,8 @@
 	ctrl->ev.hangup.cref = c->cr;          		
 	ctrl->ev.hangup.call = c->master_call;
 	ctrl->ev.hangup.aoc_units = c->aoc_units;
+	ctrl->ev.hangup.call_held = NULL;
+	ctrl->ev.hangup.call_active = NULL;
 	libpri_copy_string(ctrl->ev.hangup.useruserinfo, c->useruserinfo, sizeof(ctrl->ev.hangup.useruserinfo));
 
 	pri_error(ctrl, "clearing, alive %d, hangupack %d\n", c->alive, c->sendhangupack);




More information about the svn-commits mailing list