static void phase_b_handler(t30_state_t *s, void *user_data, int result) { int session; session = (intptr_t) user_data; printf("Phase B handler on session %d - (0x%X) %s\n", session, result, t30_frametype(result)); }
static void phase_b_handler(t30_state_t *s, void *user_data, int result) { int i; i = (int) (intptr_t) user_data; printf("%c: Phase B handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result)); }
static void print_frame(const char *io, const uint8_t *fr, int frlen) { int i; int type; const char *country; const char *vendor; const char *model; fprintf(stderr, "%s %s:", io, t30_frametype(fr[2])); for (i = 2; i < frlen; i++) fprintf(stderr, " %02x", fr[i]); fprintf(stderr, "\n"); type = fr[2] & 0xFE; if (type == T30_DIS || type == T30_DTC || type == T30_DCS) t30_decode_dis_dtc_dcs(&t30_dummy, fr, frlen); if (type == T30_CSI || type == T30_TSI || type == T30_PWD || type == T30_SEP || type == T30_SUB || type == T30_SID) decode_20digit_msg(fr, frlen); if (type == T30_NSF || type == T30_NSS || type == T30_NSC) { if (t35_decode(&fr[3], frlen - 3, &country, &vendor, &model)) { if (country) fprintf(stderr, "The remote was made in '%s'\n", country); if (vendor) fprintf(stderr, "The remote was made by '%s'\n", vendor); if (model) fprintf(stderr, "The remote is a '%s'\n", model); } } }
static int phase_b_handler(t30_state_t *s, void *user_data, int result) { int i; char tag[20]; i = (int) (intptr_t) user_data; snprintf(tag, sizeof(tag), "%c: Phase B", i); printf("%c: Phase B handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result)); fax_log_rx_parameters(s, tag); return T30_ERR_OK; }
static int phase_b_handler(void *user_data, int result) { int ch; t30_state_t *s; char tag[20]; ch = 'A'; s = (t30_state_t *) user_data; snprintf(tag, sizeof(tag), "%c: Phase B", ch); printf("%c: Phase B handler on channel %c - (0x%X) %s\n", ch, ch, result, t30_frametype(result)); fax_log_rx_parameters(s, tag); return T30_ERR_OK; }
static void real_time_gateway_frame_handler(t38_gateway_state_t *s, void *user_data, int direction, const uint8_t *msg, int len) { int i; i = (intptr_t) user_data; printf("%c: Real time gateway frame handler - %s, %s, length = %d\n", i + 'A', (direction) ? "PSTN->T.38" : "T.38->PSTN", t30_frametype(msg[2]), len); }
static void real_time_frame_handler(t30_state_t *s, void *user_data, int direction, const uint8_t *msg, int len) { int i; i = (intptr_t) user_data; printf("%c: Real time frame handler - %s, %s, length = %d\n", i + 'A', (direction) ? "line->T.30" : "T.30->line", t30_frametype(msg[2]), len); }
static int phase_d_handler(t30_state_t *s, void *user_data, int result) { int i; char tag[20]; i = (int) (intptr_t) user_data; snprintf(tag, sizeof(tag), "%c: Phase D", i + 'A'); printf("%c: Phase D handler - (0x%X) %s\n", i + 'A', result, t30_frametype(result)); fax_log_page_transfer_statistics(s, tag); fax_log_tx_parameters(s, tag); fax_log_rx_parameters(s, tag); if (use_receiver_not_ready) t30_set_receiver_not_ready(s, 3); if (test_local_interrupt) { if (i == 'A') { printf("%c: Initiating interrupt request\n", i); t30_local_interrupt_request(s, TRUE); } else { switch (result) { case T30_PIP: case T30_PRI_MPS: case T30_PRI_EOM: case T30_PRI_EOP: printf("%c: Accepting interrupt request\n", i); t30_local_interrupt_request(s, TRUE); break; case T30_PIN: break; } } } return T30_ERR_OK; }
static void phase_d_handler(t30_state_t *s, void *user_data, int result) { int i; t30_stats_t t; char ident[21]; i = (int) (intptr_t) user_data; printf("%c: Phase D handler on channel %c - (0x%X) %s\n", i, i, result, t30_frametype(result)); t30_get_transfer_statistics(s, &t); printf("%c: Phase D: bit rate %d\n", i, t.bit_rate); printf("%c: Phase D: ECM %s\n", i, (t.error_correcting_mode) ? "on" : "off"); printf("%c: Phase D: pages transferred %d\n", i, t.pages_transferred); printf("%c: Phase D: image size %d x %d\n", i, t.width, t.length); printf("%c: Phase D: image resolution %d x %d\n", i, t.x_resolution, t.y_resolution); printf("%c: Phase D: bad rows %d\n", i, t.bad_rows); printf("%c: Phase D: longest bad row run %d\n", i, t.longest_bad_row_run); printf("%c: Phase D: coding method %s\n", i, t4_encoding_to_str(t.encoding)); printf("%c: Phase D: image size %d\n", i, t.image_size); t30_get_local_ident(s, ident); printf("%c: Phase D: local ident '%s'\n", i, ident); t30_get_far_ident(s, ident); printf("%c: Phase D: remote ident '%s'\n", i, ident); }
static void decode_20digit_msg(const uint8_t *pkt, int len) { int p; int k; char msg[T30_MAX_IDENT_LEN + 1]; if (len > T30_MAX_IDENT_LEN + 3) { fprintf(stderr, "XXX %d %d\n", len, T30_MAX_IDENT_LEN + 1); msg[0] = '\0'; return; } pkt += 2; p = len - 2; /* Strip trailing spaces */ while (p > 1 && pkt[p - 1] == ' ') p--; /* The string is actually backwards in the message */ k = 0; while (p > 1) msg[k++] = pkt[--p]; msg[k] = '\0'; fprintf(stderr, "%s is: \"%s\"\n", t30_frametype(pkt[0]), msg); }
static int phase_b_handler(t30_state_t *s, void *user_data, int result) { int i; int ch; int status; int len; char tag[20]; const char *u; const uint8_t *v; i = (int) (intptr_t) user_data; ch = i + 'A'; snprintf(tag, sizeof(tag), "%c: Phase B", ch); printf("%c: Phase B handler - (0x%X) %s\n", ch, result, t30_frametype(result)); fax_log_rx_parameters(s, tag); status = T30_ERR_OK; if ((u = t30_get_rx_ident(s))) { printf("%c: Phase B remote ident '%s'\n", ch, u); if (expected_rx_info[i].ident[0] && strcmp(expected_rx_info[i].ident, u)) { printf("%c: Phase B: remote ident incorrect! - expected '%s'\n", ch, expected_rx_info[i].ident); status = T30_ERR_IDENT_UNACCEPTABLE; } } else { if (expected_rx_info[i].ident[0]) { printf("%c: Phase B: remote ident missing!\n", ch); status = T30_ERR_IDENT_UNACCEPTABLE; } } if ((u = t30_get_rx_sub_address(s))) { printf("%c: Phase B: remote sub-address '%s'\n", ch, u); if (expected_rx_info[i].sub_address[0] && strcmp(expected_rx_info[i].sub_address, u)) { printf("%c: Phase B: remote sub-address incorrect! - expected '%s'\n", ch, expected_rx_info[i].sub_address); status = T30_ERR_SUB_UNACCEPTABLE; } } else { if (expected_rx_info[i].sub_address[0]) { printf("%c: Phase B: remote sub-address missing!\n", ch); status = T30_ERR_SUB_UNACCEPTABLE; } } if ((u = t30_get_rx_polled_sub_address(s))) { printf("%c: Phase B: remote polled sub-address '%s'\n", ch, u); if (expected_rx_info[i].polled_sub_address[0] && strcmp(expected_rx_info[i].polled_sub_address, u)) { printf("%c: Phase B: remote polled sub-address incorrect! - expected '%s'\n", ch, expected_rx_info[i].polled_sub_address); status = T30_ERR_PSA_UNACCEPTABLE; } } else { if (expected_rx_info[i].polled_sub_address[0]) { printf("%c: Phase B: remote polled sub-address missing!\n", ch); status = T30_ERR_PSA_UNACCEPTABLE; } } if ((u = t30_get_rx_selective_polling_address(s))) { printf("%c: Phase B: remote selective polling address '%s'\n", ch, u); if (expected_rx_info[i].selective_polling_address[0] && strcmp(expected_rx_info[i].selective_polling_address, u)) { printf("%c: Phase B: remote selective polling address incorrect! - expected '%s'\n", ch, expected_rx_info[i].selective_polling_address); status = T30_ERR_SEP_UNACCEPTABLE; } } else { if (expected_rx_info[i].selective_polling_address[0]) { printf("%c: Phase B: remote selective polling address missing!\n", ch); status = T30_ERR_SEP_UNACCEPTABLE; } } if ((u = t30_get_rx_sender_ident(s))) { printf("%c: Phase B: remote sender ident '%s'\n", ch, u); if (expected_rx_info[i].sender_ident[0] && strcmp(expected_rx_info[i].sender_ident, u)) { printf("%c: Phase B: remote sender ident incorrect! - expected '%s'\n", ch, expected_rx_info[i].sender_ident); status = T30_ERR_SID_UNACCEPTABLE; } } else { if (expected_rx_info[i].sender_ident[0]) { printf("%c: Phase B: remote sender ident missing!\n", ch); status = T30_ERR_SID_UNACCEPTABLE; } } if ((u = t30_get_rx_password(s))) { printf("%c: Phase B: remote password '%s'\n", ch, u); if (expected_rx_info[i].password[0] && strcmp(expected_rx_info[i].password, u)) { printf("%c: Phase B: remote password incorrect! - expected '%s'\n", ch, expected_rx_info[i].password); status = T30_ERR_PWD_UNACCEPTABLE; } } else { if (expected_rx_info[i].password[0]) { printf("%c: Phase B: remote password missing!\n", ch); status = T30_ERR_PWD_UNACCEPTABLE; } } if ((len = t30_get_rx_nsf(s, &v))) { printf("%c: Phase B: NSF %d bytes\n", ch, len); if (expected_rx_info[i].nsf_len && (expected_rx_info[i].nsf_len != len || memcmp(expected_rx_info[i].nsf, v, len))) { printf("%c: Phase B: remote NSF incorrect! - expected %u bytes\n", ch, (unsigned int) expected_rx_info[i].nsf_len); } } else { if (expected_rx_info[i].nsf_len) { printf("%c: Phase B: remote NSF missing! - expected %u bytes\n", ch, (unsigned int) expected_rx_info[i].nsf_len); } } if ((len = t30_get_rx_nsc(s, &v))) { printf("%c: Phase B: NSC %d bytes\n", ch, len); if (expected_rx_info[i].nsc_len && (expected_rx_info[i].nsc_len != len || memcmp(expected_rx_info[i].nsc, v, len))) { printf("%c: Phase B: remote NSC incorrect! - expected %u bytes\n", ch, (unsigned int) expected_rx_info[i].nsc_len); } } else { if (expected_rx_info[i].nsc_len) { printf("%c: Phase B: remote NSC missing! - expected %u bytes\n", ch, (unsigned int) expected_rx_info[i].nsc_len); } } if ((len = t30_get_rx_nss(s, &v))) { printf("%c: Phase B: NSS %d bytes\n", ch, len); if (expected_rx_info[i].nss_len && (expected_rx_info[i].nss_len != len || memcmp(expected_rx_info[i].nss, v, len))) { printf("%c: Phase B: remote NSS incorrect! - expected %u bytes\n", ch, (unsigned int) expected_rx_info[i].nss_len); } } else { if (expected_rx_info[i].nss_len) { printf("%c: Phase B: remote NSS missing! - expected %u bytes\n", ch, (unsigned int) expected_rx_info[i].nsf_len); } } return status; }
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; uint8_t buf2[len]; s = (t38_terminal_state_t *) user_data; #if 0 /* In termination mode we don't care very much what the data type is. */ switch (data_type) { case T38_DATA_V21: case T38_DATA_V27TER_2400: case T38_DATA_V27TER_4800: case T38_DATA_V29_7200: case T38_DATA_V29_9600: case T38_DATA_V17_7200: case T38_DATA_V17_9600: case T38_DATA_V17_12000: case T38_DATA_V17_14400: case T38_DATA_V8: case T38_DATA_V34_PRI_RATE: case T38_DATA_V34_CC_1200: case T38_DATA_V34_PRI_CH: case T38_DATA_V33_12000: case T38_DATA_V33_14400: default: break; } #endif switch (field_type) { case T38_FIELD_HDLC_DATA: if (s->rx_len + len <= T38_MAX_HDLC_LEN) { bit_reverse(s->rx_buf + s->rx_len, buf, len); s->rx_len += len; } s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT); break; case T38_FIELD_HDLC_FCS_OK: 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. */ } /* Don't deal with repeats of the same field type. Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_OK packets, when they have sent no data for the body of the frame. */ if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type) { span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC OK (%s)\n", (s->rx_len >= 3) ? t30_frametype(s->rx_buf[2]) : "???", (s->missing_data) ? "missing octets" : "clean"); t30_hdlc_accept(&(s->t30_state), !s->missing_data, s->rx_buf, s->rx_len); } s->rx_len = 0; s->missing_data = FALSE; s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT); break; case T38_FIELD_HDLC_FCS_BAD: 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. */ } /* Don't deal with repeats of the same field type. Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_BAD packets, when they have sent no data for the body of the frame. */ if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type) { span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC bad (%s)\n", (s->rx_len >= 3) ? t30_frametype(s->rx_buf[2]) : "???", (s->missing_data) ? "missing octets" : "clean"); t30_hdlc_accept(&(s->t30_state), FALSE, s->rx_buf, s->rx_len); } s->rx_len = 0; s->missing_data = FALSE; s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT); break; case T38_FIELD_HDLC_FCS_OK_SIG_END: 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. */ } /* Don't deal with repeats of the same field type. Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_OK_SIG_END packets, when they have sent no data for the body of the frame. */ if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type) { span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC OK, sig end (%s)\n", (s->rx_len >= 3) ? t30_frametype(s->rx_buf[2]) : "???", (s->missing_data) ? "missing octets" : "clean"); t30_hdlc_accept(&(s->t30_state), !s->missing_data, s->rx_buf, s->rx_len); t30_hdlc_accept(&(s->t30_state), TRUE, NULL, PUTBIT_CARRIER_DOWN); } s->rx_len = 0; s->missing_data = FALSE; s->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. */ } /* Don't deal with repeats of the same field type. Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_BAD_SIG_END packets, when they have sent no data for the body of the frame. */ if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type) { span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC bad, sig end (%s)\n", (s->rx_len >= 3) ? t30_frametype(s->rx_buf[2]) : "???", (s->missing_data) ? "missing octets" : "clean"); t30_hdlc_accept(&(s->t30_state), FALSE, s->rx_buf, s->rx_len); t30_hdlc_accept(&(s->t30_state), TRUE, NULL, PUTBIT_CARRIER_DOWN); } s->rx_len = 0; s->missing_data = FALSE; s->timeout_rx_samples = 0; break; case T38_FIELD_HDLC_SIG_END: if (len > 0) { span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_SIG_END!\n"); /* The sender has incorrectly included data in this message, but there seems nothing meaningful it could be. There could not be an FCS good/bad report beyond this. */ } /* This message is expected under 2 circumstances. One is as an alternative to T38_FIELD_HDLC_FCS_OK_SIG_END - i.e. they send T38_FIELD_HDLC_FCS_OK, and then T38_FIELD_HDLC_SIG_END when the carrier actually drops. The other is because the HDLC signal drops unexpectedly - i.e. not just after a final frame. */ if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type) { /* WORKAROUND: At least some Mediatrix boxes have a bug, where they can send this message at the end of non-ECM data. We need to tolerate this. We use the generic receive complete indication, rather than the specific HDLC carrier down. */ s->rx_len = 0; s->missing_data = FALSE; s->timeout_rx_samples = 0; t30_receive_complete(&(s->t30_state)); } break; case T38_FIELD_T4_NON_ECM_DATA: if (!s->rx_signal_present) { t30_non_ecm_put_bit(&(s->t30_state), PUTBIT_TRAINING_SUCCEEDED); s->rx_signal_present = TRUE; } bit_reverse(buf2, buf, len); t30_non_ecm_put_chunk(&(s->t30_state), buf2, len); s->timeout_rx_samples = s->samples + ms_to_samples(MID_RX_TIMEOUT); break; case T38_FIELD_T4_NON_ECM_SIG_END: if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type) { if (len > 0) { if (!s->rx_signal_present) { t30_non_ecm_put_bit(&(s->t30_state), PUTBIT_TRAINING_SUCCEEDED); s->rx_signal_present = TRUE; } bit_reverse(buf2, buf, len); t30_non_ecm_put_chunk(&(s->t30_state), buf2, len); } /* WORKAROUND: At least some Mediatrix boxes have a bug, where they can send HDLC signal end where they should send non-ECM signal end. It is possible they also do the opposite. We need to tolerate this, so we use the generic receive complete indication, rather than the specific non-ECM carrier down. */ t30_receive_complete(&(s->t30_state)); } s->rx_signal_present = FALSE; s->timeout_rx_samples = 0; break; case T38_FIELD_CM_MESSAGE: case T38_FIELD_JM_MESSAGE: case T38_FIELD_CI_MESSAGE: case T38_FIELD_V34RATE: default: break; } return 0; }