예제 #1
0
static void set_t30_callbacks(t30_state_t *t30, int chan)
{
    t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) chan);
    t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) chan);
    t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) chan);
    t30_set_real_time_frame_handler(t30, real_time_frame_handler, (void *) (intptr_t) chan);
    t30_set_document_handler(t30, document_handler, (void *) (intptr_t) chan);
}
예제 #2
0
static int fax_set_common(struct cw_channel *chan, t30_state_t *t30, const char *file, int calling_party, int verbose)
{
    char *x;

    x = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
    if (x  &&  x[0])
        t30_set_tx_ident(t30, x);
    x = pbx_builtin_getvar_helper(chan, "LOCALSUBADDRESS");
    if (x  &&  x[0])
        t30_set_tx_sub_address(t30, x);
    x = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO");
    if (x  &&  x[0])
        t30_set_tx_page_header_info(t30, x);
    t30_set_rx_file(t30, file, -1);

    x = pbx_builtin_getvar_helper(chan, "FAX_DISABLE_V17");
    if (x  &&  x[0])
        t30_set_supported_modems(t30, T30_SUPPORT_V29 | T30_SUPPORT_V27TER);

    x = pbx_builtin_getvar_helper(chan, "FAX_DISABLE_ECM");
    if (x  &&  x[0])
    {
        t30_set_supported_compressions(t30,
                                       T30_SUPPORT_T4_1D_COMPRESSION
                                     | T30_SUPPORT_T4_2D_COMPRESSION);
        cw_log(LOG_DEBUG, "Disabling ECM mode\n");
    }
    else 
    {
        t30_set_ecm_capability(t30, TRUE);
        t30_set_supported_compressions(t30,
                                       T30_SUPPORT_T4_1D_COMPRESSION
                                     | T30_SUPPORT_T4_2D_COMPRESSION
                                     | T30_SUPPORT_T6_COMPRESSION);
    }

    t30_set_supported_image_sizes(t30,
                                  T30_SUPPORT_US_LETTER_LENGTH
                                | T30_SUPPORT_US_LEGAL_LENGTH
                                | T30_SUPPORT_UNLIMITED_LENGTH
                                | T30_SUPPORT_215MM_WIDTH
                                | T30_SUPPORT_255MM_WIDTH
                                | T30_SUPPORT_303MM_WIDTH);
    t30_set_supported_resolutions(t30,
                                  T30_SUPPORT_STANDARD_RESOLUTION
                                | T30_SUPPORT_FINE_RESOLUTION
                                | T30_SUPPORT_SUPERFINE_RESOLUTION
                                | T30_SUPPORT_R8_RESOLUTION
                                | T30_SUPPORT_R16_RESOLUTION);

    //t30_set_phase_b_handler(t30, phase_b_handler, chan);
    t30_set_phase_d_handler(t30, phase_d_handler, chan);
    t30_set_phase_e_handler(t30, phase_e_handler, chan);

    return 0;
}
static int t30_tests(int t38_mode, int use_ecm, int use_gui, int log_audio, int test_sending, int g1050_model_no, int g1050_speed_pattern_no)
{
    t38_terminal_state_t *t38_state;
    fax_state_t *fax_state;
    uint8_t msg[1024];
    char buf[1024];
    int len;
    int msg_len;
    int t30_len;
    int t31_len;
    int t38_version;
    int without_pacing;
    int use_tep;
    int seq_no;
    double tx_when;
    double rx_when;
    t30_state_t *t30;
    t38_core_state_t *t38_core;
    logging_state_t *logging;
    int k;
    int outframes;
    int ret;
    int16_t t30_amp[SAMPLES_PER_CHUNK];
    int16_t t31_amp[SAMPLES_PER_CHUNK];
    int16_t silence[SAMPLES_PER_CHUNK];
    int16_t out_amp[2*SAMPLES_PER_CHUNK];
    SNDFILE *wave_handle;
    SNDFILE *in_handle;
    at_state_t *at_state;
#if defined(WIN32)
	DWORD read_bytes;
	OVERLAPPED o;
#endif

    /* Test the T.31 modem against the full FAX machine in spandsp */
    
    /* Set up the test environment */
    t38_version = 1;
    without_pacing = FALSE;
    use_tep = FALSE;

    wave_handle = NULL;
    if (log_audio)
    {
        if ((wave_handle = sf_open_telephony_write(OUTPUT_WAVE_FILE_NAME, 2)) == NULL)
        {
            fprintf(stderr, "    Cannot create audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
            exit(2);
        }
    }

    in_handle = NULL;
    if (decode_test_file)
    {
        if ((in_handle = sf_open_telephony_read(decode_test_file, 1)) == NULL)
        {
            fprintf(stderr, "    Cannot create audio file '%s'\n", decode_test_file);
            exit(2);
        }
    }

    srand48(0x1234567);
    if ((path_a_to_b = g1050_init(g1050_model_no, g1050_speed_pattern_no, 100, 33)) == NULL)
    {
        fprintf(stderr, "Failed to start IP network path model\n");
        exit(2);
    }
    if ((path_b_to_a = g1050_init(g1050_model_no, g1050_speed_pattern_no, 100, 33)) == NULL)
    {
        fprintf(stderr, "Failed to start IP network path model\n");
        exit(2);
    }

    t38_state = NULL;
    fax_state = NULL;
    if (test_sending)
    {
        if (t38_mode)
        {
            if ((t38_state = t38_terminal_init(NULL, FALSE, t38_tx_packet_handler, t31_state)) == NULL)
            {
                fprintf(stderr, "Cannot start the T.38 channel\n");
                exit(2);
            }
            t30 = t38_terminal_get_t30_state(t38_state);
        }
        else
        {
            fax_state = fax_init(NULL, FALSE);
            t30 = fax_get_t30_state(fax_state);
        }
        t30_set_rx_file(t30, OUTPUT_FILE_NAME, -1);
        countdown = 0;
    }
    else
    {
        if (t38_mode)
        {
            if ((t38_state = t38_terminal_init(NULL, TRUE, t38_tx_packet_handler, t31_state)) == NULL)
            {
                fprintf(stderr, "Cannot start the T.38 channel\n");
                exit(2);
            }
            t30 = t38_terminal_get_t30_state(t38_state);
        }
        else
        {
            fax_state = fax_init(NULL, TRUE);
            t30 = fax_get_t30_state(fax_state);
        }
        t30_set_tx_file(t30, INPUT_FILE_NAME, -1, -1);
        countdown = 250;
    }

    t30_set_ecm_capability(t30, use_ecm);

    if (t38_mode)
    {
        t38_core = t38_terminal_get_t38_core_state(t38_state);
        t38_set_t38_version(t38_core, t38_version);
        t38_terminal_set_config(t38_state, without_pacing);
        t38_terminal_set_tep_mode(t38_state, use_tep);
    }

    t30_set_tx_ident(t30, "11111111");
    t30_set_supported_modems(t30, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17);
    //t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12);
    t30_set_phase_b_handler(t30, phase_b_handler, (void *) 'A');
    t30_set_phase_d_handler(t30, phase_d_handler, (void *) 'A');
    t30_set_phase_e_handler(t30, phase_e_handler, (void *) 'A');

    if (t38_mode)
        logging = t38_terminal_get_logging_state(t38_state);
    else
        logging = t30_get_logging_state(t30);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, (t38_mode)  ?  "T.38"  :  "FAX");

    if (t38_mode)
    {
        t38_core = t38_terminal_get_t38_core_state(t38_state);
        logging = t38_core_get_logging_state(t38_core);
        span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
        span_log_set_tag(logging, "T.38");

        logging = t30_get_logging_state(t30);
        span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
        span_log_set_tag(logging, "T.38");
    }
    else
    {
        logging = fax_get_logging_state(fax_state);
        span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
        span_log_set_tag(logging, "FAX");
    }

    memset(silence, 0, sizeof(silence));
    memset(t30_amp, 0, sizeof(t30_amp));

    /* Now set up and run the T.31 modem */
    if ((t31_state = t31_init(NULL, at_tx_handler, &modem[0], t31_call_control, &modem[0], t31_tx_packet_handler, NULL)) == NULL)
    {
        fprintf(stderr, "    Cannot start the T.31 modem\n");
        exit(2);
    }
    at_state = t31_get_at_state(t31_state);

    logging = t31_get_logging_state(t31_state);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, "T.31");

    logging = at_get_logging_state(at_state);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, "T.31");

    if (t38_mode)
    {
        t38_core = t31_get_t38_core_state(t31_state);
        logging = t38_core_get_logging_state(t38_core);
        span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
        span_log_set_tag(logging, "T.31");

        t31_set_mode(t31_state, TRUE);
        t38_set_t38_version(t38_core, t38_version);
    }

    at_reset_call_info(at_state);
    at_set_call_info(at_state, "DATE", "1231");
    at_set_call_info(at_state, "TIME", "1200");
    at_set_call_info(at_state, "NAME", "Name");
    at_set_call_info(at_state, "NMBR", "123456789");
    at_set_call_info(at_state, "ANID", "987654321");
    at_set_call_info(at_state, "USER", "User");
    at_set_call_info(at_state, "CDID", "234567890");
    at_set_call_info(at_state, "NDID", "345678901");

#if defined(ENABLE_GUI)
    if (use_gui)
        start_media_monitor();
#endif

    while (!done)
    {
        /* Deal with call setup, through the AT interface. */ 
        if (test_sending)
        {
        }
        else
        {
            if (answered == 0)
            {
                if (--countdown == 0)
                {
                    t31_call_event(t31_state, AT_CALL_EVENT_ALERTING);
                    countdown = 250;
                }
            }
            else if (answered == 1)
            {
printf("ZZZ\n");
                answered = 2;
                t31_call_event(t31_state, AT_CALL_EVENT_ANSWERED);
            }
        }

        ret = modem_wait_sock(modem[0].master, 20, MODEM_POLL_READ);
        if ((ret & MODEM_POLL_READ))
        {
#if defined(WIN32)
			o.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

			/* Initialize the rest of the OVERLAPPED structure to zero. */
			o.Internal = 0;
			o.InternalHigh = 0;
			o.Offset = 0;
			o.OffsetHigh = 0;
			assert(o.hEvent);
			if (!ReadFile(modem->master, buf, avail, &read_bytes, &o))
				GetOverlappedResult(modem->master, &o, &read_bytes, TRUE);
			CloseHandle (o.hEvent);
			if ((len = read_bytes))
#else
            if ((len = read(modem[0].master, buf, 1024)))
#endif
{
int i;

printf("YYY %d - ", len);
for (i = 0;  i < len;  i++)
    printf(" 0x%02x", buf[i] & 0xFF);
printf("\n");
                t31_at_rx(t31_state, buf, len);
}
        }

        if (answered == 2)
        {
            if (t38_mode)
            {
                while ((msg_len = g1050_get(path_a_to_b, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0)
                {
#if defined(ENABLE_GUI)
                    if (use_gui)
                        media_monitor_rx(seq_no, tx_when, rx_when);
#endif
                    t38_core = t31_get_t38_core_state(t31_state);
                    t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no);
                }
                while ((msg_len = g1050_get(path_b_to_a, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0)
                {
#if defined(ENABLE_GUI)
                    if (use_gui)
                        media_monitor_rx(seq_no, tx_when, rx_when);
#endif
                    t38_core = t38_terminal_get_t38_core_state(t38_state);
                    t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no);
                }
#if defined(ENABLE_GUI)
                if (use_gui)
                    media_monitor_update_display();
#endif
                /* Bump the G.1050 models along */
                when += (float) SAMPLES_PER_CHUNK/(float) SAMPLE_RATE;

                /* Bump things along on the t38_terminal side */
                span_log_bump_samples(t38_terminal_get_logging_state(t38_state), SAMPLES_PER_CHUNK);
                t38_core = t38_terminal_get_t38_core_state(t38_state);
                span_log_bump_samples(t38_core_get_logging_state(t38_core), SAMPLES_PER_CHUNK);

                t38_terminal_send_timeout(t38_state, SAMPLES_PER_CHUNK);
                t31_t38_send_timeout(t31_state, SAMPLES_PER_CHUNK);
            }
            else
            {
                t30_len = fax_tx(fax_state, t30_amp, SAMPLES_PER_CHUNK);
                /* The receive side always expects a full block of samples, but the
                   transmit side may not be sending any when it doesn't need to. We
                   may need to pad with some silence. */
                if (t30_len < SAMPLES_PER_CHUNK)
                {
                    memset(t30_amp + t30_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t30_len));
                    t30_len = SAMPLES_PER_CHUNK;
                }
                if (log_audio)
                {
                    for (k = 0;  k < t30_len;  k++)
                        out_amp[2*k] = t30_amp[k];
                }
                if (t31_rx(t31_state, t30_amp, t30_len))
                    break;
                t31_len = t31_tx(t31_state, t31_amp, SAMPLES_PER_CHUNK);
                if (t31_len < SAMPLES_PER_CHUNK)
                {
                    memset(t31_amp + t31_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t31_len));
                    t31_len = SAMPLES_PER_CHUNK;
                }
                if (log_audio)
                {
                    for (k = 0;  k < t31_len;  k++)
                        out_amp[2*k + 1] = t31_amp[k];
                }
                if (fax_rx(fax_state, t31_amp, SAMPLES_PER_CHUNK))
                    break;

                if (log_audio)
                {
                    outframes = sf_writef_short(wave_handle, out_amp, SAMPLES_PER_CHUNK);
                    if (outframes != SAMPLES_PER_CHUNK)
                        break;
                }

                /* Bump things along on the FAX machine side */
                span_log_bump_samples(fax_get_logging_state(fax_state), SAMPLES_PER_CHUNK);
            }
            /* Bump things along on the FAX machine side */
            span_log_bump_samples(t30_get_logging_state(t30), SAMPLES_PER_CHUNK);

            /* Bump things along on the T.31 modem side */
            t38_core = t31_get_t38_core_state(t31_state);
            span_log_bump_samples(t38_core_get_logging_state(t38_core), SAMPLES_PER_CHUNK);
            span_log_bump_samples(t31_get_logging_state(t31_state), SAMPLES_PER_CHUNK);
            span_log_bump_samples(at_get_logging_state(t31_get_at_state(t31_state)), SAMPLES_PER_CHUNK);
        }
    }

    if (t38_mode)
        t38_terminal_release(t38_state);

    if (decode_test_file)
    {
        if (sf_close_telephony(in_handle))
        {
            fprintf(stderr, "    Cannot close audio file '%s'\n", decode_test_file);
            exit(2);
        }
    }
    if (log_audio)
    {
        if (sf_close_telephony(wave_handle))
        {
            fprintf(stderr, "    Cannot close audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
            exit(2);
        }
    }

    if (!done)
    {
        printf("Tests failed\n");
        return 2;
    }

    return 0;
}
예제 #4
0
static int t38_tests(int use_gui, int test_sending, int model_no, int speed_pattern_no)
{
    t38_terminal_state_t *t38_state;
    int fast_send;
    int fast_send_tcf;
    int fast_blocks;
    uint8_t fast_buf[1000];
    int msg_len;
    uint8_t msg[1024];
    int t38_version;
    int without_pacing;
    int use_tep;
    int seq_no;
    double tx_when;
    double rx_when;
    t30_state_t *t30;
    t38_core_state_t *t38_core;
    logging_state_t *logging;
    int i;

    t38_version = 1;
    without_pacing = FALSE;
    use_tep = FALSE;

    srand48(0x1234567);
    if ((path_a_to_b = g1050_init(model_no, speed_pattern_no, 100, 33)) == NULL)
    {
        fprintf(stderr, "Failed to start IP network path model\n");
        exit(2);
    }
    if ((path_b_to_a = g1050_init(model_no, speed_pattern_no, 100, 33)) == NULL)
    {
        fprintf(stderr, "Failed to start IP network path model\n");
        exit(2);
    }
    if ((t31_state = t31_init(NULL, at_tx_handler, NULL, modem_call_control, NULL, t31_tx_packet_handler, NULL)) == NULL)
    {
        fprintf(stderr, "    Cannot start the T.31 T.38 modem\n");
        exit(2);
    }
    logging = t31_get_logging_state(t31_state);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, "T.31");

    t38_core = t31_get_t38_core_state(t31_state);
    logging = t38_core_get_logging_state(t38_core);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, "T.31");

    span_log_set_level(&t31_state->at_state.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(&t31_state->at_state.logging, "T.31");

    t31_set_mode(t31_state, TRUE);
    t38_set_t38_version(t38_core, t38_version);

    if (test_sending)
    {
        if ((t38_state = t38_terminal_init(NULL, FALSE, t38_tx_packet_handler, t31_state)) == NULL)
        {
            fprintf(stderr, "Cannot start the T.38 channel\n");
            exit(2);
        }
        t30 = t38_terminal_get_t30_state(t38_state);
        t30_set_rx_file(t30, OUTPUT_FILE_NAME, -1);
        fax_test_seq = fax_send_test_seq;
        countdown = 0;
    }
    else
    {
        if ((t38_state = t38_terminal_init(NULL, TRUE, t38_tx_packet_handler, t31_state)) == NULL)
        {
            fprintf(stderr, "Cannot start the T.38 channel\n");
            exit(2);
        }
        t30 = t38_terminal_get_t30_state(t38_state);
        t30_set_tx_file(t30, INPUT_FILE_NAME, -1, -1);
        fax_test_seq = fax_receive_test_seq;
        countdown = 250;
    }

    t30 = t38_terminal_get_t30_state(t38_state);
    t38_core = t38_terminal_get_t38_core_state(t38_state);
    t38_set_t38_version(t38_core, t38_version);
    t38_terminal_set_config(t38_state, without_pacing);
    t38_terminal_set_tep_mode(t38_state, use_tep);

    t30_set_tx_ident(t30, "11111111");
    t30_set_supported_modems(t30, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17);
    //t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12);
    t30_set_phase_b_handler(t30, phase_b_handler, (void *) 'A');
    t30_set_phase_d_handler(t30, phase_d_handler, (void *) 'A');
    t30_set_phase_e_handler(t30, phase_e_handler, (void *) 'A');

    logging = t38_terminal_get_logging_state(t38_state);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, "T.38");

    t38_core = t38_terminal_get_t38_core_state(t38_state);
    span_log_set_level(&t38_core->logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(&t38_core->logging, "T.38");

    logging = t30_get_logging_state(t30);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, "T.38");

    fast_send = FALSE;
    fast_send_tcf = TRUE;
    fast_blocks = 0;
    kick = TRUE;
#if defined(ENABLE_GUI)
    if (use_gui)
        start_media_monitor();
#endif
    while (!done)
    {
        logging = t38_terminal_get_logging_state(t38_state);
        span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
        t38_core = t38_terminal_get_t38_core_state(t38_state);
        logging = t38_core_get_logging_state(t38_core);
        span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
        t30 = t38_terminal_get_t30_state(t38_state);
        logging = t30_get_logging_state(t30);
        span_log_bump_samples(logging, SAMPLES_PER_CHUNK);

        logging = t31_get_logging_state(t31_state);
        span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
        t38_core = t31_get_t38_core_state(t31_state);
        logging = t38_core_get_logging_state(t38_core);
        span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
        span_log_bump_samples(&t31_state->at_state.logging, SAMPLES_PER_CHUNK);

        t38_terminal_send_timeout(t38_state, SAMPLES_PER_CHUNK);
        t31_t38_send_timeout(t31_state, SAMPLES_PER_CHUNK);

        when += (float) SAMPLES_PER_CHUNK/(float) SAMPLE_RATE;

        if (kick)
        {
            kick = FALSE;
            if (fax_test_seq[test_seq_ptr].command > (const char *) 2)
            {
                if (fax_test_seq[test_seq_ptr].command[0])
                {
                    printf("%s\n", fax_test_seq[test_seq_ptr].command);
                    t31_at_rx(t31_state, fax_test_seq[test_seq_ptr].command, fax_test_seq[test_seq_ptr].len_command);
                }
            }
            else
            {
                if (fax_test_seq[test_seq_ptr].command == (const char *) 2)
                {
                    printf("Fast send TCF\n");
                    fast_send = TRUE;
                    fast_send_tcf = TRUE;
                    fast_blocks = 100;
                }
                else
                {
                    printf("Fast send image\n");
                    fast_send = TRUE;
                    fast_send_tcf = FALSE;
                    fast_blocks = 100;
                }
            }
        }
        if (fast_send)
        {
            /* Send fast modem data */
            if (fast_send_tcf)
            {
                memset(fast_buf, 0, 36);
            }
            else
            {
                if (fast_blocks == 1)
                {
                    /* Create the end of page condition */
                    for (i = 0;  i < 36;  i += 2)
                    {
                        fast_buf[i] = 0x00;
                        fast_buf[i + 1] = 0x80;
                    }
                }
                else
                {
                    /* Create a chunk of white page */
                    for (i = 0;  i < 36;  i += 4)
                    {
                        fast_buf[i] = 0x00;
                        fast_buf[i + 1] = 0x80;
                        fast_buf[i + 2] = 0xB2;
                        fast_buf[i + 3] = 0x01;
                    }
                }
            }
            if (fast_blocks == 1)
            {
                /* Insert EOLs */
                fast_buf[35] = ETX;
                fast_buf[34] = DLE;
                fast_buf[31] =
                fast_buf[28] =
                fast_buf[25] =
                fast_buf[22] =
                fast_buf[19] =
                fast_buf[16] = 1;
            }
            t31_at_rx(t31_state, (char *) fast_buf, 36);
            if (--fast_blocks == 0)
                fast_send = FALSE;
        }
        if (countdown)
        {
            if (answered)
            {
                countdown = 0;
                t31_call_event(t31_state, AT_CALL_EVENT_ANSWERED);
            }
            else if (--countdown == 0)
            {
                t31_call_event(t31_state, AT_CALL_EVENT_ALERTING);
                countdown = 250;
            }
        }
        while ((msg_len = g1050_get(path_a_to_b, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0)
        {
#if defined(ENABLE_GUI)
            if (use_gui)
                media_monitor_rx(seq_no, tx_when, rx_when);
#endif
            t38_core = t31_get_t38_core_state(t31_state);
            t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no);
        }
        while ((msg_len = g1050_get(path_b_to_a, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0)
        {
#if defined(ENABLE_GUI)
            if (use_gui)
                media_monitor_rx(seq_no, tx_when, rx_when);
#endif
            t38_core = t38_terminal_get_t38_core_state(t38_state);
            t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no);
        }
#if defined(ENABLE_GUI)
        if (use_gui)
            media_monitor_update_display();
#endif
    }
    t38_terminal_release(t38_state);
    return 0;
}
예제 #5
0
static int transmit_audio(fax_session *s)
{
	int res = -1;
	int original_read_fmt = AST_FORMAT_SLINEAR;
	int original_write_fmt = AST_FORMAT_SLINEAR;
	fax_state_t fax;
	struct ast_dsp *dsp = NULL;
	int detect_tone = 0;
	struct ast_frame *inf = NULL;
	struct ast_frame *fr;
	int last_state = 0;
	struct timeval now, start, state_change;
	enum ast_control_t38 t38control;

	original_read_fmt = s->chan->readformat;
	if (original_read_fmt != AST_FORMAT_SLINEAR) {
		res = ast_set_read_format(s->chan, AST_FORMAT_SLINEAR);
		if (res < 0) {
			ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
			goto done;
		}
	}

	original_write_fmt = s->chan->writeformat;
	if (original_write_fmt != AST_FORMAT_SLINEAR) {
		res = ast_set_write_format(s->chan, AST_FORMAT_SLINEAR);
		if (res < 0) {
			ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
			goto done;
		}
	}

	/* Initialize T30 terminal */
	fax_init(&fax, s->caller_mode);

	/* Setup logging */
	set_logging(&fax.logging);
	set_logging(&fax.t30_state.logging);

	/* Configure terminal */
	set_local_info(&fax.t30_state, s);
	set_file(&fax.t30_state, s);
	set_ecm(&fax.t30_state, TRUE);

	fax_set_transmit_on_idle(&fax, TRUE);

	t30_set_phase_e_handler(&fax.t30_state, phase_e_handler, s);

	if (s->t38state == T38_STATE_UNAVAILABLE) {
		ast_debug(1, "T38 is unavailable on %s\n", s->chan->name);
	} else if (!s->direction) {
		/* We are receiving side and this means we are the side which should
		   request T38 when the fax is detected. Use DSP to detect fax tone */
		ast_debug(1, "Setting up CNG detection on %s\n", s->chan->name);
		dsp = ast_dsp_new();
		ast_dsp_set_features(dsp, DSP_FEATURE_FAX_DETECT);
		ast_dsp_set_faxmode(dsp, DSP_FAXMODE_DETECT_CNG);
		detect_tone = 1;
	}

	start = state_change = ast_tvnow();

	ast_activate_generator(s->chan, &generator, &fax);

	while (!s->finished) {
		res = ast_waitfor(s->chan, 20);
		if (res < 0)
			break;
		else if (res > 0)
			res = 0;

		inf = ast_read(s->chan);
		if (inf == NULL) {
			ast_debug(1, "Channel hangup\n");
			res = -1;
			break;
		}

		ast_debug(10, "frame %d/%d, len=%d\n", inf->frametype, inf->subclass, inf->datalen);

		/* Detect fax tone */
		if (detect_tone && inf->frametype == AST_FRAME_VOICE) {
			/* Duplicate frame because ast_dsp_process may free the frame passed */
			fr = ast_frdup(inf);

			/* Do not pass channel to ast_dsp_process otherwise it may queue modified audio frame back */
			fr = ast_dsp_process(NULL, dsp, fr);
			if (fr && fr->frametype == AST_FRAME_DTMF && fr->subclass == 'f') {
				ast_debug(1, "Fax tone detected. Requesting T38\n");
				t38control = AST_T38_REQUEST_NEGOTIATE;
				ast_indicate_data(s->chan, AST_CONTROL_T38, &t38control, sizeof(t38control));
				detect_tone = 0;
			}

			ast_frfree(fr);
		}


		/* Check the frame type. Format also must be checked because there is a chance
		   that a frame in old format was already queued before we set chanel format
		   to slinear so it will still be received by ast_read */
		if (inf->frametype == AST_FRAME_VOICE && inf->subclass == AST_FORMAT_SLINEAR) {

			if (fax_rx(&fax, inf->data, inf->samples) < 0) {
				/* I know fax_rx never returns errors. The check here is for good style only */
				ast_log(LOG_WARNING, "fax_rx returned error\n");
				res = -1;
				break;
			}

			/* Watchdog */
			if (last_state != fax.t30_state.state) {
				state_change = ast_tvnow();
				last_state = fax.t30_state.state;
			}
		} else if (inf->frametype == AST_FRAME_CONTROL && inf->subclass == AST_CONTROL_T38 &&
				inf->datalen == sizeof(enum ast_control_t38)) {
			t38control =*((enum ast_control_t38 *) inf->data);
			if (t38control == AST_T38_NEGOTIATED) {
				/* T38 switchover completed */
				ast_debug(1, "T38 negotiated, finishing audio loop\n");
				res = 1;
				break;
			}
		}

		ast_frfree(inf);
		inf = NULL;

		/* Watchdog */
		now = ast_tvnow();
		if (ast_tvdiff_sec(now, start) > WATCHDOG_TOTAL_TIMEOUT || ast_tvdiff_sec(now, state_change) > WATCHDOG_STATE_TIMEOUT) {
			ast_log(LOG_WARNING, "It looks like we hung. Aborting.\n");
			res = -1;
			break;
		}
	}

	ast_debug(1, "Loop finished, res=%d\n", res);

	if (inf)
		ast_frfree(inf);

	if (dsp)
		ast_dsp_free(dsp);

	ast_deactivate_generator(s->chan);

	/* If we are switching to T38, remove phase E handler. Otherwise it will be executed
	   by t30_terminate, display diagnostics and set status variables although no transmittion
	   has taken place yet. */
	if (res > 0) {
		t30_set_phase_e_handler(&fax.t30_state, NULL, NULL);
	}

	t30_terminate(&fax.t30_state);
	fax_release(&fax);

done:
	if (original_write_fmt != AST_FORMAT_SLINEAR) {
		if (ast_set_write_format(s->chan, original_write_fmt) < 0)
			ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", s->chan->name);
	}

	if (original_read_fmt != AST_FORMAT_SLINEAR) {
		if (ast_set_read_format(s->chan, original_read_fmt) < 0)
			ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", s->chan->name);
	}

	return res;

}
예제 #6
0
static int transmit_t38(fax_session *s)
{
	int res = 0;
	t38_terminal_state_t t38;
	struct ast_frame *inf = NULL;
	int last_state = 0;
	struct timeval now, start, state_change, last_frame;
	enum ast_control_t38 t38control;

	/* Initialize terminal */
	memset(&t38, 0, sizeof(t38));
	if (t38_terminal_init(&t38, s->caller_mode, t38_tx_packet_handler, s->chan) == NULL) {
		ast_log(LOG_WARNING, "Unable to start T.38 termination.\n");
		return -1;
	}

	/* Setup logging */
	set_logging(&t38.logging);
	set_logging(&t38.t30_state.logging);
	set_logging(&t38.t38.logging);

	/* Configure terminal */
	set_local_info(&t38.t30_state, s);
	set_file(&t38.t30_state, s);
	set_ecm(&t38.t30_state, TRUE);

	t30_set_phase_e_handler(&t38.t30_state, phase_e_handler, s);

	now = start = state_change = ast_tvnow();

	while (!s->finished) {

		res = ast_waitfor(s->chan, 20);
		if (res < 0)
			break;
		else if (res > 0)
			res = 0;

		last_frame = now;
		now = ast_tvnow();
		t38_terminal_send_timeout(&t38, ast_tvdiff_us(now, last_frame) / (1000000 / 8000));

		inf = ast_read(s->chan);
		if (inf == NULL) {
			ast_debug(1, "Channel hangup\n");
			res = -1;
			break;
		}

		ast_debug(10, "frame %d/%d, len=%d\n", inf->frametype, inf->subclass, inf->datalen);

		if (inf->frametype == AST_FRAME_MODEM && inf->subclass == AST_MODEM_T38) {
			t38_core_rx_ifp_packet(&t38.t38, inf->data, inf->datalen, inf->seqno);

			/* Watchdog */
			if (last_state != t38.t30_state.state) {
				state_change = ast_tvnow();
				last_state = t38.t30_state.state;
			}
		} else if (inf->frametype == AST_FRAME_CONTROL && inf->subclass == AST_CONTROL_T38 &&
				inf->datalen == sizeof(enum ast_control_t38)) {

			t38control = *((enum ast_control_t38 *) inf->data);

			if (t38control == AST_T38_TERMINATED || t38control == AST_T38_REFUSED) {
				ast_debug(1, "T38 down, terminating\n");
				res = -1;
				break;
			}
		}

		ast_frfree(inf);
		inf = NULL;

		/* Watchdog */
		if (ast_tvdiff_sec(now, start) > WATCHDOG_TOTAL_TIMEOUT || ast_tvdiff_sec(now, state_change) > WATCHDOG_STATE_TIMEOUT) {
			ast_log(LOG_WARNING, "It looks like we hung. Aborting.\n");
			res = -1;
			break;
		}
	}

	ast_debug(1, "Loop finished, res=%d\n", res);

	if (inf)
		ast_frfree(inf);

	t30_terminate(&t38.t30_state);
	t38_terminal_release(&t38);

	return res;
}
예제 #7
0
int main(int argc, char *argv[])
{
    int16_t silence[SAMPLES_PER_CHUNK];
    int16_t t30_amp_a[SAMPLES_PER_CHUNK];
    int16_t t38_amp_a[SAMPLES_PER_CHUNK];
    int16_t t38_amp_b[SAMPLES_PER_CHUNK];
    int16_t t30_amp_b[SAMPLES_PER_CHUNK];
    int16_t out_amp[SAMPLES_PER_CHUNK*4];
    int t30_len_a;
    int t38_len_a;
    int t38_len_b;
    int t30_len_b;
    int log_audio;
    int msg_len;
    uint8_t msg[1024];
    int outframes;
    AFfilesetup filesetup;
    AFfilehandle wave_handle;
    int use_ecm;
    int use_tep;
    int use_transmit_on_idle;
    int t38_version;
    const char *input_file_name;
    int i;
    int seq_no;
    int model_no;
    int speed_pattern_no;
    double tx_when;
    double rx_when;
    int use_gui;
    int opt;

    log_audio = FALSE;
    use_ecm = FALSE;
    t38_version = 1;
    input_file_name = INPUT_FILE_NAME;
    simulate_incrementing_repeats = FALSE;
    model_no = 0;
    speed_pattern_no = 1;
    use_gui = FALSE;
    use_tep = FALSE;
    use_transmit_on_idle = TRUE;
    while ((opt = getopt(argc, argv, "egi:Ilm:s:tv:")) != -1)
    {
        switch (opt)
        {
        case 'e':
            use_ecm = TRUE;
            break;
        case 'g':
            use_gui = TRUE;
            break;
        case 'i':
            input_file_name = optarg;
            break;
        case 'I':
            simulate_incrementing_repeats = TRUE;
            break;
        case 'l':
            log_audio = TRUE;
            break;
        case 'm':
            model_no = optarg[0] - 'A' + 1;
            break;
        case 's':
            speed_pattern_no = atoi(optarg);
            break;
        case 't':
            use_tep = TRUE;
            break;
        case 'v':
            t38_version = atoi(optarg);
            break;
        }
    }

    printf("Using T.38 version %d\n", t38_version);
    if (use_ecm)
        printf("Using ECM\n");

    filesetup = AF_NULL_FILESETUP;
    wave_handle = AF_NULL_FILEHANDLE;
    if (log_audio)
    {
        if ((filesetup = afNewFileSetup()) == AF_NULL_FILESETUP)
        {
            fprintf(stderr, "    Failed to create file setup\n");
            exit(2);
        }
        afInitSampleFormat(filesetup, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 16);
        afInitRate(filesetup, AF_DEFAULT_TRACK, (float) SAMPLE_RATE);
        afInitFileFormat(filesetup, AF_FILE_WAVE);
        afInitChannels(filesetup, AF_DEFAULT_TRACK, 4);
        if ((wave_handle = afOpenFile(OUTPUT_FILE_NAME_WAVE, "w", filesetup)) == AF_NULL_FILEHANDLE)
        {
            fprintf(stderr, "    Cannot create wave file '%s'\n", OUTPUT_FILE_NAME_WAVE);
            exit(2);
        }
    }
    memset(silence, 0, sizeof(silence));
 
    srand48(0x1234567);
    if ((path_a_to_b = g1050_init(model_no, speed_pattern_no, 100, 33)) == NULL)
    {
        fprintf(stderr, "Failed to start IP network path model\n");
        exit(2);
    }
    if ((path_b_to_a = g1050_init(model_no, speed_pattern_no, 100, 33)) == NULL)
    {
        fprintf(stderr, "Failed to start IP network path model\n");
        exit(2);
    }

    if (fax_init(&fax_state_a, TRUE) == NULL)
    {
        fprintf(stderr, "Cannot start FAX\n");
        exit(2);
    }
    fax_set_transmit_on_idle(&fax_state_a, use_transmit_on_idle);
    fax_set_tep_mode(&fax_state_a, use_tep);
    //t30_set_supported_modems(&(fax_state_a.t30_state), T30_SUPPORT_V27TER | T30_SUPPORT_V29);
    t30_set_local_ident(&fax_state_a.t30_state, "11111111");
    t30_set_tx_file(&fax_state_a.t30_state, input_file_name, -1, -1);
    t30_set_phase_b_handler(&fax_state_a.t30_state, phase_b_handler, (void *) (intptr_t) 'A');
    t30_set_phase_d_handler(&fax_state_a.t30_state, phase_d_handler, (void *) (intptr_t) 'A');
    t30_set_phase_e_handler(&fax_state_a.t30_state, phase_e_handler, (void *) (intptr_t) 'A');
    t30_set_local_nsf(&fax_state_a.t30_state, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12);
    t30_set_ecm_capability(&fax_state_a.t30_state, use_ecm);
    if (use_ecm)
        t30_set_supported_compressions(&fax_state_a.t30_state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
    span_log_set_level(&fax_state_a.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(&fax_state_a.logging, "FAX-A ");
    span_log_set_level(&fax_state_a.t30_state.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(&fax_state_a.t30_state.logging, "FAX-A ");
    memset(t30_amp_a, 0, sizeof(t30_amp_a));

    if (t38_gateway_init(&t38_state_a, tx_packet_handler_a, &t38_state_b) == NULL)
    {
        fprintf(stderr, "Cannot start the T.38 channel\n");
        exit(2);
    }
    t38_gateway_set_transmit_on_idle(&t38_state_a, use_transmit_on_idle);
    //t38_gateway_set_supported_modems(&t38_state_a, T30_SUPPORT_V27TER | T30_SUPPORT_V29);
    //t38_gateway_set_nsx_suppression(&t38_state_a, FALSE);
    t38_set_t38_version(&t38_state_a.t38, t38_version);
    t38_gateway_set_ecm_capability(&t38_state_a, use_ecm);
    span_log_set_level(&t38_state_a.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(&t38_state_a.logging, "T.38-A");
    span_log_set_level(&t38_state_a.t38.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(&t38_state_a.t38.logging, "T.38-A");
    memset(t38_amp_a, 0, sizeof(t38_amp_a));

    if (t38_gateway_init(&t38_state_b, tx_packet_handler_b, &t38_state_a) == NULL)
    {
        fprintf(stderr, "Cannot start the T.38 channel\n");
        exit(2);
    }
    t38_gateway_set_transmit_on_idle(&t38_state_b, use_transmit_on_idle);
    //t38_gateway_set_supported_modems(&t38_state_b, T30_SUPPORT_V27TER | T30_SUPPORT_V29);
    //t38_gateway_set_nsx_suppression(&t38_state_b, FALSE);
    t38_set_t38_version(&t38_state_b.t38, t38_version);
    t38_gateway_set_ecm_capability(&t38_state_b, use_ecm);
    span_log_set_level(&t38_state_b.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(&t38_state_b.logging, "T.38-B");
    span_log_set_level(&t38_state_b.t38.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(&t38_state_b.t38.logging, "T.38-B");
    memset(t38_amp_b, 0, sizeof(t38_amp_b));

    if (fax_init(&fax_state_b, FALSE) == NULL)
    {
        fprintf(stderr, "Cannot start FAX\n");
        exit(2);
    }
    fax_set_transmit_on_idle(&fax_state_b, use_transmit_on_idle);
    fax_set_tep_mode(&fax_state_b, use_tep);
    t30_set_local_ident(&fax_state_b.t30_state, "22222222");
    t30_set_rx_file(&fax_state_b.t30_state, OUTPUT_FILE_NAME, -1);
    t30_set_phase_b_handler(&fax_state_b.t30_state, phase_b_handler, (void *) (intptr_t) 'B');
    t30_set_phase_d_handler(&fax_state_b.t30_state, phase_d_handler, (void *) (intptr_t) 'B');
    t30_set_phase_e_handler(&fax_state_b.t30_state, phase_e_handler, (void *) (intptr_t) 'B');
    t30_set_local_nsf(&fax_state_b.t30_state, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12);
    t30_set_ecm_capability(&fax_state_b.t30_state, use_ecm);
    if (use_ecm)
        t30_set_supported_compressions(&fax_state_b.t30_state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
    span_log_set_level(&fax_state_b.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(&fax_state_b.logging, "FAX-B ");
    span_log_set_level(&fax_state_b.t30_state.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(&fax_state_b.t30_state.logging, "FAX-B ");
    memset(t30_amp_b, 0, sizeof(t30_amp_b));

#if defined(ENABLE_GUI)
    if (use_gui)
        start_media_monitor();
#endif
    for (;;)
    {
        span_log_bump_samples(&fax_state_a.logging, SAMPLES_PER_CHUNK);
        span_log_bump_samples(&fax_state_a.t30_state.logging, SAMPLES_PER_CHUNK);
        span_log_bump_samples(&t38_state_a.logging, SAMPLES_PER_CHUNK);
        span_log_bump_samples(&t38_state_a.t38.logging, SAMPLES_PER_CHUNK);
        span_log_bump_samples(&t38_state_b.logging, SAMPLES_PER_CHUNK);
        span_log_bump_samples(&t38_state_b.t38.logging, SAMPLES_PER_CHUNK);
        span_log_bump_samples(&fax_state_b.logging, SAMPLES_PER_CHUNK);
        span_log_bump_samples(&fax_state_b.t30_state.logging, SAMPLES_PER_CHUNK);
        memset(out_amp, 0, sizeof(out_amp));

        t30_len_a = fax_tx(&fax_state_a, t30_amp_a, SAMPLES_PER_CHUNK);
        if (!use_transmit_on_idle)
        {
            /* The receive side always expects a full block of samples, but the
               transmit side may not be sending any when it doesn't need to. We
               may need to pad with some silence. */
            if (t30_len_a < SAMPLES_PER_CHUNK)
            {
                memset(t30_amp_a + t30_len_a, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t30_len_a));
                t30_len_a = SAMPLES_PER_CHUNK;
            }
        }
        if (log_audio)
        {
            for (i = 0;  i < t30_len_a;  i++)
                out_amp[i*4] = t30_amp_a[i];
        }
        if (t38_gateway_rx(&t38_state_a, t30_amp_a, t30_len_a))
            break;

        t38_len_a = t38_gateway_tx(&t38_state_a, t38_amp_a, SAMPLES_PER_CHUNK);
        if (!use_transmit_on_idle)
        {
            if (t38_len_a < SAMPLES_PER_CHUNK)
            {
                memset(t38_amp_a + t38_len_a, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t38_len_a));
                t38_len_a = SAMPLES_PER_CHUNK;
            }
        }
        if (log_audio)
        {
            for (i = 0;  i < t38_len_a;  i++)
                out_amp[i*4 + 1] = t38_amp_a[i];
        }
        if (fax_rx(&fax_state_a, t38_amp_a, SAMPLES_PER_CHUNK))
            break;

        t30_len_b = fax_tx(&fax_state_b, t30_amp_b, SAMPLES_PER_CHUNK);
        if (!use_transmit_on_idle)
        {
            /* The receive side always expects a full block of samples, but the
               transmit side may not be sending any when it doesn't need to. We
               may need to pad with some silence. */
            if (t30_len_b < SAMPLES_PER_CHUNK)
            {
                memset(t30_amp_b + t30_len_b, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t30_len_b));
                t30_len_b = SAMPLES_PER_CHUNK;
            }
        }
        if (log_audio)
        {
            for (i = 0;  i < t30_len_b;  i++)
                out_amp[i*4 + 3] = t30_amp_b[i];
        }
        if (t38_gateway_rx(&t38_state_b, t30_amp_b, t30_len_b))
            break;

        t38_len_b = t38_gateway_tx(&t38_state_b, t38_amp_b, SAMPLES_PER_CHUNK);
        if (!use_transmit_on_idle)
        {
            if (t38_len_b < SAMPLES_PER_CHUNK)
            {
                memset(t38_amp_b + t38_len_b, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t38_len_b));
                t38_len_b = SAMPLES_PER_CHUNK;
            }
        }
        if (log_audio)
        {
            for (i = 0;  i < t38_len_b;  i++)
                out_amp[i*4 + 2] = t38_amp_b[i];
        }
        if (fax_rx(&fax_state_b, t38_amp_b, SAMPLES_PER_CHUNK))
            break;

        when += 0.02;

        while ((msg_len = g1050_get(path_a_to_b, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0)
        {
#if defined(ENABLE_GUI)
            if (use_gui)
                media_monitor_rx(seq_no, tx_when, rx_when);
#endif
            t38_core_rx_ifp_packet(&t38_state_b.t38, msg, msg_len, seq_no);
        }
        while ((msg_len = g1050_get(path_b_to_a, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0)
        {
#if defined(ENABLE_GUI)
            if (use_gui)
                media_monitor_rx(seq_no, tx_when, rx_when);
#endif
            t38_core_rx_ifp_packet(&t38_state_a.t38, msg, msg_len, seq_no);
        }
        if (log_audio)
        {
            outframes = afWriteFrames(wave_handle, AF_DEFAULT_TRACK, out_amp, SAMPLES_PER_CHUNK);
            if (outframes != SAMPLES_PER_CHUNK)
                break;
        }

        if (done[0]  &&  done[1])
            break;
#if defined(ENABLE_GUI)
        if (use_gui)
            media_monitor_update_display();
#endif
    }
    if (log_audio)
    {
        if (afCloseFile(wave_handle) != 0)
        {
            fprintf(stderr, "    Cannot close wave file '%s'\n", OUTPUT_FILE_NAME_WAVE);
            exit(2);
        }
        afFreeFileSetup(filesetup);
    }
    if (!succeeded[0]  ||  !succeeded[1])
    {
        printf("Tests failed\n");
        exit(2);
    }
    printf("Tests passed\n");
    return  0;
}
예제 #8
0
static void handle_uc_event(uc_t *uc, void *user_data, uc_event_t *e)
{
    int chan;
    
    chan = (int) user_data;

    printf ("-- %s (%d)\n", uc_event2str(e->e), chan);
    switch (e->e)
    {
    case UC_EVENT_DEVICEFAIL:
        break;
    case UC_EVENT_PROTOCOLFAIL:
        printf("-- Protocol failure on channel %d, cause %d\n", e->gen.channel, e->gen.data);
        break;
    case UC_EVENT_SIGCHANSTATUS:
        printf("-- Signalling channel status - %s\n", e->sigchanstatus.ok  ?  "Up"  :  "Down");
        break;
    case UC_EVENT_ALARM:
        printf("-- Alarm - 0x%X 0x%X\n", e->alarm.raised, e->alarm.cleared);
        break;
    case UC_EVENT_FARBLOCKED:
        printf("-- Channel far end blocked! :-(\n");
        chan_stuff[chan].xxx &= ~1;
        break;
    case UC_EVENT_FARUNBLOCKED:
        printf("-- Channel far end unblocked! :-)\n");
        chan_stuff[chan].xxx |= 1;
        if (chan_stuff[chan].xxx == 3)
        {
            if (caller_mode)
                initiate_call(uc, chan, e);
            /*endif*/
        }
        /*endif*/
        break;
    case UC_EVENT_LOCALBLOCKED:
        printf("-- Channel local end blocked! :-(\n");
        chan_stuff[chan].xxx &= ~2;
        break;
    case UC_EVENT_LOCALUNBLOCKED:
        printf("-- Channel local end unblocked! :-)\n");
        chan_stuff[chan].xxx |= 2;
        if (chan_stuff[chan].xxx == 3)
        {
            if (caller_mode)
                initiate_call(uc, chan, e);
            /*endif*/
        }
        /*endif*/
        break;
    case UC_EVENT_DIALING:
        printf("-- Dialing on channel %d\n", e->gen.channel);
        break;
    case UC_EVENT_PROCEEDING:
        printf("-- Proceeding on channel %d\n", e->gen.channel);
        break;
    case UC_EVENT_ACCEPTED:
        printf("-- Accepted on channel %d\n", e->gen.channel);
        if (uc_call_control(uc, UC_OP_ANSWERCALL, e->gen.crn, (void *) -1))
            fprintf(stderr, "Answer Call failed\n");
        /*endif*/
        break;
    case UC_EVENT_DETECTED:
        printf("-- Detected on channel %d\n", e->gen.channel);
        break;
    case UC_EVENT_MOREDIGITS:
        printf("-- More digits on channel %d, CRN %d (ANI: %s, DNIS: %s)\n", e->offered.channel, e->offered.crn, e->offered.parms.originating_number, e->offered.parms.destination_number);
        break;
    case UC_EVENT_ALERTING:
        printf("-- Alerting on channel %d\n", e->gen.channel);
        /* This is just a notification of call progress. We need take no action at this point. */
        break;
    case UC_EVENT_FARDISCONNECTED:
        printf("-- Far end disconnected on channel %d\n", e->fardisconnected.channel);
        /* Kill any outstanding audio processing */
        uc_set_channel_read_callback(uc, 0, NULL, 0);
        uc_set_channel_write_callback(uc, 0, NULL, 0);
        if (uc_call_control(uc, UC_OP_DROPCALL, e->fardisconnected.crn, (void *) UC_CAUSE_NORMAL_CLEARING))
            fprintf(stderr, "C Drop Call failed\n");
        /*endif*/
        break;
    case UC_EVENT_DROPCALL:
        printf("-- Drop call on channel %d\n", e->gen.channel);
        if (uc_call_control(uc, UC_OP_RELEASECALL, e->gen.crn, NULL))
            fprintf(stderr, "uc_ReleaseCall failed\n");
        /*endif*/
        break;
    case UC_EVENT_RELEASECALL:
        printf("-- Released on channel %d\n", e->gen.channel);
        if (caller_mode)
            initiate_call(uc, chan, e);
        /*endif*/
        break;
    case UC_EVENT_OFFERED:
        printf("-- Offered on channel %d, CRN %d (ANI: %s, DNIS: %s)\n", e->offered.channel, e->offered.crn, e->offered.parms.originating_number, e->offered.parms.destination_number);
        if (!caller_mode)
        {
            switch (chan_stuff[chan].cause)
            {
            case 0:
                if (uc_call_control(uc, UC_OP_ACCEPTCALL, e->offered.crn, (void *) -1))
                    fprintf(stderr, "uc_AcceptCall failed\n");
                /*endif*/
                chan_stuff[chan].crn = e->offered.crn;
                break;
            case 1:
                if (uc_call_control(uc, UC_OP_ANSWERCALL, e->offered.crn, (void *) -1))
                    fprintf(stderr, "uc_AnswerCall failed\n");
                /*endif*/
                chan_stuff[chan].crn = e->offered.crn;
                break;
            case 2:
                if (uc_call_control(uc, UC_OP_DROPCALL, e->offered.crn, (void *) UC_CAUSE_USER_BUSY))
                    fprintf(stderr, "E Drop Call failed\n");
                /*endif*/
                break;
            case 3:
                if (uc_call_control(uc, UC_OP_DROPCALL, e->offered.crn, (void *) UC_CAUSE_UNASSIGNED_NUMBER))
                    fprintf(stderr, "F Drop Call failed\n");
                /*endif*/
                break;
            case 4:
                if (uc_call_control(uc, UC_OP_DROPCALL, e->offered.crn, (void *) UC_CAUSE_NETWORK_CONGESTION))
                    fprintf(stderr, "G Drop Call failed\n");
                /*endif*/
                break;
            case 5:
                if (uc_call_control(uc, UC_OP_DROPCALL, e->offered.crn, (void *) UC_CAUSE_DEST_OUT_OF_ORDER))
                    fprintf(stderr, "H Drop Call failed\n");
                /*endif*/
                break;
            }
            /*endswitch*/
            if (++chan_stuff[chan].cause > 5)
                chan_stuff[chan].cause = 0;
            /*endif*/
        }
        /*endif*/
        break;
    case UC_EVENT_ANSWERED:
        printf("-- Answered on channel %d\n", e->gen.channel);
        uc_set_channel_read_callback(uc, 0, channel_read_fax_channel, (void *) chan);
printf("XXX read callback set\n");
        uc_set_channel_write_callback(uc, 0, channel_write_fax_channel, (void *) chan);
printf("XXX write callback set\n");
        t30_init(&(chan_stuff[chan].fax), FALSE, uc);
        t30_set_local_ident(&(chan_stuff[chan].fax), "12345678");
        t30_set_tx_file(&(chan_stuff[chan].fax), "tx.tif");
        //t30_set_rx_file(&(chan_stuff[chan].fax), "rx.tif");
        t30_set_phase_b_handler(&(chan_stuff[chan].fax), phase_b_handler, &(chan_stuff[chan]));
        t30_set_phase_d_handler(&(chan_stuff[chan].fax), phase_d_handler, &(chan_stuff[chan]));
        t30_set_phase_e_handler(&(chan_stuff[chan].fax), phase_e_handler, &(chan_stuff[chan]));
        t30_set_flush_handler(&(chan_stuff[chan].fax), flush_handler, &(chan_stuff[chan]));
printf("XXX FAX inited\n");
        dtmf_rx_init(&chan_stuff[chan].dtmf_state, NULL, NULL);
printf("XXX DTMF inited\n");
        break;
    case UC_EVENT_CONNECTED:
        printf("-- Connected on channel %d\n", e->gen.channel);
        uc_set_channel_read_callback(uc, 0, channel_read_fax_channel, (void *) chan);
printf("XXX read callback set\n");
        uc_set_channel_write_callback(uc, 0, channel_write_fax_channel, (void *) chan);
printf("XXX write callback set\n");
        t30_init(&(chan_stuff[chan].fax), TRUE, uc);
        t30_set_local_ident(&(chan_stuff[chan].fax), "87654321");
        t30_set_tx_file(&(chan_stuff[chan].fax), "tx.tif");
        //t30_set_rx_file(&(chan_stuff[chan].fax), "rx.tif");
        t30_set_phase_b_handler(&(chan_stuff[chan].fax), phase_b_handler, &(chan_stuff[chan]));
        t30_set_phase_d_handler(&(chan_stuff[chan].fax), phase_d_handler, &(chan_stuff[chan]));
        t30_set_phase_e_handler(&(chan_stuff[chan].fax), phase_e_handler, &(chan_stuff[chan]));
printf("XXX FAX inited\n");
#if 0
        if (uc_call_control(uc, UC_OP_DROPCALL, e->offered.crn, (void *) UC_CAUSE_NORMAL_CLEARING))
            printf ("I Drop Call failed\n");
        /*endif*/
#endif
        break;
    default:
        fprintf(stderr, "--!! Unknown signaling event %d\n", e->e);
        break;
    }
    /*endswitch*/
}
예제 #9
0
static int transmit_audio(fax_session *s)
{
	int res = -1;
	struct ast_format original_read_fmt;
	struct ast_format original_write_fmt;
	fax_state_t fax;
	t30_state_t *t30state;
	struct ast_frame *inf = NULL;
	int last_state = 0;
	struct timeval now, start, state_change;
	enum ast_t38_state t38_state;
	struct ast_control_t38_parameters t38_parameters = { .version = 0,
							     .max_ifp = 800,
							     .rate = AST_T38_RATE_14400,
							     .rate_management = AST_T38_RATE_MANAGEMENT_TRANSFERRED_TCF,
							     .fill_bit_removal = 1,
/*
 * spandsp has API calls to support MMR and JBIG transcoding, but they aren't
 * implemented quite yet... so don't offer them to the remote endpoint
 *							     .transcoding_mmr = 1,
 *							     .transcoding_jbig = 1,
*/
	};

	ast_format_clear(&original_read_fmt);
	ast_format_clear(&original_write_fmt);

	/* if in called party mode, try to use T.38 */
	if (s->caller_mode == FALSE) {
		/* check if we are already in T.38 mode (unlikely), or if we can request
		 * a switch... if so, request it now and wait for the result, rather
		 * than starting an audio FAX session that will have to be cancelled
		 */
		if ((t38_state = ast_channel_get_t38_state(s->chan)) == T38_STATE_NEGOTIATED) {
			return 1;
		} else if ((t38_state != T38_STATE_UNAVAILABLE) &&
			   (t38_parameters.request_response = AST_T38_REQUEST_NEGOTIATE,
			    (ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) == 0))) {
			/* wait up to five seconds for negotiation to complete */
			unsigned int timeout = 5000;
			int ms;

			ast_debug(1, "Negotiating T.38 for receive on %s\n", ast_channel_name(s->chan));
			while (timeout > 0) {
				ms = ast_waitfor(s->chan, 1000);
				if (ms < 0) {
					ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", ast_channel_name(s->chan));
					return -1;
				}
				if (!ms) {
					/* nothing happened */
					if (timeout > 0) {
						timeout -= 1000;
						continue;
					} else {
						ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 negotiation.\n", ast_channel_name(s->chan));
						break;
					}
				}
				if (!(inf = ast_read(s->chan))) {
					return -1;
				}
				if ((inf->frametype == AST_FRAME_CONTROL) &&
				    (inf->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
				    (inf->datalen == sizeof(t38_parameters))) {
					struct ast_control_t38_parameters *parameters = inf->data.ptr;

					switch (parameters->request_response) {
					case AST_T38_NEGOTIATED:
						ast_debug(1, "Negotiated T.38 for receive on %s\n", ast_channel_name(s->chan));
						res = 1;
						break;
					case AST_T38_REFUSED:
						ast_log(LOG_WARNING, "channel '%s' refused to negotiate T.38\n", ast_channel_name(s->chan));
						break;
					default:
						ast_log(LOG_ERROR, "channel '%s' failed to negotiate T.38\n", ast_channel_name(s->chan));
						break;
					}
					ast_frfree(inf);
					if (res == 1) {
						return 1;
					} else {
						break;
					}
				}
				ast_frfree(inf);
			}
		}
	}

#if SPANDSP_RELEASE_DATE >= 20080725
        /* for spandsp shaphots 0.0.6 and higher */
        t30state = &fax.t30;
#else
        /* for spandsp release 0.0.5 */
        t30state = &fax.t30_state;
#endif

	ast_format_copy(&original_read_fmt, ast_channel_readformat(s->chan));
	if (original_read_fmt.id != AST_FORMAT_SLINEAR) {
		res = ast_set_read_format_by_id(s->chan, AST_FORMAT_SLINEAR);
		if (res < 0) {
			ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
			goto done;
		}
	}

	ast_format_copy(&original_write_fmt, ast_channel_writeformat(s->chan));
	if (original_write_fmt.id != AST_FORMAT_SLINEAR) {
		res = ast_set_write_format_by_id(s->chan, AST_FORMAT_SLINEAR);
		if (res < 0) {
			ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
			goto done;
		}
	}

	/* Initialize T30 terminal */
	fax_init(&fax, s->caller_mode);

	/* Setup logging */
	set_logging(&fax.logging);
	set_logging(&t30state->logging);

	/* Configure terminal */
	set_local_info(t30state, s);
	set_file(t30state, s);
	set_ecm(t30state, TRUE);

	fax_set_transmit_on_idle(&fax, TRUE);

	t30_set_phase_e_handler(t30state, phase_e_handler, s);

	start = state_change = ast_tvnow();

	ast_activate_generator(s->chan, &generator, &fax);

	while (!s->finished) {
		inf = NULL;

		if ((res = ast_waitfor(s->chan, 25)) < 0) {
			ast_debug(1, "Error waiting for a frame\n");
			break;
		}

		/* Watchdog */
		now = ast_tvnow();
		if (ast_tvdiff_sec(now, start) > WATCHDOG_TOTAL_TIMEOUT || ast_tvdiff_sec(now, state_change) > WATCHDOG_STATE_TIMEOUT) {
			ast_log(LOG_WARNING, "It looks like we hung. Aborting.\n");
			res = -1;
			break;
		}

		if (!res) {
			/* There was timeout waiting for a frame. Loop around and wait again */
			continue;
		}

		/* There is a frame available. Get it */
		res = 0;

		if (!(inf = ast_read(s->chan))) {
			ast_debug(1, "Channel hangup\n");
			res = -1;
			break;
		}

		ast_debug(10, "frame %d/%u, len=%d\n", inf->frametype, (unsigned int) inf->subclass.format.id, inf->datalen);

		/* Check the frame type. Format also must be checked because there is a chance
		   that a frame in old format was already queued before we set channel format
		   to slinear so it will still be received by ast_read */
		if (inf->frametype == AST_FRAME_VOICE && inf->subclass.format.id == AST_FORMAT_SLINEAR) {
			if (fax_rx(&fax, inf->data.ptr, inf->samples) < 0) {
				/* I know fax_rx never returns errors. The check here is for good style only */
				ast_log(LOG_WARNING, "fax_rx returned error\n");
				res = -1;
				break;
			}
			if (last_state != t30state->state) {
				state_change = ast_tvnow();
				last_state = t30state->state;
			}
		} else if ((inf->frametype == AST_FRAME_CONTROL) &&
			   (inf->subclass.integer == AST_CONTROL_T38_PARAMETERS)) {
			struct ast_control_t38_parameters *parameters = inf->data.ptr;

			if (parameters->request_response == AST_T38_NEGOTIATED) {
				/* T38 switchover completed */
				s->t38parameters = *parameters;
				ast_debug(1, "T38 negotiated, finishing audio loop\n");
				res = 1;
				break;
			} else if (parameters->request_response == AST_T38_REQUEST_NEGOTIATE) {
				t38_parameters.request_response = AST_T38_NEGOTIATED;
				ast_debug(1, "T38 request received, accepting\n");
				/* Complete T38 switchover */
				ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
				/* Do not break audio loop, wait until channel driver finally acks switchover
				 * with AST_T38_NEGOTIATED
				 */
			}
		}

		ast_frfree(inf);
		inf = NULL;
	}

	ast_debug(1, "Loop finished, res=%d\n", res);

	if (inf)
		ast_frfree(inf);

	ast_deactivate_generator(s->chan);

	/* If we are switching to T38, remove phase E handler. Otherwise it will be executed
	   by t30_terminate, display diagnostics and set status variables although no transmittion
	   has taken place yet. */
	if (res > 0) {
		t30_set_phase_e_handler(t30state, NULL, NULL);
	}

	t30_terminate(t30state);
	fax_release(&fax);

done:
	if (original_write_fmt.id != AST_FORMAT_SLINEAR) {
		if (ast_set_write_format(s->chan, &original_write_fmt) < 0)
			ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", ast_channel_name(s->chan));
	}

	if (original_read_fmt.id != AST_FORMAT_SLINEAR) {
		if (ast_set_read_format(s->chan, &original_read_fmt) < 0)
			ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", ast_channel_name(s->chan));
	}

	return res;

}

static int transmit_t38(fax_session *s)
{
	int res = 0;
	t38_terminal_state_t t38;
	struct ast_frame *inf = NULL;
	int last_state = 0;
	struct timeval now, start, state_change, last_frame;
	t30_state_t *t30state;
	t38_core_state_t *t38state;

#if SPANDSP_RELEASE_DATE >= 20080725
	/* for spandsp shaphots 0.0.6 and higher */
	t30state = &t38.t30;
	t38state = &t38.t38_fe.t38;
#else
	/* for spandsp releases 0.0.5 */
	t30state = &t38.t30_state;
	t38state = &t38.t38;
#endif

	/* Initialize terminal */
	memset(&t38, 0, sizeof(t38));
	if (t38_terminal_init(&t38, s->caller_mode, t38_tx_packet_handler, s->chan) == NULL) {
		ast_log(LOG_WARNING, "Unable to start T.38 termination.\n");
		res = -1;
		goto disable_t38;
	}

	t38_set_max_datagram_size(t38state, s->t38parameters.max_ifp);

	if (s->t38parameters.fill_bit_removal) {
		t38_set_fill_bit_removal(t38state, TRUE);
	}
	if (s->t38parameters.transcoding_mmr) {
		t38_set_mmr_transcoding(t38state, TRUE);
	}
	if (s->t38parameters.transcoding_jbig) {
		t38_set_jbig_transcoding(t38state, TRUE);
	}

	/* Setup logging */
	set_logging(&t38.logging);
	set_logging(&t30state->logging);
	set_logging(&t38state->logging);

	/* Configure terminal */
	set_local_info(t30state, s);
	set_file(t30state, s);
	set_ecm(t30state, TRUE);

	t30_set_phase_e_handler(t30state, phase_e_handler, s);

	now = start = state_change = ast_tvnow();

	while (!s->finished) {
		inf = NULL;

		if ((res = ast_waitfor(s->chan, 25)) < 0) {
			ast_debug(1, "Error waiting for a frame\n");
			break;
		}

		last_frame = now;

		/* Watchdog */
		now = ast_tvnow();
		if (ast_tvdiff_sec(now, start) > WATCHDOG_TOTAL_TIMEOUT || ast_tvdiff_sec(now, state_change) > WATCHDOG_STATE_TIMEOUT) {
			ast_log(LOG_WARNING, "It looks like we hung. Aborting.\n");
			res = -1;
			break;
		}

		t38_terminal_send_timeout(&t38, ast_tvdiff_us(now, last_frame) / (1000000 / 8000));

		if (!res) {
			/* There was timeout waiting for a frame. Loop around and wait again */
			continue;
		}

		/* There is a frame available. Get it */
		res = 0;

		if (!(inf = ast_read(s->chan))) {
			ast_debug(1, "Channel hangup\n");
			res = -1;
			break;
		}

		ast_debug(10, "frame %d/%d, len=%d\n", inf->frametype, inf->subclass.integer, inf->datalen);

		if (inf->frametype == AST_FRAME_MODEM && inf->subclass.integer == AST_MODEM_T38) {
			t38_core_rx_ifp_packet(t38state, inf->data.ptr, inf->datalen, inf->seqno);
			if (last_state != t30state->state) {
				state_change = ast_tvnow();
				last_state = t30state->state;
			}
		} else if (inf->frametype == AST_FRAME_CONTROL && inf->subclass.integer == AST_CONTROL_T38_PARAMETERS) {
			struct ast_control_t38_parameters *parameters = inf->data.ptr;
			if (parameters->request_response == AST_T38_TERMINATED) {
				ast_debug(1, "T38 down, finishing\n");
				break;
			}
		}

		ast_frfree(inf);
		inf = NULL;
	}

	ast_debug(1, "Loop finished, res=%d\n", res);

	if (inf)
		ast_frfree(inf);

	t30_terminate(t30state);
	t38_terminal_release(&t38);

disable_t38:
	/* if we are not the caller, it's our job to shut down the T.38
	 * session when the FAX transmisson is complete.
	 */
	if ((s->caller_mode == FALSE) &&
	    (ast_channel_get_t38_state(s->chan) == T38_STATE_NEGOTIATED)) {
		struct ast_control_t38_parameters t38_parameters = { .request_response = AST_T38_REQUEST_TERMINATE, };

		if (ast_indicate_data(s->chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters)) == 0) {
			/* wait up to five seconds for negotiation to complete */
			unsigned int timeout = 5000;
			int ms;

			ast_debug(1, "Shutting down T.38 on %s\n", ast_channel_name(s->chan));
			while (timeout > 0) {
				ms = ast_waitfor(s->chan, 1000);
				if (ms < 0) {
					ast_log(LOG_WARNING, "something bad happened while channel '%s' was polling.\n", ast_channel_name(s->chan));
					return -1;
				}
				if (!ms) {
					/* nothing happened */
					if (timeout > 0) {
						timeout -= 1000;
						continue;
					} else {
						ast_log(LOG_WARNING, "channel '%s' timed-out during the T.38 shutdown.\n", ast_channel_name(s->chan));
						break;
					}
				}
				if (!(inf = ast_read(s->chan))) {
					return -1;
				}
				if ((inf->frametype == AST_FRAME_CONTROL) &&
				    (inf->subclass.integer == AST_CONTROL_T38_PARAMETERS) &&
				    (inf->datalen == sizeof(t38_parameters))) {
					struct ast_control_t38_parameters *parameters = inf->data.ptr;

					switch (parameters->request_response) {
					case AST_T38_TERMINATED:
						ast_debug(1, "Shut down T.38 on %s\n", ast_channel_name(s->chan));
						break;
					case AST_T38_REFUSED:
						ast_log(LOG_WARNING, "channel '%s' refused to disable T.38\n", ast_channel_name(s->chan));
						break;
					default:
						ast_log(LOG_ERROR, "channel '%s' failed to disable T.38\n", ast_channel_name(s->chan));
						break;
					}
					ast_frfree(inf);
					break;
				}
				ast_frfree(inf);
			}
		}
	}

	return res;
}
예제 #10
0
int main(int argc, char *argv[])
{
    int i;
    int k;
    int outframes;
    fax_state_t fax_state;
    int16_t t30_amp[SAMPLES_PER_CHUNK];
    int16_t t31_amp[SAMPLES_PER_CHUNK];
    int16_t silence[SAMPLES_PER_CHUNK];
    int16_t out_amp[2*SAMPLES_PER_CHUNK];
    int t30_len;
    int t31_len;
    AFfilesetup filesetup;
    AFfilehandle wave_handle;
    AFfilehandle in_handle;
    int log_audio;
    int test_sending;
    int fast_send;
    int fast_blocks;
    uint8_t fast_buf[1000];
    
    decode_test_file = NULL;
    log_audio = FALSE;
    test_sending = FALSE;
    for (i = 1;  i < argc;  i++)
    {
        if (strcmp(argv[i], "-d") == 0)
        {
            decode_test_file = argv[++i];
            continue;
        }
        if (strcmp(argv[i], "-l") == 0)
        {
            log_audio = TRUE;
            continue;
        }
        if (strcmp(argv[i], "-r") == 0)
        {
            test_sending = FALSE;
            continue;
        }
        if (strcmp(argv[i], "-s") == 0)
        {
            test_sending = TRUE;
            continue;
        }
    }

    filesetup = AF_NULL_FILESETUP;
    wave_handle = AF_NULL_FILEHANDLE;
    if (log_audio)
    {
        if ((filesetup = afNewFileSetup()) == AF_NULL_FILESETUP)
        {
            fprintf(stderr, "    Failed to create file setup\n");
            exit(2);
        }
        afInitSampleFormat(filesetup, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 16);
        afInitRate(filesetup, AF_DEFAULT_TRACK, (float) SAMPLE_RATE);
        afInitFileFormat(filesetup, AF_FILE_WAVE);
        afInitChannels(filesetup, AF_DEFAULT_TRACK, 2);
        if ((wave_handle = afOpenFile(OUTPUT_WAVE_FILE_NAME, "w", filesetup)) == AF_NULL_FILEHANDLE)
        {
            fprintf(stderr, "    Cannot create wave file '%s'\n", OUTPUT_WAVE_FILE_NAME);
            exit(2);
        }
    }

    memset(silence, 0, sizeof(silence));
 
    in_handle = NULL;
    if (decode_test_file)
    {
        if ((in_handle = afOpenFile(decode_test_file, "r", NULL)) == AF_NULL_FILEHANDLE)
        {
            fprintf(stderr, "    Cannot create wave file '%s'\n", decode_test_file);
            exit(2);
        }
    }

    if (test_sending)
    {
        fax_init(&fax_state, FALSE);
        t30_set_rx_file(&fax_state.t30_state, OUTPUT_FILE_NAME, -1);
        fax_test_seq = fax_send_test_seq;
        countdown = 0;
    }
    else
    {
        fax_init(&fax_state, TRUE);
        t30_set_tx_file(&fax_state.t30_state, INPUT_FILE_NAME, -1, -1);
        fax_test_seq = fax_receive_test_seq;
        countdown = 250;
    }
    
    t30_set_local_ident(&fax_state.t30_state, "11111111");
    t30_set_phase_b_handler(&fax_state.t30_state, phase_b_handler, (void *) 0);
    t30_set_phase_d_handler(&fax_state.t30_state, phase_d_handler, (void *) 0);
    t30_set_phase_e_handler(&fax_state.t30_state, phase_e_handler, (void *) 0);
    memset(t30_amp, 0, sizeof(t30_amp));
    
    span_log_set_level(&fax_state.t30_state.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW);
    span_log_set_tag(&fax_state.t30_state.logging, "YYY");
    span_log_set_level(&fax_state.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW);
    span_log_set_tag(&fax_state.logging, "YYY");

    if (t31_init(&t31_state, at_tx_handler, NULL, modem_call_control, NULL, NULL, NULL) == NULL)
    {
        fprintf(stderr, "    Cannot start the FAX modem\n");
        exit(2);
    }

    span_log_set_level(&t31_state.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_FLOW);
    span_log_set_tag(&t31_state.logging, "XXX");

    fast_send = FALSE;
    fast_blocks = 0;
    kick = TRUE;
    while (!done)
    {
        if (kick)
        {
            kick = FALSE;
            if (fax_test_seq[test_seq_ptr].command > (const char *) 1)
            {
                if (fax_test_seq[test_seq_ptr].command[0])
                {
                    printf("%s\n", fax_test_seq[test_seq_ptr].command);
                    t31_at_rx(&t31_state, fax_test_seq[test_seq_ptr].command, fax_test_seq[test_seq_ptr].len_command);
                }
            }
            else
            {
                printf("Fast send\n");
                fast_send = TRUE;
                fast_blocks = 100;
            }
        }
        if (fast_send)
        {
            /* Send fast modem data */
            memset(fast_buf, 0, 36);
            if (fast_blocks == 1)
            {
                /* Insert EOLs */
                fast_buf[35] = ETX;
                fast_buf[34] = DLE;
                fast_buf[31] =
                fast_buf[28] =
                fast_buf[25] =
                fast_buf[22] =
                fast_buf[19] =
                fast_buf[16] = 1;
            }
            t31_at_rx(&t31_state, (char *) fast_buf, 36);
            if (--fast_blocks == 0)
                fast_send = FALSE;
        }
        t30_len = fax_tx(&fax_state, t30_amp, SAMPLES_PER_CHUNK);
        /* The receive side always expects a full block of samples, but the
           transmit side may not be sending any when it doesn't need to. We
           may need to pad with some silence. */
        if (t30_len < SAMPLES_PER_CHUNK)
        {
            memset(t30_amp + t30_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t30_len));
            t30_len = SAMPLES_PER_CHUNK;
        }
        if (log_audio)
        {
            for (k = 0;  k < t30_len;  k++)
                out_amp[2*k] = t30_amp[k];
        }
        if (t31_rx(&t31_state, t30_amp, t30_len))
            break;
        if (countdown)
        {
            if (answered)
            {
                countdown = 0;
                t31_call_event(&t31_state, AT_CALL_EVENT_ANSWERED);
            }
            else if (--countdown == 0)
            {
                t31_call_event(&t31_state, AT_CALL_EVENT_ALERTING);
                countdown = 250;
            }
        }

        t31_len = t31_tx(&t31_state, t31_amp, SAMPLES_PER_CHUNK);
        if (t31_len < SAMPLES_PER_CHUNK)
        {
            memset(t31_amp + t31_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t31_len));
            t31_len = SAMPLES_PER_CHUNK;
        }
        if (log_audio)
        {
            for (k = 0;  k < t31_len;  k++)
                out_amp[2*k + 1] = t31_amp[k];
        }
        if (fax_rx(&fax_state, t31_amp, SAMPLES_PER_CHUNK))
            break;

        if (log_audio)
        {
            outframes = afWriteFrames(wave_handle, AF_DEFAULT_TRACK, out_amp, SAMPLES_PER_CHUNK);
            if (outframes != SAMPLES_PER_CHUNK)
                break;
        }
    }
    if (decode_test_file)
    {
        if (afCloseFile(in_handle) != 0)
        {
            fprintf(stderr, "    Cannot close wave file '%s'\n", decode_test_file);
            exit(2);
        }
    }
    if (log_audio)
    {
        if (afCloseFile(wave_handle) != 0)
        {
            fprintf(stderr, "    Cannot close wave file '%s'\n", OUTPUT_WAVE_FILE_NAME);
            exit(2);
        }
        afFreeFileSetup(filesetup);
    }
    if (done)
    {
        printf("Tests passed\n");
    }
    return  0;
}
예제 #11
0
int main(int argc, char *argv[])
{
    int16_t t38_amp_b[SAMPLES_PER_CHUNK];
    int16_t t30_amp_b[SAMPLES_PER_CHUNK];
    int16_t out_amp[2*SAMPLES_PER_CHUNK];
    int t38_len_b;
    int t30_len_b;
    int msg_len;
    uint8_t msg[1024];
    int log_audio;
    int outframes;
    SNDFILE *wave_handle;
    int t38_version;
    int use_ecm;
    int use_tep;
    int feedback_audio;
    int use_transmit_on_idle;
    const char *input_file_name;
    int i;
    int seq_no;
    int g1050_model_no;
    int g1050_speed_pattern_no;
    double tx_when;
    double rx_when;
    int use_gui;
    int supported_modems;
    int opt;
    t30_state_t *t30;
    t38_core_state_t *t38_core;
    logging_state_t *logging;

    log_audio = false;
    t38_version = 1;
    use_ecm = false;
    input_file_name = INPUT_FILE_NAME;
    simulate_incrementing_repeats = false;
    g1050_model_no = 0;
    g1050_speed_pattern_no = 1;
    use_gui = false;
    use_tep = false;
    feedback_audio = false;
    use_transmit_on_idle = true;
    supported_modems = T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17;
    while ((opt = getopt(argc, argv, "efgi:Ilm:M:s:tv:")) != -1)
    {
        switch (opt)
        {
        case 'e':
            use_ecm = true;
            break;
        case 'f':
            feedback_audio = true;
            break;
        case 'g':
#if defined(ENABLE_GUI)
            use_gui = true;
#else
            fprintf(stderr, "Graphical monitoring not available\n");
            exit(2);
#endif
            break;
        case 'i':
            input_file_name = optarg;
            break;
        case 'I':
            simulate_incrementing_repeats = true;
            break;
        case 'l':
            log_audio = true;
            break;
        case 'm':
            supported_modems = atoi(optarg);
            break;
        case 'M':
            g1050_model_no = optarg[0] - 'A' + 1;
            break;
        case 's':
            g1050_speed_pattern_no = atoi(optarg);
            break;
        case 't':
            use_tep = true;
            break;
        case 'v':
            t38_version = atoi(optarg);
            break;
        default:
            //usage();
            exit(2);
            break;
        }
    }

    printf("Using T.38 version %d\n", t38_version);
    if (use_ecm)
        printf("Using ECM\n");

    wave_handle = NULL;
    if (log_audio)
    {
        if ((wave_handle = sf_open_telephony_write(OUTPUT_FILE_NAME_WAVE, 2)) == NULL)
        {
            fprintf(stderr, "    Cannot create audio file '%s'\n", OUTPUT_FILE_NAME_WAVE);
            exit(2);
        }
    }

    srand48(0x1234567);
    if ((path_a_to_b = g1050_init(g1050_model_no, g1050_speed_pattern_no, 100, 33)) == NULL)
    {
        fprintf(stderr, "Failed to start IP network path model\n");
        exit(2);
    }
    if ((path_b_to_a = g1050_init(g1050_model_no, g1050_speed_pattern_no, 100, 33)) == NULL)
    {
        fprintf(stderr, "Failed to start IP network path model\n");
        exit(2);
    }

    if ((t38_state_a = t38_terminal_init(NULL, true, tx_packet_handler_a, &t38_state_b)) == NULL)
    {
        fprintf(stderr, "Cannot start the T.38 channel\n");
        exit(2);
    }
    t30 = t38_terminal_get_t30_state(t38_state_a);
    t38_core = t38_terminal_get_t38_core_state(t38_state_a);
    t38_set_t38_version(t38_core, t38_version);

    logging = t38_terminal_get_logging_state(t38_state_a);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, "T.38-A");

    logging = t38_core_get_logging_state(t38_core);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, "T.38-A");

    logging = t30_get_logging_state(t30);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, "T.38-A");

    t30_set_supported_modems(t30, supported_modems);
    t30_set_tx_ident(t30, "11111111");
    t30_set_tx_file(t30, input_file_name, -1, -1);
    t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) 'A');
    t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'A');
    t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'A');
    t30_set_ecm_capability(t30, use_ecm);
    if (use_ecm)
        t30_set_supported_compressions(t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);

    if ((t38_state_b = t38_gateway_init(NULL, tx_packet_handler_b, &t38_state_a)) == NULL)
    {
        fprintf(stderr, "Cannot start the T.38 channel\n");
        exit(2);
    }
    t38_core = t38_gateway_get_t38_core_state(t38_state_b);
    t38_gateway_set_transmit_on_idle(t38_state_b, use_transmit_on_idle);
    t38_set_t38_version(t38_core, t38_version);
    t38_gateway_set_ecm_capability(t38_state_b, use_ecm);

    logging = t38_gateway_get_logging_state(t38_state_b);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, "T.38-B");

    logging = t38_core_get_logging_state(t38_core);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, "T.38-B");

    memset(t38_amp_b, 0, sizeof(t38_amp_b));

    if ((fax_state_b = fax_init(NULL, false)) == NULL)
    {
        fprintf(stderr, "Cannot start FAX\n");
        exit(2);
    }
    t30 = fax_get_t30_state(fax_state_b);
    fax_set_transmit_on_idle(fax_state_b, use_transmit_on_idle);
    fax_set_tep_mode(fax_state_b, use_tep);
    t30_set_supported_modems(t30, supported_modems);
    t30_set_tx_ident(t30, "22222222");
    t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12);
    t30_set_rx_file(t30, OUTPUT_FILE_NAME, -1);
    t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) 'B');
    t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'B');
    t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'B');
    t30_set_ecm_capability(t30, use_ecm);
    if (use_ecm)
        t30_set_supported_compressions(t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);

    logging = fax_get_logging_state(fax_state_b);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, "FAX-B ");

    logging = t30_get_logging_state(t30);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, "FAX-B ");

    memset(t30_amp_b, 0, sizeof(t30_amp_b));

#if defined(ENABLE_GUI)
    if (use_gui)
        start_media_monitor();
#endif
    for (;;)
    {
        logging = t38_terminal_get_logging_state(t38_state_a);
        span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
        t38_core = t38_terminal_get_t38_core_state(t38_state_a);
        logging = t38_core_get_logging_state(t38_core);
        span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
        t30 = t38_terminal_get_t30_state(t38_state_a);
        logging = t30_get_logging_state(t30);
        span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
        logging = t38_gateway_get_logging_state(t38_state_b);
        span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
        t38_core = t38_gateway_get_t38_core_state(t38_state_b);
        logging = t38_core_get_logging_state(t38_core);
        span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
        logging = fax_get_logging_state(fax_state_b);
        span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
        t30 = fax_get_t30_state(fax_state_b);
        logging = t30_get_logging_state(t30);
        span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
        memset(out_amp, 0, sizeof(out_amp));

        t38_terminal_send_timeout(t38_state_a, SAMPLES_PER_CHUNK);

        t30_len_b = fax_tx(fax_state_b, t30_amp_b, SAMPLES_PER_CHUNK);
        if (!use_transmit_on_idle)
        {
            /* The receive side always expects a full block of samples, but the
               transmit side may not be sending any when it doesn't need to. We
               may need to pad with some silence. */
            if (t30_len_b < SAMPLES_PER_CHUNK)
            {
                memset(t30_amp_b + t30_len_b, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t30_len_b));
                t30_len_b = SAMPLES_PER_CHUNK;
            }
        }
        if (feedback_audio)
        {
            for (i = 0;  i < t30_len_b;  i++)
                t30_amp_b[i] += t38_amp_b[i] >> 1;
        }
        if (log_audio)
        {
            for (i = 0;  i < t30_len_b;  i++)
                out_amp[2*i + 1] = t30_amp_b[i];
        }
        if (t38_gateway_rx(t38_state_b, t30_amp_b, t30_len_b))
            break;
    
        t38_len_b = t38_gateway_tx(t38_state_b, t38_amp_b, SAMPLES_PER_CHUNK);
        if (!use_transmit_on_idle)
        {
            if (t38_len_b < SAMPLES_PER_CHUNK)
            {
                memset(t38_amp_b + t38_len_b, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t38_len_b));
                t38_len_b = SAMPLES_PER_CHUNK;
            }
        }
        if (log_audio)
        {
            for (i = 0;  i < t38_len_b;  i++)
                out_amp[2*i] = t38_amp_b[i];
        }
        if (fax_rx(fax_state_b, t38_amp_b, SAMPLES_PER_CHUNK))
            break;

        when += (float) SAMPLES_PER_CHUNK/(float) SAMPLE_RATE;

        while ((msg_len = g1050_get(path_a_to_b, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0)
        {
#if defined(ENABLE_GUI)
            if (use_gui)
                media_monitor_rx(seq_no, tx_when, rx_when);
#endif
            t38_core = t38_gateway_get_t38_core_state(t38_state_b);
            t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no);
        }
        while ((msg_len = g1050_get(path_b_to_a, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0)
        {
#if defined(ENABLE_GUI)
            if (use_gui)
                media_monitor_rx(seq_no, tx_when, rx_when);
#endif
            t38_core = t38_terminal_get_t38_core_state(t38_state_a);
            t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no);
        }
        if (log_audio)
        {
            outframes = sf_writef_short(wave_handle, out_amp, SAMPLES_PER_CHUNK);
            if (outframes != SAMPLES_PER_CHUNK)
                break;
        }

        if (done[0]  &&  done[1])
            break;
#if defined(ENABLE_GUI)
        if (use_gui)
            media_monitor_update_display();
#endif
    }
    t38_terminal_release(t38_state_a);
    fax_release(fax_state_b);
    if (log_audio)
    {
        if (sf_close(wave_handle) != 0)
        {
            fprintf(stderr, "    Cannot close audio file '%s'\n", OUTPUT_FILE_NAME_WAVE);
            exit(2);
        }
    }
    if (!succeeded[0]  ||  !succeeded[1])
    {
        printf("Tests failed\n");
        exit(2);
    }
    printf("Tests passed\n");
    return 0;
}
예제 #12
0
static int t30_tests(int log_audio, int test_sending)
{
    int k;
    int outframes;
    fax_state_t *fax_state;
    int16_t t30_amp[SAMPLES_PER_CHUNK];
    int16_t t31_amp[SAMPLES_PER_CHUNK];
    int16_t silence[SAMPLES_PER_CHUNK];
    int16_t out_amp[2*SAMPLES_PER_CHUNK];
    int t30_len;
    int t31_len;
    SNDFILE *wave_handle;
    SNDFILE *in_handle;
    int fast_send;
    int fast_send_tcf;
    int fast_blocks;
    uint8_t fast_buf[1000];
    t30_state_t *t30;
    logging_state_t *logging;
    int i;

    wave_handle = NULL;
    if (log_audio)
    {
        if ((wave_handle = sf_open_telephony_write(OUTPUT_WAVE_FILE_NAME, 2)) == NULL)
        {
            fprintf(stderr, "    Cannot create audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
            exit(2);
        }
    }

    memset(silence, 0, sizeof(silence));
 
    in_handle = NULL;
    if (decode_test_file)
    {
        if ((in_handle = sf_open_telephony_read(decode_test_file, 1)) == NULL)
        {
            fprintf(stderr, "    Cannot create audio file '%s'\n", decode_test_file);
            exit(2);
        }
    }

    if ((t31_state = t31_init(NULL, at_tx_handler, NULL, modem_call_control, NULL, NULL, NULL)) == NULL)
    {
        fprintf(stderr, "    Cannot start the T.31 FAX modem\n");
        exit(2);
    }
    logging = t31_get_logging_state(t31_state);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, "T.31");

    if (test_sending)
    {
        fax_state = fax_init(NULL, FALSE);
        t30 = fax_get_t30_state(fax_state);
        t30_set_rx_file(t30, OUTPUT_FILE_NAME, -1);
        fax_test_seq = fax_send_test_seq;
        countdown = 0;
    }
    else
    {
        fax_state = fax_init(NULL, TRUE);
        t30 = fax_get_t30_state(fax_state);
        t30_set_tx_file(t30, INPUT_FILE_NAME, -1, -1);
        fax_test_seq = fax_receive_test_seq;
        countdown = 250;
    }
    
    t30_set_tx_ident(t30, "11111111");
    t30_set_supported_modems(t30, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17);
    t30_set_phase_b_handler(t30, phase_b_handler, (void *) 'A');
    t30_set_phase_d_handler(t30, phase_d_handler, (void *) 'A');
    t30_set_phase_e_handler(t30, phase_e_handler, (void *) 'A');
    memset(t30_amp, 0, sizeof(t30_amp));
    
    logging = t30_get_logging_state(t30);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, "FAX");

    logging = fax_get_logging_state(fax_state);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, "FAX");

    fast_send = FALSE;
    fast_send_tcf = TRUE;
    fast_blocks = 0;
    kick = TRUE;
    while (!done)
    {
        if (kick)
        {
            kick = FALSE;
            if (fax_test_seq[test_seq_ptr].command > (const char *) 2)
            {
                if (fax_test_seq[test_seq_ptr].command[0])
                {
                    printf("%s\n", fax_test_seq[test_seq_ptr].command);
                    t31_at_rx(t31_state, fax_test_seq[test_seq_ptr].command, fax_test_seq[test_seq_ptr].len_command);
                }
            }
            else
            {
                if (fax_test_seq[test_seq_ptr].command == (const char *) 2)
                {
                    printf("Fast send TCF\n");
                    fast_send = TRUE;
                    fast_send_tcf = TRUE;
                    fast_blocks = 100;
                }
                else
                {
                    printf("Fast send image\n");
                    fast_send = TRUE;
                    fast_send_tcf = FALSE;
                    fast_blocks = 100;
                }
            }
        }
        if (fast_send)
        {
            /* Send fast modem data */
            if (fast_send_tcf)
            {
                memset(fast_buf, 0, 36);
            }
            else
            {
                if (fast_blocks == 1)
                {
                    /* Create the end of page condition */
                    for (i = 0;  i < 36;  i += 2)
                    {
                        fast_buf[i] = 0x00;
                        fast_buf[i + 1] = 0x80;
                    }
                }
                else
                {
                    /* Create a chunk of white page */
                    for (i = 0;  i < 36;  i += 4)
                    {
                        fast_buf[i] = 0x00;
                        fast_buf[i + 1] = 0x80;
                        fast_buf[i + 2] = 0xB2;
                        fast_buf[i + 3] = 0x01;
                    }
                }
            }
            if (fast_blocks == 1)
            {
                /* Insert EOLs */
                fast_buf[35] = ETX;
                fast_buf[34] = DLE;
                fast_buf[31] =
                fast_buf[28] =
                fast_buf[25] =
                fast_buf[22] =
                fast_buf[19] =
                fast_buf[16] = 1;
            }
            t31_at_rx(t31_state, (char *) fast_buf, 36);
            if (--fast_blocks == 0)
                fast_send = FALSE;
        }
        t30_len = fax_tx(fax_state, t30_amp, SAMPLES_PER_CHUNK);
        /* The receive side always expects a full block of samples, but the
           transmit side may not be sending any when it doesn't need to. We
           may need to pad with some silence. */
        if (t30_len < SAMPLES_PER_CHUNK)
        {
            memset(t30_amp + t30_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t30_len));
            t30_len = SAMPLES_PER_CHUNK;
        }
        if (log_audio)
        {
            for (k = 0;  k < t30_len;  k++)
                out_amp[2*k] = t30_amp[k];
        }
        if (t31_rx(t31_state, t30_amp, t30_len))
            break;
        if (countdown)
        {
            if (answered)
            {
                countdown = 0;
                t31_call_event(t31_state, AT_CALL_EVENT_ANSWERED);
            }
            else if (--countdown == 0)
            {
                t31_call_event(t31_state, AT_CALL_EVENT_ALERTING);
                countdown = 250;
            }
        }

        t31_len = t31_tx(t31_state, t31_amp, SAMPLES_PER_CHUNK);
        if (t31_len < SAMPLES_PER_CHUNK)
        {
            memset(t31_amp + t31_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t31_len));
            t31_len = SAMPLES_PER_CHUNK;
        }
        if (log_audio)
        {
            for (k = 0;  k < t31_len;  k++)
                out_amp[2*k + 1] = t31_amp[k];
        }
        if (fax_rx(fax_state, t31_amp, SAMPLES_PER_CHUNK))
            break;

        logging = fax_get_logging_state(fax_state);
        span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
        logging = t30_get_logging_state(t30);
        span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
        logging = t31_get_logging_state(t31_state);
        span_log_bump_samples(logging, SAMPLES_PER_CHUNK);

        if (log_audio)
        {
            outframes = sf_writef_short(wave_handle, out_amp, SAMPLES_PER_CHUNK);
            if (outframes != SAMPLES_PER_CHUNK)
                break;
        }
    }
    if (decode_test_file)
    {
        if (sf_close_telephony(in_handle))
        {
            fprintf(stderr, "    Cannot close audio file '%s'\n", decode_test_file);
            exit(2);
        }
    }
    if (log_audio)
    {
        if (sf_close_telephony(wave_handle))
        {
            fprintf(stderr, "    Cannot close audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
            exit(2);
        }
    }
    return 0;
}
예제 #13
0
int main(int argc, char *argv[])
{
    t30_state_t *t30;
    logging_state_t *logging;
    const char *input_file_name;
    int t38_version;
    int caller;
    int use_ecm;
    int use_tep;
    int options;
    int supported_modems;
    int fill_removal;
    int opt;
    int t38_terminal_operation;
    uint32_t src_addr;
    uint16_t src_port;
    uint32_t dest_addr;
    uint16_t dest_port;

    caller = false;
    use_ecm = false;
    t38_version = 0;
    options = 0;
    input_file_name = INPUT_FILE_NAME;
    fill_removal = false;
    use_tep = false;
    use_transmit_on_idle = true;
    supported_modems = T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17;
    t38_terminal_operation = true;
    log_audio = false;
    src_addr = 0;
    src_port = 0;
    dest_addr = 0;
    dest_port = 0;
    while ((opt = getopt(argc, argv, "cD:d:eFGi:lm:oS:s:tv:")) != -1)
    {
        switch (opt)
        {
        case 'c':
            caller = true;
            break;
        case 'D':
            dest_addr = parse_inet_addr(optarg);
            break;
        case 'd':
            dest_port = atoi(optarg);
            break;
        case 'e':
            use_ecm = true;
            break;
        case 'F':
            fill_removal = true;
            break;
        case 'G':
            t38_terminal_operation = false;
            break;
        case 'i':
            input_file_name = optarg;
            break;
        case 'l':
            log_audio = true;
            break;
        case 'm':
            supported_modems = atoi(optarg);
            break;
        case 'o':
            options = atoi(optarg);
            break;
        case 'S':
            src_addr = parse_inet_addr(optarg);
            break;
        case 's':
            src_port = atoi(optarg);
            break;
        case 't':
            use_tep = true;
            break;
        case 'v':
            t38_version = atoi(optarg);
            break;
        default:
            //usage();
            exit(2);
            break;
        }
    }

    printf("Using T.38 version %d\n", t38_version);

    if (t38_terminal_operation)
    {
        if ((t38_terminal_state = t38_terminal_init(NULL, caller, tx_packet_handler, NULL)) == NULL)
        {
            fprintf(stderr, "Cannot start the T.38 channel\n");
            exit(2);
        }
        t30 = t38_terminal_get_t30_state(t38_terminal_state);
        t38_core = t38_terminal_get_t38_core_state(t38_terminal_state);
        t38_set_t38_version(t38_core, t38_version);
        t38_terminal_set_config(t38_terminal_state, options);
        t38_terminal_set_tep_mode(t38_terminal_state, use_tep);
        t38_terminal_set_fill_bit_removal(t38_terminal_state, fill_removal);

        logging = t38_terminal_get_logging_state(t38_terminal_state);
        span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
        span_log_set_tag(logging, "T.38");

        logging = t38_core_get_logging_state(t38_core);
        span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
        span_log_set_tag(logging, "T.38");

        logging = t30_get_logging_state(t30);
        span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
        span_log_set_tag(logging, "T.38");

        t30_set_supported_modems(t30, supported_modems);
        t30_set_tx_ident(t30, "11111111");
        t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12);
        if (caller)
            t30_set_tx_file(t30, INPUT_TIFF_FILE_NAME, -1, -1);
        else
            t30_set_rx_file(t30, OUTPUT_TIFF_FILE_NAME, -1);
        t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) 'A');
        t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'A');
        t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'A');
        t30_set_ecm_capability(t30, use_ecm);
        t30_set_supported_compressions(t30, T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6 | T4_COMPRESSION_T85);

        if (pcap_scan_pkts(input_file_name, src_addr, src_port, dest_addr, dest_port, t38_terminal_timing_update, process_packet, NULL))
            exit(2);
        /* Push the time along, to flush out any remaining activity from the application. */
        now.tv_sec += 60;
        t38_terminal_timing_update(NULL, &now);
    }
    else
    {
        wave_handle = NULL;
        if (log_audio)
        {
            if ((wave_handle = sf_open_telephony_write(OUTPUT_WAVE_FILE_NAME, 2)) == NULL)
            {
                fprintf(stderr, "    Cannot create audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
                exit(2);
            }
        }

        if ((t38_gateway_state = t38_gateway_init(NULL, tx_packet_handler, NULL)) == NULL)
        {
            fprintf(stderr, "Cannot start the T.38 channel\n");
            exit(2);
        }
        t38_core = t38_gateway_get_t38_core_state(t38_gateway_state);
        t38_gateway_set_transmit_on_idle(t38_gateway_state, use_transmit_on_idle);
        t38_set_t38_version(t38_core, t38_version);
        t38_gateway_set_ecm_capability(t38_gateway_state, use_ecm);

        logging = t38_gateway_get_logging_state(t38_gateway_state);
        span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
        span_log_set_tag(logging, "T.38");

        logging = t38_core_get_logging_state(t38_core);
        span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
        span_log_set_tag(logging, "T.38");

        if ((fax_state = fax_init(NULL, caller)) == NULL)
        {
            fprintf(stderr, "Cannot start FAX\n");
            exit(2);
        }
        t30 = fax_get_t30_state(fax_state);
        fax_set_transmit_on_idle(fax_state, use_transmit_on_idle);
        fax_set_tep_mode(fax_state, use_tep);
        t30_set_supported_modems(t30, supported_modems);
        t30_set_tx_ident(t30, "22222222");
        t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12);
        if (caller)
            t30_set_tx_file(t30, INPUT_TIFF_FILE_NAME, -1, -1);
        else
            t30_set_rx_file(t30, OUTPUT_TIFF_FILE_NAME, -1);
        t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) 'B');
        t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'B');
        t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'B');
        t30_set_ecm_capability(t30, use_ecm);
        t30_set_supported_compressions(t30, T4_COMPRESSION_T4_1D | T4_COMPRESSION_T4_2D | T4_COMPRESSION_T6);

        logging = fax_get_logging_state(fax_state);
        span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
        span_log_set_tag(logging, "FAX ");

        logging = t30_get_logging_state(t30);
        span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
        span_log_set_tag(logging, "FAX ");

        if (pcap_scan_pkts(input_file_name, src_addr, src_port, dest_addr, dest_port, t38_gateway_timing_update, process_packet, NULL))
            exit(2);
        /* Push the time along, to flush out any remaining activity from the application. */
        now.tv_sec += 60;
        t38_gateway_timing_update(NULL, &now);

        fax_release(fax_state);
        t38_gateway_release(t38_gateway_state);
        if (log_audio)
        {
            if (sf_close_telephony(wave_handle))
            {
                fprintf(stderr, "    Cannot close audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
                exit(2);
            }
        }
    }
}
예제 #14
0
int main(int argc, char *argv[])
{
    int16_t t38_amp_a[SAMPLES_PER_CHUNK];
    int16_t t30_amp_a[SAMPLES_PER_CHUNK];
    int16_t out_amp[2*SAMPLES_PER_CHUNK];
    int t38_len_a;
    int t30_len_a;
    int msg_len;
    uint8_t msg[1024];
    int log_audio;
    int outframes;
    int t38_version;
    int use_ecm;
    AFfilesetup filesetup;
    AFfilehandle wave_handle;
    const char *input_file_name;
    int i;
    int seq_no;

    log_audio = FALSE;
    t38_version = 1;
    use_ecm = FALSE;
    input_file_name = INPUT_FILE_NAME;
    simulate_incrementing_repeats = FALSE;
    for (i = 1;  i < argc;  i++)
    {
        if (strcmp(argv[i], "-e") == 0)
        {
            use_ecm = TRUE;
            continue;
        }
        if (strcmp(argv[i], "-i") == 0)
        {
            i++;
            input_file_name = argv[i];
            continue;
        }
        if (strcmp(argv[i], "-I") == 0)
        {
            simulate_incrementing_repeats = TRUE;
            continue;
        }
        if (strcmp(argv[i], "-l") == 0)
        {
            log_audio = TRUE;
            continue;
        }
        if (strcmp(argv[i], "-v") == 0)
        {
            i++;
            t38_version = atoi(argv[i]);
            continue;
        }
    }

    printf("Using T.38 version %d\n", t38_version);
    if (use_ecm)
        printf("Using ECM\n");

    filesetup = AF_NULL_FILESETUP;
    wave_handle = AF_NULL_FILEHANDLE;
    if (log_audio)
    {
        if ((filesetup = afNewFileSetup()) == AF_NULL_FILESETUP)
        {
            fprintf(stderr, "    Failed to create file setup\n");
            exit(2);
        }
        afInitSampleFormat(filesetup, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, 16);
        afInitRate(filesetup, AF_DEFAULT_TRACK, (float) SAMPLE_RATE);
        afInitFileFormat(filesetup, AF_FILE_WAVE);
        afInitChannels(filesetup, AF_DEFAULT_TRACK, 2);

        wave_handle = afOpenFile(OUTPUT_FILE_NAME_WAVE, "w", filesetup);
        if (wave_handle == AF_NULL_FILEHANDLE)
        {
            fprintf(stderr, "    Cannot create wave file '%s'\n", OUTPUT_FILE_NAME_WAVE);
            exit(2);
        }
    }

    if ((path_a_to_b = ip_network_model_init(800, 2000, 0)) == NULL)
    {
        fprintf(stderr, "Failed to start IP network path model\n");
        exit(2);
    }
    if ((path_b_to_a = ip_network_model_init(800, 2000, 0)) == NULL)
    {
        fprintf(stderr, "Failed to start IP network path model\n");
        exit(2);
    }

    fax_init(&fax_state_a, TRUE);
    t30_set_local_ident(&fax_state_a.t30_state, "11111111");
    t30_set_tx_file(&fax_state_a.t30_state, input_file_name, -1, -1);
    t30_set_phase_b_handler(&fax_state_a.t30_state, phase_b_handler, (void *) (intptr_t) 'A');
    t30_set_phase_d_handler(&fax_state_a.t30_state, phase_d_handler, (void *) (intptr_t) 'A');
    t30_set_phase_e_handler(&fax_state_a.t30_state, phase_e_handler, (void *) (intptr_t) 'A');
    t30_set_ecm_capability(&fax_state_a.t30_state, use_ecm);
    if (use_ecm)
        t30_set_supported_compressions(&fax_state_a.t30_state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
    span_log_set_level(&fax_state_a.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(&fax_state_a.logging, "FAX-A ");
    span_log_set_level(&fax_state_a.t30_state.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(&fax_state_a.t30_state.logging, "FAX-A ");
    memset(t30_amp_a, 0, sizeof(t30_amp_a));

    if (t38_gateway_init(&t38_state_a, tx_packet_handler_a, &t38_state_b) == NULL)
    {
        fprintf(stderr, "Cannot start the T.38 channel\n");
        exit(2);
    }
    t38_set_t38_version(&t38_state_a.t38, t38_version);
    t38_gateway_ecm_control(&t38_state_a, use_ecm);
    span_log_set_level(&t38_state_a.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(&t38_state_a.logging, "T.38-A");
    span_log_set_level(&t38_state_a.t38.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(&t38_state_a.t38.logging, "T.38-A");
    memset(t38_amp_a, 0, sizeof(t38_amp_a));

    if (t38_terminal_init(&t38_state_b, FALSE, tx_packet_handler_b, &t38_state_a) == NULL)
    {
        fprintf(stderr, "Cannot start the T.38 channel\n");
        exit(2);
    }
    t38_set_t38_version(&t38_state_b.t38, t38_version);
    span_log_set_level(&t38_state_b.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(&t38_state_b.logging, "T.38-B");
    span_log_set_level(&t38_state_b.t38.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(&t38_state_b.t38.logging, "T.38-B");
    span_log_set_level(&t38_state_b.t30_state.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(&t38_state_b.t30_state.logging, "T.38-B");

    t30_set_local_ident(&t38_state_b.t30_state, "22222222");
    t30_set_rx_file(&t38_state_b.t30_state, OUTPUT_FILE_NAME, -1);
    t30_set_phase_b_handler(&t38_state_b.t30_state, phase_b_handler, (void *) (intptr_t) 'B');
    t30_set_phase_d_handler(&t38_state_b.t30_state, phase_d_handler, (void *) (intptr_t) 'B');
    t30_set_phase_e_handler(&t38_state_b.t30_state, phase_e_handler, (void *) (intptr_t) 'B');
    t30_set_ecm_capability(&t38_state_b.t30_state, use_ecm);
    if (use_ecm)
        t30_set_supported_compressions(&t38_state_b.t30_state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);

    for (;;)
    {
        span_log_bump_samples(&fax_state_a.logging, SAMPLES_PER_CHUNK);
        span_log_bump_samples(&fax_state_a.t30_state.logging, SAMPLES_PER_CHUNK);
        span_log_bump_samples(&t38_state_a.logging, SAMPLES_PER_CHUNK);
        span_log_bump_samples(&t38_state_a.t38.logging, SAMPLES_PER_CHUNK);
        span_log_bump_samples(&t38_state_b.logging, SAMPLES_PER_CHUNK);
        span_log_bump_samples(&t38_state_b.t38.logging, SAMPLES_PER_CHUNK);
        span_log_bump_samples(&t38_state_b.t30_state.logging, SAMPLES_PER_CHUNK);
        memset(out_amp, 0, sizeof(out_amp));

        t38_terminal_send_timeout(&t38_state_b, SAMPLES_PER_CHUNK);

        t30_len_a = fax_tx(&fax_state_a, t30_amp_a, SAMPLES_PER_CHUNK);
        /* The receive side always expects a full block of samples, but the
           transmit side may not be sending any when it doesn't need to. We
           may need to pad with some silence. */
        if (t30_len_a < SAMPLES_PER_CHUNK)
        {
            memset(t30_amp_a + t30_len_a, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t30_len_a));
            t30_len_a = SAMPLES_PER_CHUNK;
        }
        if (log_audio)
        {
            for (i = 0;  i < t30_len_a;  i++)
                out_amp[2*i] = t30_amp_a[i];
        }
        if (t38_gateway_rx(&t38_state_a, t30_amp_a, t30_len_a))
            break;
    
        t38_len_a = t38_gateway_tx(&t38_state_a, t38_amp_a, SAMPLES_PER_CHUNK);
        if (t38_len_a < SAMPLES_PER_CHUNK)
        {
            memset(t38_amp_a + t38_len_a, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t38_len_a));
            t38_len_a = SAMPLES_PER_CHUNK;
        }
        if (log_audio)
        {
            for (i = 0;  i < t38_len_a;  i++)
                out_amp[2*i + 1] = t38_amp_a[i];
        }
        if (fax_rx(&fax_state_a, t38_amp_a, SAMPLES_PER_CHUNK))
            break;

        while ((msg_len = ip_network_model_get(path_a_to_b, SAMPLES_PER_CHUNK, msg, 1024, &seq_no)) >= 0)
            t38_core_rx_ifp_packet(&t38_state_b.t38, seq_no, msg, msg_len);
        while ((msg_len = ip_network_model_get(path_b_to_a, SAMPLES_PER_CHUNK, msg, 1024, &seq_no)) >= 0)
            t38_core_rx_ifp_packet(&t38_state_a.t38, seq_no, msg, msg_len);

        if (log_audio)
        {
            outframes = afWriteFrames(wave_handle, AF_DEFAULT_TRACK, out_amp, SAMPLES_PER_CHUNK);
            if (outframes != SAMPLES_PER_CHUNK)
                break;
        }

        if (done[0]  &&  done[1])
            break;
    }
    if (log_audio)
    {
        if (afCloseFile(wave_handle) != 0)
        {
            fprintf(stderr, "    Cannot close wave file '%s'\n", OUTPUT_FILE_NAME_WAVE);
            exit(2);
        }
        afFreeFileSetup(filesetup);
    }
    if (!succeeded[0]  ||  !succeeded[1])
    {
        printf("Tests failed\n");
        exit(2);
    }
    printf("Tests passed\n");
    return  0;
}
예제 #15
0
파일: fax.c 프로젝트: Ardameon/experiments
/*
 *  Init appropriate spandsp objects to receive fax
 */
static int spanfax_init(fax_session_t *f_session, fax_transport_mod_e trans_mode)
{
    t38_terminal_state_t *t38;
    t38_core_state_t *t38_core;
    t30_state_t *t30;
    logging_state_t *logging;
    int log_level;

    int fec_entries = DEFAULT_FEC_ENTRIES;
    int fec_span = DEFAULT_FEC_SPAN;

    printf("fax: %s: start!\n", __func__);

    switch(trans_mode) {
        case FAX_TRANSPORT_T38_MOD:

            memset(f_session->pvt.t38_state, 0, sizeof(t38_terminal_state_t));

			if (t38_terminal_init(f_session->pvt.t38_state, f_session->pvt.caller,
								  t38_tx_packet_handler, f_session) == NULL) {
				printf("fax: Cannot initialize T.38 structs\n");
				return 0;
			}

			t38 = f_session->pvt.t38_state;
			t30 = t38_terminal_get_t30_state(t38);

			t38_core = f_session->pvt.t38_core = t38_terminal_get_t38_core_state(t38);
			t38_terminal_set_config(t38, 0);
			t38_terminal_set_tep_mode(t38, 0);

			if (udptl_init(f_session->pvt.udptl_state, UDPTL_ERROR_CORRECTION_REDUNDANCY,
						   fec_span, fec_entries, (udptl_rx_packet_handler_t *) t38_core_rx_ifp_packet,
						   (void *) f_session->pvt.t38_core) == NULL) {
				printf("fax: Cannot initialize UDPTL structs\n");
				return 0;
			}

			if (f_session->pvt.verbose) {
				log_level = SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG |
						SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL |
						SPAN_LOG_FLOW;

				logging = t38_terminal_get_logging_state(t38);
				span_log_set_message_handler(logging, spanfax_log_message);
				span_log_set_level(logging, log_level);
				span_log_set_tag(logging, f_session->log_tag);

				logging = t38_core_get_logging_state(t38_core);
				span_log_set_message_handler(logging, spanfax_log_message);
				span_log_set_level(logging, log_level);
				span_log_set_tag(logging, f_session->log_tag);

				logging = t30_get_logging_state(t30);
				span_log_set_message_handler(logging, spanfax_log_message);
				span_log_set_level(logging, log_level);
				span_log_set_tag(logging, f_session->log_tag);
			}

            break;
        case FAX_TRANSPORT_AUDIO_MOD:
        default:
            return 0;
            break;
    }

	/* All the things which are common to audio and T.38 FAX setup */

	t30_set_tx_ident(t30, f_session->pvt.ident);
	t30_set_tx_page_header_info(t30, f_session->pvt.header);

	t30_set_phase_e_handler(t30, phase_e_handler, f_session);
	t30_set_phase_d_handler(t30, phase_d_handler, f_session);
	t30_set_phase_b_handler(t30, phase_b_handler, f_session);

	t30_set_supported_image_sizes(t30, T30_SUPPORT_US_LETTER_LENGTH
								  | T30_SUPPORT_US_LEGAL_LENGTH
								  | T30_SUPPORT_UNLIMITED_LENGTH
								  | T30_SUPPORT_215MM_WIDTH
								  | T30_SUPPORT_255MM_WIDTH
								  | T30_SUPPORT_303MM_WIDTH
								  );
	t30_set_supported_resolutions(t30, T30_SUPPORT_STANDARD_RESOLUTION
								  | T30_SUPPORT_FINE_RESOLUTION
								  | T30_SUPPORT_SUPERFINE_RESOLUTION
								  | T30_SUPPORT_R16_RESOLUTION
								  |	T30_SUPPORT_R8_RESOLUTION
								  | T30_SUPPORT_300_300_RESOLUTION
								  | T30_SUPPORT_400_400_RESOLUTION
								  | T30_SUPPORT_600_600_RESOLUTION
								  |	T30_SUPPORT_1200_1200_RESOLUTION
								  |	T30_SUPPORT_300_600_RESOLUTION
								  | T30_SUPPORT_400_800_RESOLUTION
								  | T30_SUPPORT_600_1200_RESOLUTION
								  );
#if 0
	t30_set_supported_colour_resolutions(t30, 0);
#endif

	if (f_session->pvt.disable_v17) {
		t30_set_supported_modems(t30, T30_SUPPORT_V29 | T30_SUPPORT_V27TER);
	} else {
		t30_set_supported_modems(t30, T30_SUPPORT_V29 | T30_SUPPORT_V27TER
								 | T30_SUPPORT_V17);
	}

	if (f_session->pvt.use_ecm) {
		t30_set_ecm_capability(t30, TRUE);
		t30_set_supported_compressions(t30,
									   T30_SUPPORT_T4_1D_COMPRESSION
									   | T30_SUPPORT_T4_2D_COMPRESSION
									   | T30_SUPPORT_T6_COMPRESSION
									   | T30_SUPPORT_T85_COMPRESSION
									   | T30_SUPPORT_T85_L0_COMPRESSION);
	} else {
		t30_set_supported_compressions(t30, T30_SUPPORT_T4_1D_COMPRESSION
									   | T30_SUPPORT_T4_2D_COMPRESSION);
	}

	if (f_session->pvt.caller) {
		t30_set_tx_file(t30, f_session->pvt.filename, -1, -1);
	} else {
		t30_set_rx_file(t30, f_session->pvt.filename, -1);
	}

	return 0;
}
예제 #16
0
파일: fax_tests.c 프로젝트: vir/spandsp
int main(int argc, char *argv[])
{
    SNDFILE *wave_handle;
    SNDFILE *input_wave_handle;
    int i;
    int j;
    int k;
    struct machine_s *mc;
    int outframes;
    char buf[128 + 1];
    int16_t silence[SAMPLES_PER_CHUNK];
    int16_t out_amp[2*SAMPLES_PER_CHUNK];
    int alldone;
    const char *input_tiff_file_name;
    const char *input_audio_file_name;
    int log_audio;
    int use_ecm;
    int use_tep;
    int use_transmit_on_idle;
#if defined(WITH_SPANDSP_INTERNALS)
    int use_line_hits;
#endif
    int polled_mode;
    int reverse_flow;
    int use_page_limits;
    int supported_modems;
    int signal_level;
    int noise_level;
    float signal_scaling;
    time_t start_time;
    time_t end_time;
    int scan_line_time;
    char *page_header_info;
    int opt;
    t30_state_t *t30;
    logging_state_t *logging;

    log_audio = false;
    input_tiff_file_name = INPUT_TIFF_FILE_NAME;
    input_audio_file_name = NULL;
    use_ecm = false;
#if defined(WITH_SPANDSP_INTERNALS)
    use_line_hits = false;
#endif
    use_tep = false;
    polled_mode = false;
    page_header_info = NULL;
    reverse_flow = false;
    use_transmit_on_idle = true;
    use_receiver_not_ready = false;
    use_page_limits = false;
    signal_level = 0;
    noise_level = -99;
    scan_line_time = 0;
    supported_modems = T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17;
    while ((opt = getopt(argc, argv, "ehH:i:I:lm:n:prRs:S:tTw:")) != -1)
    {
        switch (opt)
        {
        case 'e':
            use_ecm = true;
            break;
#if defined(WITH_SPANDSP_INTERNALS)
        case 'h':
            use_line_hits = true;
            break;
#endif
        case 'H':
            page_header_info = optarg;
            break;
        case 'i':
            input_tiff_file_name = optarg;
            break;
        case 'I':
            input_audio_file_name = optarg;
            break;
        case 'l':
            log_audio = true;
            break;
        case 'm':
            supported_modems = atoi(optarg);
            break;
        case 'n':
            noise_level = atoi(optarg);
            break;
        case 'p':
            polled_mode = true;
            break;
        case 'r':
            reverse_flow = true;
            break;
        case 'R':
            use_receiver_not_ready = true;
            break;
        case 's':
            signal_level = atoi(optarg);
            break;
        case 'S':
            scan_line_time = atoi(optarg);
            break;
        case 't':
            use_tep = true;
            break;
        case 'T':
            use_page_limits = true;
            break;
        case 'w':
            t30_state_to_wreck = atoi(optarg);
            break;
        default:
            //usage();
            exit(2);
            break;
        }
    }

    input_wave_handle = NULL;
    if (input_audio_file_name)
    {
        if ((input_wave_handle = sf_open_telephony_read(input_audio_file_name, 1)) == NULL)
        {
            fprintf(stderr, "    Cannot open audio file '%s'\n", input_audio_file_name);
            exit(2);
        }
    }

    wave_handle = NULL;
    if (log_audio)
    {
        if ((wave_handle = sf_open_telephony_write(OUTPUT_FILE_NAME_WAVE, 2)) == NULL)
        {
            fprintf(stderr, "    Cannot create audio file '%s'\n", OUTPUT_FILE_NAME_WAVE);
            exit(2);
        }
    }

    memset(silence, 0, sizeof(silence));
    for (j = 0;  j < FAX_MACHINES;  j++)
    {
        machines[j].chan = j;
        mc = &machines[j];

        i = mc->chan + 1;
        sprintf(buf, "%d%d%d%d%d%d%d%d", i, i, i, i, i, i, i, i);
        if (reverse_flow)
            mc->fax = fax_init(NULL, (mc->chan & 1)  ?  true  :  false);
        else
            mc->fax = fax_init(NULL, (mc->chan & 1)  ?  false  :  true);
        mc->awgn = NULL;
        signal_scaling = 1.0f;
        if (noise_level > -99)
        {
            mc->awgn = awgn_init_dbm0(NULL, 1234567, noise_level);
            signal_scaling = powf(10.0f, signal_level/20.0f);
            printf("Signal scaling %f\n", signal_scaling);
        }
        fax_set_transmit_on_idle(mc->fax, use_transmit_on_idle);
        fax_set_tep_mode(mc->fax, use_tep);
        t30 = fax_get_t30_state(mc->fax);
        t30_set_tx_ident(t30, buf);
        t30_set_tx_sub_address(t30, "Sub-address");
        t30_set_tx_sender_ident(t30, "Sender ID");
        t30_set_tx_password(t30, "Password");
        t30_set_tx_polled_sub_address(t30, "Polled sub-address");
        t30_set_tx_selective_polling_address(t30, "Selective polling address");
        t30_set_tx_page_header_info(t30, page_header_info);
        t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12);
        t30_set_ecm_capability(t30, use_ecm);
        t30_set_supported_t30_features(t30,
                                       T30_SUPPORT_IDENTIFICATION
                                     | T30_SUPPORT_SELECTIVE_POLLING
                                     | T30_SUPPORT_SUB_ADDRESSING);

        if ((mc->chan & 1))
            t30_set_minimum_scan_line_time(t30, scan_line_time);
        t30_set_supported_image_sizes(t30,
                                      T30_SUPPORT_US_LETTER_LENGTH
                                    | T30_SUPPORT_US_LEGAL_LENGTH
                                    | T30_SUPPORT_UNLIMITED_LENGTH
                                    | T30_SUPPORT_215MM_WIDTH
                                    | T30_SUPPORT_255MM_WIDTH
                                    | T30_SUPPORT_303MM_WIDTH);
        t30_set_supported_resolutions(t30,
                                      T30_SUPPORT_STANDARD_RESOLUTION
                                    | T30_SUPPORT_FINE_RESOLUTION
                                    | T30_SUPPORT_SUPERFINE_RESOLUTION
                                    | T30_SUPPORT_R8_RESOLUTION
                                    | T30_SUPPORT_R16_RESOLUTION
                                    | T30_SUPPORT_300_300_RESOLUTION
                                    | T30_SUPPORT_400_400_RESOLUTION
                                    | T30_SUPPORT_600_600_RESOLUTION
                                    | T30_SUPPORT_1200_1200_RESOLUTION
                                    | T30_SUPPORT_300_600_RESOLUTION
                                    | T30_SUPPORT_400_800_RESOLUTION
                                    | T30_SUPPORT_600_1200_RESOLUTION);
        t30_set_supported_modems(t30, supported_modems);
        if (use_ecm)
#if defined(SPANDSP_SUPPORT_T85)
            t30_set_supported_compressions(t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION | T30_SUPPORT_T85_COMPRESSION);
#else
            t30_set_supported_compressions(t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
#endif
        if ((mc->chan & 1))
        {
            if (polled_mode)
            {
                if (use_page_limits)
                    t30_set_tx_file(t30, input_tiff_file_name, 3, 6);
                else
                    t30_set_tx_file(t30, input_tiff_file_name, -1, -1);
            }
            else
            {
                sprintf(buf, "fax_tests_%d.tif", (mc->chan + 1)/2);
                t30_set_rx_file(t30, buf, -1);
                t30_set_rx_encoding(t30, T4_COMPRESSION_ITU_T6);
            }
        }
        else
        {
            if (polled_mode)
            {
                sprintf(buf, "fax_tests_%d.tif", (mc->chan + 1)/2);
                t30_set_rx_file(t30, buf, -1);
                t30_set_rx_encoding(t30, T4_COMPRESSION_ITU_T6);
            }
            else
            {
                if (use_page_limits)
                    t30_set_tx_file(t30, input_tiff_file_name, 3, 6);
                else
                    t30_set_tx_file(t30, input_tiff_file_name, -1, -1);
            }
        }
        t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) mc->chan + 'A');
        t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) mc->chan + 'A');
        t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) mc->chan + 'A');
        t30_set_real_time_frame_handler(t30, real_time_frame_handler, (void *) (intptr_t) mc->chan + 'A');
        t30_set_document_handler(t30, document_handler, (void *) (intptr_t) mc->chan + 'A');
        sprintf(mc->tag, "FAX-%d", j + 1);

        logging = t30_get_logging_state(t30);
        span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
        span_log_set_tag(logging, mc->tag);
        if ((j & 1))
        {
            span_log_set_level(&t30->t4.rx.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
            span_log_set_tag(&t30->t4.rx.logging, mc->tag);
        }
        else
        {
            span_log_set_level(&t30->t4.tx.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
            span_log_set_tag(&t30->t4.tx.logging, mc->tag);
        }
        logging = fax_get_logging_state(mc->fax);
        span_log_set_level(logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME | SPAN_LOG_FLOW);
        span_log_set_tag(logging, mc->tag);

        memset(mc->amp, 0, sizeof(mc->amp));
        mc->total_audio_time = 0;
        mc->done = false;
    }
    time(&start_time);
    for (;;)
    {
        alldone = true;
        for (j = 0;  j < FAX_MACHINES;  j++)
        {
            mc = &machines[j];

            if ((j & 1) == 0  &&  input_audio_file_name)
            {
                mc->len = sf_readf_short(input_wave_handle, mc->amp, SAMPLES_PER_CHUNK);
                if (mc->len == 0)
                    break;
            }
            else
            {
                mc->len = fax_tx(mc->fax, mc->amp, SAMPLES_PER_CHUNK);
                if (mc->awgn)
                {
                    for (k = 0;  k < mc->len;  k++)
                        mc->amp[k] = ((int16_t) (mc->amp[k]*signal_scaling)) + awgn(mc->awgn);
                }
            }
            mc->total_audio_time += SAMPLES_PER_CHUNK;
            if (!use_transmit_on_idle)
            {
                /* The receive side always expects a full block of samples, but the
                   transmit side may not be sending any when it doesn't need to. We
                   may need to pad with some silence. */
                if (mc->len < SAMPLES_PER_CHUNK)
                {
                    memset(mc->amp + mc->len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - mc->len));
                    mc->len = SAMPLES_PER_CHUNK;
                }
            }
            t30 = fax_get_t30_state(mc->fax);
            logging = t30_get_logging_state(t30);
            span_log_bump_samples(logging, mc->len);
            logging = fax_get_logging_state(mc->fax);
            span_log_bump_samples(logging, mc->len);

            if (log_audio)
            {
                for (k = 0;  k < mc->len;  k++)
                    out_amp[2*k + j] = mc->amp[k];
            }
            if (machines[j ^ 1].len < SAMPLES_PER_CHUNK)
                memset(machines[j ^ 1].amp + machines[j ^ 1].len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - machines[j ^ 1].len));
            t30 = fax_get_t30_state(mc->fax);
#if defined(WITH_SPANDSP_INTERNALS)
            if (use_line_hits)
            {
                /* TODO: This applies very crude line hits. improve it */
                if (t30->state == 22)
                {
                    if (++mc->error_delay == 100)
                    {
                        fprintf(stderr, "HIT %d!\n", j);
                        mc->error_delay = 0;
                        for (k = 0;  k < 5;  k++)
                            mc->amp[k] = 0;
                    }
                }
            }
            if (t30->state == t30_state_to_wreck)
                memset(machines[j ^ 1].amp, 0, sizeof(int16_t)*SAMPLES_PER_CHUNK);
#endif
            if (fax_rx(mc->fax, machines[j ^ 1].amp, SAMPLES_PER_CHUNK))
                break;
            if (!mc->done)
                alldone = false;
        }

        if (log_audio)
        {
            outframes = sf_writef_short(wave_handle, out_amp, SAMPLES_PER_CHUNK);
            if (outframes != SAMPLES_PER_CHUNK)
                break;
        }

        if (alldone  ||  j < FAX_MACHINES)
            break;
    }
    time(&end_time);
    for (j = 0;  j < FAX_MACHINES;  j++)
    {
        mc = &machines[j];
        fax_release(mc->fax);
    }
    if (log_audio)
    {
        if (sf_close(wave_handle))
        {
            fprintf(stderr, "    Cannot close audio file '%s'\n", OUTPUT_FILE_NAME_WAVE);
            exit(2);
        }
    }
    if (input_audio_file_name)
    {
        if (sf_close(input_wave_handle))
        {
            fprintf(stderr, "    Cannot close audio file '%s'\n", input_audio_file_name);
            exit(2);
        }
    }
    printf("Total audio time = %ds (wall time %ds)\n", machines[0].total_audio_time/8000, (int) (end_time - start_time));
    return 0;
}
예제 #17
0
void client_run(int client_socket, char *local_ip, int local_port, char *remote_ip, int remote_port)
{
    char sendbuf[RCVBUFSIZE], recvbuf[RCVBUFSIZE], infobuf[RCVBUFSIZE];
	struct sockaddr_in addr = {0}, sendaddr = {0};
    int read_bytes;
	int usock;
	int reuse_addr = 1;
    fax_state_t fax;
	char tmp[512], fn[512], *file_name = "/tmp/test.tiff";
	int send_fax = FALSE;
	int g711 = 0;
	int pcmu = 0;

	snprintf(sendbuf, sizeof(sendbuf), "connect\n\n");
	send(client_socket, sendbuf, strlen(sendbuf), 0);

    if ((read_bytes = recv(client_socket, infobuf, sizeof(infobuf), 0)) < 0) {
        die("recv() failed");
	}

#if SOCKET2ME_DEBUG
	printf("READ [%s]\n", infobuf);
#endif

	if (cheezy_get_var(infobuf, "Channel-Read-Codec-Name", tmp, sizeof(tmp))) {
		if (!strcasecmp(tmp, "pcmu")) {
			g711 = 1;
			pcmu = 1;
		} else if (!strcasecmp(tmp, "pcma")) {
			g711 = 1;
		}
	}


	snprintf(sendbuf, sizeof(sendbuf), "sendmsg\n"
			 "call-command: unicast\n"
			 "local-ip: %s\n"
			 "local-port: %d\n"
			 "remote-ip: %s\n"
			 "remote-port: %d\n"
			 "transport: udp\n"
			 "%s"
			 "\n",
			 local_ip, local_port,
			 remote_ip, remote_port,
			 g711 ? "flags: native\n" : ""
			 );

	
	if (cheezy_get_var(infobuf, "variable_fax_file_name", fn, sizeof(fn))) {
		file_name = fn;
	}

	if (cheezy_get_var(infobuf, "variable_fax_mode", tmp, sizeof(tmp))) {
		if (!strcasecmp(tmp, "send")) {
			send_fax = TRUE;
		}
	}

	if (cheezy_get_var(infobuf, "variable_fax_preexec", tmp, sizeof(tmp))) {
	  set_vars(infobuf);
	  system(tmp);
	}

#if SOCKET2ME_DEBUG
	printf("SEND: [%s]\n", sendbuf);
#endif
	send(client_socket, sendbuf, strlen(sendbuf), 0);

	memset(recvbuf, 0, sizeof(recvbuf));
    if ((read_bytes = recv(client_socket, recvbuf, sizeof(recvbuf), 0)) < 0) {
        die("recv() failed");
	}
#if SOCKET2ME_DEBUG
	printf("READ [%s]\n", recvbuf);
#endif
	
	if ((usock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
        die("socket() failed");
	}

	setsockopt(usock, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, sizeof(reuse_addr));

    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    /*addr.sin_addr.s_addr = inet_addr(remote_ip);*/
    addr.sin_port = htons(remote_port);

    sendaddr.sin_family = AF_INET;
    sendaddr.sin_addr.s_addr = inet_addr(local_ip);
    sendaddr.sin_port = htons(local_port);
	
    if (bind(usock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
        die("bind() failed");
	}

	printf("%s Fax filename: [%s] from %s:%d -> %s:%d\n", send_fax ? "Sending" : "Receiving", file_name, local_ip, local_port, remote_ip, remote_port);
	
    fax_init(&fax, send_fax);
    t30_set_local_ident(&fax.t30_state, "Socket 2 ME");
    t30_set_header_info(&fax.t30_state, "Socket 2 ME");
	if (send_fax) {
		t30_set_tx_file(&fax.t30_state, file_name, -1, -1);
	} else {
		t30_set_rx_file(&fax.t30_state, file_name, -1);
	}
    t30_set_phase_b_handler(&fax.t30_state, phase_b_handler, NULL);
    t30_set_phase_d_handler(&fax.t30_state, phase_d_handler, NULL);
    t30_set_phase_e_handler(&fax.t30_state, phase_e_handler, NULL);
    t30_set_document_handler(&fax.t30_state, document_handler, NULL);

    t30_set_ecm_capability(&fax.t30_state, TRUE);
    t30_set_supported_compressions(&fax.t30_state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);

    t30_set_supported_image_sizes(&fax.t30_state, T30_SUPPORT_US_LETTER_LENGTH | T30_SUPPORT_US_LEGAL_LENGTH | T30_SUPPORT_UNLIMITED_LENGTH
                                  | T30_SUPPORT_215MM_WIDTH | T30_SUPPORT_255MM_WIDTH | T30_SUPPORT_303MM_WIDTH);
    t30_set_supported_resolutions(&fax.t30_state, T30_SUPPORT_STANDARD_RESOLUTION | T30_SUPPORT_FINE_RESOLUTION | T30_SUPPORT_SUPERFINE_RESOLUTION
                                  | T30_SUPPORT_R8_RESOLUTION | T30_SUPPORT_R16_RESOLUTION);

	for (;;) {
		struct sockaddr_in local_addr = {0};
        size_t cliAddrLen = sizeof(local_addr);
		unsigned char audiobuf[1024], rawbuf[1024], outbuf[1024];
		short *usebuf = NULL;
		int tx, tx_bytes, bigger, sample_count;
		fd_set ready;

		FD_ZERO(&ready);

		FD_SET(usock, &ready);
		FD_SET(client_socket, &ready);
		
		bigger = usock > client_socket ? usock : client_socket;
		select(++bigger, &ready, NULL, NULL, NULL);
		
		if (FD_ISSET(client_socket, &ready)) {
			memset(recvbuf, 0, sizeof(recvbuf));
			if ((read_bytes = recv(client_socket, recvbuf, sizeof(recvbuf), 0)) < 0) {
				die("recv() failed");
			}

			if (read_bytes == 0) {
				break;
			}
#if SOCKET2ME_DEBUG
			printf("READ [%s]\n", recvbuf);
#endif
		}

		if (!FD_ISSET(usock, &ready)) {
			continue;
		}

        if ((read_bytes = recvfrom(usock, audiobuf, sizeof(audiobuf), 0, (struct sockaddr *) &local_addr, &cliAddrLen)) < 0) {
			die("recvfrom() failed");
		}

		if (g711) {
			int i;
			short *rp = (short *) rawbuf;
			
			for (i = 0; i < read_bytes; i++) {
				if (pcmu) {
					rp[i] = ulaw_to_linear(audiobuf[i]);
				} else {
					rp[i] = alaw_to_linear(audiobuf[i]);
				}
			}
			usebuf = rp;
			sample_count = read_bytes;
		} else {
			usebuf = (short *) audiobuf;
			sample_count = read_bytes / 2;
		}
		
		fax_rx(&fax, usebuf, sample_count);
#if SOCKET2ME_DEBUG
		printf("Handling client %s:%d %d bytes\n", inet_ntoa(local_addr.sin_addr), ntohs(local_addr.sin_port), read_bytes);
#endif

		
		if ((tx = fax_tx(&fax, (short *)outbuf, sample_count)) < 0) {
            printf("Fax Error\n");
			break;
        } else if (!tx) {
			continue;
		}
		

		if (g711) {
			int i;
			short *bp = (short *) outbuf;
			for (i = 0; i < tx; i++) {
				if (pcmu) {
					rawbuf[i] = linear_to_ulaw(bp[i]);
				} else {
					rawbuf[i] = linear_to_alaw(bp[i]);
				}
			}
			usebuf = (short *) rawbuf;
			tx_bytes = tx;
		} else {
			usebuf = (short *)outbuf;
			tx_bytes = tx * 2;
		}	
		

		cliAddrLen = sizeof(sendaddr);
        if (sendto(usock, usebuf, tx_bytes, 0, (struct sockaddr *) &sendaddr, sizeof(sendaddr)) != tx_bytes) {
			die("sendto() sent a different number of bytes than expected");
		}
	}

	close(client_socket);
	close(usock);
		
    t30_terminate(&fax.t30_state);
    fax_release(&fax);

    if (cheezy_get_var(infobuf, "variable_fax_postexec", tmp, sizeof(tmp))) {
      set_vars(infobuf);
      system(tmp);
    }
	printf("Done\n");
	snprintf(sendbuf, sizeof(sendbuf), "hangup\n\n");
	send(client_socket, sendbuf, strlen(sendbuf), 0);
	
}
예제 #18
0
int main(int argc, char *argv[])
{
    int msg_len;
    uint8_t msg[1024];
    int t38_version;
    int i;
    int seq_no;
    int use_ecm;
    int without_pacing;
    const char *input_file_name;
    
    t38_version = 1;
    without_pacing = FALSE;
    input_file_name = INPUT_FILE_NAME;
    use_ecm = FALSE;
    simulate_incrementing_repeats = FALSE;
    for (i = 1;  i < argc;  i++)
    {
        if (strcmp(argv[i], "-e") == 0)
        {
            use_ecm = TRUE;
            continue;
        }
        if (strcmp(argv[i], "-i") == 0)
        {
            i++;
            input_file_name = argv[i];
            continue;
        }
        if (strcmp(argv[i], "-I") == 0)
        {
            simulate_incrementing_repeats = TRUE;
            continue;
        }
        if (strcmp(argv[i], "-p") == 0)
        {
            without_pacing = TRUE;
            continue;
        }
        if (strcmp(argv[i], "-v") == 0)
        {
            i++;
            t38_version = atoi(argv[i]);
            continue;
        }
    }

    printf("Using T.38 version %d\n", t38_version);
    if (use_ecm)
        printf("Using ECM\n");

    if ((path_a_to_b = ip_network_model_init(800, 2000, 0)) == NULL)
    {
        fprintf(stderr, "Failed to start IP network path model\n");
        exit(2);
    }
    if ((path_b_to_a = ip_network_model_init(800, 2000, 0)) == NULL)
    {
        fprintf(stderr, "Failed to start IP network path model\n");
        exit(2);
    }

    if (t38_terminal_init(&t38_state_a, TRUE, tx_packet_handler_a, &t38_state_b) == NULL)
    {
        fprintf(stderr, "Cannot start the T.38 channel\n");
        exit(2);
    }
    t38_set_t38_version(&t38_state_a.t38, t38_version);
    t38_terminal_set_config(&t38_state_a, without_pacing);
    span_log_set_level(&t38_state_a.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(&t38_state_a.logging, "T.38-A");
    span_log_set_level(&t38_state_a.t38.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(&t38_state_a.t38.logging, "T.38-A");
    span_log_set_level(&t38_state_a.t30_state.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(&t38_state_a.t30_state.logging, "T.38-A");

    t30_set_local_ident(&t38_state_a.t30_state, "11111111");
    t30_set_tx_file(&t38_state_a.t30_state, input_file_name, -1, -1);
    t30_set_phase_b_handler(&t38_state_a.t30_state, phase_b_handler, (void *) (intptr_t) 'A');
    t30_set_phase_d_handler(&t38_state_a.t30_state, phase_d_handler, (void *) (intptr_t) 'A');
    t30_set_phase_e_handler(&t38_state_a.t30_state, phase_e_handler, (void *) (intptr_t) 'A');
    t30_set_ecm_capability(&t38_state_a.t30_state, use_ecm);
    if (use_ecm)
        t30_set_supported_compressions(&t38_state_a.t30_state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);

    if (t38_terminal_init(&t38_state_b, FALSE, tx_packet_handler_b, &t38_state_a) == NULL)
    {
        fprintf(stderr, "Cannot start the T.38 channel\n");
        exit(2);
    }
    t38_set_t38_version(&t38_state_b.t38, t38_version);
    t38_terminal_set_config(&t38_state_b, without_pacing);
    span_log_set_level(&t38_state_b.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(&t38_state_b.logging, "T.38-B");
    span_log_set_level(&t38_state_b.t38.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(&t38_state_b.t38.logging, "T.38-B");
    span_log_set_level(&t38_state_b.t30_state.logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(&t38_state_b.t30_state.logging, "T.38-B");

    t30_set_local_ident(&t38_state_b.t30_state, "22222222");
    t30_set_rx_file(&t38_state_b.t30_state, OUTPUT_FILE_NAME, -1);
    t30_set_phase_b_handler(&t38_state_b.t30_state, phase_b_handler, (void *) (intptr_t) 'B');
    t30_set_phase_d_handler(&t38_state_b.t30_state, phase_d_handler, (void *) (intptr_t) 'B');
    t30_set_phase_e_handler(&t38_state_b.t30_state, phase_e_handler, (void *) (intptr_t) 'B');
    t30_set_ecm_capability(&t38_state_b.t30_state, use_ecm);
    if (use_ecm)
        t30_set_supported_compressions(&t38_state_b.t30_state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);

    for (;;)
    {
        span_log_bump_samples(&t38_state_a.logging, SAMPLES_PER_CHUNK);
        span_log_bump_samples(&t38_state_a.t38.logging, SAMPLES_PER_CHUNK);
        span_log_bump_samples(&t38_state_a.t30_state.logging, SAMPLES_PER_CHUNK);
        span_log_bump_samples(&t38_state_b.logging, SAMPLES_PER_CHUNK);
        span_log_bump_samples(&t38_state_b.t38.logging, SAMPLES_PER_CHUNK);
        span_log_bump_samples(&t38_state_b.t30_state.logging, SAMPLES_PER_CHUNK);

        done[0] = t38_terminal_send_timeout(&t38_state_a, SAMPLES_PER_CHUNK);
        done[1] = t38_terminal_send_timeout(&t38_state_b, SAMPLES_PER_CHUNK);

        while ((msg_len = ip_network_model_get(path_a_to_b, SAMPLES_PER_CHUNK, msg, 1024, &seq_no)) >= 0)
        {
            t38_core_rx_ifp_packet(&t38_state_b.t38, seq_no, msg, msg_len);
        }
        while ((msg_len = ip_network_model_get(path_b_to_a, SAMPLES_PER_CHUNK, msg, 1024, &seq_no)) >= 0)
        {
            t38_core_rx_ifp_packet(&t38_state_a.t38, seq_no, msg, msg_len);
        }
        if (done[0]  &&  done[1])
            break;
    }
    if (!succeeded[0]  ||  !succeeded[1])
    {
        printf("Tests failed\n");
        exit(2);
    }
    printf("Tests passed\n");
    return  0;
}
예제 #19
0
static int t30_tests(int t38_mode, int use_gui, int log_audio, int test_sending, int g1050_model_no, int g1050_speed_pattern_no)
{
    t38_terminal_state_t *t38_state;
    fax_state_t *fax_state;
    int fast_send;
    int fast_send_tcf;
    int fast_blocks;
    int msg_len;
    int t30_len;
    int t31_len;
    int t38_version;
    int without_pacing;
    int use_tep;
    int seq_no;
    int i;
    int k;
    int outframes;
    uint8_t fast_buf[1000];
    uint8_t msg[1024];
    double tx_when;
    double rx_when;
    t30_state_t *t30;
    t38_core_state_t *t38_core;
    logging_state_t *logging;
    int16_t t30_amp[SAMPLES_PER_CHUNK];
    int16_t t31_amp[SAMPLES_PER_CHUNK];
    int16_t silence[SAMPLES_PER_CHUNK];
    int16_t out_amp[2*SAMPLES_PER_CHUNK];
    SNDFILE *wave_handle;
    SNDFILE *in_handle;

    /* Test the T.31 modem against the full FAX machine in spandsp */

    /* Set up the test environment */
    t38_version = 1;
    without_pacing = false;
    use_tep = false;

    wave_handle = NULL;
    if (log_audio)
    {
        if ((wave_handle = sf_open_telephony_write(OUTPUT_WAVE_FILE_NAME, 2)) == NULL)
        {
            fprintf(stderr, "    Cannot create audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
            exit(2);
        }
    }

    in_handle = NULL;
    if (decode_test_file)
    {
        if ((in_handle = sf_open_telephony_read(decode_test_file, 1)) == NULL)
        {
            fprintf(stderr, "    Cannot create audio file '%s'\n", decode_test_file);
            exit(2);
        }
    }

    srand48(0x1234567);
    if ((path_a_to_b = g1050_init(g1050_model_no, g1050_speed_pattern_no, 100, 33)) == NULL)
    {
        fprintf(stderr, "Failed to start IP network path model\n");
        exit(2);
    }
    if ((path_b_to_a = g1050_init(g1050_model_no, g1050_speed_pattern_no, 100, 33)) == NULL)
    {
        fprintf(stderr, "Failed to start IP network path model\n");
        exit(2);
    }

    t38_state = NULL;
    fax_state = NULL;
    if (test_sending)
    {
        if (t38_mode)
        {
            if ((t38_state = t38_terminal_init(NULL, false, t38_tx_packet_handler, t31_state)) == NULL)
            {
                fprintf(stderr, "Cannot start the T.38 channel\n");
                exit(2);
            }
            t30 = t38_terminal_get_t30_state(t38_state);
        }
        else
        {
            fax_state = fax_init(NULL, false);
            t30 = fax_get_t30_state(fax_state);
        }
        t30_set_rx_file(t30, OUTPUT_FILE_NAME, -1);
        fax_test_seq = fax_send_test_seq;
        countdown = 0;
    }
    else
    {
        if (t38_mode)
        {
            if ((t38_state = t38_terminal_init(NULL, true, t38_tx_packet_handler, t31_state)) == NULL)
            {
                fprintf(stderr, "Cannot start the T.38 channel\n");
                exit(2);
            }
            t30 = t38_terminal_get_t30_state(t38_state);
        }
        else
        {
            fax_state = fax_init(NULL, true);
            t30 = fax_get_t30_state(fax_state);
        }
        t30_set_tx_file(t30, INPUT_FILE_NAME, -1, -1);
        fax_test_seq = fax_receive_test_seq;
        countdown = 250;
    }

    if (t38_mode)
    {
        t38_core = t38_terminal_get_t38_core_state(t38_state);
        t38_set_t38_version(t38_core, t38_version);
        t38_terminal_set_config(t38_state, without_pacing);
        t38_terminal_set_tep_mode(t38_state, use_tep);
    }

    t30_set_tx_ident(t30, "11111111");
    t30_set_supported_modems(t30, T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17);
    //t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12);
    t30_set_phase_b_handler(t30, phase_b_handler, (void *) 'A');
    t30_set_phase_d_handler(t30, phase_d_handler, (void *) 'A');
    t30_set_phase_e_handler(t30, phase_e_handler, (void *) 'A');

    if (t38_mode)
        logging = t38_terminal_get_logging_state(t38_state);
    else
        logging = t30_get_logging_state(t30);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, (t38_mode)  ?  "T.38"  :  "FAX");

    if (t38_mode)
    {
        t38_core = t38_terminal_get_t38_core_state(t38_state);
        span_log_set_level(&t38_core->logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
        span_log_set_tag(&t38_core->logging, "T.38");

        logging = t30_get_logging_state(t30);
        span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
        span_log_set_tag(logging, "T.38");
    }
    else
    {
        logging = fax_get_logging_state(fax_state);
        span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
        span_log_set_tag(logging, "FAX");
    }

    memset(silence, 0, sizeof(silence));
    memset(t30_amp, 0, sizeof(t30_amp));

    /* Now set up and run the T.31 modem */
    if ((t31_state = t31_init(NULL, at_tx_handler, NULL, modem_call_control, NULL, t31_tx_packet_handler, NULL)) == NULL)
    {
        fprintf(stderr, "    Cannot start the T.31 modem\n");
        exit(2);
    }
    logging = t31_get_logging_state(t31_state);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, "T.31");

    logging = at_get_logging_state(t31_get_at_state(t31_state));
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, "T.31");

    if (t38_mode)
    {
        t38_core = t31_get_t38_core_state(t31_state);
        logging = t38_core_get_logging_state(t38_core);
        span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
        span_log_set_tag(logging, "T.31");

        t31_set_mode(t31_state, true);
        t38_set_t38_version(t38_core, t38_version);
    }

    fast_send = false;
    fast_send_tcf = true;
    fast_blocks = 0;
    kick = true;
#if defined(ENABLE_GUI)
    if (use_gui)
        start_media_monitor();
#endif
    while (!done)
    {
        if (countdown)
        {
            /* Deal with call setup, through the AT interface. */
            if (answered)
            {
                countdown = 0;
                t31_call_event(t31_state, AT_CALL_EVENT_ANSWERED);
            }
            else if (--countdown == 0)
            {
                t31_call_event(t31_state, AT_CALL_EVENT_ALERTING);
                countdown = 250;
            }
        }

        if (kick)
        {
            /* Work through the script */
            kick = false;
            if (fax_test_seq[test_seq_ptr].command > (const char *) 2)
            {
                if (fax_test_seq[test_seq_ptr].command[0])
                {
                    printf("%s\n", fax_test_seq[test_seq_ptr].command);
                    t31_at_rx(t31_state, fax_test_seq[test_seq_ptr].command, fax_test_seq[test_seq_ptr].len_command);
                }
            }
            else
            {
                if (fax_test_seq[test_seq_ptr].command == (const char *) 2)
                {
                    printf("Fast send TCF\n");
                    fast_send = true;
                    fast_send_tcf = true;
                    fast_blocks = 100;
                }
                else
                {
                    printf("Fast send image\n");
                    fast_send = true;
                    fast_send_tcf = false;
                    fast_blocks = 100;
                }
            }
        }
        if (fast_send)
        {
            /* Send fast modem data */
            if (fast_send_tcf)
            {
                /* If we are sending TCF, its simply zeros */
                memset(fast_buf, 0, 36);
                if (fast_blocks == 1)
                {
                    /* Tell the modem this is the end of the TCF data */
                    fast_buf[34] = DLE;
                    fast_buf[35] = ETX;
                }
            }
            else
            {
                /* If we are sending image data, we need to make it look like genuine image data,
                   with proper EOL and RTC markers. */
                if (fast_blocks > 1)
                {
                    /* Create a chunk of white page, 1728 pixels wide. */
                    for (i = 0;  i < 36;  i += 4)
                    {
                        fast_buf[i] = 0x00;
                        fast_buf[i + 1] = 0x80;
                        fast_buf[i + 2] = 0xB2;
                        fast_buf[i + 3] = 0x01;
                    }
                }
                else
                {
                    /* Create the end of page condition. */
                    for (i = 0;  i < 36;  i += 3)
                    {
                        fast_buf[i] = 0x00;
                        fast_buf[i + 1] = 0x08;
                        fast_buf[i + 2] = 0x80;
                    }
                    /* Tell the modem this is the end of the image data. */
                    fast_buf[34] = DLE;
                    fast_buf[35] = ETX;
                }
            }
            t31_at_rx(t31_state, (char *) fast_buf, 36);
            if (--fast_blocks == 0)
                fast_send = false;
        }

        if (t38_mode)
        {
            while ((msg_len = g1050_get(path_a_to_b, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0)
            {
#if defined(ENABLE_GUI)
                if (use_gui)
                    media_monitor_rx(seq_no, tx_when, rx_when);
#endif
                t38_core = t31_get_t38_core_state(t31_state);
                t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no);
            }
            while ((msg_len = g1050_get(path_b_to_a, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0)
            {
#if defined(ENABLE_GUI)
                if (use_gui)
                    media_monitor_rx(seq_no, tx_when, rx_when);
#endif
                t38_core = t38_terminal_get_t38_core_state(t38_state);
                t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no);
            }
#if defined(ENABLE_GUI)
            if (use_gui)
                media_monitor_update_display();
#endif
            /* Bump the G.1050 models along */
            when += (float) SAMPLES_PER_CHUNK/(float) SAMPLE_RATE;

            /* Bump things along on the t38_terminal side */
            span_log_bump_samples(t38_terminal_get_logging_state(t38_state), SAMPLES_PER_CHUNK);
            t38_core = t38_terminal_get_t38_core_state(t38_state);
            span_log_bump_samples(t38_core_get_logging_state(t38_core), SAMPLES_PER_CHUNK);

            t38_terminal_send_timeout(t38_state, SAMPLES_PER_CHUNK);
            t31_t38_send_timeout(t31_state, SAMPLES_PER_CHUNK);
        }
        else
        {
            t30_len = fax_tx(fax_state, t30_amp, SAMPLES_PER_CHUNK);
            /* The receive side always expects a full block of samples, but the
               transmit side may not be sending any when it doesn't need to. We
               may need to pad with some silence. */
            if (t30_len < SAMPLES_PER_CHUNK)
            {
                memset(t30_amp + t30_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t30_len));
                t30_len = SAMPLES_PER_CHUNK;
            }
            if (log_audio)
            {
                for (k = 0;  k < t30_len;  k++)
                    out_amp[2*k] = t30_amp[k];
            }
            if (t31_rx(t31_state, t30_amp, t30_len))
                break;
            t31_len = t31_tx(t31_state, t31_amp, SAMPLES_PER_CHUNK);
            if (t31_len < SAMPLES_PER_CHUNK)
            {
                memset(t31_amp + t31_len, 0, sizeof(int16_t)*(SAMPLES_PER_CHUNK - t31_len));
                t31_len = SAMPLES_PER_CHUNK;
            }
            if (log_audio)
            {
                for (k = 0;  k < t31_len;  k++)
                    out_amp[2*k + 1] = t31_amp[k];
            }
            if (fax_rx(fax_state, t31_amp, SAMPLES_PER_CHUNK))
                break;

            if (log_audio)
            {
                outframes = sf_writef_short(wave_handle, out_amp, SAMPLES_PER_CHUNK);
                if (outframes != SAMPLES_PER_CHUNK)
                    break;
            }

            /* Bump things along on the FAX machine side */
            span_log_bump_samples(fax_get_logging_state(fax_state), SAMPLES_PER_CHUNK);
        }

        /* Bump things along on the FAX machine side */
        span_log_bump_samples(t30_get_logging_state(t30), SAMPLES_PER_CHUNK);

        /* Bump things along on the T.31 modem side */
        t38_core = t31_get_t38_core_state(t31_state);
        span_log_bump_samples(t38_core_get_logging_state(t38_core), SAMPLES_PER_CHUNK);
        span_log_bump_samples(t31_get_logging_state(t31_state), SAMPLES_PER_CHUNK);
        span_log_bump_samples(at_get_logging_state(t31_get_at_state(t31_state)), SAMPLES_PER_CHUNK);
    }

    if (t38_mode)
        t38_terminal_release(t38_state);

    if (decode_test_file)
    {
        if (sf_close_telephony(in_handle))
        {
            fprintf(stderr, "    Cannot close audio file '%s'\n", decode_test_file);
            exit(2);
        }
    }
    if (log_audio)
    {
        if (sf_close_telephony(wave_handle))
        {
            fprintf(stderr, "    Cannot close audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
            exit(2);
        }
    }

    if (!done  ||  !sequence_terminated)
    {
        printf("Tests failed\n");
        return -1;
    }

    return 0;
}
예제 #20
0
static int txfax_exec(struct ast_channel *chan, void *data)
{
    int res = 0;
    char source_file[256];
    char *x;
    char *s;
    char *t;
    char *v;
    int option;
    int len;
    t30_state_t fax;
    int calling_party;
    int verbose;
    int samples;
    
    struct localuser *u;
    struct ast_frame *inf = NULL;
    struct ast_frame outf;

    int original_read_fmt;
    int original_write_fmt;
    
    uint8_t __buf[sizeof(uint16_t)*MAX_BLOCK_SIZE + 2*AST_FRIENDLY_OFFSET];
    uint8_t *buf = __buf + AST_FRIENDLY_OFFSET;

    if (chan == NULL)
    {
        ast_log(LOG_WARNING, "Fax transmit channel is NULL. Giving up.\n");
        return -1;
    }

    span_set_message_handler(span_message);

    /* The next few lines of code parse out the filename and header from the input string */
    if (data == NULL)
    {
        /* No data implies no filename or anything is present */
        ast_log(LOG_WARNING, "Txfax requires an argument (filename)\n");
        return -1;
    }
    
    calling_party = FALSE;
    verbose = FALSE;
    source_file[0] = '\0'; 

    for (option = 0, v = s = data;  v;  option++, s++)
    {
        t = s;
        v = strchr(s, '|');
        s = (v)  ?  v  :  s + strlen(s);
        strncpy((char *) buf, t, s - t);
        buf[s - t] = '\0';
        if (option == 0)
        {
            /* The first option is always the file name */
            len = s - t;
            if (len > 255)
                len = 255;
            strncpy(source_file, t, len);
            source_file[len] = '\0';
        }
        else if (strncmp("caller", t, s - t) == 0)
        {
            calling_party = TRUE;
        }
        else if (strncmp("debug", t, s - t) == 0)
        {
            verbose = TRUE;
        }
    }

    /* Done parsing */

    LOCAL_USER_ADD(u);

    if (chan->_state != AST_STATE_UP)
    {
        /* Shouldn't need this, but checking to see if channel is already answered
         * Theoretically asterisk should already have answered before running the app */
        res = ast_answer(chan);
    }
    
    if (!res)
    {
        original_read_fmt = chan->readformat;
        if (original_read_fmt != AST_FORMAT_SLINEAR)
        {
            res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
            if (res < 0)
            {
                ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
                return -1;
            }
        }
        original_write_fmt = chan->writeformat;
        if (original_write_fmt != AST_FORMAT_SLINEAR)
        {
            res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
            if (res < 0)
            {
                ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
                res = ast_set_read_format(chan, original_read_fmt);
                if (res)
                    ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
                return -1;
            }
        }
        fax_init(&fax, calling_party, NULL);
        if (verbose)
	    fax.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;

        x = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
        if (x  &&  x[0])
            t30_set_local_ident(&fax, x);
        x = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO");
        if (x  &&  x[0])
            t30_set_header_info(&fax, x);
        t30_set_tx_file(&fax, source_file, -1, -1);
        //t30_set_phase_b_handler(&fax, phase_b_handler, chan);
        //t30_set_phase_d_handler(&fax, phase_d_handler, chan);
        t30_set_phase_e_handler(&fax, phase_e_handler, chan);
        while (ast_waitfor(chan, -1) > -1)
        {
            inf = ast_read(chan);
            if (inf == NULL)
            {
                res = -1;
                break;
            }
            if (inf->frametype == AST_FRAME_VOICE)
            {
                if (fax_rx(&fax, inf->data, inf->samples))
                    break;
                samples = (inf->samples <= MAX_BLOCK_SIZE)  ?  inf->samples  :  MAX_BLOCK_SIZE;
                len = fax_tx(&fax, (int16_t *) &buf[AST_FRIENDLY_OFFSET], samples);
                if (len)
                {
                    memset(&outf, 0, sizeof(outf));
                    outf.frametype = AST_FRAME_VOICE;
                    outf.subclass = AST_FORMAT_SLINEAR;
                    outf.datalen = len*sizeof(int16_t);
                    outf.samples = len;
                    outf.data = &buf[AST_FRIENDLY_OFFSET];
                    outf.offset = AST_FRIENDLY_OFFSET;
                    if (ast_write(chan, &outf) < 0)
                    {
                        ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno));
                        break;
                    }
                }
            }
            ast_frfree(inf);
        }
        if (inf == NULL)
        {
            ast_log(LOG_DEBUG, "Got hangup\n");
            res = -1;
        }
        if (original_read_fmt && original_read_fmt != AST_FORMAT_SLINEAR)
        {
            res = ast_set_read_format(chan, original_read_fmt);
            if (res)
                ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
        }
        if (original_write_fmt && original_write_fmt != AST_FORMAT_SLINEAR)
        {
            res = ast_set_write_format(chan, original_write_fmt);
            if (res)
                ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", chan->name);
        }
        fax_release(&fax);
    }
    else
    {
        ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
    }
    LOCAL_USER_REMOVE(u);
    return res;
}
예제 #21
0
int main(int argc, char *argv[])
{
    int msg_len;
    uint8_t msg[1024];
    int t38_version;
    int seq_no;
    int use_ecm;
    int without_pacing;
    int use_tep;
    int model_no;
    int speed_pattern_no;
    const char *input_file_name;
    double tx_when;
    double rx_when;
    int use_gui;
    int supported_modems;
    int opt;
    t30_state_t *t30;
    t38_core_state_t *t38_core;
    logging_state_t *logging;

    t38_version = 1;
    without_pacing = FALSE;
    use_tep = FALSE;
    input_file_name = INPUT_FILE_NAME;
    use_ecm = FALSE;
    simulate_incrementing_repeats = FALSE;
    model_no = 0;
    speed_pattern_no = 1;
    use_gui = FALSE;
    supported_modems = T30_SUPPORT_V27TER | T30_SUPPORT_V29 | T30_SUPPORT_V17;
    while ((opt = getopt(argc, argv, "efgi:Im:M:ps:tv:")) != -1)
    {
        switch (opt)
        {
        case 'e':
            use_ecm = TRUE;
            break;
        case 'g':
#if defined(ENABLE_GUI)
            use_gui = TRUE;
#else
            fprintf(stderr, "Graphical monitoring not available\n");
            exit(2);
#endif
            break;
        case 'i':
            input_file_name = optarg;
            break;
        case 'I':
            simulate_incrementing_repeats = TRUE;
            break;
        case 'm':
            supported_modems = atoi(optarg);
            break;
        case 'M':
            model_no = optarg[0] - 'A' + 1;
            break;
        case 'p':
            without_pacing = TRUE;
            break;
        case 's':
            speed_pattern_no = atoi(optarg);
            break;
        case 't':
            use_tep = TRUE;
            break;
        case 'v':
            t38_version = atoi(optarg);
            break;
        default:
            //usage();
            exit(2);
            break;
        }
    }

    printf("Using T.38 version %d\n", t38_version);
    if (use_ecm)
        printf("Using ECM\n");

    srand48(0x1234567);
    if ((path_a_to_b = g1050_init(model_no, speed_pattern_no, 100, 33)) == NULL)
    {
        fprintf(stderr, "Failed to start IP network path model\n");
        exit(2);
    }
    if ((path_b_to_a = g1050_init(model_no, speed_pattern_no, 100, 33)) == NULL)
    {
        fprintf(stderr, "Failed to start IP network path model\n");
        exit(2);
    }

    if ((t38_state_a = t38_terminal_init(NULL, TRUE, tx_packet_handler_a, t38_state_b)) == NULL)
    {
        fprintf(stderr, "Cannot start the T.38 channel\n");
        exit(2);
    }
    t30 = t38_terminal_get_t30_state(t38_state_a);
    t38_core = t38_terminal_get_t38_core_state(t38_state_a);
    t38_set_t38_version(t38_core, t38_version);
    t38_terminal_set_config(t38_state_a, without_pacing);
    t38_terminal_set_tep_mode(t38_state_a, use_tep);
    
    logging = t38_terminal_get_logging_state(t38_state_a);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, "T.38-A");

    logging = t38_core_get_logging_state(t38_core);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, "T.38-A");

    logging = t30_get_logging_state(t30);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, "T.38-A");

    t30_set_supported_modems(t30, supported_modems);
    t30_set_tx_ident(t30, "11111111");
    t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12);
    t30_set_tx_file(t30, input_file_name, -1, -1);
    t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) 'A');
    t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'A');
    t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'A');
    t30_set_ecm_capability(t30, use_ecm);
    if (use_ecm)
        t30_set_supported_compressions(t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);

    if ((t38_state_b = t38_terminal_init(NULL, FALSE, tx_packet_handler_b, t38_state_a)) == NULL)
    {
        fprintf(stderr, "Cannot start the T.38 channel\n");
        exit(2);
    }
    t30 = t38_terminal_get_t30_state(t38_state_b);
    t38_core = t38_terminal_get_t38_core_state(t38_state_b);
    t38_set_t38_version(t38_core, t38_version);
    t38_terminal_set_config(t38_state_b, without_pacing);
    t38_terminal_set_tep_mode(t38_state_b, use_tep);

    logging = t38_terminal_get_logging_state(t38_state_b);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, "T.38-B");

    logging = t38_core_get_logging_state(t38_core);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, "T.38-B");

    logging = t30_get_logging_state(t30);
    span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_SAMPLE_TIME);
    span_log_set_tag(logging, "T.38-B");

    t30_set_supported_modems(t30, supported_modems);
    t30_set_tx_ident(t30, "22222222");
    t30_set_tx_nsf(t30, (const uint8_t *) "\x50\x00\x00\x00Spandsp\x00", 12);
    t30_set_rx_file(t30, OUTPUT_FILE_NAME, -1);
    t30_set_phase_b_handler(t30, phase_b_handler, (void *) (intptr_t) 'B');
    t30_set_phase_d_handler(t30, phase_d_handler, (void *) (intptr_t) 'B');
    t30_set_phase_e_handler(t30, phase_e_handler, (void *) (intptr_t) 'B');
    t30_set_ecm_capability(t30, use_ecm);
    if (use_ecm)
        t30_set_supported_compressions(t30, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);

#if defined(ENABLE_GUI)
    if (use_gui)
        start_media_monitor();
#endif
    for (;;)
    {
        logging = t38_terminal_get_logging_state(t38_state_a);
        span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
        t38_core = t38_terminal_get_t38_core_state(t38_state_a);
        logging = t38_core_get_logging_state(t38_core);
        span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
        t30 = t38_terminal_get_t30_state(t38_state_a);
        logging = t30_get_logging_state(t30);
        span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
        logging = t38_terminal_get_logging_state(t38_state_b);
        span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
        t38_core = t38_terminal_get_t38_core_state(t38_state_b);
        logging = t38_core_get_logging_state(t38_core);
        span_log_bump_samples(logging, SAMPLES_PER_CHUNK);
        t30 = t38_terminal_get_t30_state(t38_state_b);
        logging = t30_get_logging_state(t30);
        span_log_bump_samples(logging, SAMPLES_PER_CHUNK);

        done[0] = t38_terminal_send_timeout(t38_state_a, SAMPLES_PER_CHUNK);
        done[1] = t38_terminal_send_timeout(t38_state_b, SAMPLES_PER_CHUNK);

        when += (float) SAMPLES_PER_CHUNK/(float) SAMPLE_RATE;

        while ((msg_len = g1050_get(path_a_to_b, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0)
        {
#if defined(ENABLE_GUI)
            if (use_gui)
                media_monitor_rx(seq_no, tx_when, rx_when);
#endif
            t38_core = t38_terminal_get_t38_core_state(t38_state_b);
            t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no);
        }
        while ((msg_len = g1050_get(path_b_to_a, msg, 1024, when, &seq_no, &tx_when, &rx_when)) >= 0)
        {
#if defined(ENABLE_GUI)
            if (use_gui)
                media_monitor_rx(seq_no, tx_when, rx_when);
#endif
            t38_core = t38_terminal_get_t38_core_state(t38_state_a);
            t38_core_rx_ifp_packet(t38_core, msg, msg_len, seq_no);
        }
        if (done[0]  &&  done[1])
            break;
#if defined(ENABLE_GUI)
        if (use_gui)
            media_monitor_update_display();
#endif
    }
    t38_terminal_release(t38_state_a);
    t38_terminal_release(t38_state_b);
    if (!succeeded[0]  ||  !succeeded[1])
    {
        printf("Tests failed\n");
        exit(2);
    }
    printf("Tests passed\n");
    return  0;
}