[libpri-commits] rmudgett: branch rmudgett/ntptmp r1105 - /team/rmudgett/ntptmp/
SVN commits to the libpri project
libpri-commits at lists.digium.com
Mon Sep 21 11:04:55 CDT 2009
Author: rmudgett
Date: Mon Sep 21 11:04:51 2009
New Revision: 1105
URL: http://svn.asterisk.org/svn-view/libpri?view=rev&rev=1105
Log:
Take into account that NT PTMP can have multiple call records for the current call.
Modified:
team/rmudgett/ntptmp/pri_q931.h
team/rmudgett/ntptmp/q931.c
Modified: team/rmudgett/ntptmp/pri_q931.h
URL: http://svn.asterisk.org/svn-view/libpri/team/rmudgett/ntptmp/pri_q931.h?view=diff&rev=1105&r1=1104&r2=1105
==============================================================================
--- team/rmudgett/ntptmp/pri_q931.h (original)
+++ team/rmudgett/ntptmp/pri_q931.h Mon Sep 21 11:04:51 2009
@@ -470,12 +470,12 @@
extern void q931_dl_indication(struct pri *pri, int event);
-int q931_send_hold(struct pri *ctrl, q931_call *call);
-int q931_send_hold_ack(struct pri *ctrl, q931_call *call);
-int q931_send_hold_rej(struct pri *ctrl, q931_call *call, int cause);
-
-int q931_send_retrieve(struct pri *ctrl, q931_call *call, int channel);
-int q931_send_retrieve_ack(struct pri *ctrl, q931_call *call, int channel);
-int q931_send_retrieve_rej(struct pri *ctrl, q931_call *call, int cause);
+int q931_send_hold(struct pri *ctrl, struct q931_call *call);
+int q931_send_hold_ack(struct pri *ctrl, struct q931_call *call);
+int q931_send_hold_rej(struct pri *ctrl, struct q931_call *call, int cause);
+
+int q931_send_retrieve(struct pri *ctrl, struct q931_call *call, int channel);
+int q931_send_retrieve_ack(struct pri *ctrl, struct q931_call *call, int channel);
+int q931_send_retrieve_rej(struct pri *ctrl, struct q931_call *call, int cause);
#endif
Modified: team/rmudgett/ntptmp/q931.c
URL: http://svn.asterisk.org/svn-view/libpri/team/rmudgett/ntptmp/q931.c?view=diff&rev=1105&r1=1104&r2=1105
==============================================================================
--- team/rmudgett/ntptmp/q931.c (original)
+++ team/rmudgett/ntptmp/q931.c Mon Sep 21 11:04:51 2009
@@ -239,9 +239,10 @@
do { \
if (((ctrl)->debug & PRI_DEBUG_Q931_STATE) && (call)->ourcallstate != (newstate)) { \
pri_message((ctrl), \
- DBGHEAD "Call %d on channel %d enters state %d (%s). Hold state: %s\n", \
- DBGINFO, (call)->cr, (call)->channelno, (newstate), \
- q931_call_state_str(newstate), q931_hold_state_str((call)->hold_state)); \
+ DBGHEAD "%s %d enters state %d (%s). Hold state: %s\n", \
+ DBGINFO, ((call) == (call)->master_call) ? "Call" : "Subcall", \
+ (call)->cr, (newstate), q931_call_state_str(newstate), \
+ q931_hold_state_str((call)->master_call->hold_state)); \
} \
(call)->ourcallstate = (newstate); \
} while (0)
@@ -252,20 +253,21 @@
#if 1
/* Update hold state with transition trace. */
-#define UPDATE_HOLD_STATE(ctrl, call, newstate) \
+#define UPDATE_HOLD_STATE(ctrl, master_call, newstate) \
do { \
- if (((ctrl)->debug & PRI_DEBUG_Q931_STATE) && (call)->hold_state != (newstate)) { \
+ if (((ctrl)->debug & PRI_DEBUG_Q931_STATE) \
+ && (master_call)->hold_state != (newstate)) { \
pri_message((ctrl), \
- DBGHEAD "Call %d on channel %d in state %d (%s) enters Hold state: %s\n", \
- DBGINFO, (call)->cr, (call)->channelno, (call)->ourcallstate, \
- q931_call_state_str((call)->ourcallstate), \
+ DBGHEAD "Call %d in state %d (%s) enters Hold state: %s\n", \
+ DBGINFO, (master_call)->cr, (master_call)->ourcallstate, \
+ q931_call_state_str((master_call)->ourcallstate), \
q931_hold_state_str(newstate)); \
} \
- (call)->hold_state = (newstate); \
+ (master_call)->hold_state = (newstate); \
} while (0)
#else
/* Update hold state with no trace. */
-#define UPDATE_HOLD_STATE(ctrl, call, newstate) (call)->hold_state = (newstate)
+#define UPDATE_HOLD_STATE(ctrl, master_call, newstate) (master_call)->hold_state = (newstate)
#endif
struct ie {
@@ -294,19 +296,27 @@
static int q931_encode_channel(const q931_call *call)
{
int held_call;
-
- switch (call->hold_state) {
+ int channelno;
+ int ds1no;
+
+ switch (call->master_call->hold_state) {
case Q931_HOLD_STATE_CALL_HELD:
case Q931_HOLD_STATE_RETRIEVE_REQ:
case Q931_HOLD_STATE_RETRIEVE_IND:
held_call = 1 << 18;
+
+ /* So a -1 does not wipe out the held_call flag. */
+ channelno = call->channelno & 0xFF;
+ ds1no = call->ds1no & 0xFF;
break;
default:
held_call = 0;
- break;
- }
- return call->channelno | (call->ds1no << 8) | (call->ds1explicit << 16)
- | (call->cis_call << 17) | held_call;
+ channelno = call->channelno;
+ ds1no = call->ds1no;
+ break;
+ }
+ return channelno | (ds1no << 8) | (call->ds1explicit << 16) | (call->cis_call << 17)
+ | held_call;
}
/*!
@@ -3721,6 +3731,11 @@
int q931_notify(struct pri *ctrl, q931_call *c, int channel, int info)
{
+/*
+ * BUGBUG Need to send the remote hold/retrieval NOTIFY to all NT PTMP subcalls
+ * that have given a positive response.
+ * States Outgoing-call-proceeding(U3/N3), Call-delivered(U4/N4), and Active(U10/N10).
+ */
if ((ctrl->switchtype == PRI_SWITCH_EUROISDN_T1) || (ctrl->switchtype != PRI_SWITCH_EUROISDN_E1)) {
if ((info > 0x2) || (info < 0x00)) {
return 0;
@@ -4237,9 +4252,35 @@
/*!
* \internal
+ * \brief Find the winning subcall if it exists or current call if not outboundbroadcast.
+ *
+ * \param call Starting Q.931 call record of search.
+ *
+ * \retval winning-call or given call if not outboundbroadcast.
+ * \retval NULL if no winning call yet.
+ */
+static struct q931_call *q931_find_winning_call(struct q931_call *call)
+{
+ struct q931_call *master;
+
+ master = call->master_call;
+ if (master->outboundbroadcast) {
+ /* We have potential subcalls. Now get the winning call if declared yet. */
+ if (master->pri_winner < 0) {
+ /* Winner not declared yet.*/
+ call = NULL;
+ } else {
+ call = master->subcalls[master->pri_winner];
+ }
+ }
+ return call;
+}
+
+/*!
+ * \internal
* \brief Send HOLD message response wait timeout.
*
- * \param data Q.931 call leg.
+ * \param data Q.931 call leg. (Master Q.931 subcall structure)
*
* \return Nothing
*/
@@ -4262,7 +4303,7 @@
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->master_call;
+ ctrl->ev.hold_rej.call = call;
ctrl->ev.hold_rej.cause = PRI_CAUSE_MESSAGE_TYPE_NONEXIST;
ctrl->ev.hold_rej.subcmds = &ctrl->subcmds;
}
@@ -4272,12 +4313,12 @@
* \brief Determine if a hold request is allowed now.
*
* \param ctrl D channel controller.
- * \param call Q.931 call leg
+ * \param call Q.931 call leg. (Master Q.931 subcall structure)
*
* \retval TRUE if we can send a HOLD request.
* \retval FALSE if not allowed.
*/
-static int q931_is_hold_allowed(const struct pri *ctrl, const q931_call *call)
+static int q931_is_hold_allowed(const struct pri *ctrl, const struct q931_call *call)
{
int allowed;
@@ -4321,20 +4362,23 @@
* \brief Send the HOLD message.
*
* \param ctrl D channel controller.
- * \param call Q.931 call leg
+ * \param call Q.931 call leg. (Master Q.931 subcall structure)
*
* \retval 0 on success.
* \retval -1 on error.
*/
-int q931_send_hold(struct pri *ctrl, q931_call *call)
-{
- if (!q931_is_hold_allowed(ctrl, call)) {
+int q931_send_hold(struct pri *ctrl, struct q931_call *call)
+{
+ struct q931_call *winner;
+
+ winner = q931_find_winning_call(call);
+ if (!winner || !q931_is_hold_allowed(ctrl, call)) {
return -1;
}
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, call, Q931_HOLD, hold_ies)) {
+ if (send_message(ctrl, winner, Q931_HOLD, hold_ies)) {
pri_schedule_del(ctrl, call->hold_timer);
call->hold_timer = 0;
return -1;
@@ -4351,26 +4395,33 @@
* \brief Send the HOLD ACKNOWLEDGE message.
*
* \param ctrl D channel controller.
- * \param call Q.931 call leg
+ * \param call Q.931 call leg. (Master Q.931 subcall structure)
*
* \retval 0 on success.
* \retval -1 on error.
*/
-int q931_send_hold_ack(struct pri *ctrl, q931_call *call)
-{
+int q931_send_hold_ack(struct pri *ctrl, struct q931_call *call)
+{
+ struct q931_call *winner;
+
/* Stop the upper layer does not implement guard timer. */
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) {
+ return -1;
+ }
+
/* Call is now on hold so forget the channel. */
- call->channelno = 0;/* No channel */
- call->ds1no = 0;
- call->ds1explicit = 0;
- call->chanflags = 0;
-
- return send_message(ctrl, call, Q931_HOLD_ACKNOWLEDGE, hold_ack_ies);
+ winner->channelno = 0;/* No channel */
+ winner->ds1no = 0;
+ winner->ds1explicit = 0;
+ winner->chanflags = 0;
+
+ return send_message(ctrl, winner, Q931_HOLD_ACKNOWLEDGE, hold_ack_ies);
}
static int hold_reject_ies[] = {
@@ -4379,23 +4430,18 @@
};
/*!
- * \brief Send the HOLD REJECT message.
+ * \internal
+ * \brief Send the HOLD REJECT message only.
*
* \param ctrl D channel controller.
- * \param call Q.931 call leg
+ * \param call Q.931 call leg. (subcall)
* \param cause Q.931 cause code for rejecting the hold request.
*
* \retval 0 on success.
* \retval -1 on error.
*/
-int q931_send_hold_rej(struct pri *ctrl, q931_call *call, int cause)
-{
- /* Stop the upper layer does not implement guard timer. */
- pri_schedule_del(ctrl, call->hold_timer);
- call->hold_timer = 0;
-
- UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_IDLE);
-
+static int q931_send_hold_rej_msg(struct pri *ctrl, struct q931_call *call, int cause)
+{
call->cause = cause;
call->causecode = CODE_CCITT;
call->causeloc = LOC_PRIV_NET_LOCAL_USER;
@@ -4403,10 +4449,38 @@
}
/*!
+ * \brief Send the HOLD REJECT message.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg. (Master Q.931 subcall structure)
+ * \param cause Q.931 cause code for rejecting the hold request.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int q931_send_hold_rej(struct pri *ctrl, struct q931_call *call, int cause)
+{
+ struct q931_call *winner;
+
+ /* Stop the upper layer does not implement guard timer. */
+ pri_schedule_del(ctrl, call->hold_timer);
+ call->hold_timer = 0;
+
+ UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_IDLE);
+
+ winner = q931_find_winning_call(call);
+ if (!winner) {
+ return -1;
+ }
+
+ return q931_send_hold_rej_msg(ctrl, winner, cause);
+}
+
+/*!
* \internal
* \brief Send HOLD message response guard timeout.
*
- * \param data Q.931 call leg.
+ * \param data Q.931 call leg. (Master Q.931 subcall structure)
*
* \return Nothing
*/
@@ -4427,7 +4501,7 @@
* \internal
* \brief Send RETRIEVE message response wait timeout.
*
- * \param data Q.931 call leg.
+ * \param data Q.931 call leg. (Master Q.931 subcall structure)
*
* \return Nothing
*/
@@ -4435,6 +4509,7 @@
{
struct q931_call *call = data;
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");
@@ -4446,17 +4521,20 @@
UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_CALL_HELD);
- /* Call is still on hold so forget the channel. */
- call->channelno = 0;/* No channel */
- call->ds1no = 0;
- call->ds1explicit = 0;
- call->chanflags = 0;
+ winner = q931_find_winning_call(call);
+ if (winner) {
+ /* Call is still on hold so forget the channel. */
+ winner->channelno = 0;/* No channel */
+ winner->ds1no = 0;
+ winner->ds1explicit = 0;
+ winner->chanflags = 0;
+ }
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->master_call;
+ ctrl->ev.retrieve_rej.call = call;
ctrl->ev.retrieve_rej.cause = PRI_CAUSE_MESSAGE_TYPE_NONEXIST;
ctrl->ev.retrieve_rej.subcmds = &ctrl->subcmds;
}
@@ -4466,12 +4544,12 @@
* \brief Determine if a retrieve request is allowed now.
*
* \param ctrl D channel controller.
- * \param call Q.931 call leg
+ * \param call Q.931 call leg. (Master Q.931 subcall structure)
*
* \retval TRUE if we can send a RETRIEVE request.
* \retval FALSE if not allowed.
*/
-static int q931_is_retrieve_allowed(const struct pri *ctrl, const q931_call *call)
+static int q931_is_retrieve_allowed(const struct pri *ctrl, const struct q931_call *call)
{
int allowed;
@@ -4516,44 +4594,47 @@
* \brief Send the RETRIEVE message.
*
* \param ctrl D channel controller.
- * \param call Q.931 call leg
+ * \param call Q.931 call leg. (Master Q.931 subcall structure)
* \param channel Encoded channel id to use. If zero do not send channel id.
*
* \retval 0 on success.
* \retval -1 on error.
*/
-int q931_send_retrieve(struct pri *ctrl, q931_call *call, int channel)
-{
- if (!q931_is_retrieve_allowed(ctrl, call)) {
+int q931_send_retrieve(struct pri *ctrl, struct q931_call *call, int channel)
+{
+ struct q931_call *winner;
+
+ winner = q931_find_winning_call(call);
+ if (!winner || !q931_is_retrieve_allowed(ctrl, call)) {
return -1;
}
if (channel) {
- call->ds1no = (channel & 0xff00) >> 8;
- call->ds1explicit = (channel & 0x10000) >> 16;
- call->channelno = channel & 0xff;
+ winner->ds1no = (channel & 0xff00) >> 8;
+ winner->ds1explicit = (channel & 0x10000) >> 16;
+ winner->channelno = channel & 0xff;
if (ctrl->localtype == PRI_NETWORK) {
- call->chanflags = FLAG_EXCLUSIVE;
+ winner->chanflags = FLAG_EXCLUSIVE;
} else {
- call->chanflags = FLAG_PREFERRED;
+ winner->chanflags = FLAG_PREFERRED;
}
} else {
/* Do not send Q931_CHANNEL_IDENT */
- call->chanflags = 0;
+ winner->chanflags = 0;
}
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, call, Q931_RETRIEVE, retrieve_ies)) {
+ if (send_message(ctrl, winner, Q931_RETRIEVE, retrieve_ies)) {
pri_schedule_del(ctrl, call->hold_timer);
call->hold_timer = 0;
/* Call is still on hold so forget the channel. */
- call->channelno = 0;/* No channel */
- call->ds1no = 0;
- call->ds1explicit = 0;
- call->chanflags = 0;
+ winner->channelno = 0;/* No channel */
+ winner->ds1no = 0;
+ winner->ds1explicit = 0;
+ winner->chanflags = 0;
return -1;
}
UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_RETRIEVE_REQ);
@@ -4569,22 +4650,29 @@
* \brief Send the RETRIEVE ACKNOWLEDGE message.
*
* \param ctrl D channel controller.
- * \param call Q.931 call leg
+ * \param call Q.931 call leg. (Master Q.931 subcall structure)
* \param channel Encoded channel id to use.
*
* \retval 0 on success.
* \retval -1 on error.
*/
-int q931_send_retrieve_ack(struct pri *ctrl, q931_call *call, int channel)
-{
- call->ds1no = (channel & 0xff00) >> 8;
- call->ds1explicit = (channel & 0x10000) >> 16;
- call->channelno = channel & 0xff;
- call->chanflags = FLAG_EXCLUSIVE;
+int q931_send_retrieve_ack(struct pri *ctrl, struct q931_call *call, int channel)
+{
+ struct q931_call *winner;
+
+ winner = q931_find_winning_call(call);
+ if (!winner) {
+ return -1;
+ }
+
+ winner->ds1no = (channel & 0xff00) >> 8;
+ winner->ds1explicit = (channel & 0x10000) >> 16;
+ winner->channelno = channel & 0xff;
+ winner->chanflags = FLAG_EXCLUSIVE;
UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_IDLE);
- return send_message(ctrl, call, Q931_RETRIEVE_ACKNOWLEDGE, retrieve_ack_ies);
+ return send_message(ctrl, winner, Q931_RETRIEVE_ACKNOWLEDGE, retrieve_ack_ies);
}
static int retrieve_reject_ies[] = {
@@ -4593,29 +4681,52 @@
};
/*!
- * \brief Send the RETRIEVE REJECT message.
+ * \internal
+ * \brief Send the RETRIEVE REJECT message only.
*
* \param ctrl D channel controller.
- * \param call Q.931 call leg
+ * \param call Q.931 call leg. (subcall)
* \param cause Q.931 cause code for rejecting the retrieve request.
*
* \retval 0 on success.
* \retval -1 on error.
*/
-int q931_send_retrieve_rej(struct pri *ctrl, q931_call *call, int cause)
-{
- /* Call is still on hold so forget the channel. */
- call->channelno = 0;/* No channel */
- call->ds1no = 0;
- call->ds1explicit = 0;
- call->chanflags = 0;
-
- UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_CALL_HELD);
-
+static int q931_send_retrieve_rej_msg(struct pri *ctrl, struct q931_call *call, int cause)
+{
call->cause = cause;
call->causecode = CODE_CCITT;
call->causeloc = LOC_PRIV_NET_LOCAL_USER;
return send_message(ctrl, call, Q931_RETRIEVE_REJECT, retrieve_reject_ies);
+}
+
+/*!
+ * \brief Send the RETRIEVE REJECT message.
+ *
+ * \param ctrl D channel controller.
+ * \param call Q.931 call leg. (Master Q.931 subcall structure)
+ * \param cause Q.931 cause code for rejecting the retrieve request.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int q931_send_retrieve_rej(struct pri *ctrl, struct q931_call *call, int cause)
+{
+ struct q931_call *winner;
+
+ UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_CALL_HELD);
+
+ winner = q931_find_winning_call(call);
+ if (!winner) {
+ return -1;
+ }
+
+ /* Call is still on hold so forget the channel. */
+ winner->channelno = 0;/* No channel */
+ winner->ds1no = 0;
+ winner->ds1explicit = 0;
+ winner->chanflags = 0;
+
+ return q931_send_retrieve_rej_msg(ctrl, winner, cause);
}
static int pri_internal_clear(void *data);
@@ -5429,6 +5540,7 @@
int res;
struct apdu_event *cur = NULL;
struct pri_subcommand *subcmd;
+ struct q931_call *master_call;
switch(mh->msg) {
case Q931_RESTART:
@@ -5987,14 +6099,23 @@
case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
if (q931_is_ptmp(ctrl)) {
/* HOLD request only allowed in these states if point-to-point mode. */
- q931_send_hold_rej(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
+ q931_send_hold_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
break;
}
/* Fall through */
case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
case Q931_CALL_STATE_CALL_DELIVERED:
case Q931_CALL_STATE_ACTIVE:
- switch (c->hold_state) {
+ if (!q931_find_winning_call(c)) {
+ /*
+ * Only the winning call of a broadcast SETUP can do hold since the
+ * call must be answered first.
+ */
+ q931_send_hold_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
+ break;
+ }
+ master_call = c->master_call;
+ switch (master_call->hold_state) {
case Q931_HOLD_STATE_HOLD_REQ:
if (ctrl->localtype == PRI_NETWORK) {
/* The network ignores HOLD request on a hold collision. */
@@ -6004,19 +6125,20 @@
case Q931_HOLD_STATE_IDLE:
ctrl->ev.e = PRI_EVENT_HOLD;
ctrl->ev.hold.channel = q931_encode_channel(c);
- ctrl->ev.hold.call = c->master_call;
+ ctrl->ev.hold.call = master_call;
ctrl->ev.hold.subcmds = &ctrl->subcmds;
res = Q931_RES_HAVEEVENT;
- UPDATE_HOLD_STATE(ctrl, c, Q931_HOLD_STATE_HOLD_IND);
+ UPDATE_HOLD_STATE(ctrl, master_call, Q931_HOLD_STATE_HOLD_IND);
/* Start the upper layer does not implement guard timer. */
- pri_schedule_del(ctrl, c->hold_timer);
- c->hold_timer = pri_schedule_event(ctrl,
- ctrl->timers[PRI_TIMER_T_HOLD] / 2, q931_hold_guard_timeout, c);
+ pri_schedule_del(ctrl, master_call->hold_timer);
+ master_call->hold_timer = pri_schedule_event(ctrl,
+ ctrl->timers[PRI_TIMER_T_HOLD] / 2, q931_hold_guard_timeout,
+ master_call);
break;
default:
- q931_send_hold_rej(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
+ q931_send_hold_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
break;
}
break;
@@ -6025,21 +6147,22 @@
/* Ignore HOLD request in these states. */
break;
default:
- q931_send_hold_rej(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
+ q931_send_hold_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
break;
}
return res;
case Q931_HOLD_ACKNOWLEDGE:
res = 0;
- switch (c->hold_state) {
+ master_call = c->master_call;
+ switch (master_call->hold_state) {
case Q931_HOLD_STATE_HOLD_REQ:
ctrl->ev.e = PRI_EVENT_HOLD_ACK;
ctrl->ev.hold_ack.channel = q931_encode_channel(c);
- ctrl->ev.hold_ack.call = c->master_call;
+ ctrl->ev.hold_ack.call = master_call;
ctrl->ev.hold_ack.subcmds = &ctrl->subcmds;
res = Q931_RES_HAVEEVENT;
- UPDATE_HOLD_STATE(ctrl, c, Q931_HOLD_STATE_CALL_HELD);
+ UPDATE_HOLD_STATE(ctrl, master_call, Q931_HOLD_STATE_CALL_HELD);
/* Call is now on hold so forget the channel. */
c->channelno = 0;/* No channel */
@@ -6048,8 +6171,8 @@
c->chanflags = 0;
/* Stop T-HOLD timer */
- pri_schedule_del(ctrl, c->hold_timer);
- c->hold_timer = 0;
+ pri_schedule_del(ctrl, master_call->hold_timer);
+ master_call->hold_timer = 0;
break;
default:
/* Ignore response. Response is late or spurrious. */
@@ -6058,7 +6181,8 @@
return res;
case Q931_HOLD_REJECT:
res = 0;
- switch (c->hold_state) {
+ master_call = c->master_call;
+ switch (master_call->hold_state) {
case Q931_HOLD_STATE_HOLD_REQ:
if (missingmand) {
/* Still, let hold rejection continue. */
@@ -6066,16 +6190,16 @@
}
ctrl->ev.e = PRI_EVENT_HOLD_REJ;
ctrl->ev.hold_rej.channel = q931_encode_channel(c);
- ctrl->ev.hold_rej.call = c->master_call;
+ ctrl->ev.hold_rej.call = master_call;
ctrl->ev.hold_rej.cause = c->cause;
ctrl->ev.hold_rej.subcmds = &ctrl->subcmds;
res = Q931_RES_HAVEEVENT;
- UPDATE_HOLD_STATE(ctrl, c, Q931_HOLD_STATE_IDLE);
+ UPDATE_HOLD_STATE(ctrl, master_call, Q931_HOLD_STATE_IDLE);
/* Stop T-HOLD timer */
- pri_schedule_del(ctrl, c->hold_timer);
- c->hold_timer = 0;
+ pri_schedule_del(ctrl, master_call->hold_timer);
+ master_call->hold_timer = 0;
break;
default:
/* Ignore response. Response is late or spurrious. */
@@ -6090,14 +6214,23 @@
case Q931_CALL_STATE_INCOMING_CALL_PROCEEDING:
if (q931_is_ptmp(ctrl)) {
/* RETRIEVE request only allowed in these states if point-to-point mode. */
- q931_send_retrieve_rej(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
+ q931_send_retrieve_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
break;
}
/* Fall through */
case Q931_CALL_STATE_OUTGOING_CALL_PROCEEDING:
case Q931_CALL_STATE_CALL_DELIVERED:
case Q931_CALL_STATE_ACTIVE:
- switch (c->hold_state) {
+ if (!q931_find_winning_call(c)) {
+ /*
+ * Only the winning call of a broadcast SETUP can do hold since the
+ * call must be answered first.
+ */
+ q931_send_retrieve_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
+ break;
+ }
+ master_call = c->master_call;
+ switch (master_call->hold_state) {
case Q931_HOLD_STATE_RETRIEVE_REQ:
if (ctrl->localtype == PRI_NETWORK) {
/* The network ignores RETRIEVE request on a retrieve collision. */
@@ -6107,23 +6240,23 @@
case Q931_HOLD_STATE_CALL_HELD:
ctrl->ev.e = PRI_EVENT_RETRIEVE;
ctrl->ev.retrieve.channel = q931_encode_channel(c);
- ctrl->ev.retrieve.call = c->master_call;
+ ctrl->ev.retrieve.call = master_call;
ctrl->ev.retrieve.flexible = !(c->chanflags & FLAG_EXCLUSIVE);
ctrl->ev.retrieve.subcmds = &ctrl->subcmds;
res = Q931_RES_HAVEEVENT;
- UPDATE_HOLD_STATE(ctrl, c, Q931_HOLD_STATE_RETRIEVE_IND);
+ UPDATE_HOLD_STATE(ctrl, master_call, Q931_HOLD_STATE_RETRIEVE_IND);
/*
* Stop any T-RETRIEVE timer.
* The upper layer must implement HOLD for a call to even get
* on hold.
*/
- pri_schedule_del(ctrl, c->hold_timer);
- c->hold_timer = 0;
+ pri_schedule_del(ctrl, master_call->hold_timer);
+ master_call->hold_timer = 0;
break;
default:
- q931_send_retrieve_rej(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
+ q931_send_retrieve_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
break;
}
break;
@@ -6132,23 +6265,24 @@
/* Ignore RETRIEVE request in these states. */
break;
default:
- q931_send_retrieve_rej(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
+ q931_send_retrieve_rej_msg(ctrl, c, PRI_CAUSE_WRONG_CALL_STATE);
break;
}
return res;
case Q931_RETRIEVE_ACKNOWLEDGE:
res = 0;
- switch (c->hold_state) {
+ master_call = c->master_call;
+ switch (master_call->hold_state) {
case Q931_HOLD_STATE_RETRIEVE_REQ:
- UPDATE_HOLD_STATE(ctrl, c, Q931_HOLD_STATE_IDLE);
+ UPDATE_HOLD_STATE(ctrl, master_call, Q931_HOLD_STATE_IDLE);
/* Stop T-RETRIEVE timer */
- pri_schedule_del(ctrl, c->hold_timer);
- c->hold_timer = 0;
+ pri_schedule_del(ctrl, master_call->hold_timer);
+ master_call->hold_timer = 0;
ctrl->ev.e = PRI_EVENT_RETRIEVE_ACK;
ctrl->ev.retrieve_ack.channel = q931_encode_channel(c);
- ctrl->ev.retrieve_ack.call = c->master_call;
+ ctrl->ev.retrieve_ack.call = master_call;
ctrl->ev.retrieve_ack.subcmds = &ctrl->subcmds;
res = Q931_RES_HAVEEVENT;
break;
@@ -6159,9 +6293,10 @@
return res;
case Q931_RETRIEVE_REJECT:
res = 0;
- switch (c->hold_state) {
+ master_call = c->master_call;
+ switch (master_call->hold_state) {
case Q931_HOLD_STATE_RETRIEVE_REQ:
- UPDATE_HOLD_STATE(ctrl, c, Q931_HOLD_STATE_CALL_HELD);
+ UPDATE_HOLD_STATE(ctrl, master_call, Q931_HOLD_STATE_CALL_HELD);
/* Call is still on hold so forget the channel. */
c->channelno = 0;/* No channel */
@@ -6170,8 +6305,8 @@
c->chanflags = 0;
/* Stop T-RETRIEVE timer */
- pri_schedule_del(ctrl, c->hold_timer);
- c->hold_timer = 0;
+ pri_schedule_del(ctrl, master_call->hold_timer);
+ master_call->hold_timer = 0;
if (missingmand) {
/* Still, let retrive rejection continue. */
@@ -6179,7 +6314,7 @@
}
ctrl->ev.e = PRI_EVENT_RETRIEVE_REJ;
ctrl->ev.retrieve_rej.channel = q931_encode_channel(c);
- ctrl->ev.retrieve_rej.call = c->master_call;
+ ctrl->ev.retrieve_rej.call = master_call;
ctrl->ev.retrieve_rej.cause = c->cause;
ctrl->ev.retrieve_rej.subcmds = &ctrl->subcmds;
res = Q931_RES_HAVEEVENT;
More information about the libpri-commits
mailing list