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. git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@2170 2fbb986a-6c06-0410-b554-c9c1f0a7f128
This commit is contained in:
parent
8dc9486287
commit
4faa2935f8
@ -532,9 +532,9 @@ struct q931_call {
|
||||
|
||||
/*! \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. */
|
||||
|
69
q931.c
69
q931.c
@ -5572,6 +5572,7 @@ int q931_connect_acknowledge(struct pri *ctrl, q931_call *call, int channel)
|
||||
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 @@ static void q931_hold_timeout(void *data)
|
||||
}
|
||||
|
||||
/* Ensure that the timer is deleted. */
|
||||
pri_schedule_del(ctrl, call->hold_timer);
|
||||
call->hold_timer = 0;
|
||||
pri_schedule_del(ctrl, master->hold_timer);
|
||||
master->hold_timer = 0;
|
||||
|
||||
UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_IDLE);
|
||||
/* 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 @@ int q931_send_hold(struct pri *ctrl, struct q931_call *call)
|
||||
}
|
||||
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 @@ int q931_send_hold_rej(struct pri *ctrl, struct q931_call *call, int cause)
|
||||
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;
|
||||
pri_schedule_del(ctrl, master->hold_timer);
|
||||
master->hold_timer = 0;
|
||||
|
||||
UPDATE_HOLD_STATE(ctrl, call, Q931_HOLD_STATE_CALL_HELD);
|
||||
/* 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);
|
||||
|
||||
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;
|
||||
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 @@ int q931_send_retrieve(struct pri *ctrl, struct q931_call *call, int channel)
|
||||
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 @@ int q931_send_retrieve(struct pri *ctrl, struct q931_call *call, int channel)
|
||||
|
||||
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 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
||||
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 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
||||
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 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
||||
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 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
||||
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 @@ static int post_handle_q931_message(struct pri *ctrl, struct q931_mh *mh, struct
|
||||
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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user