Beispiel #1
0
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));
}     
Beispiel #2
0
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));
}
Beispiel #3
0
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);
        }
    }
}
Beispiel #4
0
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;
}
Beispiel #5
0
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;
}
Beispiel #6
0
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);
}
Beispiel #7
0
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);
}
Beispiel #8
0
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;
}
Beispiel #9
0
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);
}
Beispiel #10
0
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);
}
Beispiel #11
0
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;
}
Beispiel #12
0
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;
}