コード例 #1
0
ファイル: t38_core_tests.c プロジェクト: Jaroslav23/sipxtapi
static int encode_decode_tests(t38_core_state_t *a, t38_core_state_t *b)
{
    t38_data_field_t field[MAX_FIELDS];
    int i;
    int j;
    
    ok_indicator_packets = 0;
    bad_indicator_packets = 0;
    ok_data_packets = 0;
    bad_data_packets = 0;
    missing_packets = 0;

    /* Try all the indicator types */
    for (i = 0;  i < 100;  i++)
    {
        current_indicator = i;
        if (t38_core_send_indicator(a, i, 3) < 0)
            break;
    }

    /* Try all the data types, as single field messages with no data */
    for (i = 0;  i < 100;  i++)
    {
        for (j = 0;  j < 100;  j++)
        {
            current_data_type = i;
            current_field_type = j;
            skip = 99;
            if (t38_core_send_data(a, i, j, (uint8_t *) "", 0, 1) < 0)
                break;
        }
        if (j == 0)
            break;
    }

    /* Try all the data types and field types, as single field messages with data */
    for (i = 0;  i < 100;  i++)
    {
        for (j = 0;  j < 100;  j++)
        {
            current_data_type = i;
            current_field_type = j;
            skip = 99;
            if (t38_core_send_data(a, i, j, (uint8_t *) "ABCD", 4, 1) < 0)
                break;
        }
        if (j == 0)
            break;
    }

    /* Try all the data types and field types, as multi-field messages */
    for (i = 0;  i < 100;  i++)
    {
        for (j = 0;  j < 100;  j++)
        {
            current_data_type = i;
            current_field_type = j;
            skip = 1;

            field_len[0] = 444;
            field_len[1] = 333;

            field[0].field_type = j;
            field[0].field = field_body[0];
            field[0].field_len = field_len[0];
            field[1].field_type = T38_FIELD_T4_NON_ECM_SIG_END;
            field[1].field = field_body[1];
            field[1].field_len = field_len[1];
            if (t38_core_send_data_multi_field(a, i, field, 2, 1) < 0)
                break;
        }
        if (j == 0)
            break;
    }
    printf("Indicator packets: OK = %d, bad = %d\n", ok_indicator_packets, bad_indicator_packets);
    printf("Data packets: OK = %d, bad = %d\n", ok_data_packets, bad_data_packets);
    printf("Missing packets = %d\n", missing_packets);
    if (t38_version == 0)
    {
        if (ok_indicator_packets != 16  ||  bad_indicator_packets != 0)
        {
            printf("Tests failed\n");
            return -1;
        }
        if (ok_data_packets != 288  ||  bad_data_packets != 0)
        {
            printf("Tests failed\n");
            return -1;
        }
    }
    else
    {
        if (ok_indicator_packets != 23  ||  bad_indicator_packets != 0)
        {
            printf("Tests failed\n");
            return -1;
        }
        if (ok_data_packets != 720  ||  bad_data_packets != 0)
        {
            printf("Tests failed\n");
            return -1;
        }
    }
    if (missing_packets > 0)
    {
        printf("Tests failed\n");
        return -1;
    }
    return 0;
}
コード例 #2
0
int t38_terminal_send_timeout(t38_terminal_state_t *s, int samples)
{
    int len;
    int i;
    int previous;
    uint8_t buf[MAX_OCTETS_PER_UNPACED_CHUNK + 50];
    /* Training times for all the modem options, with and without TEP */
    static const int training_time[] =
    {
           0,      0,   /* T38_IND_NO_SIGNAL */
           0,      0,   /* T38_IND_CNG */
           0,      0,   /* T38_IND_CED */
        1000,   1000,   /* T38_IND_V21_PREAMBLE */ /* TODO: 850 should be OK for this, but it causes trouble with some ATAs. Why? */
         943,   1158,   /* T38_IND_V27TER_2400_TRAINING */
         708,    923,   /* T38_IND_V27TER_4800_TRAINING */
         234,    454,   /* T38_IND_V29_7200_TRAINING */
         234,    454,   /* T38_IND_V29_9600_TRAINING */
         142,    367,   /* T38_IND_V17_7200_SHORT_TRAINING */
        1393,   1618,   /* T38_IND_V17_7200_LONG_TRAINING */
         142,    367,   /* T38_IND_V17_9600_SHORT_TRAINING */
        1393,   1618,   /* T38_IND_V17_9600_LONG_TRAINING */
         142,    367,   /* T38_IND_V17_12000_SHORT_TRAINING */
        1393,   1618,   /* T38_IND_V17_12000_LONG_TRAINING */
         142,    367,   /* T38_IND_V17_14400_SHORT_TRAINING */
        1393,   1618,   /* T38_IND_V17_14400_LONG_TRAINING */
           0,      0,   /* T38_IND_V8_ANSAM */
           0,      0,   /* T38_IND_V8_SIGNAL */
           0,      0,   /* T38_IND_V34_CNTL_CHANNEL_1200 */
           0,      0,   /* T38_IND_V34_PRI_CHANNEL */
           0,      0,   /* T38_IND_V34_CC_RETRAIN */
           0,      0,   /* T38_IND_V33_12000_TRAINING */
           0,      0    /* T38_IND_V33_14400_TRAINING */
    };

    if (s->current_rx_type == T30_MODEM_DONE  ||  s->current_tx_type == T30_MODEM_DONE)
        return TRUE;

    s->samples += samples;
    t30_timer_update(&s->t30_state, samples);
    if (s->timeout_rx_samples  &&  s->samples > s->timeout_rx_samples)
    {
        span_log(&s->logging, SPAN_LOG_FLOW, "Timeout mid-receive\n");
        s->timeout_rx_samples = 0;
        t30_receive_complete(&(s->t30_state));
    }
    if (s->timed_step == T38_TIMED_STEP_NONE)
        return FALSE;
    if (s->samples < s->next_tx_samples)
        return FALSE;
    /* Its time to send something */
    switch (s->timed_step)
    {
    case T38_TIMED_STEP_NON_ECM_MODEM:
        /* Create a 75ms silence */
        if (s->t38.current_tx_indicator != T38_IND_NO_SIGNAL)
            t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, s->indicator_tx_count);
        s->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_2;
        s->next_tx_samples += ms_to_samples(75);
        break;
    case T38_TIMED_STEP_NON_ECM_MODEM_2:
        /* Switch on a fast modem, and give the training time to complete */
        t38_core_send_indicator(&s->t38, s->next_tx_indicator, s->indicator_tx_count);
        s->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_3;
        s->next_tx_samples += ms_to_samples(training_time[s->next_tx_indicator << 1]);
        break;
    case T38_TIMED_STEP_NON_ECM_MODEM_3:
        /* Send a chunk of non-ECM image data */
        /* T.38 says it is OK to send the last of the non-ECM data in the signal end message.
           However, I think the early versions of T.38 said the signal end message should not
           contain data. Hopefully, following the current spec will not cause compatibility
           issues. */
        len = t30_non_ecm_get_chunk(&s->t30_state, buf, s->octets_per_data_packet);
        bit_reverse(buf, buf, len);
        if (len >= s->octets_per_data_packet)
        {
            s->next_tx_samples += ms_to_samples(s->ms_per_tx_chunk);
            t38_core_send_data(&s->t38, s->current_tx_data_type, T38_FIELD_T4_NON_ECM_DATA, buf, len, DATA_TX_COUNT);
        }
        else
        {
            t38_core_send_data(&s->t38, s->current_tx_data_type, T38_FIELD_T4_NON_ECM_SIG_END, buf, len, s->data_end_tx_count);
            /* This should not be needed, since the message above indicates the end of the signal, but it
               seems like it can improve compatibility with quirky implementations. */
            t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, s->indicator_tx_count);
            s->timed_step = T38_TIMED_STEP_NONE;
            t30_send_complete(&(s->t30_state));
        }
        break;
    case T38_TIMED_STEP_HDLC_MODEM:
        /* Send HDLC preambling */
        t38_core_send_indicator(&s->t38, s->next_tx_indicator, s->indicator_tx_count);
        s->next_tx_samples += ms_to_samples(training_time[s->next_tx_indicator << 1]);
        s->timed_step = T38_TIMED_STEP_HDLC_MODEM_2;
        break;
    case T38_TIMED_STEP_HDLC_MODEM_2:
        /* Send a chunk of HDLC data */
        i = s->octets_per_data_packet;
        if (i >= (s->tx_len - s->tx_ptr))
        {
            i = s->tx_len - s->tx_ptr;
            s->timed_step = T38_TIMED_STEP_HDLC_MODEM_3;
        }
        t38_core_send_data(&s->t38, s->current_tx_data_type, T38_FIELD_HDLC_DATA, &s->tx_buf[s->tx_ptr], i, DATA_TX_COUNT);
        s->tx_ptr += i;
        s->next_tx_samples += ms_to_samples(s->ms_per_tx_chunk);
        break;
    case T38_TIMED_STEP_HDLC_MODEM_3:
        /* End of HDLC frame */
        previous = s->current_tx_data_type;
        s->tx_ptr = 0;
        s->tx_len = 0;
        t30_send_complete(&s->t30_state);
        if (s->tx_len < 0)
        {
            t38_core_send_data(&s->t38, previous, T38_FIELD_HDLC_FCS_OK_SIG_END, NULL, 0, s->data_end_tx_count);
            /* We have already sent T38_FIELD_HDLC_FCS_OK_SIG_END. It seems some boxes may not like
               us sending a T38_FIELD_HDLC_SIG_END at this point. Just say there is no signal. */
            t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, s->indicator_tx_count);
            s->tx_len = 0;
            t30_send_complete(&s->t30_state);
            if (s->tx_len)
                s->timed_step = T38_TIMED_STEP_HDLC_MODEM;
        }
        else
        {
            t38_core_send_data(&s->t38, previous, T38_FIELD_HDLC_FCS_OK, NULL, 0, DATA_TX_COUNT);
            if (s->tx_len)
                s->timed_step = T38_TIMED_STEP_HDLC_MODEM_2;
        }
        s->next_tx_samples += ms_to_samples(s->ms_per_tx_chunk);
        break;
    case T38_TIMED_STEP_CED:
        /* It seems common practice to start with a no signal indicator, though
           this is not a specified requirement. Since we should be sending 200ms
           of silence, starting the delay with a no signal indication makes sense.
           We do need a 200ms delay, as that is a specification requirement. */
        s->timed_step = T38_TIMED_STEP_CED_2;
        s->next_tx_samples = s->samples + ms_to_samples(200);
        t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, s->indicator_tx_count);
        s->current_tx_data_type = T38_DATA_NONE;
        break;
    case T38_TIMED_STEP_CED_2:
        /* Initial 200ms delay over. Send the CED indicator */
        s->next_tx_samples = s->samples + ms_to_samples(3000);
        s->timed_step = T38_TIMED_STEP_PAUSE;
        t38_core_send_indicator(&s->t38, T38_IND_CED, s->indicator_tx_count);
        s->current_tx_data_type = T38_DATA_NONE;
        break;
    case T38_TIMED_STEP_CNG:
        /* It seems common practice to start with a no signal indicator, though
           this is not a specified requirement. Since we should be sending 200ms
           of silence, starting the delay with a no signal indication makes sense.
           We do need a 200ms delay, as that is a specification requirement. */
        s->timed_step = T38_TIMED_STEP_CNG_2;
        s->next_tx_samples = s->samples + ms_to_samples(200);
        t38_core_send_indicator(&s->t38, T38_IND_NO_SIGNAL, s->indicator_tx_count);
        s->current_tx_data_type = T38_DATA_NONE;
        break;
    case T38_TIMED_STEP_CNG_2:
        /* Initial short delay over. Send the CNG indicator */
        s->timed_step = T38_TIMED_STEP_NONE;
        t38_core_send_indicator(&s->t38, T38_IND_CNG, s->indicator_tx_count);
        s->current_tx_data_type = T38_DATA_NONE;
        break;
    case T38_TIMED_STEP_PAUSE:
        /* End of timed pause */
        s->timed_step = T38_TIMED_STEP_NONE;
        t30_send_complete(&s->t30_state);
        break;
    }
    return FALSE;
}