Improved HDLC abort handling

This commit is contained in:
Steve Underwood 2014-07-29 21:22:47 +08:00
parent 0732c0b027
commit af64da86f2
2 changed files with 62 additions and 16 deletions

View File

@ -126,7 +126,7 @@ static __inline__ void octet_count(hdlc_rx_state_t *s)
static void rx_flag_or_abort(hdlc_rx_state_t *s)
{
if ((s->raw_bit_stream & 0x8000))
if ((s->raw_bit_stream & 0x0100))
{
/* Hit HDLC abort */
s->rx_aborts++;
@ -196,7 +196,10 @@ static void rx_flag_or_abort(hdlc_rx_state_t *s)
{
/* Check the flags are back-to-back when testing for valid preamble. This
greatly reduces the chances of false preamble detection, and anything
which doesn't send them back-to-back is badly broken. */
which doesn't send them back-to-back is badly broken. When we are one
flag away from OK we should not apply the back-to-back consition, as
between an abort and the following start of frame things might not be
octet aligned. */
if (s->flags_seen != s->framing_ok_threshold - 1 && s->num_bits != 7)
{
/* Don't set the flags seen indicator back to zero too aggressively.
@ -222,13 +225,22 @@ static void rx_flag_or_abort(hdlc_rx_state_t *s)
static __inline__ void hdlc_rx_put_bit_core(hdlc_rx_state_t *s)
{
if ((s->raw_bit_stream & 0x3F00) == 0x3E00)
if ((s->raw_bit_stream & 0x3E00) == 0x3E00)
{
/* Its time to either skip a bit, for stuffing, or process a
flag or abort */
if ((s->raw_bit_stream & 0x4000))
/* There are at least 5 ones in a row. We could be at a:
- point where stuffing occurs
- a flag
- an abort
- the result of bit errors */
/* Is this a bit to be skipped for destuffing? */
if ((s->raw_bit_stream & 0x4100) == 0)
return;
/* Is this a flag or abort? */
if ((s->raw_bit_stream & 0xFE00) == 0x7E00)
{
rx_flag_or_abort(s);
return;
return;
}
}
s->num_bits++;
if (s->flags_seen < s->framing_ok_threshold)

View File

@ -152,6 +152,8 @@
/*! The number of consecutive flags to declare HDLC framing is OK. */
#define HDLC_FRAMING_OK_THRESHOLD 5
#define HDLC_TRAMISSION_LAG_OCTETS 2
enum
{
DISBIT1 = 0x01,
@ -1765,7 +1767,7 @@ static void rx_flag_or_abort(hdlc_rx_state_t *t)
s = (t38_gateway_state_t *) t->frame_user_data;
u = &s->core.to_t38;
if ((t->raw_bit_stream & 0x80))
if ((t->raw_bit_stream & 0x01))
{
/* Hit HDLC abort */
t->rx_aborts++;
@ -1774,6 +1776,23 @@ static void rx_flag_or_abort(hdlc_rx_state_t *t)
else
t->flags_seen = t->framing_ok_threshold - 1;
/*endif*/
if (t->len > 0)
{
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC frame aborted at %d\n", t->len);
/* If we have sent some of this frame we need to treat the abort as though it is a CRC error,
as reporting a bad CRC is the only way T.38 allows us to scrub a frame in progress. */
/* It seems some boxes may not like us sending a _SIG_END here, and then another
when the carrier actually drops. Lets just send T38_FIELD_HDLC_FCS_OK here. */
if (t->len > 2)
{
category = (s->t38x.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA : T38_PACKET_CATEGORY_IMAGE_DATA;
if (t38_core_send_data(&s->t38x.t38, s->t38x.current_tx_data_type, T38_FIELD_HDLC_FCS_BAD, NULL, 0, category) < 0)
span_log(&s->logging, SPAN_LOG_WARNING, "T.38 send failed\n");
/*endif*/
}
/*endif*/
}
/*endif*/
}
else
{
@ -1863,7 +1882,10 @@ static void rx_flag_or_abort(hdlc_rx_state_t *t)
{
/* Check the flags are back-to-back when testing for valid preamble. This
greatly reduces the chances of false preamble detection, and anything
which doesn't send them back-to-back is badly broken. */
which doesn't send them back-to-back is badly broken. When we are one
flag away from OK we should not apply the back-to-back consition, as
between an abort and the following start of frame things might not be
octet aligned. */
if (t->flags_seen != t->framing_ok_threshold - 1 && t->num_bits != 7)
t->flags_seen = 0;
/*endif*/
@ -1906,12 +1928,24 @@ static void t38_hdlc_rx_put_bit(hdlc_rx_state_t *t, int new_bit)
}
/*endif*/
t->raw_bit_stream = (t->raw_bit_stream << 1) | (new_bit & 1);
if ((t->raw_bit_stream & 0x3F) == 0x3E)
if ((t->raw_bit_stream & 0x3E) == 0x3E)
{
/* Its time to either skip a bit, for stuffing, or process a flag or abort */
if ((t->raw_bit_stream & 0x40))
/* There are at least 5 ones in a row. We could be at a:
- point where stuffing occurs
- a flag
- an abort
- the result of bit errors */
/* Is this a bit to be skipped for destuffing? */
if ((t->raw_bit_stream & 0x41) == 0)
return;
/*endif*/
/* Is this a flag or abort? */
if ((t->raw_bit_stream & 0xFE) == 0x7E)
{
rx_flag_or_abort(t);
return;
return;
}
/*endif*/
}
/*endif*/
t->num_bits++;
@ -1928,7 +1962,7 @@ static void t38_hdlc_rx_put_bit(hdlc_rx_state_t *t, int new_bit)
if (t->len >= (int) sizeof(t->buffer))
{
/* This is too long. Abandon the frame, and wait for the next flag octet. */
if ((t->len + 2) >= u->octets_per_data_packet)
if ((t->len + HDLC_TRAMISSION_LAG_OCTETS) >= u->octets_per_data_packet)
{
/* We will have sent some of this frame already, so we need to send termination of this bad HDLC frame. */
category = (s->t38x.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA : T38_PACKET_CATEGORY_IMAGE_DATA;
@ -1968,7 +2002,7 @@ static void t38_hdlc_rx_put_bit(hdlc_rx_state_t *t, int new_bit)
u->crc = crc_itu16_calc(&t->buffer[t->len], 1, u->crc);
/* Make the transmission lag by two octets, so we do not send the CRC, and
do not report the CRC result too late. */
if (++t->len <= 2)
if (++t->len <= HDLC_TRAMISSION_LAG_OCTETS)
return;
/*endif*/
if (s->t38x.current_tx_data_type == T38_DATA_V21)
@ -1979,7 +2013,7 @@ static void t38_hdlc_rx_put_bit(hdlc_rx_state_t *t, int new_bit)
}
if (++u->data_ptr >= u->octets_per_data_packet)
{
bit_reverse(u->data, &t->buffer[t->len - 2 - u->data_ptr], u->data_ptr);
bit_reverse(u->data, &t->buffer[t->len - HDLC_TRAMISSION_LAG_OCTETS - u->data_ptr], u->data_ptr);
category = (s->t38x.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA : T38_PACKET_CATEGORY_IMAGE_DATA;
if (t38_core_send_data(&s->t38x.t38, s->t38x.current_tx_data_type, T38_FIELD_HDLC_DATA, u->data, u->data_ptr, category) < 0)
span_log(&s->logging, SPAN_LOG_WARNING, "T.38 send failed\n");