Improved TSB85 tests, which now check call clearing.
FAX now differentiates properly between <page result code> and <image> <page resuly code> when deciding how to retry.
This commit is contained in:
parent
d886cc12fa
commit
b780371943
|
@ -33,6 +33,7 @@
|
|||
modem CDATA #IMPLIED
|
||||
tag CDATA #IMPLIED
|
||||
value CDATA #IMPLIED
|
||||
timein CDATA #IMPLIED
|
||||
timeout CDATA #IMPLIED
|
||||
crc_error CDATA #IMPLIED
|
||||
pattern CDATA #IMPLIED
|
||||
|
|
|
@ -91,6 +91,9 @@
|
|||
<step dir="T" type="PREAMBLE" modem="V.21"/>
|
||||
<step dir="T" type="HDLC" tag="DCN" value="FF C8 5F"/>
|
||||
<step dir="T" type="POSTAMBLE"/>
|
||||
<step dir="T" type="CLEAR"/>
|
||||
<step dir="R" type="CLEAR" timein="0" timeout="100"/>
|
||||
<step type="STATUS" value="RX_DCNDATA"/>
|
||||
</test>
|
||||
<test name="V17-12000-V29-9600">
|
||||
<!-- Tester calls, trying to provoke a crash seen in some versions of spandsp, when
|
||||
|
@ -183,6 +186,9 @@
|
|||
<step dir="T" type="PREAMBLE" modem="V.21"/>
|
||||
<step dir="T" type="HDLC" tag="DCN" value="FF C8 5F"/>
|
||||
<step dir="T" type="POSTAMBLE"/>
|
||||
<step dir="T" type="CLEAR"/>
|
||||
<step dir="R" type="CLEAR" timein="0" timeout="100"/>
|
||||
<step type="STATUS" value="OK"/>
|
||||
</test>
|
||||
<test name="Phase-D-collision">
|
||||
<!-- DUT calls tester and sends 1 IMPRESS and 1 WHITE page. The MCF after the first
|
||||
|
@ -224,6 +230,8 @@
|
|||
<step dir="T" type="POSTAMBLE"/>
|
||||
|
||||
<step dir="R" type="HDLC" modem="V.21" tag="DCN+" value="FF C8 DF"/>
|
||||
<step dir="R" type="CLEAR" timein="800" timeout="1200"/>
|
||||
<step type="STATUS" value="OK"/>
|
||||
</test>
|
||||
</test-group>
|
||||
</fax-tests>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -181,6 +181,10 @@ struct t30_state_s
|
|||
/*! \brief True if the short training sequence should be used. */
|
||||
bool short_train;
|
||||
|
||||
/*! \brief True if an image carrier appears to have been received, even if it did not successfully
|
||||
train. */
|
||||
bool image_carrier_attempted;
|
||||
|
||||
/*! \brief A count of the number of bits in the trainability test. This counts down to zero when
|
||||
sending TCF, and counts up when receiving it. */
|
||||
int tcf_test_bits;
|
||||
|
@ -293,6 +297,8 @@ struct t30_state_s
|
|||
partial pages still to come. */
|
||||
bool ecm_at_page_end;
|
||||
|
||||
/*! \brief The last result for a received non-ECM page - T30_MPS, T30_RTP, or T30_RTN. */
|
||||
int last_rx_page_result;
|
||||
/*! \brief The transmission step queued to follow the one in progress. */
|
||||
int next_tx_step;
|
||||
/*! \brief The FCF for the next receive step. */
|
||||
|
@ -310,11 +316,6 @@ struct t30_state_s
|
|||
/*! \brief The current completion status. */
|
||||
int current_status;
|
||||
|
||||
/*! \brief The number of RTP events */
|
||||
int rtp_events;
|
||||
/*! \brief The number of RTN events */
|
||||
int rtn_events;
|
||||
|
||||
/*! \brief the FCF2 field of the last PPS message we received. */
|
||||
uint8_t last_pps_fcf2;
|
||||
/*! \brief True if all frames of the current received ECM block are now OK */
|
||||
|
@ -323,6 +324,11 @@ struct t30_state_s
|
|||
deciding whether to continue error correction when PPRs keep repeating. */
|
||||
int ecm_progress;
|
||||
|
||||
/*! \brief The number of RTP events */
|
||||
int rtp_events;
|
||||
/*! \brief The number of RTN events */
|
||||
int rtn_events;
|
||||
|
||||
/*! \brief Error and flow logging control */
|
||||
logging_state_t logging;
|
||||
};
|
||||
|
|
|
@ -173,9 +173,7 @@ enum
|
|||
T30_STATE_I,
|
||||
T30_STATE_II,
|
||||
T30_STATE_II_Q,
|
||||
T30_STATE_III_Q_MCF,
|
||||
T30_STATE_III_Q_RTP,
|
||||
T30_STATE_III_Q_RTN,
|
||||
T30_STATE_III_Q,
|
||||
T30_STATE_IV,
|
||||
T30_STATE_IV_PPS_NULL,
|
||||
T30_STATE_IV_PPS_Q,
|
||||
|
@ -210,9 +208,7 @@ static const char *state_names[] =
|
|||
"I",
|
||||
"II",
|
||||
"II_Q",
|
||||
"III_Q_MCF",
|
||||
"III_Q_RTP",
|
||||
"III_Q_RTN",
|
||||
"III_Q",
|
||||
"IV",
|
||||
"IV_PPS_NULL",
|
||||
"IV_PPS_Q",
|
||||
|
@ -3600,7 +3596,7 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int
|
|||
state, it looks like either:
|
||||
- we didn't see the image data carrier properly, or
|
||||
- they didn't see our T30_CFR, and are repeating the DCS/TCF sequence.
|
||||
- they didn't see out T30_MCF, and are repeating the end of page message. */
|
||||
- they didn't see our T30_MCF, T30_RTP or T30_RTN and are repeating the end of page message. */
|
||||
fcf = msg[2] & 0xFE;
|
||||
switch (fcf)
|
||||
{
|
||||
|
@ -3616,13 +3612,22 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int
|
|||
}
|
||||
/* Fall through */
|
||||
case T30_MPS:
|
||||
/* Treat this as a bad quality page. */
|
||||
if (s->phase_d_handler)
|
||||
s->phase_d_handler(s->phase_d_user_data, fcf);
|
||||
s->next_rx_step = fcf;
|
||||
queue_phase(s, T30_PHASE_D_TX);
|
||||
set_state(s, T30_STATE_III_Q_RTN);
|
||||
send_simple_frame(s, T30_RTN);
|
||||
if (s->image_carrier_attempted)
|
||||
{
|
||||
/* Treat this as a bad quality page. */
|
||||
if (s->phase_d_handler)
|
||||
s->phase_d_handler(s->phase_d_user_data, fcf);
|
||||
s->next_rx_step = fcf;
|
||||
s->last_rx_page_result = T30_RTN;
|
||||
queue_phase(s, T30_PHASE_D_TX);
|
||||
set_state(s, T30_STATE_III_Q);
|
||||
send_simple_frame(s, s->last_rx_page_result);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This appears to be a retry, because the far end didn't see our last response */
|
||||
repeat_last_command(s);
|
||||
}
|
||||
break;
|
||||
case T30_PRI_EOM:
|
||||
if (s->remote_interrupts_allowed)
|
||||
|
@ -3631,14 +3636,23 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int
|
|||
/* Fall through */
|
||||
case T30_EOM:
|
||||
case T30_EOS:
|
||||
/* Treat this as a bad quality page. */
|
||||
if (s->phase_d_handler)
|
||||
s->phase_d_handler(s->phase_d_user_data, fcf);
|
||||
s->next_rx_step = fcf;
|
||||
/* Return to phase B */
|
||||
queue_phase(s, T30_PHASE_B_TX);
|
||||
set_state(s, T30_STATE_III_Q_RTN);
|
||||
send_simple_frame(s, T30_RTN);
|
||||
if (s->image_carrier_attempted)
|
||||
{
|
||||
/* Treat this as a bad quality page. */
|
||||
if (s->phase_d_handler)
|
||||
s->phase_d_handler(s->phase_d_user_data, fcf);
|
||||
s->next_rx_step = fcf;
|
||||
s->last_rx_page_result = T30_RTN;
|
||||
/* Return to phase B */
|
||||
queue_phase(s, T30_PHASE_B_TX);
|
||||
set_state(s, T30_STATE_III_Q);
|
||||
send_simple_frame(s, s->last_rx_page_result);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This appears to be a retry, because the far end didn't see our last response */
|
||||
repeat_last_command(s);
|
||||
}
|
||||
break;
|
||||
case T30_PRI_EOP:
|
||||
if (s->remote_interrupts_allowed)
|
||||
|
@ -3646,13 +3660,22 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int
|
|||
}
|
||||
/* Fall through */
|
||||
case T30_EOP:
|
||||
/* Treat this as a bad quality page. */
|
||||
if (s->phase_d_handler)
|
||||
s->phase_d_handler(s->phase_d_user_data, fcf);
|
||||
s->next_rx_step = fcf;
|
||||
queue_phase(s, T30_PHASE_D_TX);
|
||||
set_state(s, T30_STATE_III_Q_RTN);
|
||||
send_simple_frame(s, T30_RTN);
|
||||
if (s->image_carrier_attempted)
|
||||
{
|
||||
/* Treat this as a bad quality page. */
|
||||
if (s->phase_d_handler)
|
||||
s->phase_d_handler(s->phase_d_user_data, fcf);
|
||||
s->next_rx_step = fcf;
|
||||
s->last_rx_page_result = T30_RTN;
|
||||
queue_phase(s, T30_PHASE_D_TX);
|
||||
set_state(s, T30_STATE_III_Q);
|
||||
send_simple_frame(s, s->last_rx_page_result);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This appears to be a retry, because the far end didn't see our last response */
|
||||
repeat_last_command(s);
|
||||
}
|
||||
break;
|
||||
case T30_DCN:
|
||||
t30_set_status(s, T30_ERR_RX_DCNDATA);
|
||||
|
@ -3705,18 +3728,18 @@ static void assess_copy_quality(t30_state_t *s, uint8_t fcf)
|
|||
{
|
||||
case T30_COPY_QUALITY_PERFECT:
|
||||
case T30_COPY_QUALITY_GOOD:
|
||||
set_state(s, T30_STATE_III_Q_MCF);
|
||||
send_simple_frame(s, T30_MCF);
|
||||
s->last_rx_page_result = T30_MCF;
|
||||
break;
|
||||
case T30_COPY_QUALITY_POOR:
|
||||
set_state(s, T30_STATE_III_Q_RTP);
|
||||
send_simple_frame(s, T30_RTP);
|
||||
s->last_rx_page_result = T30_RTP;
|
||||
break;
|
||||
case T30_COPY_QUALITY_BAD:
|
||||
set_state(s, T30_STATE_III_Q_RTN);
|
||||
send_simple_frame(s, T30_RTN);
|
||||
default:
|
||||
s->last_rx_page_result = T30_RTN;
|
||||
break;
|
||||
}
|
||||
set_state(s, T30_STATE_III_Q);
|
||||
send_simple_frame(s, s->last_rx_page_result);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -3761,6 +3784,10 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg,
|
|||
queue_phase(s, T30_PHASE_D_TX);
|
||||
assess_copy_quality(s, fcf);
|
||||
break;
|
||||
case T30_DCS:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "DCS received after CFR\n");
|
||||
process_rx_dcs(s, msg, len);
|
||||
break;
|
||||
case T30_DCN:
|
||||
t30_set_status(s, T30_ERR_RX_DCNFAX);
|
||||
terminate_call(s);
|
||||
|
@ -3823,6 +3850,7 @@ static void process_state_f_doc_and_post_doc_ecm(t30_state_t *s, const uint8_t *
|
|||
case T30_EOM:
|
||||
case T30_EOS:
|
||||
case T30_MPS:
|
||||
s->image_carrier_attempted = false;
|
||||
s->next_rx_step = fcf2;
|
||||
queue_phase(s, T30_PHASE_D_TX);
|
||||
set_state(s, T30_STATE_F_DOC_ECM);
|
||||
|
@ -3837,6 +3865,7 @@ static void process_state_f_doc_and_post_doc_ecm(t30_state_t *s, const uint8_t *
|
|||
process_rx_pps(s, msg, len);
|
||||
break;
|
||||
case T30_CTC:
|
||||
s->image_carrier_attempted = false;
|
||||
/* T.30 says we change back to long training here */
|
||||
s->short_train = false;
|
||||
queue_phase(s, T30_PHASE_D_TX);
|
||||
|
@ -4270,7 +4299,7 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void process_state_iii_q_mcf(t30_state_t *s, const uint8_t *msg, int len)
|
||||
static void process_state_iii_q(t30_state_t *s, const uint8_t *msg, int len)
|
||||
{
|
||||
uint8_t fcf;
|
||||
|
||||
|
@ -4283,8 +4312,8 @@ static void process_state_iii_q_mcf(t30_state_t *s, const uint8_t *msg, int len)
|
|||
case T30_MPS:
|
||||
/* Looks like they didn't see our signal. Repeat it */
|
||||
queue_phase(s, T30_PHASE_D_TX);
|
||||
set_state(s, T30_STATE_III_Q_MCF);
|
||||
send_simple_frame(s, T30_MCF);
|
||||
set_state(s, T30_STATE_III_Q);
|
||||
send_simple_frame(s, s->last_rx_page_result);
|
||||
break;
|
||||
case T30_DIS:
|
||||
if (msg[2] == T30_DTC)
|
||||
|
@ -4297,78 +4326,8 @@ static void process_state_iii_q_mcf(t30_state_t *s, const uint8_t *msg, int len)
|
|||
process_rx_fnv(s, msg, len);
|
||||
break;
|
||||
case T30_DCN:
|
||||
terminate_call(s);
|
||||
break;
|
||||
default:
|
||||
/* We don't know what to do with this. */
|
||||
unexpected_final_frame(s, msg, len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void process_state_iii_q_rtp(t30_state_t *s, const uint8_t *msg, int len)
|
||||
{
|
||||
uint8_t fcf;
|
||||
|
||||
fcf = msg[2] & 0xFE;
|
||||
switch (fcf)
|
||||
{
|
||||
case T30_EOP:
|
||||
case T30_EOM:
|
||||
case T30_EOS:
|
||||
case T30_MPS:
|
||||
/* Looks like they didn't see our signal. Repeat it */
|
||||
queue_phase(s, T30_PHASE_D_TX);
|
||||
set_state(s, T30_STATE_III_Q_RTP);
|
||||
send_simple_frame(s, T30_RTP);
|
||||
break;
|
||||
case T30_DIS:
|
||||
if (msg[2] == T30_DTC)
|
||||
process_rx_dis_dtc(s, msg, len);
|
||||
break;
|
||||
case T30_CRP:
|
||||
repeat_last_command(s);
|
||||
break;
|
||||
case T30_FNV:
|
||||
process_rx_fnv(s, msg, len);
|
||||
break;
|
||||
default:
|
||||
/* We don't know what to do with this. */
|
||||
unexpected_final_frame(s, msg, len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void process_state_iii_q_rtn(t30_state_t *s, const uint8_t *msg, int len)
|
||||
{
|
||||
uint8_t fcf;
|
||||
|
||||
fcf = msg[2] & 0xFE;
|
||||
switch (fcf)
|
||||
{
|
||||
case T30_EOP:
|
||||
case T30_EOM:
|
||||
case T30_EOS:
|
||||
case T30_MPS:
|
||||
/* Looks like they didn't see our signal. Repeat it */
|
||||
queue_phase(s, T30_PHASE_D_TX);
|
||||
set_state(s, T30_STATE_III_Q_RTN);
|
||||
send_simple_frame(s, T30_RTN);
|
||||
break;
|
||||
case T30_DIS:
|
||||
if (msg[2] == T30_DTC)
|
||||
process_rx_dis_dtc(s, msg, len);
|
||||
break;
|
||||
case T30_CRP:
|
||||
repeat_last_command(s);
|
||||
break;
|
||||
case T30_FNV:
|
||||
process_rx_fnv(s, msg, len);
|
||||
break;
|
||||
case T30_DCN:
|
||||
t30_set_status(s, T30_ERR_RX_DCNNORTN);
|
||||
if (s->last_rx_page_result == T30_RTN)
|
||||
t30_set_status(s, T30_ERR_RX_DCNNORTN);
|
||||
terminate_call(s);
|
||||
break;
|
||||
default:
|
||||
|
@ -5090,14 +5049,8 @@ static void process_rx_control_msg(t30_state_t *s, const uint8_t *msg, int len)
|
|||
case T30_STATE_II_Q:
|
||||
process_state_ii_q(s, msg, len);
|
||||
break;
|
||||
case T30_STATE_III_Q_MCF:
|
||||
process_state_iii_q_mcf(s, msg, len);
|
||||
break;
|
||||
case T30_STATE_III_Q_RTP:
|
||||
process_state_iii_q_rtp(s, msg, len);
|
||||
break;
|
||||
case T30_STATE_III_Q_RTN:
|
||||
process_state_iii_q_rtn(s, msg, len);
|
||||
case T30_STATE_III_Q:
|
||||
process_state_iii_q(s, msg, len);
|
||||
break;
|
||||
case T30_STATE_IV:
|
||||
process_state_iv(s, msg, len);
|
||||
|
@ -5315,17 +5268,10 @@ static void repeat_last_command(t30_state_t *s)
|
|||
queue_phase(s, T30_PHASE_B_TX);
|
||||
send_dis_or_dtc_sequence(s, true);
|
||||
break;
|
||||
case T30_STATE_III_Q_MCF:
|
||||
case T30_STATE_F_DOC_NON_ECM:
|
||||
case T30_STATE_III_Q:
|
||||
queue_phase(s, T30_PHASE_D_TX);
|
||||
send_simple_frame(s, T30_MCF);
|
||||
break;
|
||||
case T30_STATE_III_Q_RTP:
|
||||
queue_phase(s, T30_PHASE_D_TX);
|
||||
send_simple_frame(s, T30_RTP);
|
||||
break;
|
||||
case T30_STATE_III_Q_RTN:
|
||||
queue_phase(s, T30_PHASE_D_TX);
|
||||
send_simple_frame(s, T30_RTN);
|
||||
send_simple_frame(s, s->last_rx_page_result);
|
||||
break;
|
||||
case T30_STATE_II_Q:
|
||||
queue_phase(s, T30_PHASE_D_TX);
|
||||
|
@ -5526,9 +5472,7 @@ static void timer_t2_expired(t30_state_t *s)
|
|||
span_log(&s->logging, SPAN_LOG_FLOW, "T2 expired in phase %s, state %s\n", phase_names[s->phase], state_names[s->state]);
|
||||
switch (s->state)
|
||||
{
|
||||
case T30_STATE_III_Q_MCF:
|
||||
case T30_STATE_III_Q_RTP:
|
||||
case T30_STATE_III_Q_RTN:
|
||||
case T30_STATE_III_Q:
|
||||
case T30_STATE_F_POST_RCP_PPR:
|
||||
case T30_STATE_F_POST_RCP_MCF:
|
||||
switch (s->next_rx_step)
|
||||
|
@ -5738,6 +5682,7 @@ static void t30_non_ecm_rx_status(void *user_data, int status)
|
|||
switch (status)
|
||||
{
|
||||
case SIG_STATUS_TRAINING_IN_PROGRESS:
|
||||
s->image_carrier_attempted = true;
|
||||
break;
|
||||
case SIG_STATUS_TRAINING_FAILED:
|
||||
s->rx_trained = false;
|
||||
|
@ -6205,6 +6150,8 @@ SPAN_DECLARE(void) t30_front_end_status(void *user_data, int status)
|
|||
case T30_STATE_F_CFR:
|
||||
if (send_cfr_sequence(s, false))
|
||||
{
|
||||
s->image_carrier_attempted = false;
|
||||
s->last_rx_page_result = -1;
|
||||
if (s->error_correcting_mode)
|
||||
{
|
||||
set_state(s, T30_STATE_F_DOC_ECM);
|
||||
|
@ -6231,9 +6178,8 @@ SPAN_DECLARE(void) t30_front_end_status(void *user_data, int status)
|
|||
timer_t2_start(s);
|
||||
}
|
||||
break;
|
||||
case T30_STATE_III_Q_MCF:
|
||||
case T30_STATE_III_Q_RTP:
|
||||
case T30_STATE_III_Q_RTN:
|
||||
case T30_STATE_F_DOC_NON_ECM:
|
||||
case T30_STATE_III_Q:
|
||||
case T30_STATE_F_POST_RCP_PPR:
|
||||
case T30_STATE_F_POST_RCP_MCF:
|
||||
if (s->step == 0)
|
||||
|
@ -6248,6 +6194,7 @@ SPAN_DECLARE(void) t30_front_end_status(void *user_data, int status)
|
|||
case T30_PRI_MPS:
|
||||
case T30_MPS:
|
||||
/* We should now start to get another page */
|
||||
s->image_carrier_attempted = false;
|
||||
if (s->error_correcting_mode)
|
||||
{
|
||||
set_state(s, T30_STATE_F_DOC_ECM);
|
||||
|
@ -6264,8 +6211,8 @@ SPAN_DECLARE(void) t30_front_end_status(void *user_data, int status)
|
|||
case T30_EOM:
|
||||
case T30_EOS:
|
||||
/* See if we get something back, before moving to phase B. */
|
||||
timer_t2_start(s);
|
||||
set_phase(s, T30_PHASE_D_RX);
|
||||
timer_t2_start(s);
|
||||
break;
|
||||
case T30_PRI_EOP:
|
||||
case T30_EOP:
|
||||
|
|
|
@ -264,32 +264,39 @@ static void parse_tone_set(super_tone_rx_descriptor_t *desc, xmlDocPtr doc, xmlN
|
|||
|
||||
static void get_tone_set(super_tone_rx_descriptor_t *desc, const char *tone_file, const char *set_id)
|
||||
{
|
||||
xmlParserCtxtPtr ctxt;
|
||||
xmlDocPtr doc;
|
||||
xmlNsPtr ns;
|
||||
xmlNodePtr cur;
|
||||
#if 1
|
||||
xmlValidCtxt valid;
|
||||
#endif
|
||||
xmlChar *x;
|
||||
|
||||
ns = NULL;
|
||||
xmlKeepBlanksDefault(0);
|
||||
xmlCleanupParser();
|
||||
if ((doc = xmlParseFile(tone_file)) == NULL)
|
||||
|
||||
if ((ctxt = xmlNewParserCtxt()) == NULL)
|
||||
{
|
||||
fprintf(stderr, "No document\n");
|
||||
fprintf(stderr, "Failed to allocate parser context\n");
|
||||
printf("Test failed\n");
|
||||
exit(2);
|
||||
}
|
||||
/*endif*/
|
||||
xmlXIncludeProcess(doc);
|
||||
#if 1
|
||||
if (!xmlValidateDocument(&valid, doc))
|
||||
/* parse the file, activating the DTD validation option */
|
||||
if ((doc = xmlCtxtReadFile(ctxt, tone_file, NULL, XML_PARSE_XINCLUDE | XML_PARSE_DTDVALID)) == NULL)
|
||||
{
|
||||
fprintf(stderr, "Invalid document\n");
|
||||
fprintf(stderr, "Failed to read the XML document\n");
|
||||
printf("Test failed\n");
|
||||
exit(2);
|
||||
}
|
||||
/*endif*/
|
||||
#endif
|
||||
if (ctxt->valid == 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to validate the XML document\n");
|
||||
xmlFreeDoc(doc);
|
||||
xmlFreeParserCtxt(ctxt);
|
||||
printf("Test failed\n");
|
||||
exit(2);
|
||||
}
|
||||
xmlFreeParserCtxt(ctxt);
|
||||
|
||||
/* Check the document is of the right kind */
|
||||
if ((cur = xmlDocGetRootElement(doc)) == NULL)
|
||||
{
|
||||
|
|
|
@ -203,33 +203,39 @@ static void parse_tone_set(xmlDocPtr doc, xmlNsPtr ns, xmlNodePtr cur)
|
|||
|
||||
static void get_tone_set(const char *tone_file, const char *set_id)
|
||||
{
|
||||
xmlParserCtxtPtr ctxt;
|
||||
xmlDocPtr doc;
|
||||
xmlNsPtr ns;
|
||||
xmlNodePtr cur;
|
||||
#if 0
|
||||
xmlValidCtxt valid;
|
||||
#endif
|
||||
xmlChar *x;
|
||||
|
||||
ns = NULL;
|
||||
xmlKeepBlanksDefault(0);
|
||||
xmlCleanupParser();
|
||||
doc = xmlParseFile(tone_file);
|
||||
if (doc == NULL)
|
||||
|
||||
if ((ctxt = xmlNewParserCtxt()) == NULL)
|
||||
{
|
||||
fprintf(stderr, "No document\n");
|
||||
fprintf(stderr, "Failed to allocate parser context\n");
|
||||
printf("Test failed\n");
|
||||
exit(2);
|
||||
}
|
||||
/*endif*/
|
||||
xmlXIncludeProcess(doc);
|
||||
#if 0
|
||||
if (!xmlValidateDocument(&valid, doc))
|
||||
/* parse the file, activating the DTD validation option */
|
||||
if ((doc = xmlCtxtReadFile(ctxt, tone_file, NULL, XML_PARSE_XINCLUDE | XML_PARSE_DTDVALID)) == NULL)
|
||||
{
|
||||
fprintf(stderr, "Invalid document\n");
|
||||
fprintf(stderr, "Failed to read the XML document\n");
|
||||
printf("Test failed\n");
|
||||
exit(2);
|
||||
}
|
||||
/*endif*/
|
||||
#endif
|
||||
if (ctxt->valid == 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to validate the XML document\n");
|
||||
xmlFreeDoc(doc);
|
||||
xmlFreeParserCtxt(ctxt);
|
||||
printf("Test failed\n");
|
||||
exit(2);
|
||||
}
|
||||
xmlFreeParserCtxt(ctxt);
|
||||
|
||||
/* Check the document is of the right kind */
|
||||
if ((cur = xmlDocGetRootElement(doc)) == NULL)
|
||||
{
|
||||
|
|
|
@ -92,9 +92,86 @@ t30_exchanged_info_t expected_rx_info;
|
|||
|
||||
char next_tx_file[1000];
|
||||
|
||||
static int timein_x = -1;
|
||||
static int timeout_x = -1;
|
||||
|
||||
static int next_step(faxtester_state_t *s);
|
||||
|
||||
static bool test_for_call_drop = false;
|
||||
static bool test_for_call_clear = false;
|
||||
static int call_clear_timer = 0;
|
||||
|
||||
static bool far_end_cleared_call = false;
|
||||
|
||||
struct
|
||||
{
|
||||
const char *tag;
|
||||
int code;
|
||||
} t30_status[] =
|
||||
{
|
||||
{"OK", T30_ERR_OK},
|
||||
{"CEDTONE", T30_ERR_CEDTONE},
|
||||
{"T0_EXPIRED", T30_ERR_T0_EXPIRED},
|
||||
{"T1_EXPIRED", T30_ERR_T1_EXPIRED},
|
||||
{"T3_EXPIRED", T30_ERR_T3_EXPIRED},
|
||||
{"HDLC_CARRIER", T30_ERR_HDLC_CARRIER},
|
||||
{"CANNOT_TRAIN", T30_ERR_CANNOT_TRAIN},
|
||||
{"OPER_INT_FAIL", T30_ERR_OPER_INT_FAIL},
|
||||
{"INCOMPATIBLE", T30_ERR_INCOMPATIBLE},
|
||||
{"RX_INCAPABLE", T30_ERR_RX_INCAPABLE},
|
||||
{"TX_INCAPABLE", T30_ERR_TX_INCAPABLE},
|
||||
{"NORESSUPPORT", T30_ERR_NORESSUPPORT},
|
||||
{"NOSIZESUPPORT", T30_ERR_NOSIZESUPPORT},
|
||||
{"UNEXPECTED", T30_ERR_UNEXPECTED},
|
||||
{"TX_BADDCS", T30_ERR_TX_BADDCS},
|
||||
{"TX_BADPG", T30_ERR_TX_BADPG},
|
||||
{"TX_ECMPHD", T30_ERR_TX_ECMPHD},
|
||||
{"TX_GOTDCN", T30_ERR_TX_GOTDCN},
|
||||
{"TX_INVALRSP", T30_ERR_TX_INVALRSP},
|
||||
{"TX_NODIS", T30_ERR_TX_NODIS},
|
||||
{"TX_PHBDEAD", T30_ERR_TX_PHBDEAD},
|
||||
{"TX_PHDDEAD", T30_ERR_TX_PHDDEAD},
|
||||
{"TX_T5EXP", T30_ERR_TX_T5EXP},
|
||||
{"RX_ECMPHD", T30_ERR_RX_ECMPHD},
|
||||
{"RX_GOTDCS", T30_ERR_RX_GOTDCS},
|
||||
{"RX_INVALCMD", T30_ERR_RX_INVALCMD},
|
||||
{"RX_NOCARRIER", T30_ERR_RX_NOCARRIER},
|
||||
{"RX_NOEOL", T30_ERR_RX_NOEOL},
|
||||
{"RX_NOFAX", T30_ERR_RX_NOFAX},
|
||||
{"RX_T2EXPDCN", T30_ERR_RX_T2EXPDCN},
|
||||
{"RX_T2EXPD", T30_ERR_RX_T2EXPD},
|
||||
{"RX_T2EXPFAX", T30_ERR_RX_T2EXPFAX},
|
||||
{"RX_T2EXPMPS", T30_ERR_RX_T2EXPMPS},
|
||||
{"RX_T2EXPRR", T30_ERR_RX_T2EXPRR},
|
||||
{"RX_T2EXP", T30_ERR_RX_T2EXP},
|
||||
{"RX_DCNWHY", T30_ERR_RX_DCNWHY},
|
||||
{"RX_DCNDATA", T30_ERR_RX_DCNDATA},
|
||||
{"RX_DCNFAX", T30_ERR_RX_DCNFAX},
|
||||
{"RX_DCNPHD", T30_ERR_RX_DCNPHD},
|
||||
{"RX_DCNRRD", T30_ERR_RX_DCNRRD},
|
||||
{"RX_DCNNORTN", T30_ERR_RX_DCNNORTN},
|
||||
{"FILEERROR", T30_ERR_FILEERROR},
|
||||
{"NOPAGE", T30_ERR_NOPAGE},
|
||||
{"BADTIFF", T30_ERR_BADTIFF},
|
||||
{"BADPAGE", T30_ERR_BADPAGE},
|
||||
{"BADTAG", T30_ERR_BADTAG},
|
||||
{"BADTIFFHDR", T30_ERR_BADTIFFHDR},
|
||||
{"NOMEM", T30_ERR_NOMEM},
|
||||
{"RETRYDCN", T30_ERR_RETRYDCN},
|
||||
{"CALLDROPPED", T30_ERR_CALLDROPPED},
|
||||
{"NOPOLL", T30_ERR_NOPOLL},
|
||||
{"IDENT_UNACCEPTABLE", T30_ERR_IDENT_UNACCEPTABLE},
|
||||
{"SUB_UNACCEPTABLE", T30_ERR_SUB_UNACCEPTABLE},
|
||||
{"SEP_UNACCEPTABLE", T30_ERR_SEP_UNACCEPTABLE},
|
||||
{"PSA_UNACCEPTABLE", T30_ERR_PSA_UNACCEPTABLE},
|
||||
{"SID_UNACCEPTABLE", T30_ERR_SID_UNACCEPTABLE},
|
||||
{"PWD_UNACCEPTABLE", T30_ERR_PWD_UNACCEPTABLE},
|
||||
{"TSA_UNACCEPTABLE", T30_ERR_TSA_UNACCEPTABLE},
|
||||
{"IRA_UNACCEPTABLE", T30_ERR_IRA_UNACCEPTABLE},
|
||||
{"CIA_UNACCEPTABLE", T30_ERR_CIA_UNACCEPTABLE},
|
||||
{"ISP_UNACCEPTABLE", T30_ERR_ISP_UNACCEPTABLE},
|
||||
{"CSA_UNACCEPTABLE", T30_ERR_CSA_UNACCEPTABLE},
|
||||
{NULL, -1}
|
||||
};
|
||||
|
||||
static int phase_b_handler(void *user_data, int result)
|
||||
{
|
||||
|
@ -622,6 +699,7 @@ static int next_step(faxtester_state_t *s)
|
|||
xmlChar *bad_rows;
|
||||
xmlChar *crc_error;
|
||||
xmlChar *pattern;
|
||||
xmlChar *timein;
|
||||
xmlChar *timeout;
|
||||
xmlChar *min_bits;
|
||||
xmlChar *frame_size;
|
||||
|
@ -638,12 +716,12 @@ static int next_step(faxtester_state_t *s)
|
|||
int ecm_frame_size;
|
||||
int ecm_block;
|
||||
int compression_type;
|
||||
int timer;
|
||||
int len;
|
||||
t4_tx_state_t t4_tx_state;
|
||||
t30_state_t *t30;
|
||||
t30_stats_t t30_stats;
|
||||
|
||||
test_for_call_drop = false;
|
||||
test_for_call_clear = false;
|
||||
if (s->cur == NULL)
|
||||
{
|
||||
if (!s->final_delayed)
|
||||
|
@ -677,6 +755,7 @@ static int next_step(faxtester_state_t *s)
|
|||
bad_rows = xmlGetProp(s->cur, (const xmlChar *) "bad_rows");
|
||||
crc_error = xmlGetProp(s->cur, (const xmlChar *) "crc_error");
|
||||
pattern = xmlGetProp(s->cur, (const xmlChar *) "pattern");
|
||||
timein = xmlGetProp(s->cur, (const xmlChar *) "timein");
|
||||
timeout = xmlGetProp(s->cur, (const xmlChar *) "timeout");
|
||||
min_bits = xmlGetProp(s->cur, (const xmlChar *) "min_bits");
|
||||
frame_size = xmlGetProp(s->cur, (const xmlChar *) "frame_size");
|
||||
|
@ -687,26 +766,31 @@ static int next_step(faxtester_state_t *s)
|
|||
|
||||
span_log(&s->logging,
|
||||
SPAN_LOG_FLOW,
|
||||
"Dir - %s, type - %s, modem - %s, value - %s, timeout - %s, tag - %s\n",
|
||||
"Dir - %s, type - %s, modem - %s, value - %s, timein - %s, timeout - %s, tag - %s\n",
|
||||
(dir) ? (const char *) dir : "",
|
||||
(type) ? (const char *) type : "",
|
||||
(modem) ? (const char *) modem : "",
|
||||
(value) ? (const char *) value : "",
|
||||
(timein) ? (const char *) timein : "",
|
||||
(timeout) ? (const char *) timeout : "",
|
||||
(tag) ? (const char *) tag : "");
|
||||
if (type == NULL)
|
||||
return 1;
|
||||
if (timeout)
|
||||
timer = atoi((const char *) timeout);
|
||||
if (timein)
|
||||
timein_x = atoi((const char *) timein);
|
||||
else
|
||||
timer = -1;
|
||||
timein_x = -1;
|
||||
if (timeout)
|
||||
timeout_x = atoi((const char *) timeout);
|
||||
else
|
||||
timeout_x = -1;
|
||||
|
||||
if (dir && strcasecmp((const char *) dir, "R") == 0)
|
||||
{
|
||||
/* Receive always has a timeout applied. */
|
||||
if (timer < 0)
|
||||
timer = 7000;
|
||||
faxtester_set_timeout(s, timer);
|
||||
if (timeout_x < 0)
|
||||
timeout_x = 7000;
|
||||
faxtester_set_timeout(s, timeout_x);
|
||||
if (modem)
|
||||
{
|
||||
hdlc = (strcasecmp((const char *) type, "PREAMBLE") == 0);
|
||||
|
@ -801,10 +885,11 @@ static int next_step(faxtester_state_t *s)
|
|||
{
|
||||
faxtest_set_rx_silence(s);
|
||||
}
|
||||
else if (strcasecmp((const char *) type, "DROPCALL") == 0)
|
||||
else if (strcasecmp((const char *) type, "CLEAR") == 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Far end should drop the call\n");
|
||||
test_for_call_drop = true;
|
||||
test_for_call_clear = true;
|
||||
call_clear_timer = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -814,7 +899,7 @@ static int next_step(faxtester_state_t *s)
|
|||
}
|
||||
else
|
||||
{
|
||||
faxtester_set_timeout(s, timer);
|
||||
faxtester_set_timeout(s, timeout_x);
|
||||
if (modem)
|
||||
{
|
||||
hdlc = (strcasecmp((const char *) type, "PREAMBLE") == 0);
|
||||
|
@ -1117,9 +1202,35 @@ static int next_step(faxtester_state_t *s)
|
|||
span_log(&s->logging, SPAN_LOG_FLOW, "ECM image is %d bytes (min row bits %d)\n", len, min_row_bits);
|
||||
faxtester_set_ecm_image_buffer(s, image, len, ecm_block, ecm_frame_size, i);
|
||||
}
|
||||
else if (strcasecmp((const char *) type, "DROPCALL") == 0)
|
||||
else if (strcasecmp((const char *) type, "CLEAR") == 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Time to drop the call\n");
|
||||
t30 = fax_get_t30_state(fax);
|
||||
t30_terminate(t30);
|
||||
return 0;
|
||||
}
|
||||
else if (strcasecmp((const char *) type, "STATUS") == 0)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
for (i = 0; t30_status[i].code >= 0; i++)
|
||||
{
|
||||
if (strcmp(t30_status[i].tag, (const char *) value) == 0)
|
||||
break;
|
||||
}
|
||||
if (t30_status[i].code >= 0)
|
||||
delay = t30_status[i].code;
|
||||
else
|
||||
delay = atoi((const char *) value);
|
||||
t30 = fax_get_t30_state(fax);
|
||||
t30_get_transfer_statistics(t30, &t30_stats);
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Expect status %d. Got %d\n", delay, t30_stats.current_status);
|
||||
if (delay != t30_stats.current_status)
|
||||
{
|
||||
printf("Test failed\n");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
|
@ -1211,12 +1322,23 @@ static void exchange(faxtester_state_t *s)
|
|||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
if (test_for_call_drop)
|
||||
if (test_for_call_clear && !far_end_cleared_call)
|
||||
{
|
||||
call_clear_timer += len;
|
||||
if (!t30_call_active(fax_get_t30_state(fax)))
|
||||
{
|
||||
printf("Call dropped\n");
|
||||
//break;
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Far end cleared after %dms (limits %dms to %dms)\n", call_clear_timer/8, timein_x, timeout_x);
|
||||
if (call_clear_timer/8 < timein_x || call_clear_timer/8 > timeout_x)
|
||||
{
|
||||
printf("Test failed\n");
|
||||
exit(2);
|
||||
}
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Clear time OK\n");
|
||||
far_end_cleared_call = true;
|
||||
test_for_call_clear = false;
|
||||
while (next_step(s) == 0)
|
||||
;
|
||||
/*endwhile*/
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
|
@ -1297,29 +1419,37 @@ static int parse_test_group(faxtester_state_t *s, xmlDocPtr doc, xmlNsPtr ns, xm
|
|||
|
||||
static int get_test_set(faxtester_state_t *s, const char *test_file, const char *test)
|
||||
{
|
||||
xmlParserCtxtPtr ctxt;
|
||||
xmlDocPtr doc;
|
||||
xmlNsPtr ns;
|
||||
xmlNodePtr cur;
|
||||
xmlValidCtxt valid;
|
||||
|
||||
ns = NULL;
|
||||
xmlKeepBlanksDefault(0);
|
||||
xmlCleanupParser();
|
||||
if ((doc = xmlParseFile(test_file)) == NULL)
|
||||
|
||||
if ((ctxt = xmlNewParserCtxt()) == NULL)
|
||||
{
|
||||
fprintf(stderr, "No document\n");
|
||||
fprintf(stderr, "Failed to allocate parser context\n");
|
||||
printf("Test failed\n");
|
||||
exit(2);
|
||||
}
|
||||
/*endif*/
|
||||
xmlXIncludeProcess(doc);
|
||||
if (!xmlValidateDocument(&valid, doc))
|
||||
/* parse the file, activating the DTD validation option */
|
||||
if ((doc = xmlCtxtReadFile(ctxt, test_file, NULL, XML_PARSE_XINCLUDE | XML_PARSE_DTDVALID)) == NULL)
|
||||
{
|
||||
fprintf(stderr, "Invalid document\n");
|
||||
fprintf(stderr, "Failed to read the XML document\n");
|
||||
printf("Test failed\n");
|
||||
exit(2);
|
||||
}
|
||||
/*endif*/
|
||||
if (ctxt->valid == 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to validate the XML document\n");
|
||||
xmlFreeDoc(doc);
|
||||
xmlFreeParserCtxt(ctxt);
|
||||
printf("Test failed\n");
|
||||
exit(2);
|
||||
}
|
||||
xmlFreeParserCtxt(ctxt);
|
||||
|
||||
/* Check the document is of the right kind */
|
||||
if ((cur = xmlDocGetRootElement(doc)) == NULL)
|
||||
|
|
|
@ -38,8 +38,7 @@ done
|
|||
#MRGN16 fails because we don't adequately distinguish between receiving a
|
||||
#bad image signal and receiving none at all.
|
||||
|
||||
#for TEST in MRGN09 MRGN10 MRGN11 MRGN12 MRGN13 MRGN14 MRGN15 MRGN16 MRGN17
|
||||
for TEST in MRGN09 MRGN10 MRGN11 MRGN12 MRGN13 MRGN15 MRGN17
|
||||
for TEST in MRGN09 MRGN10 MRGN11 MRGN12 MRGN13 MRGN14 MRGN15 MRGN16 MRGN17
|
||||
do
|
||||
run_tsb85_test
|
||||
done
|
||||
|
@ -58,8 +57,7 @@ done
|
|||
# MRGX05 is failing because we don't distinguish MPS immediately after MCF from MPS after
|
||||
# a corrupt image signal.
|
||||
|
||||
#for TEST in MRGX01 MRGX02 MRGX03 MRGX04 MRGX05 MRGX06 MRGX07 MRGX08
|
||||
for TEST in MRGX01 MRGX02 MRGX04 MRGX06 MRGX07 MRGX08
|
||||
for TEST in MRGX01 MRGX02 MRGX03 MRGX04 MRGX05 MRGX06 MRGX07 MRGX08
|
||||
do
|
||||
run_tsb85_test
|
||||
done
|
||||
|
|
Loading…
Reference in New Issue