[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