home *** CD-ROM | disk | FTP | other *** search
/ Software Recommendations - 1998 Season 1 / DNBCD4.iso / share / DOS / ipxcopy / SRC.ZIP / SRC / TPTX.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-16  |  26.4 KB  |  1,047 lines

  1. /*
  2.  
  3.    TPTX.C
  4.  
  5.    (c) 1996 by Oliver Kraus
  6.  
  7. */
  8.  
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <conio.h>
  12. #include <assert.h>
  13. #include <dos.h>
  14. #include <fcntl.h>
  15. #include "tptx.h"
  16. #include "crc16.h"
  17. #include "crc32.h"
  18. /* #include "debugmem.h" */
  19.  
  20. #define TPTX_ID_STR "transmitter: "
  21.  
  22. char *tptx_es_ipx_not_found     = TPTX_ID_STR "ipx not found";
  23. char *tptx_es_socket_table_full = TPTX_ID_STR "socket table full";
  24. char *tptx_es_socket_open       = TPTX_ID_STR "socket already open";
  25. char *tptx_es_out_of_memory     = TPTX_ID_STR "out of memory";
  26.  
  27. /* - - - - - state prototypes  - - - - - - - - - - - - - - - - - - - - - - */
  28.  
  29. void tptx_state_none(tptx_type tptx);
  30. void tptx_state_gen_request(tptx_type tptx);
  31. void tptx_state_chk_request(tptx_type tptx);
  32. void tptx_state_wait_ack_request(tptx_type tptx);
  33. void tptx_state_user_check(tptx_type tptx);
  34. void tptx_state_gen_file_start(tptx_type tptx);
  35. void tptx_state_chk_file_start(tptx_type tptx);
  36. void tptx_state_wait_ack_file_start(tptx_type tptx);
  37. void tptx_state_gen_block_start(tptx_type tptx);
  38. void tptx_state_chk_block_start(tptx_type tptx);
  39. void tptx_state_wait_ack_block_start(tptx_type tptx);
  40. void tptx_state_gen_data(tptx_type tptx);
  41. void tptx_state_chk_data(tptx_type tptx);
  42. void tptx_state_gen_block_end(tptx_type tptx);
  43. void tptx_state_chk_block_end(tptx_type tptx);
  44. void tptx_state_wait_ack_block_end(tptx_type tptx);
  45. void tptx_state_gen_file_end(tptx_type tptx);
  46. void tptx_state_chk_file_end(tptx_type tptx);
  47. void tptx_state_wait_ack_file_end(tptx_type tptx);
  48.  
  49. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  50.  
  51. /*
  52.    allocate pool memory
  53. */
  54. int tptx_OpenPool(tptx_type tptx, size_t b_len, int b_cnt)
  55. {
  56.    int i;
  57.  
  58.    /* check against 16 bit system */
  59.  
  60.    if ( (long)b_len*(long)b_cnt > 65500 )
  61.       return 1;
  62.  
  63.    /* assign parameter */
  64.  
  65.    tptx->b_len = b_len;
  66.    tptx->b_cnt = b_cnt;
  67.    tptx->tx_cnt = b_cnt+TPTX_TX_ADD;
  68.    tptx->b_pool_size = b_cnt*b_len;
  69.  
  70.    /* data buffers for ipx listen process */
  71.  
  72.    tptx->tx_data = (char **)malloc(tptx->tx_cnt*sizeof(char *));
  73.    if ( tptx->tx_data != NULL )
  74.    {
  75.       for( i = 0; i < tptx->tx_cnt; i++ )
  76.          tptx->tx_data[i] = (char *)malloc(tptx->b_len+TP_BLK_INFO_SIZE);
  77.       for( i = 0; i < tptx->tx_cnt; i++ )
  78.          if ( tptx->tx_data[i] == NULL )
  79.             break;
  80.       if ( i >= tptx->tx_cnt )
  81.       {
  82.  
  83.    /* allocate ipx ecb data buffers */
  84.  
  85.          tptx->tx_ecb = (ipx_ecb_struct **)malloc(tptx->tx_cnt*sizeof(ipx_ecb_struct *));
  86.          if ( tptx->tx_ecb != NULL )
  87.          {
  88.             for( i = 0; i < tptx->tx_cnt; i++ )
  89.                tptx->tx_ecb[i] = (ipx_ecb_struct *)malloc(sizeof(ipx_ecb_struct));
  90.             for( i = 0; i < tptx->tx_cnt; i++ )
  91.                if ( tptx->tx_ecb[i] == NULL )
  92.                   break;
  93.             if ( i >= tptx->tx_cnt )
  94.             {
  95.  
  96.    /* clear ecb buffers */
  97.  
  98.                for( i = 0; i < tptx->tx_cnt; i++ )
  99.                {
  100.                   tptx->tx_ecb[i]->inuse = 0;
  101.                   tp_set_blk_id(tptx->tx_data[i], TP_ID_NONE);
  102.                }
  103.  
  104.    /* allocate block send list */
  105.  
  106.                tptx->b_list_ptr = (short *)malloc(tptx->b_cnt*sizeof(short));
  107.                if ( tptx->b_list_ptr != NULL )
  108.                {
  109.  
  110.    /* allocate memory pool */
  111.  
  112.                   tptx->b_pool_ptr = (char *)malloc(tptx->b_pool_size);
  113.                   if ( tptx->b_pool_ptr != NULL )
  114.                   {
  115.                      tptx->b_pool_dptr = (char *)malloc(tptx->b_pool_size);
  116.                      if ( tptx->b_pool_dptr != NULL )
  117.                      {
  118.  
  119.                         return 1;
  120.                      }
  121.                      free(tptx->b_pool_dptr);
  122.                      tptx->b_pool_dptr = NULL;
  123.                   }
  124.  
  125.    /* deallocate everything, if something went wrong */
  126.  
  127.                   free(tptx->b_list_ptr);
  128.                   tptx->b_list_ptr = NULL;
  129.                }
  130.             }
  131.             for( i = 0; i < tptx->tx_cnt; i++ )
  132.                if ( tptx->tx_ecb[i] != NULL )
  133.                   free(tptx->tx_ecb[i]);
  134.             free(tptx->tx_ecb);
  135.             tptx->tx_ecb = NULL;
  136.          }
  137.       }
  138.       for( i = 0; i < tptx->tx_cnt; i++ )
  139.          if ( tptx->tx_data[i] != NULL )
  140.             free(tptx->tx_data[i]);
  141.       free(tptx->tx_data);
  142.       tptx->tx_data = NULL;
  143.    }
  144.    return 0;
  145. }
  146.  
  147. int tptx_IsOk(tptx_type tptx)
  148. {
  149.    assert(tptx != NULL);
  150.    assert(tptx->tx_cnt == tptx->b_cnt+TPTX_TX_ADD);
  151.    assert(tptx->b_cnt*2 < (int)tptx->b_len);
  152.    return 1;
  153. }
  154.  
  155. tptx_type tptx_Open(unsigned short socket)
  156. {
  157.    tptx_type tptx;
  158.  
  159.    if ( ipx_init() == 0 )
  160.    {
  161.       fprintf(stderr, tptx_es_ipx_not_found);
  162.       return NULL;
  163.    }
  164.  
  165.    switch(ipx_open_socket(socket))
  166.    {
  167.       case 0x0fe:
  168.          fprintf(stderr, tptx_es_socket_table_full);
  169.          return NULL;
  170.       case 0x0ff:
  171.          fprintf(stderr, tptx_es_socket_open);
  172.          return NULL;
  173.    }
  174.  
  175.    tptx = (tptx_type)malloc(sizeof(tptx_struct));
  176.    if ( tptx != NULL )
  177.    {
  178.       tptx->flags = 0;
  179.  
  180.       tptx->socket   = socket;
  181.       tptx->is_adr_known = 0;
  182.  
  183.       tptx->f_name = NULL;
  184.       tptx->f_logname = NULL;
  185.       tptx->fp = NULL;
  186.  
  187.       tptx->small_delay = CLOCKS_PER_SEC/2;
  188.       tptx->large_delay = CLOCKS_PER_SEC*2;
  189.  
  190.       tptx_SetState(tptx, tptx_state_none);
  191.  
  192.       tptx->is_aux = 0;
  193.       tptx->f_time_sum = (clock_t)0;
  194.       tptx->f_len_sum = 0L;
  195.  
  196.       if ( tptx_OpenPool(tptx, TPTX_B_LEN, TPTX_B_CNT) != 0 )
  197.       {
  198.          tptx->rx_data = (char *)malloc(tptx->b_len+TP_BLK_INFO_SIZE);
  199.          if ( tptx->rx_data != NULL )
  200.          {
  201.             tptx->rx_ecb = (ipx_ecb_struct *)malloc(sizeof(ipx_ecb_struct));
  202.             if ( tptx->rx_ecb != NULL )
  203.             {
  204.                tptx->rx_ecb->inuse = 0;
  205.                tptx->rx_ecb->cc = 0;
  206.                tp_set_blk_id(tptx->rx_data, TP_ID_NONE);
  207.                tptx_ListenECB(tptx);
  208.                return tptx;
  209.             }
  210.             free(tptx->rx_data);
  211.          }
  212.          tptx_ClosePool(tptx);
  213.       }
  214.       free(tptx);
  215.    }
  216.    ipx_close_socket(socket);
  217.    return NULL;
  218. }
  219.  
  220. void tptx_ClosePool(tptx_type tptx)
  221. {
  222.    int i;
  223.  
  224.    assert(tptx != NULL);
  225.  
  226.    free(tptx->b_pool_ptr);
  227.    tptx->b_pool_ptr = NULL;
  228.  
  229.    free(tptx->b_pool_dptr);
  230.    tptx->b_pool_dptr = NULL;
  231.  
  232.    free(tptx->b_list_ptr);
  233.    tptx->b_list_ptr = NULL;
  234.  
  235.    for( i = 0; i < tptx->tx_cnt; i++ )
  236.       if ( tptx->tx_ecb[i] != NULL )
  237.       {
  238.          ipx_cancel_ecb(tptx->tx_ecb[i]);
  239.          free(tptx->tx_ecb[i]);
  240.       }
  241.    free(tptx->tx_ecb);
  242.    tptx->tx_ecb = NULL;
  243.  
  244.    for( i = 0; i < tptx->tx_cnt; i++ )
  245.       if ( tptx->tx_data[i] != NULL )
  246.          free(tptx->tx_data[i]);
  247.    free(tptx->tx_data);
  248.    tptx->tx_data = NULL;
  249.  
  250. }
  251.  
  252. void tptx_CloseFile(tptx_type tptx)
  253. {
  254.    if ( tptx->fp != NULL )
  255.    {
  256.       fclose(tptx->fp);
  257.       tptx->fp = NULL;
  258.       tptx->f_time_sum += clock()-tptx->f_start;
  259.       tptx->f_len_sum += tptx->f_len;
  260.    }
  261.  
  262.    if ( tptx->f_name != NULL )
  263.    {
  264.       free(tptx->f_name);
  265.       tptx->f_name = NULL;
  266.    }
  267.  
  268.    tptx->is_ended = 1;
  269. }
  270.  
  271. int tptx_OpenFile(tptx_type tptx, char *name)
  272. {
  273.    tptx_CloseFile(tptx);
  274.  
  275.    tptx->f_len = 0L;
  276.    tptx->f_pos = 0L;
  277.    tptx->f_crc = 0UL;
  278.    tptx->f_d_crc = 0UL;
  279.    tptx->f_is_skip = 0;
  280.    tptx->f_start = clock();
  281.    tptx->b_is_dptr_ok = 0;
  282.    tptx->f_date = 0;
  283.    tptx->f_time = 0;
  284.    tptx->fp = NULL;
  285.  
  286.    tptx->f_name = NULL;
  287.    if ( name != NULL )
  288.    {
  289.       tptx->f_name = (char *)malloc(strlen(name)+1);
  290.       if ( tptx->f_name == NULL )
  291.          return 0;
  292.       strcpy(tptx->f_name, name);
  293.  
  294.       tptx->fp = fopen(name, "rb");
  295.       if ( tptx->fp == NULL )
  296.          return 0;
  297.  
  298.       fseek(tptx->fp, 0L, SEEK_END);
  299.       tptx->f_len = ftell( tptx->fp );
  300.       fseek(tptx->fp, 0L, SEEK_SET);
  301.       /* tptx->f_len = filelength(fileno(tptx->fp)); */
  302.       _dos_getfileattr( name, &(tptx->f_attr) );
  303.       {
  304.          int handle;
  305.          _dos_open( name, _O_RDONLY, &handle );
  306.          _dos_getftime( handle, &(tptx->f_date), &(tptx->f_time) );
  307.          _dos_close( handle );
  308.       }
  309.    }
  310.  
  311.    tptx_SetState(tptx, tptx_state_gen_request);
  312.    tptx_ListenECB(tptx);
  313.  
  314.    return 1;
  315. }
  316.  
  317.  
  318. void tptx_Close(tptx_type tptx)
  319. {
  320.    assert(tptx != NULL);
  321.  
  322.    if ( tptx->f_logname != NULL )
  323.       free(tptx->f_logname);
  324.  
  325.    tptx_CloseFile(tptx);
  326.  
  327.    ipx_cancel_ecb(tptx->rx_ecb);
  328.    free(tptx->rx_ecb);
  329.    free(tptx->rx_data);
  330.  
  331.    tptx_ClosePool(tptx);
  332.  
  333.    ipx_close_socket(tptx->socket);
  334.    free(tptx);
  335. }
  336.  
  337. void tptx_SetAux(tptx_type tptx, int (*aux)( int msg, void *data ))
  338. {
  339.    if ( tptx_IsOk(tptx) == 0 )
  340.       return;
  341.    tptx->aux = aux;
  342.    tptx->is_aux = 1;
  343. }
  344.  
  345. void tptx_DoAux(tptx_type tptx, int msg, void *data)
  346. {
  347.    if ( tptx_IsOk(tptx) == 0 )
  348.       return;
  349.    if ( tptx->is_aux != 0 )
  350.       tptx->aux(msg, data);
  351. }
  352.  
  353. void tptx_DoPAux(tptx_type tptx, int msg)
  354. {
  355.    tptx->pdata.total       = tptx->f_len;
  356.    tptx->pdata.curr        = tptx->f_pos;
  357.    tptx->pdata.crc         = tptx->f_crc;
  358.    tptx->pdata.path        = tptx->f_name;
  359.    tptx->pdata.file_start  = tptx->f_start;
  360.    if ( tptx->pdata.path == NULL )
  361.    {
  362.       tptx->pdata.path     = tptx->f_logname;
  363.    }
  364.    tptx_DoAux(tptx, msg, (void *)&(tptx->pdata));
  365. }
  366.  
  367. int tptx_Send(tptx_type tptx, char *phy_name, char *log_name)
  368. {
  369.    if ( tptx->f_logname != NULL )
  370.    {
  371.       free(tptx->f_logname);
  372.       tptx->f_logname = NULL;
  373.    }
  374.  
  375.    tptx->f_logname = (char *)malloc(strlen(log_name)+1);
  376.    if ( tptx->f_logname == NULL )
  377.       return 0;
  378.    strcpy(tptx->f_logname, log_name);
  379.  
  380.    if ( tptx_OpenFile(tptx, phy_name) == 0 )
  381.       return 0;
  382.  
  383.    tptx->is_ended = 0;
  384.  
  385.    return 1;
  386. }
  387.  
  388. size_t tptx_GetExpectedReadSize(tptx_type tptx)
  389. {
  390.    size_t elen;
  391.  
  392.    if ( tptx->f_len-tptx->f_pos >= (long)tptx->b_pool_size )
  393.       elen = tptx->b_pool_size;
  394.    else
  395.       elen = (size_t)(tptx->f_len-tptx->f_pos);
  396.  
  397.    return elen;
  398. }
  399.  
  400. int tptx_Read(tptx_type tptx)
  401. {
  402.    size_t len, i;
  403.    len = 0;
  404.  
  405.    if ( tptx_IsOk(tptx) == 0 )
  406.       return 0;
  407.  
  408.    if ( tptx->b_is_dptr_ok != 0 )
  409.       return 1;
  410.  
  411.    if ( tptx->fp != NULL )
  412.    {
  413.       assert(tptx->f_pos == ftell(tptx->fp));
  414.  
  415.       len = fread(tptx->b_pool_dptr, 1, tptx->b_pool_size, tptx->fp);
  416.       if (len != tptx_GetExpectedReadSize(tptx))
  417.       {
  418.          static char s[80];
  419.          sprintf(s, "read error at position %ld", tptx->f_pos);
  420.          tptx_Error(tptx, s);
  421.          return 0;
  422.       }
  423.       if ( (tptx->flags & TP_FLAG_IS_DISABLE_CRC) == 0 )
  424.       {
  425.          if ( (tptx->flags & TP_FLAG_IS_CRC32) == 0 )
  426.          {
  427.             for( i = 0; i < len; i += 1024 )
  428.             {
  429.                ipx_dispatch();
  430.                tptx->f_d_crc = (unsigned long)crc16((unsigned short)tptx->f_d_crc,
  431.                   (unsigned char *)tptx->b_pool_dptr+(size_t)i,
  432.                   (len > i+1024) ? 1024 : len-i);
  433.             }
  434.          }
  435.          else
  436.          {
  437.             for( i = 0; i < len; i += 1024 )
  438.             {
  439.                ipx_dispatch();
  440.                tptx->f_d_crc = crc32(tptx->f_d_crc,
  441.                   (unsigned char *)tptx->b_pool_dptr+(size_t)i,
  442.                   (len > i+1024) ? 1024 : len-i);
  443.             }
  444.          }
  445.  
  446.          /*
  447.          tptx->f_d_crc = crc32(tptx->f_d_crc,
  448.             (unsigned char *)tptx->b_pool_dptr, len);
  449.          */
  450.       }
  451.    }
  452.    tptx->f_read_len = (long)len;
  453.    tptx->b_is_dptr_ok = 1;
  454.    return 1;
  455. }
  456.  
  457.  
  458. int tptx_CopyRead(tptx_type tptx)
  459. {
  460.    if ( tptx->b_is_dptr_ok == 0 )
  461.    {
  462.       if ( tptx_Read(tptx) == 0 )
  463.          return 0;
  464.    }
  465.    memcpy(tptx->b_pool_ptr, tptx->b_pool_dptr, tptx->f_read_len);
  466.    tptx->f_crc = tptx->f_d_crc;
  467.    tptx->f_pos += tptx->f_read_len;
  468.    tptx->b_is_dptr_ok = 0;
  469.    return 1;
  470. }
  471.  
  472. void tptx_InitPool(tptx_type tptx, int b_curr_cnt, short *list)
  473. {
  474.    int i;
  475.    tptx->b_curr_cnt = b_curr_cnt;
  476.    tptx->b_list_cnt = 0;
  477.    if ( list == NULL )
  478.    {
  479.       for( i = 0; i < b_curr_cnt; i++ )
  480.          tptx->b_list_ptr[i] = (short)i;
  481.    }
  482.    else
  483.    {
  484.       for( i = 0; i < b_curr_cnt; i++ )
  485.          tptx->b_list_ptr[i] = list[i];
  486.    }
  487. }
  488.  
  489. void tptx_CopyMemoryFromPool(tptx_type tptx, int no, void *adr, size_t len)
  490. {
  491.    assert(no < tptx->b_cnt);
  492.    memcpy(adr, tptx->b_pool_ptr+no*tptx->b_len, len);
  493. }
  494.  
  495. void tptx_SendECB(tptx_type tptx, int no)
  496. {
  497.    tp_set_blk_ver(tptx->tx_data[no], TP_VERSION);
  498.  
  499.    if ( tptx->is_adr_known == 0 )
  500.    {
  501.       ipx_fill_send_ecb(
  502.          tptx->tx_ecb[no],
  503.          ipx_get_header(NULL, tptx->socket, tptx->socket),
  504.          tptx->tx_data[no],
  505.          tptx->b_len+TP_BLK_INFO_SIZE);
  506.    }
  507.    else
  508.    {
  509.       ipx_fill_send_ecb(
  510.          tptx->tx_ecb[no],
  511.          ipx_get_header(&(tptx->adr), tptx->socket, tptx->socket),
  512.          tptx->tx_data[no],
  513.          tptx->b_len+TP_BLK_INFO_SIZE);
  514.    }
  515.  
  516.    if ( ipx_send_ecb(tptx->tx_ecb[no]) == 0 )
  517.    {
  518.       static char s[80];
  519.       sprintf(s, "cannot send msg %d", tp_get_blk_id(tptx->tx_data[no]) );
  520.       tptx_Error(tptx, s);
  521.    }
  522. }
  523.  
  524. void tptx_Error(tptx_type tptx, char *s)
  525. {
  526.    fprintf(stderr, "\n");
  527.    fprintf(stderr, TPTX_ID_STR "%s\n", s);
  528.    tptx->is_ended = 2;
  529.    tptx_SetState(tptx, tptx_state_none);
  530.  
  531.    if ( tptx->is_adr_known != 0 )
  532.    {
  533.       clock_t c1 = clock() + CLOCKS_PER_SEC;
  534.       long cnt = 4L;
  535.       while ( clock() < c1 && cnt > 0L )
  536.       {
  537.          clock_t c2;
  538.          ipx_dispatch();
  539.          while ( tptx->tx_ecb[0]->inuse == 0 )
  540.          {
  541.             tp_set_blk_id(tptx->tx_data[0], TP_ID_ERROR);
  542.             tp_set_blk_ver(tptx->tx_data[0], TP_VERSION);
  543.             strcpy(tp_get_blk_data_adr(tptx->tx_data[0]), s);
  544.  
  545.             ipx_fill_send_ecb(
  546.                tptx->tx_ecb[0],
  547.                ipx_get_header(&(tptx->adr), tptx->socket, tptx->socket),
  548.                tptx->tx_data[0],
  549.                tptx->b_len+TP_BLK_INFO_SIZE);
  550.  
  551.             ipx_send_ecb(tptx->tx_ecb[0]);
  552.             cnt--;
  553.          }
  554.          c2 = clock() + CLOCKS_PER_SEC/8;
  555.          while ( clock() < c2 )
  556.             ;
  557.       }
  558.    }
  559. }
  560.  
  561.  
  562. int tptx_ListenECB(tptx_type tptx)
  563. {
  564.    if ( tptx->rx_ecb->inuse != 0 )
  565.    {
  566.       return 1;
  567.    }
  568.    if ( ipx_fill_receive_ecb(
  569.       tptx->rx_ecb,
  570.       tptx->socket,
  571.       tptx->rx_data,
  572.       tptx->b_len+TP_BLK_INFO_SIZE) == NULL )
  573.    {
  574.       tptx_Error(tptx, "cannot fill receive ecb");
  575.       return 0;
  576.    }
  577.    if ( ipx_listen_ecb(tptx->rx_ecb) == 0 )
  578.    {
  579.       tptx_Error(tptx, "cannot listen to ecb");
  580.       return 0;
  581.    }
  582.    return 1;
  583. }
  584.  
  585. int tptx_ListenAndSearch(tptx_type tptx, short id1, short id2)
  586. {
  587.    if ( tptx->rx_ecb->inuse == 0 )
  588.    {
  589.       /* printf("inuse: %d   \r", tptx->rx_ecb->inuse); */
  590.       if ( tptx->rx_ecb->cc == 0 )
  591.       {
  592.          if (tp_ecb_get_id(tptx->rx_ecb) == TP_ID_ERROR )
  593.          {
  594.             static char s[80];
  595.             sprintf(s, "remote error: '%s'", tp_ecb_get_data_adr(tptx->rx_ecb));
  596.             tptx_Error(tptx, s);
  597.             return 0;
  598.          }
  599.          if (tp_ecb_get_id(tptx->rx_ecb) != id1 &&
  600.              tp_ecb_get_id(tptx->rx_ecb) != id2 )
  601.          {
  602.             if ( tptx_ListenECB(tptx) == 0 )
  603.                return 0;
  604.          }
  605.          else
  606.          {
  607.             return 1;
  608.          }
  609.       }
  610.       else
  611.       {
  612.          printf(TPTX_ID_STR "receive warning: %s\n", 
  613.             ipx_get_ecb_cc_string(tptx->rx_ecb));
  614.          if ( tptx_ListenECB(tptx) == 0 )
  615.             return 0;
  616.       }
  617.    }
  618.    return 0;
  619. }
  620.  
  621. void tptx_WaitSend(tptx_type tptx,
  622.    int no,
  623.    void (*next_state)(tptx_type tptx),
  624.    void (*repeated_state)(tptx_type tptx),
  625.    clock_t delay)
  626. {
  627.    if ( tptx->tx_ecb[no]->inuse == 0 )
  628.    {
  629.       if ( tptx->tx_ecb[no]->cc != 0 )
  630.       {
  631.          tptx_Error(tptx, ipx_get_ecb_cc_string(tptx->tx_ecb[0]));
  632.       }
  633.       else
  634.       {
  635.          tptx->clock_dest = clock()+delay;
  636.          tptx_SetRepeatedState(tptx, repeated_state);
  637.          tptx_SetState(tptx, next_state);
  638.       }
  639.    }
  640. }
  641.  
  642. int tptx_CheckTime(tptx_type tptx)
  643. {
  644.    if ( tptx->clock_dest < clock() )
  645.    {
  646.       tptx_SetState(tptx, tptx_GetRepeatedState(tptx));
  647.       return 0;
  648.    }
  649.    return 1;
  650. }
  651.  
  652. int tptx_Dispatch(tptx_type tptx)
  653. {
  654.    ipx_dispatch();
  655.    if ( tptx->is_ended != 0 )
  656.       return tptx->is_ended;
  657.    tptx->state_fn(tptx);
  658.    if ( tptx->state_fn != tptx_state_user_check )
  659.    {
  660.       if ( kbhit() != 0 )
  661.       {
  662.          if ( getch() == 27 )
  663.          {
  664.             tptx_Error(tptx, "user break");
  665.          }
  666.       }
  667.    }
  668.    return tptx->is_ended;
  669. }
  670.  
  671. /* - - - - - state functions - - - - - - - - - - - - - - - - - - - - - - - */
  672.  
  673. void tptx_state_none(tptx_type tptx)
  674. {
  675.    tptx_ListenECB(tptx);
  676. }
  677.  
  678. void tptx_state_gen_request(tptx_type tptx)
  679. {
  680.    tp_request request;
  681.  
  682.    tp_debug_out("tptx_state_gen_request");
  683.  
  684.    request = (tp_request)tp_get_blk_data_adr(tptx->tx_data[0]);
  685.  
  686.    request->adr = *ipx_get_local_net_number();
  687.    request->file_size = tptx->f_len;
  688.    /* request->flags = 0; */
  689.    request->flags = tptx->flags;
  690.    if ( tptx->f_name == NULL )
  691.       request->flags |= TP_FLAG_IS_DIR;
  692.    request->attr = tptx->f_attr;
  693.    request->time = tptx->f_time;
  694.    request->date = tptx->f_date;
  695.    strcpy(
  696.       tp_get_blk_data_adr(tptx->tx_data[0])+sizeof(tp_request_struct),
  697.       tptx->f_logname);
  698.  
  699.    tp_set_blk_id(tptx->tx_data[0], TP_ID_REQUEST);
  700.  
  701.    tptx_SendECB(tptx, 0);
  702.  
  703.    tptx_SetState(tptx, tptx_state_chk_request);
  704. }
  705.  
  706. void tptx_state_chk_request(tptx_type tptx)
  707. {
  708.    tp_debug_out("tptx_state_chk_request");
  709.  
  710.    tptx_WaitSend(tptx, 0,
  711.       tptx_state_wait_ack_request,
  712.       tptx_state_gen_request,
  713.       tptx->large_delay);
  714. }
  715.  
  716. void tptx_state_wait_ack_request(tptx_type tptx)
  717. {
  718.    /* tp_debug_out("tptx_state_wait_ack_request"); */
  719.  
  720.    if ( tptx_CheckTime(tptx) == 0 )
  721.       return;
  722.    if ( tptx_ListenAndSearch(tptx, TP_ID_ACK_REQUEST, TP_ID_NONE) != 0 )
  723.    {
  724.       tp_ack_request ack_request;
  725.       ack_request = (tp_ack_request)tp_ecb_get_data_adr(tptx->rx_ecb);
  726.       tptx->adr = ack_request->adr;
  727.       tptx->is_adr_known = 1;
  728.       tptx_ListenECB(tptx);
  729.       if ( ack_request->exist != 0 &&
  730.           (tptx->flags & TP_FLAG_IS_NO_USER_CHECK) == 0 )
  731.       {
  732.          printf("remote file '%s' exists, overwrite (y,n,a)? ",
  733.             tptx->f_logname);
  734.          fflush(stdout);
  735.          tptx_SetState(tptx, tptx_state_user_check);
  736.       }
  737.       else
  738.       {
  739.          tptx_DoPAux(tptx, TP_MSG_PSTART);
  740.          tptx_SetState(tptx, tptx_state_gen_file_start);
  741.       }
  742.    }
  743. }
  744.  
  745. void tptx_state_user_check(tptx_type tptx)
  746. {
  747.    if ( kbhit() != 0 )
  748.    {
  749.       int c = getch();
  750.       switch(c)
  751.       {
  752.          case 'n':
  753.          case 'N':
  754.             printf("%c\n", c);
  755.             tptx->f_is_skip = 1;
  756.             tptx_SetState(tptx, tptx_state_gen_file_end);
  757.             return;
  758.          case 'a':
  759.          case 'A':
  760.             printf("%c\n", c);
  761.             tptx_SetFlag(tptx, TP_FLAG_IS_NO_USER_CHECK);
  762.             tptx_DoPAux(tptx, TP_MSG_PSTART);
  763.             tptx_SetState(tptx, tptx_state_gen_file_start);
  764.             return;
  765.          case 'y':
  766.          case 'Y':
  767.          case 'j':
  768.          case 'J':
  769.             printf("%c\n", c);
  770.             tptx_DoPAux(tptx, TP_MSG_PSTART);
  771.             tptx_SetState(tptx, tptx_state_gen_file_start);
  772.             return;
  773.          case 27:
  774.             tptx_Error(tptx, "user escape");
  775.             return;
  776.       }
  777.    }
  778.    if ( tptx_ListenAndSearch(tptx, TP_ID_FILE_START, TP_ID_NONE) != 0 )
  779.    {
  780.       tp_file_start file_start;
  781.       file_start = (tp_file_start)tp_get_blk_data_adr(tptx->rx_data);
  782.       tptx->f_is_skip = file_start->is_skip_file;
  783.       tptx->flags = file_start->flags;
  784.       tptx_ListenECB(tptx);
  785.       if ( tptx->f_is_skip != 0 )
  786.       {
  787.          printf("n\n");
  788.          tptx_SetState(tptx, tptx_state_gen_file_end);
  789.       }
  790.       else
  791.       {
  792.          printf("y/a\n");
  793.          tptx_DoPAux(tptx, TP_MSG_PSTART);
  794.          tptx_SetState(tptx, tptx_state_gen_file_start);
  795.       }
  796.    }
  797.  
  798. }
  799.  
  800. void tptx_state_gen_file_start(tptx_type tptx)
  801. {
  802.    tp_file_start file_start;
  803.  
  804.    tp_debug_out("tptx_state_gen_file_start");
  805.  
  806.    file_start = (tp_file_start)tp_get_blk_data_adr(tptx->tx_data[0]);
  807.    file_start->is_skip_file = 0;
  808.    file_start->flags = tptx->flags;
  809.  
  810.    tp_set_blk_id(tptx->tx_data[0], TP_ID_FILE_START);
  811.    tptx_SendECB(tptx, 0);
  812.  
  813.    tptx_SetState(tptx, tptx_state_chk_file_start);
  814. }
  815.  
  816. void tptx_state_chk_file_start(tptx_type tptx)
  817. {
  818.    tp_debug_out("tptx_state_chk_file_start");
  819.  
  820.    tptx_WaitSend(tptx, 0,
  821.       tptx_state_wait_ack_file_start,
  822.       tptx_state_gen_file_start,
  823.       tptx->small_delay);
  824. }
  825.  
  826. void tptx_state_wait_ack_file_start(tptx_type tptx)
  827. {
  828.    /* tp_debug_out("tptx_state_wait_ack_file_start"); */
  829.  
  830.    if ( tptx_CheckTime(tptx) == 0 )
  831.       return;
  832.    if ( tptx_ListenAndSearch(tptx, TP_ID_ACK_FILE_START, TP_ID_NONE) != 0 )
  833.    {
  834.       tptx->f_start = clock();
  835.       tptx_ListenECB(tptx);
  836.       tptx_SetState(tptx, tptx_state_gen_block_start);
  837.    }
  838. }
  839.  
  840. void tptx_state_gen_block_start(tptx_type tptx)
  841. {
  842.    tp_block_start block_start;
  843.  
  844.    tp_debug_out("tptx_state_gen_block_start");
  845.    /* printf("filepos: %ld\n", tptx->f_pos); */
  846.    tptx_DoPAux(tptx, TP_MSG_PDATA);
  847.  
  848.  
  849.    block_start = (tp_block_start)tp_get_blk_data_adr(tptx->tx_data[0]);
  850.    block_start->cnt =
  851.       (tptx_GetExpectedReadSize(tptx)+tptx->b_len-1)/tptx->b_len;
  852.  
  853.    tp_set_blk_id(tptx->tx_data[0], TP_ID_BLOCK_START);
  854.    tptx_SendECB(tptx, 0);
  855.  
  856.    tptx_SetState(tptx, tptx_state_chk_block_start);
  857. }
  858.  
  859. void tptx_state_chk_block_start(tptx_type tptx)
  860. {
  861.    tp_debug_out("tptx_state_chk_block_start");
  862.  
  863.    tptx_WaitSend(tptx, 0,
  864.       tptx_state_wait_ack_block_start,
  865.       tptx_state_gen_block_start,
  866.       tptx->small_delay);
  867. }
  868.  
  869. void tptx_state_wait_ack_block_start(tptx_type tptx)
  870. {
  871.    tp_debug_out("tptx_state_wait_ack_block_start");
  872.  
  873.    if ( tptx_CheckTime(tptx) == 0 )
  874.       return;
  875.    if ( tptx_ListenAndSearch(tptx, TP_ID_ACK_BLOCK_START, TP_ID_NONE) != 0 )
  876.    {
  877.       tptx_ListenECB(tptx);
  878.       tptx_CopyRead(tptx);
  879.       tptx_InitPool(tptx,
  880.          (tptx_GetExpectedReadSize(tptx)+tptx->b_len-1)/tptx->b_len,
  881.          NULL);
  882.       tptx_SetState(tptx, tptx_state_gen_data);
  883.    }
  884. }
  885.  
  886. void tptx_state_gen_data(tptx_type tptx)
  887. {
  888.    /* tp_debug_out("tptx_state_gen_data"); */
  889.  
  890.    if ( tptx->b_list_cnt < tptx->b_curr_cnt )
  891.    {
  892.       tp_data data;
  893.  
  894.       /*
  895.       printf("(%d,%d/%d)", (int)tptx->b_list_ptr[tptx->b_list_cnt],
  896.          tptx->b_list_cnt, tptx->b_curr_cnt);
  897.       */
  898.  
  899.       data = (tp_data)tp_get_blk_data_adr(tptx->tx_data[tptx->b_list_cnt]);
  900.       data->no = tptx->b_list_ptr[tptx->b_list_cnt];
  901.       if ( tptx->b_pool_size-(size_t)(((size_t)data->no)*tptx->b_len) <
  902.                tptx->b_len )
  903.          data->len = tptx->b_pool_size-(size_t)(((size_t)data->no)*tptx->b_len);
  904.       else
  905.          data->len = tptx->b_len;
  906.       tptx_CopyMemoryFromPool(tptx,
  907.          data->no,
  908.          tp_get_blk_data_adr(tptx->tx_data[tptx->b_list_cnt])+sizeof(tp_data_struct),
  909.          data->len);
  910.  
  911.       tp_set_blk_id(tptx->tx_data[tptx->b_list_cnt], TP_ID_DATA);
  912.       tptx_SendECB(tptx, tptx->b_list_cnt);
  913.       tptx->b_list_cnt++;
  914.    }
  915.    else
  916.    {
  917.       tptx_SetState(tptx, tptx_state_chk_data);
  918.       tptx_Read(tptx);
  919.    }
  920. }
  921.  
  922. void tptx_state_chk_data(tptx_type tptx)
  923. {
  924.    int i, c;
  925.  
  926.    /* tp_debug_out("tptx_state_chk_data"); */
  927.  
  928.    c = 0;
  929.    for( i = 0; i < tptx->b_curr_cnt; i++ )
  930.    {
  931.       if ( tptx->tx_ecb[i]->inuse == 0 )
  932.       {
  933.          if ( tptx->tx_ecb[i]->cc != 0 )
  934.          {
  935.             tptx_Error(tptx, ipx_get_ecb_cc_string(tptx->tx_ecb[0]));
  936.          }
  937.          else
  938.          {
  939.             c++;
  940.          }
  941.       }
  942.    }
  943.    if ( c == tptx->b_curr_cnt )
  944.    {
  945.       tptx_SetState(tptx, tptx_state_gen_block_end);
  946.    }
  947. }
  948.  
  949. void tptx_state_gen_block_end(tptx_type tptx)
  950. {
  951.    tp_block_end block_end;
  952.  
  953.    tp_debug_out("tptx_state_gen_block_end");
  954.  
  955.    block_end = (tp_block_end)tp_get_blk_data_adr(tptx->tx_data[0]);
  956.    block_end->crc = tptx->f_crc;
  957.  
  958.    tp_set_blk_id(tptx->tx_data[0], TP_ID_BLOCK_END);
  959.    tptx_SendECB(tptx, 0);
  960.  
  961.    tptx_SetState(tptx, tptx_state_chk_block_end);
  962. }
  963.  
  964. void tptx_state_chk_block_end(tptx_type tptx)
  965. {
  966.    tp_debug_out("tptx_state_chk_block_end");
  967.  
  968.    tptx_WaitSend(tptx, 0,
  969.       tptx_state_wait_ack_block_end,
  970.       tptx_state_gen_block_end,
  971.       tptx->small_delay);
  972. }
  973.  
  974. void tptx_state_wait_ack_block_end(tptx_type tptx)
  975. {
  976.    /* tp_debug_out("tptx_state_wait_ack_block_end"); */
  977.  
  978.    if ( tptx_CheckTime(tptx) == 0 )
  979.       return;
  980.    if ( tptx_ListenAndSearch(tptx, TP_ID_ACK_BLOCK_END, TP_ID_MISSED_BLOCKS) != 0 )
  981.    {
  982.       if ( tp_ecb_get_id(tptx->rx_ecb) == TP_ID_MISSED_BLOCKS )
  983.       {
  984.          tp_missed_blocks missed_blocks;
  985.          missed_blocks = (tp_missed_blocks)tp_ecb_get_data_adr(tptx->rx_ecb);
  986.          /* printf("missed: %d\n", (int)missed_blocks->cnt); */
  987.          tptx_InitPool(tptx,
  988.             missed_blocks->cnt,
  989.             (short *)(tp_ecb_get_data_adr(tptx->rx_ecb)+
  990.                sizeof(tp_missed_blocks_struct)));
  991.          tptx_SetState(tptx, tptx_state_gen_data);
  992.          tptx_ListenECB(tptx);
  993.          return;
  994.       }
  995.       else if ( tp_ecb_get_id(tptx->rx_ecb) == TP_ID_ACK_BLOCK_END )
  996.       {
  997.          if ( tptx->f_pos == tptx->f_len )
  998.          {
  999.             tptx_SetState(tptx, tptx_state_gen_file_end);
  1000.          }
  1001.          else
  1002.          {
  1003.             tptx_SetState(tptx, tptx_state_gen_block_start);
  1004.          }
  1005.          tptx_ListenECB(tptx);
  1006.       }
  1007.    }
  1008. }
  1009.  
  1010. void tptx_state_gen_file_end(tptx_type tptx)
  1011. {
  1012.    tp_debug_out("tptx_state_gen_file_end");
  1013.  
  1014.    tp_set_blk_id(tptx->tx_data[0], TP_ID_FILE_END);
  1015.    tptx_SendECB(tptx, 0);
  1016.    tptx_SetState(tptx, tptx_state_chk_file_end);
  1017. }
  1018.  
  1019. void tptx_state_chk_file_end(tptx_type tptx)
  1020. {
  1021.    tp_debug_out("tptx_state_chk_file_end");
  1022.  
  1023.    tptx_WaitSend(tptx, 0,
  1024.       tptx_state_wait_ack_file_end,
  1025.       tptx_state_gen_file_end,
  1026.       tptx->large_delay);
  1027. }
  1028.  
  1029. void tptx_state_wait_ack_file_end(tptx_type tptx)
  1030. {
  1031.    tp_debug_out("tptx_state_wait_ack_file_end");
  1032.  
  1033.    if ( tptx_CheckTime(tptx) == 0 )
  1034.       return;
  1035.    if ( tptx_ListenAndSearch(tptx, TP_ID_ACK_FILE_END, TP_ID_NONE) != 0 )
  1036.    {
  1037.       if ( tptx->f_is_skip == 0 )
  1038.       {
  1039.          tptx_DoPAux(tptx, TP_MSG_PDATA);
  1040.          tptx_DoPAux(tptx, TP_MSG_PEND);
  1041.       }
  1042.       tptx_CloseFile(tptx);
  1043.       tptx_ListenECB(tptx);
  1044.       tptx_SetState(tptx, tptx_state_none);
  1045.    }
  1046. }
  1047.