Fix for T.30 processing of operator interrupts, to improve compatibility

with some machines, which seem to send them when no operator is around.

Fix for T.38 gateway not kicking off or ending transmission under certain
timing conditions.
This commit is contained in:
Steve Underwood 2010-09-09 00:16:18 +08:00
parent 86de47ff31
commit 84ee0ae61b
4 changed files with 248 additions and 274 deletions

View File

@ -2377,6 +2377,8 @@ static int send_response_to_pps(t30_state_t *s)
}
/*- End of function --------------------------------------------------------*/
#define VET_ALL_FCD_FRAMES
static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len)
{
int page;
@ -2387,6 +2389,10 @@ static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len)
int frame_no;
int first_bad_frame;
int image_ended;
#if defined(VET_ALL_FCD_FRAMES)
int first;
int expected_len;
#endif
if (len < 7)
{
@ -2469,12 +2475,35 @@ static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len)
/* Build a bit map of which frames we now have stored OK */
first_bad_frame = 256;
#if defined(VET_ALL_FCD_FRAMES)
first = TRUE;
expected_len = 256;
#endif
for (i = 0; i < 32; i++)
{
s->ecm_frame_map[i + 3] = 0;
for (j = 0; j < 8; j++)
{
frame_no = (i << 3) + j;
#if defined(VET_ALL_FCD_FRAMES)
if (s->ecm_len[frame_no] >= 0)
{
if (frame_no < s->ecm_frames - 1)
{
if (first)
{
if (s->ecm_len[frame_no] == 64)
expected_len = 64;
first = FALSE;
}
if (s->ecm_len[frame_no] != expected_len)
{
span_log(&s->logging, SPAN_LOG_FLOW, "Bad length ECM frame - %d\n", s->ecm_len[frame_no]);
s->ecm_len[frame_no] = -1;
}
}
}
#endif
if (s->ecm_len[frame_no] < 0)
{
s->ecm_frame_map[i + 3] |= (1 << j);
@ -2524,14 +2553,18 @@ static int process_rx_pps(t30_state_t *s, const uint8_t *msg, int len)
switch (s->last_pps_fcf2)
{
case T30_NULL:
case T30_EOP:
case T30_PRI_EOP:
case T30_EOM:
case T30_PRI_EOM:
case T30_EOS:
case T30_MPS:
case T30_PRI_MPS:
case T30_PRI_EOM:
case T30_PRI_EOP:
if (s->remote_interrupts_allowed)
{
}
/* Fall through */
case T30_NULL:
case T30_MPS:
case T30_EOM:
case T30_EOS:
case T30_EOP:
if (s->receiver_not_ready_count > 0)
{
s->receiver_not_ready_count--;
@ -2635,7 +2668,13 @@ static void process_rx_fcd(t30_state_t *s, const uint8_t *msg, int len)
switch (s->state)
{
case T30_STATE_F_DOC_ECM:
if (len <= 4 + 256)
if (len > 4 + 256)
{
/* For other frame types we kill the call on an unexpected frame length. For FCD frames it is better to just ignore
the frame, and let retries sort things out. */
span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected %s frame length - %d\n", t30_frametype(msg[0]), len);
}
else
{
frame_no = msg[3];
/* Just store the actual image data, and record its length */
@ -2645,10 +2684,6 @@ static void process_rx_fcd(t30_state_t *s, const uint8_t *msg, int len)
/* In case we are just after a CTC/CTR exchange, which kicked us back to long training */
s->short_train = TRUE;
}
else
{
unexpected_frame_length(s, msg, len);
}
/* We have received something, so any missing carrier status is out of date */
if (s->current_status == T30_ERR_RX_NOCARRIER)
s->current_status = T30_ERR_OK;
@ -2677,6 +2712,7 @@ static void process_rx_rcp(t30_state_t *s, const uint8_t *msg, int len)
case T30_STATE_F_POST_DOC_ECM:
/* Just ignore this. It must be an extra RCP. Several are usually sent, to maximise the chance
of receiving a correct one. */
timer_t2_start(s);
break;
default:
unexpected_non_final_frame(s, msg, len);
@ -3063,6 +3099,11 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int
case T30_DCS:
process_rx_dcs(s, msg, len);
break;
case T30_PRI_MPS:
if (s->remote_interrupts_allowed)
{
}
/* Fall through */
case T30_MPS:
/* Treat this as a bad quality page. */
if (s->phase_d_handler)
@ -3072,16 +3113,11 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int
set_state(s, T30_STATE_III_Q_RTN);
send_simple_frame(s, T30_RTN);
break;
case T30_PRI_MPS:
/* Treat this as a bad quality page. */
if (s->phase_d_handler)
case T30_PRI_EOM:
if (s->remote_interrupts_allowed)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
s->next_rx_step = msg[2] & 0xFE;
set_state(s, T30_STATE_III_Q_RTN);
break;
/* Fall through */
case T30_EOM:
case T30_EOS:
/* Treat this as a bad quality page. */
@ -3093,16 +3129,11 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int
set_state(s, T30_STATE_III_Q_RTN);
send_simple_frame(s, T30_RTN);
break;
case T30_PRI_EOM:
/* Treat this as a bad quality page. */
if (s->phase_d_handler)
case T30_PRI_EOP:
if (s->remote_interrupts_allowed)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
s->next_rx_step = T30_PRI_EOM;
set_state(s, T30_STATE_III_Q_RTN);
break;
/* Fall through */
case T30_EOP:
/* Treat this as a bad quality page. */
if (s->phase_d_handler)
@ -3112,16 +3143,6 @@ static void process_state_f_doc_non_ecm(t30_state_t *s, const uint8_t *msg, int
set_state(s, T30_STATE_III_Q_RTN);
send_simple_frame(s, T30_RTN);
break;
case T30_PRI_EOP:
/* Treat this as a bad quality page. */
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
s->next_rx_step = msg[2] & 0xFE;
set_state(s, T30_STATE_III_Q_RTN);
break;
case T30_DCN:
s->current_status = T30_ERR_RX_DCNDATA;
disconnect(s);
@ -3148,6 +3169,11 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg,
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_PRI_MPS:
if (s->remote_interrupts_allowed)
{
}
/* Fall through */
case T30_MPS:
s->next_rx_step = fcf;
queue_phase(s, T30_PHASE_D_TX);
@ -3179,41 +3205,11 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg,
break;
}
break;
case T30_PRI_MPS:
s->next_rx_step = fcf;
switch (copy_quality(s))
case T30_PRI_EOM:
if (s->remote_interrupts_allowed)
{
case T30_COPY_QUALITY_PERFECT:
case T30_COPY_QUALITY_GOOD:
rx_end_page(s);
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
terminate_operation_in_progress(s);
set_state(s, T30_STATE_III_Q_MCF);
break;
case T30_COPY_QUALITY_POOR:
rx_end_page(s);
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
terminate_operation_in_progress(s);
set_state(s, T30_STATE_III_Q_RTP);
break;
case T30_COPY_QUALITY_BAD:
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
set_state(s, T30_STATE_III_Q_RTN);
break;
}
break;
/* Fall through */
case T30_EOM:
case T30_EOS:
s->next_rx_step = fcf;
@ -3247,41 +3243,11 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg,
break;
}
break;
case T30_PRI_EOM:
s->next_rx_step = fcf;
switch (copy_quality(s))
case T30_PRI_EOP:
if (s->remote_interrupts_allowed)
{
case T30_COPY_QUALITY_PERFECT:
case T30_COPY_QUALITY_GOOD:
rx_end_page(s);
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
terminate_operation_in_progress(s);
set_state(s, T30_STATE_III_Q_MCF);
break;
case T30_COPY_QUALITY_POOR:
rx_end_page(s);
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
terminate_operation_in_progress(s);
set_state(s, T30_STATE_III_Q_RTP);
break;
case T30_COPY_QUALITY_BAD:
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
set_state(s, T30_STATE_III_Q_RTN);
break;
}
break;
/* Fall through */
case T30_EOP:
s->next_rx_step = fcf;
queue_phase(s, T30_PHASE_D_TX);
@ -3312,41 +3278,6 @@ static void process_state_f_post_doc_non_ecm(t30_state_t *s, const uint8_t *msg,
break;
}
break;
case T30_PRI_EOP:
s->next_rx_step = fcf;
switch (copy_quality(s))
{
case T30_COPY_QUALITY_PERFECT:
case T30_COPY_QUALITY_GOOD:
rx_end_page(s);
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
terminate_operation_in_progress(s);
set_state(s, T30_STATE_III_Q_MCF);
break;
case T30_COPY_QUALITY_POOR:
rx_end_page(s);
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
terminate_operation_in_progress(s);
set_state(s, T30_STATE_III_Q_RTP);
break;
case T30_COPY_QUALITY_BAD:
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
set_state(s, T30_STATE_III_Q_RTN);
break;
}
break;
case T30_DCN:
s->current_status = T30_ERR_RX_DCNFAX;
disconnect(s);
@ -3384,21 +3315,7 @@ static void process_state_f_doc_and_post_doc_ecm(t30_state_t *s, const uint8_t *
case T4_RCP:
/* Return to control for partial page. These might come through with or without the final frame tag.
Here we deal with the "final frame tag" case. */
if (s->state == T30_STATE_F_DOC_ECM)
{
/* Return to control for partial page */
set_state(s, T30_STATE_F_POST_DOC_ECM);
queue_phase(s, T30_PHASE_D_RX);
timer_t2_start(s);
/* We have received something, so any missing carrier status is out of date */
if (s->current_status == T30_ERR_RX_NOCARRIER)
s->current_status = T30_ERR_OK;
}
else
{
/* Just ignore this. It must be an extra RCP. Several are usually sent, to maximise the chance
of receiving a correct one. */
}
process_rx_rcp(s, msg, len);
break;
case T30_EOR:
if (len != 4)
@ -3413,7 +3330,10 @@ static void process_state_f_doc_and_post_doc_ecm(t30_state_t *s, const uint8_t *
case T30_PRI_EOP:
case T30_PRI_EOM:
case T30_PRI_MPS:
/* TODO: Alert operator */
if (s->remote_interrupts_allowed)
{
/* TODO: Alert operator */
}
/* Fall through */
case T30_NULL:
case T30_EOP:
@ -3651,11 +3571,22 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_PIP:
if (s->remote_interrupts_allowed)
{
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
}
/* Fall through */
case T30_MCF:
switch (s->next_tx_step)
{
case T30_MPS:
case T30_PRI_MPS:
case T30_MPS:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf);
@ -3668,8 +3599,8 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
set_state(s, T30_STATE_I);
queue_phase(s, T30_PHASE_C_NON_ECM_TX);
break;
case T30_EOM:
case T30_PRI_EOM:
case T30_EOM:
case T30_EOS:
tx_end_page(s);
if (s->phase_d_handler)
@ -3678,8 +3609,8 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
report_tx_result(s, TRUE);
return_to_phase_b(s, FALSE);
break;
case T30_EOP:
case T30_PRI_EOP:
case T30_EOP:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf);
@ -3690,13 +3621,11 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
}
break;
case T30_RTP:
#if 0
s->rtp_events++;
#endif
switch (s->next_tx_step)
{
case T30_MPS:
case T30_PRI_MPS:
case T30_MPS:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf);
@ -3717,8 +3646,8 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
queue_phase(s, T30_PHASE_B_TX);
restart_sending_document(s);
break;
case T30_EOM:
case T30_PRI_EOM:
case T30_EOM:
case T30_EOS:
tx_end_page(s);
if (s->phase_d_handler)
@ -3727,8 +3656,8 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
/* TODO: should go back to T, and resend */
return_to_phase_b(s, TRUE);
break;
case T30_EOP:
case T30_PRI_EOP:
case T30_EOP:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf);
@ -3737,20 +3666,27 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
break;
}
break;
case T30_PIN:
if (s->remote_interrupts_allowed)
{
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
}
/* Fall through */
case T30_RTN:
#if 0
s->rtn_events++;
#endif
switch (s->next_tx_step)
{
case T30_MPS:
case T30_PRI_MPS:
case T30_MPS:
s->retries = 0;
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf);
#if 0
if (!s->retransmit_capable)
#endif
{
/* Send the next page, regardless of the problem with the current one. */
if (tx_start_page(s))
@ -3771,29 +3707,26 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
queue_phase(s, T30_PHASE_B_TX);
restart_sending_document(s);
break;
case T30_EOM:
case T30_PRI_EOM:
case T30_EOM:
case T30_EOS:
s->retries = 0;
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf);
#if 0
if (s->retransmit_capable)
{
/* Wait for DIS */
}
else
#endif
{
return_to_phase_b(s, TRUE);
}
break;
case T30_EOP:
case T30_PRI_EOP:
case T30_EOP:
s->retries = 0;
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf);
#if 0
if (s->retransmit_capable)
{
/* Send fresh training, and then repeat the last page */
@ -3809,36 +3742,19 @@ static void process_state_ii_q(t30_state_t *s, const uint8_t *msg, int len)
restart_sending_document(s);
}
else
#endif
{
send_dcn(s);
}
break;
}
break;
case T30_PIP:
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
break;
case T30_PIN:
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
break;
case T30_DCN:
switch (s->next_tx_step)
{
case T30_MPS:
case T30_PRI_MPS:
case T30_EOM:
case T30_PRI_EOM:
case T30_MPS:
case T30_EOM:
case T30_EOS:
/* Unexpected DCN after EOM, EOS or MPS sequence */
s->current_status = T30_ERR_RX_DCNPHD;
@ -4019,8 +3935,8 @@ static void process_state_iv_pps_null(t30_state_t *s, const uint8_t *msg, int le
span_log(&s->logging, SPAN_LOG_FLOW, "Moving on to the next page\n");
switch (s->next_tx_step)
{
case T30_MPS:
case T30_PRI_MPS:
case T30_MPS:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf);
@ -4036,8 +3952,8 @@ static void process_state_iv_pps_null(t30_state_t *s, const uint8_t *msg, int le
send_first_ecm_frame(s);
}
break;
case T30_EOM:
case T30_PRI_EOM:
case T30_EOM:
case T30_EOS:
tx_end_page(s);
if (s->phase_d_handler)
@ -4046,8 +3962,8 @@ static void process_state_iv_pps_null(t30_state_t *s, const uint8_t *msg, int le
report_tx_result(s, TRUE);
return_to_phase_b(s, FALSE);
break;
case T30_EOP:
case T30_PRI_EOP:
case T30_EOP:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf);
@ -4094,6 +4010,17 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len)
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_PIP:
if (s->remote_interrupts_allowed)
{
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
}
/* Fall through */
case T30_MCF:
s->retries = 0;
s->timer_t5 = 0;
@ -4112,8 +4039,8 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len)
span_log(&s->logging, SPAN_LOG_FLOW, "Moving on to the next page\n");
switch (s->next_tx_step)
{
case T30_MPS:
case T30_PRI_MPS:
case T30_MPS:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf);
@ -4129,8 +4056,8 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len)
send_first_ecm_frame(s);
}
break;
case T30_EOM:
case T30_PRI_EOM:
case T30_EOM:
case T30_EOS:
tx_end_page(s);
if (s->phase_d_handler)
@ -4139,8 +4066,8 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len)
report_tx_result(s, TRUE);
return_to_phase_b(s, FALSE);
break;
case T30_EOP:
case T30_PRI_EOP:
case T30_EOP:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf);
@ -4158,22 +4085,6 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len)
set_state(s, T30_STATE_IV_PPS_RNR);
send_rr(s);
break;
case T30_PIP:
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
break;
case T30_PIN:
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
break;
case T30_PPR:
process_rx_ppr(s, msg, len);
break;
@ -4187,6 +4098,17 @@ static void process_state_iv_pps_q(t30_state_t *s, const uint8_t *msg, int len)
case T30_FNV:
process_rx_fnv(s, msg, len);
break;
case T30_PIN:
if (s->remote_interrupts_allowed)
{
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
}
/* Fall through */
default:
/* We don't know what to do with this. */
unexpected_final_frame(s, msg, len);
@ -4203,6 +4125,17 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len
fcf = msg[2] & 0xFE;
switch (fcf)
{
case T30_PIP:
if (s->remote_interrupts_allowed)
{
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
}
/* Fall through */
case T30_MCF:
s->retries = 0;
s->timer_t5 = 0;
@ -4221,8 +4154,8 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len
span_log(&s->logging, SPAN_LOG_FLOW, "Moving on to the next page\n");
switch (s->next_tx_step)
{
case T30_MPS:
case T30_PRI_MPS:
case T30_MPS:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf);
@ -4238,8 +4171,8 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len
send_first_ecm_frame(s);
}
break;
case T30_EOM:
case T30_PRI_EOM:
case T30_EOM:
case T30_EOS:
tx_end_page(s);
if (s->phase_d_handler)
@ -4248,8 +4181,8 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len
report_tx_result(s, TRUE);
return_to_phase_b(s, FALSE);
break;
case T30_EOP:
case T30_PRI_EOP:
case T30_EOP:
tx_end_page(s);
if (s->phase_d_handler)
s->phase_d_handler(s, s->phase_d_user_data, fcf);
@ -4267,22 +4200,6 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len
set_state(s, T30_STATE_IV_PPS_RNR);
send_rr(s);
break;
case T30_PIP:
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
break;
case T30_PIN:
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
break;
case T30_DCN:
s->current_status = T30_ERR_RX_DCNRRD;
disconnect(s);
@ -4293,6 +4210,17 @@ static void process_state_iv_pps_rnr(t30_state_t *s, const uint8_t *msg, int len
case T30_FNV:
process_rx_fnv(s, msg, len);
break;
case T30_PIN:
if (s->remote_interrupts_allowed)
{
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
}
/* Fall through */
default:
/* We don't know what to do with this. */
unexpected_final_frame(s, msg, len);
@ -4345,14 +4273,6 @@ static void process_state_iv_eor(t30_state_t *s, const uint8_t *msg, int len)
set_state(s, T30_STATE_IV_EOR_RNR);
send_rr(s);
break;
case T30_PIN:
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
break;
case T30_ERR:
/* TODO: Continue with the next message if MPS or EOM? */
s->timer_t5 = 0;
@ -4364,6 +4284,17 @@ static void process_state_iv_eor(t30_state_t *s, const uint8_t *msg, int len)
case T30_FNV:
process_rx_fnv(s, msg, len);
break;
case T30_PIN:
if (s->remote_interrupts_allowed)
{
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
}
/* Fall through */
default:
/* We don't know what to do with this. */
unexpected_final_frame(s, msg, len);
@ -4386,14 +4317,6 @@ static void process_state_iv_eor_rnr(t30_state_t *s, const uint8_t *msg, int len
set_state(s, T30_STATE_IV_EOR_RNR);
send_rr(s);
break;
case T30_PIN:
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
break;
case T30_ERR:
/* TODO: Continue with the next message if MPS or EOM? */
s->timer_t5 = 0;
@ -4409,6 +4332,17 @@ static void process_state_iv_eor_rnr(t30_state_t *s, const uint8_t *msg, int len
case T30_FNV:
process_rx_fnv(s, msg, len);
break;
case T30_PIN:
if (s->remote_interrupts_allowed)
{
s->retries = 0;
if (s->phase_d_handler)
{
s->phase_d_handler(s, s->phase_d_user_data, fcf);
s->timer_t3 = ms_to_samples(DEFAULT_TIMER_T3);
}
}
/* Fall through */
default:
/* We don't know what to do with this. */
unexpected_final_frame(s, msg, len);
@ -4596,7 +4530,7 @@ static void process_rx_control_msg(t30_state_t *s, const uint8_t *msg, int len)
/* The following handles context sensitive message types, which should
occur at the end of message sequences. They should, therefore have
the final frame flag set. */
span_log(&s->logging, SPAN_LOG_FLOW, "In state %d\n", s->state);
span_log(&s->logging, SPAN_LOG_FLOW, "Rx final frame in state %d\n", s->state);
switch (s->state)
{
@ -5082,11 +5016,11 @@ static void timer_t2_expired(t30_state_t *s)
case T30_STATE_F_POST_RCP_MCF:
switch (s->next_rx_step)
{
case T30_EOM:
case T30_PRI_EOM:
case T30_EOM:
case T30_EOS:
/* We didn't receive a response to our T30_MCF after T30_EOM, so we must be OK
to proceed to phase B, and pretty act like its the beginning of a call. */
to proceed to phase B, and pretty much act like its the beginning of a call. */
span_log(&s->logging, SPAN_LOG_FLOW, "Returning to phase B after %s\n", t30_frametype(s->next_rx_step));
set_phase(s, T30_PHASE_B_TX);
timer_t2_start(s);
@ -5109,6 +5043,8 @@ static void timer_t2_expired(t30_state_t *s)
case T30_STATE_F_POST_DOC_ECM:
case T30_STATE_F_POST_DOC_NON_ECM:
/* While waiting for next FAX page */
/* Figure 5-2b/T.30 and note 7 says we should allow 1 to 3 tries at this point.
The way we work now is effectively hard coding a 1 try limit */
s->current_status = T30_ERR_RX_T2EXPMPS;
break;
#if 0
@ -5873,8 +5809,8 @@ SPAN_DECLARE(void) t30_front_end_status(void *user_data, int status)
{
switch (s->next_rx_step)
{
case T30_MPS:
case T30_PRI_MPS:
case T30_MPS:
/* We should now start to get another page */
if (s->error_correcting_mode)
{
@ -5888,15 +5824,15 @@ SPAN_DECLARE(void) t30_front_end_status(void *user_data, int status)
}
timer_t2_start(s);
break;
case T30_EOM:
case T30_PRI_EOM:
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);
break;
case T30_EOP:
case T30_PRI_EOP:
case T30_EOP:
/* Wait for a DCN. */
set_phase(s, T30_PHASE_D_RX);
timer_t4_start(s);
@ -6256,6 +6192,12 @@ SPAN_DECLARE(void) t30_local_interrupt_request(t30_state_t *s, int state)
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) t30_remote_interrupts_allowed(t30_state_t *s, int state)
{
s->remote_interrupts_allowed = state;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) t30_restart(t30_state_t *s)
{
s->phase = T30_PHASE_IDLE;
@ -6276,10 +6218,9 @@ SPAN_DECLARE(int) t30_restart(t30_state_t *s)
/* The page number is only reset at call establishment */
s->rx_page_number = 0;
s->tx_page_number = 0;
#if 0
s->rtn_events = 0;
s->rtp_events = 0;
#endif
s->local_interrupt_pending = FALSE;
s->far_end_detected = FALSE;
s->timer_t0_t1 = ms_to_samples(DEFAULT_TIMER_T0);
if (s->calling_party)

View File

@ -2602,7 +2602,9 @@ SPAN_DECLARE(t31_state_t *) t31_init(t31_state_t *s,
t38_tx_packet_handler_t *tx_t38_packet_handler,
void *tx_t38_packet_user_data)
{
#if 0
v8_parms_t v8_parms;
#endif
int alloced;
if (at_tx_handler == NULL || modem_control_handler == NULL)

View File

@ -426,7 +426,6 @@ static int set_next_tx_type(t38_gateway_state_t *s)
t38_gateway_hdlc_state_t *u;
t = &s->audio.modems;
u = &s->core.hdlc_to_modem;
t38_non_ecm_buffer_report_output_status(&s->core.non_ecm_to_modem, &s->logging);
if (t->next_tx_handler)
{
@ -447,6 +446,7 @@ static int set_next_tx_type(t38_gateway_state_t *s)
return TRUE;
}
/*endif*/
u = &s->core.hdlc_to_modem;
if (u->in == u->out)
return FALSE;
/*endif*/
@ -1057,7 +1057,9 @@ static int process_rx_missing(t38_core_state_t *t, void *user_data, int rx_seq_n
static int process_rx_indicator(t38_core_state_t *t, void *user_data, int indicator)
{
t38_gateway_state_t *s;
t38_gateway_hdlc_state_t *u;
int immediate;
s = (t38_gateway_state_t *) user_data;
t38_non_ecm_buffer_report_input_status(&s->core.non_ecm_to_modem, &s->logging);
@ -1067,25 +1069,50 @@ static int process_rx_indicator(t38_core_state_t *t, void *user_data, int indica
return 0;
}
/*endif*/
if (s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in].contents)
u = &s->core.hdlc_to_modem;
immediate = (u->in == u->out);
if (u->buf[u->in].contents)
{
if (++s->core.hdlc_to_modem.in >= T38_TX_HDLC_BUFS)
s->core.hdlc_to_modem.in = 0;
if (++u->in >= T38_TX_HDLC_BUFS)
u->in = 0;
/*endif*/
}
/*endif*/
s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in].contents = (indicator | FLAG_INDICATOR);
if (++s->core.hdlc_to_modem.in >= T38_TX_HDLC_BUFS)
s->core.hdlc_to_modem.in = 0;
u->buf[u->in].contents = (indicator | FLAG_INDICATOR);
if (++u->in >= T38_TX_HDLC_BUFS)
u->in = 0;
/*endif*/
t38_non_ecm_buffer_set_mode(&s->core.non_ecm_to_modem, s->core.image_data_mode, s->core.min_row_bits);
span_log(&s->logging,
SPAN_LOG_FLOW,
"Queued change - (%d) %s -> %s\n",
silence_gen_remainder(&(s->audio.modems.silence_gen)),
t38_indicator_to_str(t->current_rx_indicator),
t38_indicator_to_str(indicator));
if (immediate)
{
span_log(&s->logging,
SPAN_LOG_FLOW,
"Changing - (%d) %s -> %s\n",
silence_gen_remainder(&(s->audio.modems.silence_gen)),
t38_indicator_to_str(t->current_rx_indicator),
t38_indicator_to_str(indicator));
switch (s->t38x.current_rx_field_class)
{
case T38_FIELD_CLASS_NONE:
break;
case T38_FIELD_CLASS_HDLC:
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC shutdown\n");
hdlc_tx_frame(&s->audio.modems.hdlc_tx, NULL, 0);
break;
case T38_FIELD_CLASS_NON_ECM:
break;
}
}
else
{
span_log(&s->logging,
SPAN_LOG_FLOW,
"Queued change - (%d) %s -> %s\n",
silence_gen_remainder(&(s->audio.modems.silence_gen)),
t38_indicator_to_str(t->current_rx_indicator),
t38_indicator_to_str(indicator));
}
s->t38x.current_rx_field_class = T38_FIELD_CLASS_NONE;
/* We need to set this here, since we might have been called as a fake
indication when the real one was missing */
@ -1440,6 +1467,8 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
xx->corrupt_current_frame[0] = FALSE;
break;
case T38_FIELD_T4_NON_ECM_DATA:
if (xx->current_rx_field_class == T38_FIELD_CLASS_NONE)
t38_non_ecm_buffer_set_mode(&s->core.non_ecm_to_modem, s->core.image_data_mode, s->core.min_row_bits);
xx->current_rx_field_class = T38_FIELD_CLASS_NON_ECM;
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
if (hdlc_buf->contents != (data_type | FLAG_DATA))
@ -1454,6 +1483,8 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
xx->corrupt_current_frame[0] = FALSE;
break;
case T38_FIELD_T4_NON_ECM_SIG_END:
if (xx->current_rx_field_class == T38_FIELD_CLASS_NONE)
t38_non_ecm_buffer_set_mode(&s->core.non_ecm_to_modem, s->core.image_data_mode, s->core.min_row_bits);
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
/* Some T.38 implementations send multiple T38_FIELD_T4_NON_ECM_SIG_END messages, in IFP packets with
incrementing sequence numbers, which are actually repeats. They get through to this point because
@ -2432,8 +2463,8 @@ SPAN_DECLARE(t38_gateway_state_t *) t38_gateway_init(t38_gateway_state_t *s,
s->core.to_t38.octets_per_data_packet = 1;
s->core.ecm_allowed = TRUE;
t38_non_ecm_buffer_init(&s->core.non_ecm_to_modem, FALSE, 0);
//s->core.ms_per_tx_chunk = DEFAULT_MS_PER_TX_CHUNK;
t38_non_ecm_buffer_init(&s->core.non_ecm_to_modem, FALSE, 0);
restart_rx_modem(s);
s->core.timed_mode = TIMED_MODE_STARTUP;
s->core.samples_to_timeout = 1;

View File

@ -111,7 +111,7 @@ static const struct dtmf_to_ascii_s dtmf_to_ascii[] =
{"##8", 'W'},
{"##9", 'Z'},
{"##0", ' '},
#if defined(WIN32) || ( defined(__SVR4) && defined (__sun))
#if defined(WIN32) || ( defined(__SVR4) && defined (__sun))
{"#*1", 'X'}, // (Note 1) 111 1011
{"#*2", 'X'}, // (Note 1) 111 1100
{"#*3", 'X'}, // (Note 1) 111 1101