PRI links do not retain active calls if the link comes back before T309 expires.
The DL-ESTABLISH confirm event was not passed from Q.921 to Q.931 so Q.931 never cancelled the T309 timer. Refactored q931_dl_tei_removal() and q931_dl_indication() into q931_dl_event() to allow the DL-ESTABLISH confirm/indication and DL-RELEASE confirm/indication events to be passed to Q.931. git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@1991 2fbb986a-6c06-0410-b554-c9c1f0a7f128
This commit is contained in:
parent
05158ec5fb
commit
384ae1e688
11
pri_q931.h
11
pri_q931.h
@ -502,8 +502,15 @@ void q931_dump(struct pri *ctrl, int tei, q931_h *h, int len, int txrx);
|
||||
|
||||
void q931_destroycall(struct pri *pri, q931_call *c);
|
||||
|
||||
void q931_dl_tei_removal(struct pri *link);
|
||||
void q931_dl_indication(struct pri *link, int event);
|
||||
enum Q931_DL_EVENT {
|
||||
Q931_DL_EVENT_NONE,
|
||||
Q931_DL_EVENT_DL_ESTABLISH_IND,
|
||||
Q931_DL_EVENT_DL_ESTABLISH_CONFIRM,
|
||||
Q931_DL_EVENT_DL_RELEASE_IND,
|
||||
Q931_DL_EVENT_DL_RELEASE_CONFIRM,
|
||||
Q931_DL_EVENT_TEI_REMOVAL,
|
||||
};
|
||||
void q931_dl_event(struct pri *link, enum Q931_DL_EVENT event);
|
||||
|
||||
int q931_send_hold(struct pri *ctrl, struct q931_call *call);
|
||||
int q931_send_hold_ack(struct pri *ctrl, struct q931_call *call);
|
||||
|
48
q921.c
48
q921.c
@ -215,7 +215,7 @@ static void t202_expire(void *vpri)
|
||||
case Q921_ESTABLISH_AWAITING_TEI:
|
||||
q921_discard_iqueue(ctrl);
|
||||
/* DL-RELEASE indication */
|
||||
q931_dl_indication(ctrl, PRI_EVENT_DCHAN_DOWN);
|
||||
q931_dl_event(ctrl, Q931_DL_EVENT_DL_RELEASE_IND);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -671,7 +671,7 @@ static void t200_expire(void *vpri)
|
||||
q921_mdl_error(ctrl, 'G');
|
||||
q921_setstate(ctrl, Q921_TEI_ASSIGNED);
|
||||
/* DL-RELEASE indication */
|
||||
q931_dl_indication(ctrl, PRI_EVENT_DCHAN_DOWN);
|
||||
q931_dl_event(ctrl, Q931_DL_EVENT_DL_RELEASE_IND);
|
||||
}
|
||||
break;
|
||||
case Q921_AWAITING_RELEASE:
|
||||
@ -682,6 +682,7 @@ static void t200_expire(void *vpri)
|
||||
} else {
|
||||
q921_mdl_error(ctrl, 'H');
|
||||
/* DL-RELEASE confirm */
|
||||
q931_dl_event(ctrl, Q931_DL_EVENT_DL_RELEASE_CONFIRM);
|
||||
q921_setstate(ctrl, Q921_TEI_ASSIGNED);
|
||||
}
|
||||
break;
|
||||
@ -1280,7 +1281,7 @@ static void q921_clear_exception_conditions(struct pri *ctrl)
|
||||
static pri_event * q921_sabme_rx(struct pri *ctrl, q921_h *h)
|
||||
{
|
||||
pri_event *res = NULL;
|
||||
int delay_q931_dl_indication;
|
||||
enum Q931_DL_EVENT delay_q931_dl_event;
|
||||
|
||||
switch (ctrl->q921_state) {
|
||||
case Q921_TIMER_RECOVERY:
|
||||
@ -1293,17 +1294,17 @@ static pri_event * q921_sabme_rx(struct pri *ctrl, q921_h *h)
|
||||
if (ctrl->v_s != ctrl->v_a) {
|
||||
q921_discard_iqueue(ctrl);
|
||||
/* DL-ESTABLISH indication */
|
||||
delay_q931_dl_indication = 1;
|
||||
delay_q931_dl_event = Q931_DL_EVENT_DL_ESTABLISH_IND;
|
||||
} else {
|
||||
delay_q931_dl_indication = 0;
|
||||
delay_q931_dl_event = Q931_DL_EVENT_NONE;
|
||||
}
|
||||
stop_t200(ctrl);
|
||||
start_t203(ctrl);
|
||||
ctrl->v_s = ctrl->v_a = ctrl->v_r = 0;
|
||||
q921_setstate(ctrl, Q921_MULTI_FRAME_ESTABLISHED);
|
||||
if (delay_q931_dl_indication) {
|
||||
if (delay_q931_dl_event != Q931_DL_EVENT_NONE) {
|
||||
/* Delayed because Q.931 could send STATUS messages. */
|
||||
q931_dl_indication(ctrl, PRI_EVENT_DCHAN_UP);
|
||||
q931_dl_event(ctrl, delay_q931_dl_event);
|
||||
}
|
||||
break;
|
||||
case Q921_TEI_ASSIGNED:
|
||||
@ -1311,17 +1312,16 @@ static pri_event * q921_sabme_rx(struct pri *ctrl, q921_h *h)
|
||||
q921_clear_exception_conditions(ctrl);
|
||||
ctrl->v_s = ctrl->v_a = ctrl->v_r = 0;
|
||||
/* DL-ESTABLISH indication */
|
||||
//delay_q931_dl_indication = 1;
|
||||
delay_q931_dl_event = Q931_DL_EVENT_DL_ESTABLISH_IND;
|
||||
if (PTP_MODE(ctrl)) {
|
||||
ctrl->ev.gen.e = PRI_EVENT_DCHAN_UP;
|
||||
res = &ctrl->ev;
|
||||
}
|
||||
start_t203(ctrl);
|
||||
q921_setstate(ctrl, Q921_MULTI_FRAME_ESTABLISHED);
|
||||
//if (delay_q931_dl_indication)
|
||||
{
|
||||
if (delay_q931_dl_event != Q931_DL_EVENT_NONE) {
|
||||
/* Delayed because Q.931 could send STATUS messages. */
|
||||
q931_dl_indication(ctrl, PRI_EVENT_DCHAN_UP);
|
||||
q931_dl_event(ctrl, delay_q931_dl_event);
|
||||
}
|
||||
break;
|
||||
case Q921_AWAITING_ESTABLISHMENT:
|
||||
@ -1360,7 +1360,7 @@ static pri_event *q921_disc_rx(struct pri *ctrl, q921_h *h)
|
||||
q921_discard_iqueue(ctrl);
|
||||
q921_send_ua(ctrl, h->u.p_f);
|
||||
/* DL-RELEASE indication */
|
||||
q931_dl_indication(ctrl, PRI_EVENT_DCHAN_DOWN);
|
||||
q931_dl_event(ctrl, Q931_DL_EVENT_DL_RELEASE_IND);
|
||||
stop_t200(ctrl);
|
||||
if (ctrl->q921_state == Q921_MULTI_FRAME_ESTABLISHED)
|
||||
stop_t203(ctrl);
|
||||
@ -1402,20 +1402,21 @@ static void q921_mdl_remove(struct pri *ctrl)
|
||||
case Q921_AWAITING_ESTABLISHMENT:
|
||||
q921_discard_iqueue(ctrl);
|
||||
/* DL-RELEASE indication */
|
||||
q931_dl_indication(ctrl, PRI_EVENT_DCHAN_DOWN);
|
||||
q931_dl_event(ctrl, Q931_DL_EVENT_DL_RELEASE_IND);
|
||||
stop_t200(ctrl);
|
||||
q921_setstate(ctrl, Q921_TEI_UNASSIGNED);
|
||||
break;
|
||||
case Q921_AWAITING_RELEASE:
|
||||
q921_discard_iqueue(ctrl);
|
||||
/* DL-RELEASE confirm */
|
||||
q931_dl_event(ctrl, Q931_DL_EVENT_DL_RELEASE_CONFIRM);
|
||||
stop_t200(ctrl);
|
||||
q921_setstate(ctrl, Q921_TEI_UNASSIGNED);
|
||||
break;
|
||||
case Q921_MULTI_FRAME_ESTABLISHED:
|
||||
q921_discard_iqueue(ctrl);
|
||||
/* DL-RELEASE indication */
|
||||
q931_dl_indication(ctrl, PRI_EVENT_DCHAN_DOWN);
|
||||
q931_dl_event(ctrl, Q931_DL_EVENT_DL_RELEASE_IND);
|
||||
stop_t200(ctrl);
|
||||
stop_t203(ctrl);
|
||||
q921_setstate(ctrl, Q921_TEI_UNASSIGNED);
|
||||
@ -1423,7 +1424,7 @@ static void q921_mdl_remove(struct pri *ctrl)
|
||||
case Q921_TIMER_RECOVERY:
|
||||
q921_discard_iqueue(ctrl);
|
||||
/* DL-RELEASE indication */
|
||||
q931_dl_indication(ctrl, PRI_EVENT_DCHAN_DOWN);
|
||||
q931_dl_event(ctrl, Q931_DL_EVENT_DL_RELEASE_IND);
|
||||
stop_t200(ctrl);
|
||||
q921_setstate(ctrl, Q921_TEI_UNASSIGNED);
|
||||
break;
|
||||
@ -1433,7 +1434,7 @@ static void q921_mdl_remove(struct pri *ctrl)
|
||||
return;
|
||||
}
|
||||
|
||||
q931_dl_tei_removal(ctrl);
|
||||
q931_dl_event(ctrl, Q931_DL_EVENT_TEI_REMOVAL);
|
||||
|
||||
/*
|
||||
* Negate the TEI value so debug messages will display a
|
||||
@ -1711,7 +1712,7 @@ static void q921_mdl_error(struct pri *ctrl, char error)
|
||||
static pri_event *q921_ua_rx(struct pri *ctrl, q921_h *h)
|
||||
{
|
||||
pri_event *res = NULL;
|
||||
int delay_q931_dl_indication;
|
||||
enum Q931_DL_EVENT delay_q931_dl_event;
|
||||
|
||||
if (ctrl->debug & PRI_DEBUG_Q921_STATE) {
|
||||
pri_message(ctrl, "TEI=%d Got UA\n", ctrl->tei);
|
||||
@ -1733,16 +1734,17 @@ static pri_event *q921_ua_rx(struct pri *ctrl, q921_h *h)
|
||||
break;
|
||||
}
|
||||
|
||||
delay_q931_dl_indication = 0;
|
||||
delay_q931_dl_event = Q931_DL_EVENT_NONE;
|
||||
if (!ctrl->l3initiated) {
|
||||
if (ctrl->v_s != ctrl->v_a) {
|
||||
q921_discard_iqueue(ctrl);
|
||||
/* DL-ESTABLISH indication */
|
||||
delay_q931_dl_indication = 1;
|
||||
delay_q931_dl_event = Q931_DL_EVENT_DL_ESTABLISH_IND;
|
||||
}
|
||||
} else {
|
||||
ctrl->l3initiated = 0;
|
||||
/* DL-ESTABLISH confirm */
|
||||
delay_q931_dl_event = Q931_DL_EVENT_DL_ESTABLISH_CONFIRM;
|
||||
}
|
||||
|
||||
if (PTP_MODE(ctrl)) {
|
||||
@ -1756,9 +1758,9 @@ static pri_event *q921_ua_rx(struct pri *ctrl, q921_h *h)
|
||||
ctrl->v_r = ctrl->v_s = ctrl->v_a = 0;
|
||||
|
||||
q921_setstate(ctrl, Q921_MULTI_FRAME_ESTABLISHED);
|
||||
if (delay_q931_dl_indication) {
|
||||
if (delay_q931_dl_event != Q931_DL_EVENT_NONE) {
|
||||
/* Delayed because Q.931 could send STATUS messages. */
|
||||
q931_dl_indication(ctrl, PRI_EVENT_DCHAN_UP);
|
||||
q931_dl_event(ctrl, delay_q931_dl_event);
|
||||
}
|
||||
break;
|
||||
case Q921_AWAITING_RELEASE:
|
||||
@ -1766,6 +1768,7 @@ static pri_event *q921_ua_rx(struct pri *ctrl, q921_h *h)
|
||||
q921_mdl_error(ctrl, 'D');
|
||||
} else {
|
||||
/* DL-RELEASE confirm */
|
||||
q931_dl_event(ctrl, Q931_DL_EVENT_DL_RELEASE_CONFIRM);
|
||||
stop_t200(ctrl);
|
||||
q921_setstate(ctrl, Q921_TEI_ASSIGNED);
|
||||
}
|
||||
@ -2181,7 +2184,7 @@ static pri_event *q921_dm_rx(struct pri *ctrl, q921_h *h)
|
||||
|
||||
q921_discard_iqueue(ctrl);
|
||||
/* DL-RELEASE indication */
|
||||
q931_dl_indication(ctrl, PRI_EVENT_DCHAN_DOWN);
|
||||
q931_dl_event(ctrl, Q931_DL_EVENT_DL_RELEASE_IND);
|
||||
stop_t200(ctrl);
|
||||
q921_setstate(ctrl, Q921_TEI_ASSIGNED);
|
||||
q921_restart_ptp_link_if_needed(ctrl);
|
||||
@ -2190,6 +2193,7 @@ static pri_event *q921_dm_rx(struct pri *ctrl, q921_h *h)
|
||||
if (!h->u.p_f)
|
||||
break;
|
||||
/* DL-RELEASE confirm */
|
||||
q931_dl_event(ctrl, Q931_DL_EVENT_DL_RELEASE_CONFIRM);
|
||||
stop_t200(ctrl);
|
||||
q921_setstate(ctrl, Q921_TEI_ASSIGNED);
|
||||
break;
|
||||
|
186
q931.c
186
q931.c
@ -8379,81 +8379,50 @@ static void pri_dl_down_cancelcall(void *data)
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Layer 2 is removing the link's TEI.
|
||||
* \internal
|
||||
* \brief Convert the DL event to a string.
|
||||
*
|
||||
* \param link Q.921 link losing it's TEI.
|
||||
* \param event Data-link event to convert to a string.
|
||||
*
|
||||
* \note
|
||||
* For NT PTMP, this deviation from the specifications is needed
|
||||
* because we have no way to re-associate any T309 calls on the
|
||||
* removed TEI.
|
||||
* \return DL event string
|
||||
*/
|
||||
static const char *q931_dl_event2str(enum Q931_DL_EVENT event)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
str = "Unknown";
|
||||
switch (event) {
|
||||
case Q931_DL_EVENT_NONE:
|
||||
str = "Q931_DL_EVENT_NONE";
|
||||
break;
|
||||
case Q931_DL_EVENT_DL_ESTABLISH_IND:
|
||||
str = "Q931_DL_EVENT_DL_ESTABLISH_IND";
|
||||
break;
|
||||
case Q931_DL_EVENT_DL_ESTABLISH_CONFIRM:
|
||||
str = "Q931_DL_EVENT_DL_ESTABLISH_CONFIRM";
|
||||
break;
|
||||
case Q931_DL_EVENT_DL_RELEASE_IND:
|
||||
str = "Q931_DL_EVENT_DL_RELEASE_IND";
|
||||
break;
|
||||
case Q931_DL_EVENT_DL_RELEASE_CONFIRM:
|
||||
str = "Q931_DL_EVENT_DL_RELEASE_CONFIRM";
|
||||
break;
|
||||
case Q931_DL_EVENT_TEI_REMOVAL:
|
||||
str = "Q931_DL_EVENT_TEI_REMOVAL";
|
||||
break;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Receive a DL event from layer 2.
|
||||
*
|
||||
* \param link Q.921 link event occurred on.
|
||||
* \param event Data-link event reporting.
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
void q931_dl_tei_removal(struct pri *link)
|
||||
{
|
||||
struct q931_call *cur;
|
||||
struct q931_call *call;
|
||||
struct pri *ctrl;
|
||||
int idx;
|
||||
|
||||
/* Find the master - He has the call pool */
|
||||
ctrl = PRI_MASTER(link);
|
||||
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
|
||||
pri_message(ctrl, "DL TEI removal\n");
|
||||
}
|
||||
|
||||
if (!BRI_NT_PTMP(ctrl)) {
|
||||
/* Only NT PTMP has anything to worry about when the TEI is removed. */
|
||||
return;
|
||||
}
|
||||
|
||||
for (cur = *ctrl->callpool; cur; cur = cur->next) {
|
||||
if (!(cur->cr & ~Q931_CALL_REFERENCE_FLAG)) {
|
||||
/* Don't do anything on the global call reference call record. */
|
||||
continue;
|
||||
}
|
||||
if (cur->outboundbroadcast) {
|
||||
/* Does this master call have a subcall on the link that went down? */
|
||||
call = NULL;
|
||||
for (idx = 0; idx < ARRAY_LEN(cur->subcalls); ++idx) {
|
||||
if (cur->subcalls[idx] && cur->subcalls[idx]->pri == link) {
|
||||
/* This subcall is on the link that went down. */
|
||||
call = cur->subcalls[idx];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!call) {
|
||||
/* No subcall is on the link that went down. */
|
||||
continue;
|
||||
}
|
||||
} else if (cur->pri != link) {
|
||||
/* This call is not on the link that went down. */
|
||||
continue;
|
||||
} else {
|
||||
call = cur;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: We are gambling that no T309 timer's have had a chance
|
||||
* to expire. They should not expire since we are either called
|
||||
* immediately after the q931_dl_indication() or after a timeout
|
||||
* of 0.
|
||||
*/
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
|
||||
pri_message(ctrl, "Cancel call cref=%d on channel %d in state %d (%s)\n",
|
||||
call->cr, call->channelno, call->ourcallstate,
|
||||
q931_call_state_str(call->ourcallstate));
|
||||
}
|
||||
call->pri = ctrl;/* Point to a safer place until the call is destroyed. */
|
||||
pri_schedule_del(ctrl, call->retranstimer);
|
||||
call->retranstimer = pri_schedule_event(ctrl, 0, pri_dl_down_cancelcall, call);
|
||||
}
|
||||
}
|
||||
|
||||
/* Receive an indication from Layer 2 */
|
||||
void q931_dl_indication(struct pri *link, int event)
|
||||
void q931_dl_event(struct pri *link, enum Q931_DL_EVENT event)
|
||||
{
|
||||
struct q931_call *cur;
|
||||
struct q931_call *call;
|
||||
@ -8467,16 +8436,73 @@ void q931_dl_indication(struct pri *link, int event)
|
||||
/* Find the master - He has the call pool */
|
||||
ctrl = PRI_MASTER(link);
|
||||
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
|
||||
pri_message(ctrl, "TEI=%d DL event: %s(%d)\n", link->tei,
|
||||
q931_dl_event2str(event), event);
|
||||
}
|
||||
|
||||
if (BRI_TE_PTMP(ctrl)) {
|
||||
/* The link is always the master */
|
||||
link = ctrl;
|
||||
}
|
||||
|
||||
switch (event) {
|
||||
case PRI_EVENT_DCHAN_DOWN:
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
|
||||
pri_message(ctrl, "DL-RELEASE indication (link is DOWN)\n");
|
||||
case Q931_DL_EVENT_TEI_REMOVAL:
|
||||
if (!BRI_NT_PTMP(ctrl)) {
|
||||
/* Only NT PTMP has anything to worry about when the TEI is removed. */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* For NT PTMP, this deviation from the specifications is needed
|
||||
* because we have no way to re-associate any T309 calls on the
|
||||
* removed TEI.
|
||||
*/
|
||||
for (cur = *ctrl->callpool; cur; cur = cur->next) {
|
||||
if (!(cur->cr & ~Q931_CALL_REFERENCE_FLAG)) {
|
||||
/* Don't do anything on the global call reference call record. */
|
||||
continue;
|
||||
}
|
||||
if (cur->outboundbroadcast) {
|
||||
/* Does this master call have a subcall on the link that went down? */
|
||||
call = NULL;
|
||||
for (idx = 0; idx < ARRAY_LEN(cur->subcalls); ++idx) {
|
||||
if (cur->subcalls[idx] && cur->subcalls[idx]->pri == link) {
|
||||
/* This subcall is on the link that went down. */
|
||||
call = cur->subcalls[idx];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!call) {
|
||||
/* No subcall is on the link that went down. */
|
||||
continue;
|
||||
}
|
||||
} else if (cur->pri != link) {
|
||||
/* This call is not on the link that went down. */
|
||||
continue;
|
||||
} else {
|
||||
call = cur;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: We are gambling that no T309 timer's have had a chance
|
||||
* to expire. They should not expire since we are either called
|
||||
* immediately after the Q931_DL_EVENT_DL_RELEASE_xxx or after a
|
||||
* timeout of 0.
|
||||
*/
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
|
||||
pri_message(ctrl, "Cancel call cref=%d on channel %d in state %d (%s)\n",
|
||||
call->cr, call->channelno, call->ourcallstate,
|
||||
q931_call_state_str(call->ourcallstate));
|
||||
}
|
||||
call->pri = ctrl;/* Point to a safer place until the call is destroyed. */
|
||||
pri_schedule_del(ctrl, call->retranstimer);
|
||||
call->retranstimer = pri_schedule_event(ctrl, 0, pri_dl_down_cancelcall,
|
||||
call);
|
||||
}
|
||||
break;
|
||||
case Q931_DL_EVENT_DL_RELEASE_IND:
|
||||
case Q931_DL_EVENT_DL_RELEASE_CONFIRM:
|
||||
for (cur = *ctrl->callpool; cur; cur = cur->next) {
|
||||
if (!(cur->cr & ~Q931_CALL_REFERENCE_FLAG)) {
|
||||
/* Don't do anything on the global call reference call record. */
|
||||
@ -8557,10 +8583,8 @@ void q931_dl_indication(struct pri *link, int event)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PRI_EVENT_DCHAN_UP:
|
||||
if (ctrl->debug & PRI_DEBUG_Q931_STATE) {
|
||||
pri_message(ctrl, "DL-ESTABLISH indication (link is UP)\n");
|
||||
}
|
||||
case Q931_DL_EVENT_DL_ESTABLISH_IND:
|
||||
case Q931_DL_EVENT_DL_ESTABLISH_CONFIRM:
|
||||
for (cur = *ctrl->callpool; cur; cur = cur->next) {
|
||||
if (!(cur->cr & ~Q931_CALL_REFERENCE_FLAG)) {
|
||||
/* Don't do anything on the global call reference call record. */
|
||||
@ -8605,6 +8629,14 @@ void q931_dl_indication(struct pri *link, int event)
|
||||
case Q931_CALL_STATE_RELEASE_REQUEST:
|
||||
break;
|
||||
default:
|
||||
if (event == Q931_DL_EVENT_DL_ESTABLISH_CONFIRM) {
|
||||
/*
|
||||
* Lets not send a STATUS message for this call as we
|
||||
* requested the link to be established as a likely
|
||||
* result of this call.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* The STATUS message sent here is not required by Q.931,
|
||||
* but it may help anyway.
|
||||
|
Loading…
Reference in New Issue
Block a user