Fixed updating of the modem type after a FAX ECM CTC.
This commit is contained in:
parent
7741f403f1
commit
ad1e7e9632
|
@ -46,6 +46,10 @@ typedef struct
|
||||||
/*! \brief If NSF, NSC, and NSS are to be suppressed by altering their contents to
|
/*! \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. */
|
something the far end will not recognise, this is the amount to overwrite. */
|
||||||
int suppress_nsx_len[2];
|
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
|
/*! \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. */
|
interpret it. The two values are for the two directions. */
|
||||||
bool corrupt_current_frame[2];
|
bool corrupt_current_frame[2];
|
||||||
|
|
|
@ -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?
|
\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;
|
typedef struct t38_gateway_state_s t38_gateway_state_t;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
|
|
@ -148,6 +148,9 @@
|
||||||
/*! The number of transmissions of terminating data IFP packets */
|
/*! The number of transmissions of terminating data IFP packets */
|
||||||
#define DATA_END_TX_COUNT 3
|
#define DATA_END_TX_COUNT 3
|
||||||
|
|
||||||
|
/*! The number of consecutive flags to declare HDLC framing is OK. */
|
||||||
|
#define HDLC_FRAMING_OK_THRESHOLD 5
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
DISBIT1 = 0x01,
|
DISBIT1 = 0x01,
|
||||||
|
@ -184,19 +187,6 @@ enum
|
||||||
TIMED_MODE_TCF_PREDICTABLE_MODEM_START_BEGIN,
|
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 restart_rx_modem(t38_gateway_state_t *s);
|
||||||
static int process_rx_indicator(t38_core_state_t *t, void *user_data, int indicator);
|
static int process_rx_indicator(t38_core_state_t *t, void *user_data, int indicator);
|
||||||
static void hdlc_underflow_handler(void *user_data);
|
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 --------------------------------------------------------*/
|
/*- 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
|
/* 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. */
|
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
|
/* 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
|
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
|
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. */
|
sane thing is to overwrite the original data with that. */
|
||||||
if (len <= s->t38x.suppress_nsx_len[from_modem])
|
if (len <= s->t38x.suppress_nsx_len[(from_modem) ? 1 : 0])
|
||||||
buf[len - 1] = nsx_overwrite[from_modem][len - 4];
|
buf[len - 1] = s->t38x.suppress_nsx_string[(from_modem) ? 1 : 0][len - 1 - 3];
|
||||||
/*endif*/
|
/*endif*/
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -510,13 +500,13 @@ static void edit_control_messages(t38_gateway_state_t *s, int from_modem, uint8_
|
||||||
case T30_NSF:
|
case T30_NSF:
|
||||||
case T30_NSC:
|
case T30_NSC:
|
||||||
case T30_NSS:
|
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
|
/* 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
|
processed, 2 machines which recognise each other might do special things
|
||||||
we cannot handle as a middle man. */
|
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]));
|
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*/
|
/*endif*/
|
||||||
break;
|
break;
|
||||||
|
@ -603,7 +593,7 @@ static void edit_control_messages(t38_gateway_state_t *s, int from_modem, uint8_
|
||||||
/*- End of function --------------------------------------------------------*/
|
/*- End of function --------------------------------------------------------*/
|
||||||
|
|
||||||
static void monitor_control_messages(t38_gateway_state_t *s,
|
static void monitor_control_messages(t38_gateway_state_t *s,
|
||||||
int from_modem,
|
bool from_modem,
|
||||||
const uint8_t *buf,
|
const uint8_t *buf,
|
||||||
int len)
|
int len)
|
||||||
{
|
{
|
||||||
|
@ -664,6 +654,27 @@ static void monitor_control_messages(t38_gateway_state_t *s,
|
||||||
s->core.image_data_mode = false;
|
s->core.image_data_mode = false;
|
||||||
s->core.short_train = false;
|
s->core.short_train = false;
|
||||||
break;
|
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:
|
case T30_CTR:
|
||||||
/* T.30 says the first image data after this does full training, yet does not
|
/* 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
|
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);
|
s->core.ecm_mode);
|
||||||
|
|
||||||
t = &s->audio.modems;
|
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_signal_present = false;
|
||||||
t->rx_trained = false;
|
t->rx_trained = false;
|
||||||
/* Default to the transmit data being V.21, unless a faster modem pops up trained. */
|
/* Default to the transmit data being V.21, unless a faster modem pops up trained. */
|
||||||
s->t38x.current_tx_data_type = T38_DATA_V21;
|
s->t38x.current_tx_data_type = T38_DATA_V21;
|
||||||
//fax_modems_start_slow_modem(t, FAX_MODEM_V21_RX);
|
//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);
|
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
|
#if 0
|
||||||
fsk_rx_signal_cutoff(&t->v21_rx, -39.09f);
|
fsk_rx_signal_cutoff(&t->v21_rx, -39.09f);
|
||||||
#endif
|
#endif
|
||||||
|
@ -2209,8 +2220,14 @@ SPAN_DECLARE(void) t38_gateway_set_nsx_suppression(t38_gateway_state_t *s,
|
||||||
const uint8_t *from_modem,
|
const uint8_t *from_modem,
|
||||||
int from_modem_len)
|
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;
|
if (from_t38_len >= 0)
|
||||||
s->t38x.suppress_nsx_len[1] = (from_modem_len < 0 || from_modem_len < MAX_NSX_SUPPRESSION) ? (from_modem_len + 3) : 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 --------------------------------------------------------*/
|
/*- 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);
|
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_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.to_t38.octets_per_data_packet = 1;
|
||||||
s->core.ecm_allowed = true;
|
s->core.ecm_allowed = true;
|
||||||
|
|
Loading…
Reference in New Issue