Fixed updating of the modem type after a FAX ECM CTC.

This commit is contained in:
Steve Underwood 2014-06-28 16:43:05 +08:00
parent 7741f403f1
commit ad1e7e9632
3 changed files with 49 additions and 24 deletions

View File

@ -46,6 +46,10 @@ typedef struct
/*! \brief If NSF, NSC, and NSS are to be suppressed by altering their contents to
something the far end will not recognise, this is the amount to overwrite. */
int suppress_nsx_len[2];
/*! \brief If NSF, NSC, and NSS are to be suppressed by altering their contents to
something the far end will not recognise, this is the string to use for overwriting. */
uint8_t suppress_nsx_string[2][MAX_NSX_SUPPRESSION];
/*! \brief True if we need to corrupt the HDLC frame in progress, so the receiver cannot
interpret it. The two values are for the two directions. */
bool corrupt_current_frame[2];

View File

@ -38,6 +38,10 @@ to maximum the tolerance of jitter and packet loss on the IP network.
\section t38_gateway_page_sec_2 How does it work?
*/
/*! The maximum number of bytes to be zapped, in order to corrupt NSF,
NSS and NSC messages, so the receiver does not recognise them. */
#define MAX_NSX_SUPPRESSION 10
typedef struct t38_gateway_state_s t38_gateway_state_t;
/*!

View File

@ -148,6 +148,9 @@
/*! The number of transmissions of terminating data IFP packets */
#define DATA_END_TX_COUNT 3
/*! The number of consecutive flags to declare HDLC framing is OK. */
#define HDLC_FRAMING_OK_THRESHOLD 5
enum
{
DISBIT1 = 0x01,
@ -184,19 +187,6 @@ enum
TIMED_MODE_TCF_PREDICTABLE_MODEM_START_BEGIN,
};
/*! The maximum number of bytes to be zapped, in order to corrupt NSF,
NSS and NSC messages, so the receiver does not recognise them. */
#define MAX_NSX_SUPPRESSION 10
/*! The number of consecutive flags to declare HDLC framing is OK. */
#define HDLC_FRAMING_OK_THRESHOLD 5
static uint8_t nsx_overwrite[2][MAX_NSX_SUPPRESSION] =
{
{0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0},
};
static int restart_rx_modem(t38_gateway_state_t *s);
static int process_rx_indicator(t38_core_state_t *t, void *user_data, int indicator);
static void hdlc_underflow_handler(void *user_data);
@ -485,18 +475,18 @@ static void finalise_hdlc_frame(t38_gateway_state_t *s, int good_fcs)
}
/*- End of function --------------------------------------------------------*/
static void edit_control_messages(t38_gateway_state_t *s, int from_modem, uint8_t *buf, int len)
static void edit_control_messages(t38_gateway_state_t *s, bool from_modem, uint8_t *buf, int len)
{
/* Frames need to be fed to this routine byte by byte as they arrive. It basically just
edits the last byte received, based on the frame up to that point. */
if (s->t38x.corrupt_current_frame[from_modem])
if (s->t38x.corrupt_current_frame[(from_modem) ? 1 : 0])
{
/* We simply need to overwrite a section of the message, so it is not recognisable at
the receiver. This is used for the NSF, NSC, and NSS messages. Several strategies are
possible for the replacement data. If you have a manufacturer code of your own, the
sane thing is to overwrite the original data with that. */
if (len <= s->t38x.suppress_nsx_len[from_modem])
buf[len - 1] = nsx_overwrite[from_modem][len - 4];
if (len <= s->t38x.suppress_nsx_len[(from_modem) ? 1 : 0])
buf[len - 1] = s->t38x.suppress_nsx_string[(from_modem) ? 1 : 0][len - 1 - 3];
/*endif*/
return;
}
@ -510,13 +500,13 @@ static void edit_control_messages(t38_gateway_state_t *s, int from_modem, uint8_
case T30_NSF:
case T30_NSC:
case T30_NSS:
if (s->t38x.suppress_nsx_len[from_modem])
if (s->t38x.suppress_nsx_len[(from_modem) ? 1 : 0])
{
/* Corrupt the message, so it will be ignored by the far end. If it were
processed, 2 machines which recognise each other might do special things
we cannot handle as a middle man. */
span_log(&s->logging, SPAN_LOG_FLOW, "Corrupting %s message to prevent recognition\n", t30_frametype(buf[2]));
s->t38x.corrupt_current_frame[from_modem] = true;
s->t38x.corrupt_current_frame[(from_modem) ? 1 : 0] = true;
}
/*endif*/
break;
@ -603,7 +593,7 @@ static void edit_control_messages(t38_gateway_state_t *s, int from_modem, uint8_
/*- End of function --------------------------------------------------------*/
static void monitor_control_messages(t38_gateway_state_t *s,
int from_modem,
bool from_modem,
const uint8_t *buf,
int len)
{
@ -664,6 +654,27 @@ static void monitor_control_messages(t38_gateway_state_t *s,
s->core.image_data_mode = false;
s->core.short_train = false;
break;
case T30_CTC:
if (len >= 5)
{
/* The table is short, and not searched often, so a brain-dead linear scan seems OK */
dcs_code = buf[4] & (DISBIT6 | DISBIT5 | DISBIT4 | DISBIT3);
for (i = 0; modem_codes[i].bit_rate; i++)
{
if (modem_codes[i].dcs_code == dcs_code)
break;
/*endif*/
}
/*endfor*/
/* If we are processing a message from the modem side, the contents determine the fast receive modem.
we are to use. If it comes from the T.38 side the contents do not. */
s->core.fast_bit_rate = modem_codes[i].bit_rate;
if (from_modem)
s->core.fast_rx_modem = modem_codes[i].modem_type;
/*endif*/
}
/*endif*/
break;
case T30_CTR:
/* T.30 says the first image data after this does full training, yet does not
return to TCF. This seems to be the sole case of long training for image
@ -1981,13 +1992,13 @@ static int restart_rx_modem(t38_gateway_state_t *s)
s->core.ecm_mode);
t = &s->audio.modems;
hdlc_rx_init(&t->hdlc_rx, false, true, HDLC_FRAMING_OK_THRESHOLD, NULL, s);
t->rx_signal_present = false;
t->rx_trained = false;
/* Default to the transmit data being V.21, unless a faster modem pops up trained. */
s->t38x.current_tx_data_type = T38_DATA_V21;
//fax_modems_start_slow_modem(t, FAX_MODEM_V21_RX);
fsk_rx_init(&t->v21_rx, &preset_fsk_specs[FSK_V21CH2], FSK_FRAME_MODE_SYNC, (put_bit_func_t) t38_hdlc_rx_put_bit, &t->hdlc_rx);
hdlc_rx_init(&t->hdlc_rx, false, true, HDLC_FRAMING_OK_THRESHOLD, NULL, s);
#if 0
fsk_rx_signal_cutoff(&t->v21_rx, -39.09f);
#endif
@ -2209,8 +2220,14 @@ SPAN_DECLARE(void) t38_gateway_set_nsx_suppression(t38_gateway_state_t *s,
const uint8_t *from_modem,
int from_modem_len)
{
s->t38x.suppress_nsx_len[0] = (from_t38_len < 0 || from_t38_len < MAX_NSX_SUPPRESSION) ? (from_t38_len + 3) : 0;
s->t38x.suppress_nsx_len[1] = (from_modem_len < 0 || from_modem_len < MAX_NSX_SUPPRESSION) ? (from_modem_len + 3) : 0;
if (from_t38_len >= 0)
s->t38x.suppress_nsx_len[0] = ((from_t38_len < MAX_NSX_SUPPRESSION) ? from_t38_len : MAX_NSX_SUPPRESSION) + 3;
if (from_t38)
memcpy(s->t38x.suppress_nsx_string[0], from_t38, s->t38x.suppress_nsx_len[0]);
if (from_modem_len >= 0)
s->t38x.suppress_nsx_len[1] = ((from_modem_len < MAX_NSX_SUPPRESSION) ? from_modem_len : MAX_NSX_SUPPRESSION) + 3;
if (from_modem)
memcpy(s->t38x.suppress_nsx_string[1], from_modem, s->t38x.suppress_nsx_len[1]);
}
/*- End of function --------------------------------------------------------*/
@ -2302,7 +2319,7 @@ SPAN_DECLARE(t38_gateway_state_t *) t38_gateway_init(t38_gateway_state_t *s,
fax_modems_set_rx_active(&s->audio.modems, true);
t38_gateway_set_supported_modems(s, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17);
t38_gateway_set_nsx_suppression(s, (const uint8_t *) "\x00\x00\x00", 3, (const uint8_t *) "\x00\x00\x00", 3);
t38_gateway_set_nsx_suppression(s, (const uint8_t *) "\xFF\x00\x00", 3, (const uint8_t *) "\xFF\x00\x00", 3);
s->core.to_t38.octets_per_data_packet = 1;
s->core.ecm_allowed = true;