Make spandsp's T.38 features tolerate the non-compliant inclusion of data
in some T.38 packets from Commetrex and Cisco machines.
This commit is contained in:
parent
744f3ab714
commit
7e79b37c0b
|
@ -396,6 +396,21 @@ static int process_rx_indicator(t38_core_state_t *t, void *user_data, int indica
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void process_hdlc_data(t31_t38_front_end_state_t *fe, const uint8_t *buf, int len)
|
||||
{
|
||||
if (fe->hdlc_rx.len + len <= T31_T38_MAX_HDLC_LEN)
|
||||
{
|
||||
bit_reverse(fe->hdlc_rx.buf + fe->hdlc_rx.len, buf, len);
|
||||
fe->hdlc_rx.len += len;
|
||||
}
|
||||
else
|
||||
{
|
||||
fe->rx_data_missing = TRUE;
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type, int field_type, const uint8_t *buf, int len)
|
||||
{
|
||||
t31_state_t *s;
|
||||
|
@ -451,16 +466,7 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
|||
/*endif*/
|
||||
if (len > 0)
|
||||
{
|
||||
if (fe->hdlc_rx.len + len <= T31_T38_MAX_HDLC_LEN)
|
||||
{
|
||||
bit_reverse(fe->hdlc_rx.buf + fe->hdlc_rx.len, buf, len);
|
||||
fe->hdlc_rx.len += len;
|
||||
}
|
||||
else
|
||||
{
|
||||
fe->rx_data_missing = TRUE;
|
||||
}
|
||||
/*endif*/
|
||||
process_hdlc_data(fe, buf, len);
|
||||
}
|
||||
/*endif*/
|
||||
fe->timeout_rx_samples = fe->samples + ms_to_samples(MID_RX_TIMEOUT);
|
||||
|
@ -469,14 +475,15 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
|||
if (len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_OK!\n");
|
||||
/* The sender has incorrectly included data in this message. It is unclear what we should do
|
||||
with it, to maximise tolerance of buggy implementations. */
|
||||
/* The sender has incorrectly included data in this message. Cisco implemented inserting
|
||||
HDLC data here and Commetrex followed for compatibility reasons. We should, too. */
|
||||
process_hdlc_data(fe, buf, len);
|
||||
}
|
||||
/*endif*/
|
||||
/* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_OK messages, in IFP packets with
|
||||
incrementing sequence numbers, which are actually repeats. They get through to this point because
|
||||
of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */
|
||||
if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type)
|
||||
if (fe->hdlc_rx.len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC OK (%s)\n", (fe->hdlc_rx.len >= 3) ? t30_frametype(fe->hdlc_rx.buf[2]) : "???", (fe->rx_data_missing) ? "missing octets" : "clean");
|
||||
if (data_type == T38_DATA_V21)
|
||||
|
@ -504,9 +511,9 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
|||
hdlc_accept_t38_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, !fe->rx_data_missing);
|
||||
}
|
||||
/*endif*/
|
||||
fe->hdlc_rx.len = 0;
|
||||
}
|
||||
/*endif*/
|
||||
fe->hdlc_rx.len = 0;
|
||||
fe->rx_data_missing = FALSE;
|
||||
fe->timeout_rx_samples = fe->samples + ms_to_samples(MID_RX_TIMEOUT);
|
||||
break;
|
||||
|
@ -514,14 +521,15 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
|||
if (len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_BAD!\n");
|
||||
/* The sender has incorrectly included data in this message. We can safely ignore it, as the
|
||||
bad FCS means we will throw away the whole message, anyway. */
|
||||
/* The sender has incorrectly included data in this message. Cisco implemented inserting
|
||||
HDLC data here and Commetrex followed for compatibility reasons. We should, too. */
|
||||
process_hdlc_data(fe, buf, len);
|
||||
}
|
||||
/*endif*/
|
||||
/* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_BAD messages, in IFP packets with
|
||||
incrementing sequence numbers, which are actually repeats. They get through to this point because
|
||||
of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */
|
||||
if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type)
|
||||
if (fe->hdlc_rx.len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC bad (%s)\n", (fe->hdlc_rx.len >= 3) ? t30_frametype(fe->hdlc_rx.buf[2]) : "???", (fe->rx_data_missing) ? "missing octets" : "clean");
|
||||
if (data_type == T38_DATA_V21)
|
||||
|
@ -529,9 +537,9 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
|||
else
|
||||
hdlc_accept_t38_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, FALSE);
|
||||
/*endif*/
|
||||
fe->hdlc_rx.len = 0;
|
||||
}
|
||||
/*endif*/
|
||||
fe->hdlc_rx.len = 0;
|
||||
fe->rx_data_missing = FALSE;
|
||||
fe->timeout_rx_samples = fe->samples + ms_to_samples(MID_RX_TIMEOUT);
|
||||
break;
|
||||
|
@ -539,14 +547,15 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
|||
if (len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_OK_SIG_END!\n");
|
||||
/* The sender has incorrectly included data in this message. It is unclear what we should do
|
||||
with it, to maximise tolerance of buggy implementations. */
|
||||
/* The sender has incorrectly included data in this message. Cisco implemented inserting
|
||||
HDLC data here and Commetrex followed for compatibility reasons. We should, too. */
|
||||
process_hdlc_data(fe, buf, len);
|
||||
}
|
||||
/*endif*/
|
||||
/* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_OK_SIG_END messages, in IFP packets with
|
||||
incrementing sequence numbers, which are actually repeats. They get through to this point because
|
||||
of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */
|
||||
if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type)
|
||||
if (fe->hdlc_rx.len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC OK, sig end (%s)\n", (fe->hdlc_rx.len >= 3) ? t30_frametype(fe->hdlc_rx.buf[2]) : "???", (fe->rx_data_missing) ? "missing octets" : "clean");
|
||||
if (data_type == T38_DATA_V21)
|
||||
|
@ -568,49 +577,60 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
|||
/*endif*/
|
||||
crc_itu16_append(fe->hdlc_rx.buf, fe->hdlc_rx.len);
|
||||
hdlc_accept_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, !fe->rx_data_missing);
|
||||
hdlc_rx_status(s, SIG_STATUS_CARRIER_DOWN);
|
||||
}
|
||||
else
|
||||
{
|
||||
hdlc_accept_t38_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, !fe->rx_data_missing);
|
||||
non_ecm_rx_status(s, SIG_STATUS_CARRIER_DOWN);
|
||||
}
|
||||
/*endif*/
|
||||
fe->hdlc_rx.len = 0;
|
||||
}
|
||||
/*endif*/
|
||||
fe->rx_data_missing = FALSE;
|
||||
if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type)
|
||||
{
|
||||
if (data_type == T38_DATA_V21)
|
||||
hdlc_rx_status(s, SIG_STATUS_CARRIER_DOWN);
|
||||
else
|
||||
non_ecm_rx_status(s, SIG_STATUS_CARRIER_DOWN);
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
fe->hdlc_rx.len = 0;
|
||||
fe->rx_data_missing = FALSE;
|
||||
fe->timeout_rx_samples = 0;
|
||||
break;
|
||||
case T38_FIELD_HDLC_FCS_BAD_SIG_END:
|
||||
if (len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_BAD_SIG_END!\n");
|
||||
/* The sender has incorrectly included data in this message. We can safely ignore it, as the
|
||||
bad FCS means we will throw away the whole message, anyway. */
|
||||
/* The sender has incorrectly included data in this message. Cisco implemented inserting
|
||||
HDLC data here and Commetrex followed for compatibility reasons. We should, too. */
|
||||
process_hdlc_data(fe, buf, len);
|
||||
}
|
||||
/*endif*/
|
||||
/* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_BAD_SIG_END messages, in IFP packets with
|
||||
incrementing sequence numbers, which are actually repeats. They get through to this point because
|
||||
of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */
|
||||
if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type)
|
||||
if (fe->hdlc_rx.len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC bad, sig end (%s)\n", (fe->hdlc_rx.len >= 3) ? t30_frametype(fe->hdlc_rx.buf[2]) : "???", (fe->rx_data_missing) ? "missing octets" : "clean");
|
||||
if (data_type == T38_DATA_V21)
|
||||
{
|
||||
hdlc_accept_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, FALSE);
|
||||
hdlc_rx_status(s, SIG_STATUS_CARRIER_DOWN);
|
||||
}
|
||||
else
|
||||
{
|
||||
hdlc_accept_t38_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, FALSE);
|
||||
/*endif*/
|
||||
fe->hdlc_rx.len = 0;
|
||||
}
|
||||
/*endif*/
|
||||
fe->rx_data_missing = FALSE;
|
||||
if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type)
|
||||
{
|
||||
if (data_type == T38_DATA_V21)
|
||||
hdlc_rx_status(s, SIG_STATUS_CARRIER_DOWN);
|
||||
else
|
||||
non_ecm_rx_status(s, SIG_STATUS_CARRIER_DOWN);
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
fe->hdlc_rx.len = 0;
|
||||
fe->rx_data_missing = FALSE;
|
||||
fe->timeout_rx_samples = 0;
|
||||
break;
|
||||
case T38_FIELD_HDLC_SIG_END:
|
||||
|
|
|
@ -935,9 +935,55 @@ static int process_rx_indicator(t38_core_state_t *t, void *user_data, int indica
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void process_hdlc_data(t38_gateway_state_t *s, int data_type, const uint8_t *buf, int len)
|
||||
{
|
||||
t38_gateway_hdlc_buf_t *hdlc_buf;
|
||||
int i;
|
||||
|
||||
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
|
||||
/* Check if this data would overflow the buffer. */
|
||||
if (hdlc_buf->len + len > T38_MAX_HDLC_LEN)
|
||||
{
|
||||
s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in].flags |= HDLC_FLAG_MISSING_DATA;
|
||||
return;
|
||||
}
|
||||
/*endif*/
|
||||
hdlc_buf->contents = (data_type | FLAG_DATA);
|
||||
bit_reverse(&hdlc_buf->buf[hdlc_buf->len], buf, len);
|
||||
/* We need to send out the control messages as they are arriving. They are
|
||||
too slow to capture a whole frame before starting to pass it on.
|
||||
For the faster frames, take in the whole frame before sending it out. Also, there
|
||||
is no need to monitor, or modify, the contents of the faster frames. */
|
||||
if (data_type == T38_DATA_V21)
|
||||
{
|
||||
for (i = 1; i <= len; i++)
|
||||
edit_control_messages(s, 0, hdlc_buf->buf, hdlc_buf->len + i);
|
||||
/*endfor*/
|
||||
/* Don't start pumping data into the actual output stream until there is
|
||||
enough backlog to create some elasticity for jitter tolerance. */
|
||||
if (hdlc_buf->len + len >= HDLC_START_BUFFER_LEVEL)
|
||||
{
|
||||
if (s->core.hdlc_to_modem.in == s->core.hdlc_to_modem.out)
|
||||
{
|
||||
/* Output is not running, so kick it into life. */
|
||||
if ((hdlc_buf->flags & HDLC_FLAG_PROCEED_WITH_OUTPUT) == 0)
|
||||
hdlc_tx_frame(&s->audio.modems.hdlc_tx, hdlc_buf->buf, hdlc_buf->len + len);
|
||||
else
|
||||
hdlc_tx_frame(&s->audio.modems.hdlc_tx, hdlc_buf->buf + hdlc_buf->len, len);
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
hdlc_buf->flags |= HDLC_FLAG_PROCEED_WITH_OUTPUT;
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
hdlc_buf->len += len;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type, int field_type, const uint8_t *buf, int len)
|
||||
{
|
||||
int i;
|
||||
t38_gateway_state_t *s;
|
||||
t38_gateway_t38_state_t *xx;
|
||||
t38_gateway_hdlc_buf_t *hdlc_buf;
|
||||
|
@ -1016,47 +1062,9 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
|||
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
|
||||
}
|
||||
/*endif*/
|
||||
/* Check if this data would overflow the buffer. */
|
||||
if (len <= 0)
|
||||
break;
|
||||
if (len > 0)
|
||||
process_hdlc_data(s, data_type, buf, len);
|
||||
/*endif*/
|
||||
if (hdlc_buf->len + len > T38_MAX_HDLC_LEN)
|
||||
{
|
||||
s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in].flags |= HDLC_FLAG_MISSING_DATA;
|
||||
break;
|
||||
}
|
||||
/*endif*/
|
||||
hdlc_buf->contents = (data_type | FLAG_DATA);
|
||||
bit_reverse(&hdlc_buf->buf[hdlc_buf->len], buf, len);
|
||||
/* We need to send out the control messages as they are arriving. They are
|
||||
too slow to capture a whole frame before starting to pass it on.
|
||||
For the faster frames, take in the whole frame before sending it out. Also, there
|
||||
is no need to monitor, or modify, the contents of the faster frames. */
|
||||
if (data_type == T38_DATA_V21)
|
||||
{
|
||||
for (i = 1; i <= len; i++)
|
||||
edit_control_messages(s, 0, hdlc_buf->buf, hdlc_buf->len + i);
|
||||
/*endfor*/
|
||||
/* Don't start pumping data into the actual output stream until there is
|
||||
enough backlog to create some elasticity for jitter tolerance. */
|
||||
if (hdlc_buf->len + len >= HDLC_START_BUFFER_LEVEL)
|
||||
{
|
||||
if (s->core.hdlc_to_modem.in == s->core.hdlc_to_modem.out)
|
||||
{
|
||||
/* Output is not running, so kick it into life. */
|
||||
if ((hdlc_buf->flags & HDLC_FLAG_PROCEED_WITH_OUTPUT) == 0)
|
||||
hdlc_tx_frame(&s->audio.modems.hdlc_tx, hdlc_buf->buf, hdlc_buf->len + len);
|
||||
else
|
||||
hdlc_tx_frame(&s->audio.modems.hdlc_tx, hdlc_buf->buf + hdlc_buf->len, len);
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
hdlc_buf->flags |= HDLC_FLAG_PROCEED_WITH_OUTPUT;
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in].len += len;
|
||||
break;
|
||||
case T38_FIELD_HDLC_FCS_OK:
|
||||
xx->current_rx_field_class = T38_FIELD_CLASS_HDLC;
|
||||
|
@ -1064,14 +1072,15 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
|||
if (len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_OK!\n");
|
||||
/* The sender has incorrectly included data in this message. It is unclear what we should do
|
||||
with it, to maximise tolerance of buggy implementations. */
|
||||
/* The sender has incorrectly included data in this message. Cisco implemented inserting
|
||||
HDLC data here and Commetrex followed for compatibility reasons. We should, too. */
|
||||
process_hdlc_data(s, data_type, buf, len);
|
||||
}
|
||||
/*endif*/
|
||||
/* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_OK messages, in IFP packets with
|
||||
incrementing sequence numbers, which are actually repeats. They get through to this point because
|
||||
of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */
|
||||
if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type)
|
||||
if (hdlc_buf->len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC frame type %s - CRC OK\n", t30_frametype(hdlc_buf->buf[2]));
|
||||
if (hdlc_buf->contents != (data_type | FLAG_DATA))
|
||||
|
@ -1112,14 +1121,15 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
|||
if (len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_BAD!\n");
|
||||
/* The sender has incorrectly included data in this message. We can safely ignore it, as the
|
||||
bad FCS means we will throw away the whole message, anyway. */
|
||||
/* The sender has incorrectly included data in this message. Cisco implemented inserting
|
||||
HDLC data here and Commetrex followed for compatibility reasons. We should, too. */
|
||||
process_hdlc_data(s, data_type, buf, len);
|
||||
}
|
||||
/*endif*/
|
||||
/* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_BAD messages, in IFP packets with
|
||||
incrementing sequence numbers, which are actually repeats. They get through to this point because
|
||||
of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */
|
||||
if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type)
|
||||
if (hdlc_buf->len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC frame type %s - CRC bad\n", t30_frametype(hdlc_buf->buf[2]));
|
||||
/* Only bother with frames that have a bad CRC, if they also have some content. */
|
||||
|
@ -1150,14 +1160,15 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
|||
if (len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_OK_SIG_END!\n");
|
||||
/* The sender has incorrectly included data in this message. It is unclear what we should do
|
||||
with it, to maximise tolerance of buggy implementations. */
|
||||
/* The sender has incorrectly included data in this message. Cisco implemented inserting
|
||||
HDLC data here and Commetrex followed for compatibility reasons. We should, too. */
|
||||
process_hdlc_data(s, data_type, buf, len);
|
||||
}
|
||||
/*endif*/
|
||||
/* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_OK_SIG_END messages, in IFP packets with
|
||||
incrementing sequence numbers, which are actually repeats. They get through to this point because
|
||||
of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */
|
||||
if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type)
|
||||
if (hdlc_buf->len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC frame type %s - CRC OK, sig end\n", t30_frametype(hdlc_buf->buf[2]));
|
||||
if (hdlc_buf->contents != (data_type | FLAG_DATA))
|
||||
|
@ -1188,6 +1199,10 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
|||
/*endif*/
|
||||
hdlc_buf->contents = (data_type | FLAG_DATA);
|
||||
finalise_hdlc_frame(s, TRUE);
|
||||
}
|
||||
/*endif*/
|
||||
if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type)
|
||||
{
|
||||
queue_missing_indicator(s, T38_DATA_NONE);
|
||||
xx->current_rx_field_class = T38_FIELD_CLASS_NONE;
|
||||
}
|
||||
|
@ -1200,14 +1215,15 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
|||
if (len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_BAD_SIG_END!\n");
|
||||
/* The sender has incorrectly included data in this message. We can safely ignore it, as the
|
||||
bad FCS means we will throw away the whole message, anyway. */
|
||||
/* The sender has incorrectly included data in this message. Cisco implemented inserting
|
||||
HDLC data here and Commetrex followed for compatibility reasons. We should, too. */
|
||||
process_hdlc_data(s, data_type, buf, len);
|
||||
}
|
||||
/*endif*/
|
||||
/* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_BAD_SIG_END messages, in IFP packets with
|
||||
incrementing sequence numbers, which are actually repeats. They get through to this point because
|
||||
of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */
|
||||
if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type)
|
||||
if (hdlc_buf->len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC frame type %s - CRC bad, sig end\n", t30_frametype(hdlc_buf->buf[2]));
|
||||
if (hdlc_buf->contents != (data_type | FLAG_DATA))
|
||||
|
@ -1228,6 +1244,10 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
|||
hdlc_buf->contents = 0;
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type)
|
||||
{
|
||||
queue_missing_indicator(s, T38_DATA_NONE);
|
||||
xx->current_rx_field_class = T38_FIELD_CLASS_NONE;
|
||||
}
|
||||
|
|
|
@ -318,6 +318,20 @@ static int fake_rx_indicator(t38_core_state_t *t, t38_terminal_state_t *s, int i
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void process_hdlc_data(t38_terminal_front_end_state_t *fe, const uint8_t *buf, int len)
|
||||
{
|
||||
if (fe->hdlc_rx.len + len <= T38_MAX_HDLC_LEN)
|
||||
{
|
||||
bit_reverse(fe->hdlc_rx.buf + fe->hdlc_rx.len, buf, len);
|
||||
fe->hdlc_rx.len += len;
|
||||
}
|
||||
else
|
||||
{
|
||||
fe->rx_data_missing = TRUE;
|
||||
}
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type, int field_type, const uint8_t *buf, int len)
|
||||
{
|
||||
t38_terminal_state_t *s;
|
||||
|
@ -416,16 +430,7 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
|||
/*endif*/
|
||||
if (len > 0)
|
||||
{
|
||||
if (fe->hdlc_rx.len + len <= T38_MAX_HDLC_LEN)
|
||||
{
|
||||
bit_reverse(fe->hdlc_rx.buf + fe->hdlc_rx.len, buf, len);
|
||||
fe->hdlc_rx.len += len;
|
||||
}
|
||||
else
|
||||
{
|
||||
fe->rx_data_missing = TRUE;
|
||||
}
|
||||
/*endif*/
|
||||
process_hdlc_data(fe, buf, len);
|
||||
}
|
||||
/*endif*/
|
||||
fe->timeout_rx_samples = fe->samples + ms_to_samples(MID_RX_TIMEOUT);
|
||||
|
@ -434,20 +439,21 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
|||
if (len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_OK!\n");
|
||||
/* The sender has incorrectly included data in this message. It is unclear what we should do
|
||||
with it, to maximise tolerance of buggy implementations. */
|
||||
/* The sender has incorrectly included data in this message. Cisco implemented inserting
|
||||
HDLC data here and Commetrex followed for compatibility reasons. We should, too. */
|
||||
process_hdlc_data(fe, buf, len);
|
||||
}
|
||||
/*endif*/
|
||||
/* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_OK messages, in IFP packets with
|
||||
incrementing sequence numbers, which are actually repeats. They get through to this point because
|
||||
of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */
|
||||
if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type)
|
||||
if (fe->hdlc_rx.len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC OK (%s)\n", (fe->hdlc_rx.len >= 3) ? t30_frametype(fe->hdlc_rx.buf[2]) : "???", (fe->rx_data_missing) ? "missing octets" : "clean");
|
||||
hdlc_accept_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, !fe->rx_data_missing);
|
||||
fe->hdlc_rx.len = 0;
|
||||
}
|
||||
/*endif*/
|
||||
fe->hdlc_rx.len = 0;
|
||||
fe->rx_data_missing = FALSE;
|
||||
fe->timeout_rx_samples = fe->samples + ms_to_samples(MID_RX_TIMEOUT);
|
||||
break;
|
||||
|
@ -455,20 +461,21 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
|||
if (len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_BAD!\n");
|
||||
/* The sender has incorrectly included data in this message. We can safely ignore it, as the
|
||||
bad FCS means we will throw away the whole message, anyway. */
|
||||
/* The sender has incorrectly included data in this message. Cisco implemented inserting
|
||||
HDLC data here and Commetrex followed for compatibility reasons. We should, too. */
|
||||
process_hdlc_data(fe, buf, len);
|
||||
}
|
||||
/*endif*/
|
||||
/* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_BAD messages, in IFP packets with
|
||||
incrementing sequence numbers, which are actually repeats. They get through to this point because
|
||||
of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */
|
||||
if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type)
|
||||
if (fe->hdlc_rx.len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC bad (%s)\n", (fe->hdlc_rx.len >= 3) ? t30_frametype(fe->hdlc_rx.buf[2]) : "???", (fe->rx_data_missing) ? "missing octets" : "clean");
|
||||
hdlc_accept_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, FALSE);
|
||||
fe->hdlc_rx.len = 0;
|
||||
}
|
||||
/*endif*/
|
||||
fe->hdlc_rx.len = 0;
|
||||
fe->rx_data_missing = FALSE;
|
||||
fe->timeout_rx_samples = fe->samples + ms_to_samples(MID_RX_TIMEOUT);
|
||||
break;
|
||||
|
@ -476,22 +483,25 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
|||
if (len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_OK_SIG_END!\n");
|
||||
/* The sender has incorrectly included data in this message. It is unclear what we should do
|
||||
with it, to maximise tolerance of buggy implementations. */
|
||||
/* The sender has incorrectly included data in this message. Cisco implemented inserting
|
||||
HDLC data here and Commetrex followed for compatibility reasons. We should, too. */
|
||||
process_hdlc_data(fe, buf, len);
|
||||
}
|
||||
/*endif*/
|
||||
/* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_OK_SIG_END messages, in IFP packets with
|
||||
incrementing sequence numbers, which are actually repeats. They get through to this point because
|
||||
of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */
|
||||
if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type)
|
||||
if (fe->hdlc_rx.len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC OK, sig end (%s)\n", (fe->hdlc_rx.len >= 3) ? t30_frametype(fe->hdlc_rx.buf[2]) : "???", (fe->rx_data_missing) ? "missing octets" : "clean");
|
||||
hdlc_accept_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, !fe->rx_data_missing);
|
||||
hdlc_accept_frame(s, NULL, SIG_STATUS_CARRIER_DOWN, TRUE);
|
||||
fe->hdlc_rx.len = 0;
|
||||
}
|
||||
/*endif*/
|
||||
fe->hdlc_rx.len = 0;
|
||||
fe->rx_data_missing = FALSE;
|
||||
if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type)
|
||||
hdlc_accept_frame(s, NULL, SIG_STATUS_CARRIER_DOWN, TRUE);
|
||||
/*endif*/
|
||||
/* Treat this like a no signal indicator has occurred, so if the no signal indicator is missing, we are still OK */
|
||||
fake_rx_indicator(t, s, T38_IND_NO_SIGNAL);
|
||||
break;
|
||||
|
@ -499,22 +509,25 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
|||
if (len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_BAD_SIG_END!\n");
|
||||
/* The sender has incorrectly included data in this message. We can safely ignore it, as the
|
||||
bad FCS means we will throw away the whole message, anyway. */
|
||||
/* The sender has incorrectly included data in this message. Cisco implemented inserting
|
||||
HDLC data here and Commetrex followed for compatibility reasons. We should, too. */
|
||||
process_hdlc_data(fe, buf, len);
|
||||
}
|
||||
/*endif*/
|
||||
/* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_BAD_SIG_END messages, in IFP packets with
|
||||
incrementing sequence numbers, which are actually repeats. They get through to this point because
|
||||
of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */
|
||||
if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type)
|
||||
if (fe->hdlc_rx.len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC bad, sig end (%s)\n", (fe->hdlc_rx.len >= 3) ? t30_frametype(fe->hdlc_rx.buf[2]) : "???", (fe->rx_data_missing) ? "missing octets" : "clean");
|
||||
hdlc_accept_frame(s, fe->hdlc_rx.buf, fe->hdlc_rx.len, FALSE);
|
||||
hdlc_accept_frame(s, NULL, SIG_STATUS_CARRIER_DOWN, TRUE);
|
||||
fe->hdlc_rx.len = 0;
|
||||
}
|
||||
/*endif*/
|
||||
fe->hdlc_rx.len = 0;
|
||||
fe->rx_data_missing = FALSE;
|
||||
if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type)
|
||||
hdlc_accept_frame(s, NULL, SIG_STATUS_CARRIER_DOWN, TRUE);
|
||||
/*endif*/
|
||||
/* Treat this like a no signal indicator has occurred, so if the no signal indicator is missing, we are still OK */
|
||||
fake_rx_indicator(t, s, T38_IND_NO_SIGNAL);
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue