home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / CPROG / TCOMM6.ZIP / QUICKB.C < prev    next >
C/C++ Source or Header  |  1991-06-02  |  25KB  |  1,126 lines

  1. /*
  2. **  QUICKB.C - Quick B Protocol Support routines
  3. **
  4. **    converted to C by Paul M. Resch
  5. **  adapted to LiteComm(tm) ToolBox by Information Technology, Ltd.
  6. */
  7.  
  8. /*
  9. ** This module implements the B-Protocol Functions.
  10. **
  11. ** bp_DLE should be invoked whenever a <DLE> is received.
  12. ** bp_ENQ should be called whenever an <ENQ> is received.
  13. ** bp_ESC_I should be called when the sequence <ESC><I> is received.
  14. **
  15. ** This source was originally derived from QUICKB.INC, written by
  16. ** Russ Ranshaw, CompuServe Incorporated.
  17. **
  18. */
  19.  
  20. #include <dos.h>
  21.  
  22. #ifdef M_I86
  23. #include <stdlib.h>
  24. #include <fcntl.h>
  25. #include <io.h>
  26. #include <sys\types.h>
  27. #include <sys\stat.h>
  28. #endif
  29.  
  30. #ifdef __TURBOC__
  31. #include <conio.h>
  32. #include <fcntl.h>
  33. #include <io.h>
  34. #include <sys\stat.h>
  35. #endif
  36.  
  37. #include "litecomm.h"
  38. #include "litexm.h"
  39. #include "cxlwin.h"
  40.  
  41. extern unsigned int port;                /* defined in TTL main */
  42.  
  43. #define    TRUE    1
  44. #define    FALSE    0
  45.  
  46. #undef DLE
  47. #undef NAK
  48.  
  49. #define    DLE        16
  50. #define    ETX        03
  51. #define    NAK        21
  52. #define    ENQ        05
  53. #define    CR        0x0D
  54. #define    LF        0x0A
  55. #define    MAX_BUF_SIZE    1032            /* Largest data block we can handle */
  56. #define    MAX_SA        2                    /* Maximum number of waiting packets */
  57.  
  58. #define    DEF_BUF_SIZE    511                /* Default data block */
  59. #define    DEF_WS        1                    /* I can send 2 packets ahead */
  60. #define    DEF_WR        1                    /* I can receive single send-ahead */
  61. #define    DEF_BS        8                    /* I can handle 1024 bytes */
  62. #define    DEF_CM        1                    /* I can handle CRC */
  63. #define    DEF_DQ        1                    /* I can handle non-quoted NUL */
  64.  
  65. #define    MAX_ERRORS    10
  66.  
  67. #define incr_seq(v)    (v == 9 ? 0 : v+1)    /* macro to incr seq number */
  68. #define incr_SA(v)  (v == MAX_SA ? 0 : v + 1 )
  69. #define    send_enq() (lc_put(port, ENQ))
  70.  
  71.  
  72. /*
  73. ** Receive States
  74. */
  75.  
  76. #define    R_GET_DLE        0
  77. #define    R_GET_B            1
  78. #define    R_GET_SEQ        2
  79. #define    R_GET_DATA        3
  80. #define    R_GET_CHECKSUM    4
  81. #define    R_SEND_ACK        5
  82. #define    R_TIMED_OUT        6
  83. #define    R_SUCCESS        7
  84.  
  85. /*
  86. ** Send States
  87. */
  88.  
  89. #define    S_GET_DLE    1
  90. #define    S_GET_NUM    2
  91. #define    S_HAVE_ACK    3
  92. #define    S_GET_PACKET    4
  93. #define    S_TIMED_OUT    5
  94. #define    S_SEND_NAK    6
  95. #define    S_SEND_ENQ    7
  96. #define    S_SEND_DATA    8
  97.  
  98. typedef    struct    PACKETB
  99. {
  100.     int        seq;                        /* Packet's sequence number */
  101.     int        num;                        /* Number of bytes in packet */
  102.     unsigned char buf[MAX_BUF_SIZE];     /* Actual packet data */
  103. } PACKET;
  104.  
  105. static    PACKET    SA_Buf[MAX_SA+1];          /* Send-ahead buffers */
  106.  
  107. /*
  108. ** Table of control characters that need to be masked
  109. */
  110.  
  111. static    char mask_table[] =
  112. {
  113.     0, 0, 0, 1, 0, 1, 0, 0,               /* NUL SOH SOB ETX EOT ENQ SYN BEL */
  114.     0, 0, 0, 0, 0, 0, 0, 0,                /* BS  HT  LF  VT  FF  CR  SO  SI  */
  115.     1, 1, 0, 1, 0, 1, 0, 0,                /* DLE DC1 DC2 DC3 DC4 NAK ^V  ^W  */
  116.     0, 0, 0, 0, 0, 0, 0, 0                /* CAN ^Y  ^Z  ESC ?   ?   ?   ?   */
  117. };
  118.  
  119. static    char    hex_digit[] = "0123456789ABCDEF";
  120.  
  121. static    int    seq_num;                    /* Current Sequence Number */
  122. static    int    lchecksm;                    /* May hold CRC */
  123. static    int    r_size;                        /* size of receiver buffer */
  124. static    unsigned int s_counter,
  125.                      r_counter;
  126. static    int    timed_out;                    /* we timed out before receiving */
  127. static    int    cchar;                        /* current character */
  128. static    int    masked;                        /* TRUE if ctrl character 'masked' */
  129. static    int    packet_received;            /* True if a packet was received */
  130. static    unsigned char r_buffer[MAX_BUF_SIZE];
  131.  
  132. /*
  133. ** Other End's Parameters
  134. */
  135.  
  136. static    char    His_WS;                    /* Sender's Window Send */
  137. static    char    His_WR;                    /* Sender's Window Receive */
  138. static    char    His_BS;                    /* Sender's Block Size */
  139. static    char    His_CM;                    /* Sender's Check Method */
  140.  
  141. /*
  142. ** Negotiated Parameters
  143. */
  144.  
  145. static    char    Our_WS;                    /* Negotiated Window Send */
  146. static    char    Our_WR;                    /* Negotiated Window Receive */
  147. static    char    Our_BS;                    /* Negotiated Block Size */
  148. static    char    Our_CM;                    /* Negotiated Check Method */
  149.  
  150. static    int    Quick_B;                    /* True if Quick B in effect */
  151. static    int    Use_CRC;                    /* True if CRC in effect */
  152. static    int    buffer_size;                /* Our_BS * 4 */
  153. static    int    SA_Max;                        /* 1 if SA not enabled, else MAX_SA */
  154. static    int    SA_Enabled;                    /* True if Send-Ahead is permitted  */
  155. static    int    ack_SA;                        /* Which SA_Buf is waiting for ACK */
  156. static    int    fill_SA;                    /* Which SA_Buf is ready, new data */
  157. static    int    SA_Waiting;                    /* Num of SA_Buf's waiting for ACK */
  158. static  int blkct;                      /* block counter for display */
  159. extern  char strbuf[];                  /* defined in qbttl */
  160.  
  161. static    void do_transport_parameters(void);
  162. static int    send_packet();
  163. static    int    SA_Flush();
  164.  
  165. /*
  166. ** crc
  167. **
  168. ** Calculates XMODEM-style CRC (uses the CCITT V.41 polynomial but
  169. ** completely backwards from the normal bit ordering).
  170. */
  171.  
  172.  
  173. static    unsigned    crc_table[] =
  174. {
  175.     0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
  176.     0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
  177.     0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
  178.     0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
  179.     0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
  180.     0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
  181.     0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
  182.     0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
  183.     0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
  184.     0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
  185.     0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
  186.     0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
  187.     0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
  188.     0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
  189.     0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
  190.     0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
  191.     0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
  192.     0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
  193.     0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
  194.     0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
  195.     0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
  196.     0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
  197.     0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
  198.     0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
  199.     0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
  200.     0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
  201.     0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
  202.     0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
  203.     0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
  204.     0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
  205.     0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
  206.     0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
  207. };
  208.  
  209. static    unsigned int    crc_16;
  210.  
  211. /*
  212. ** Upd_CRC updates crc_16 and returns the updated value.
  213. */
  214.  
  215. static    unsigned int    upd_CRC (value)
  216. unsigned int    value;
  217. {
  218.     crc_16 = crc_table [((crc_16 >> 8) ^ (value)) & 0xff] ^    (crc_16 << 8);
  219.     return( crc_16 );
  220. }
  221.  
  222. /*
  223. ** Update the checksum/CRC
  224. */
  225.  
  226. static    void    do_checksum(c)
  227. int    c;
  228. {
  229.     if (Quick_B && Use_CRC)
  230.         lchecksm = upd_CRC (c);
  231.     else
  232.     {
  233.         lchecksm = lchecksm << 1;
  234.  
  235.         if (lchecksm > 255)
  236.             lchecksm = (lchecksm & 0xFF) + 1;
  237.  
  238.         lchecksm = lchecksm + c;
  239.  
  240.         if (lchecksm > 255)
  241.             lchecksm = (lchecksm & 0xFF) + 1;
  242.     }
  243. }
  244.  
  245. static    void    send_failure( code )
  246. int    code;
  247. {
  248.     register PACKET    *p;
  249.  
  250.     ack_SA = 0;
  251.     fill_SA = 0;
  252.     SA_Waiting = 0;
  253.  
  254.     p = &SA_Buf [0];
  255.     p->buf[0] = 'F';
  256.     p->buf[1] = code;
  257.  
  258.     if ( send_packet (1))
  259.         SA_Flush();   /* Gotta wait for the host to ACK it */
  260. }
  261.  
  262. /*
  263. ** bp_ENQ is called when the terminal emulator receives the character <ENQ>
  264. ** from the host.  Its purpose is to initialize for B Protocol and tell the
  265. ** host that we support Quick B.
  266. */
  267.  
  268. void    bp_ENQ()
  269. {
  270.     seq_num = 0;
  271.     buffer_size = 511;               /* Set up defaults */
  272.     Quick_B     = FALSE;             /* Not Quick B Protocol */
  273.     Use_CRC     = FALSE;             /* Not CRC_16      */
  274.     SA_Enabled  = FALSE;             /* No Send-Ahead by us */
  275.     SA_Max      = 1;                 /* = single packet sent */
  276.  
  277.     lc_put (port, DLE);
  278.     lc_put (port, '+');
  279.  
  280.     lc_put (port, DLE);
  281.     lc_put (port, '0');
  282. }
  283.  
  284. /*
  285. ** bp_ESC_I is called when <ESC><I> is received by the terminal emulator.
  286. ** Note that Quick B allows +XX to be added to the end of the response, where
  287. ** XX is the two hex digits of the standard B Protocol checksum of the
  288. ** preceeding characters in the response.  The Qbttl program also supports
  289. ** standard VIDTEX cursor control.
  290. */
  291. static    char    esc_I_response[] = "#VCO,CC,PB,DT,+";
  292.  
  293. void    bp_ESC_I()
  294. {
  295.     int    save_Use_CRC;
  296.     register int    i;
  297.  
  298.     save_Use_CRC = Use_CRC;
  299.     Use_CRC = FALSE;
  300.     lchecksm = 0;
  301.  
  302.     i = 0;
  303.     while( esc_I_response[i] )
  304.     {
  305.         lc_put(port, esc_I_response [i]);
  306.         do_checksum (esc_I_response [i]);
  307.         i++;
  308.     }
  309.  
  310. /*
  311. ** Append two hex digits of checksum to response
  312. */
  313.  
  314.     lc_put(port,  hex_digit[ (lchecksm >> 4) & 0x0F ]);
  315.     lc_put(port,  hex_digit[ lchecksm & 0x0F ] );
  316.     lc_put(port, CR);
  317.  
  318.     Use_CRC = save_Use_CRC;
  319.     while (lc_ocnt(port) > 0)
  320.         ;
  321. }
  322.  
  323.  
  324. static    void    send_masked_byte(c)
  325. int    c;
  326. {
  327.     c = c & 0xFF;
  328.  
  329.     if (c < 32)
  330.     {
  331.         if (mask_table [c] != 0)
  332.         {
  333.             lc_put(port, DLE);
  334.             lc_put(port, c + '@');
  335.         }
  336.         else
  337.             lc_put(port, c);
  338.     }
  339.     else
  340.         lc_put(port, c);
  341.  
  342.     s_counter = (s_counter + 1) % 512;
  343. }
  344.  
  345. static    void    send_ack()
  346. {
  347.     lc_put(port, DLE);
  348.     lc_put(port, seq_num + '0');
  349. }
  350.  
  351. static    int    read_byte()
  352. {
  353.     timed_out = FALSE;
  354.  
  355.     cchar = wait(port, 10, 0x00);
  356.     if (cchar < 0 )
  357.         return( FALSE );
  358.  
  359.     r_counter = (r_counter + 1) % 512;
  360.     return( TRUE );
  361. }
  362.  
  363.  
  364. static    int    read_masked_byte()
  365. {
  366.     masked = FALSE;
  367.  
  368.     if (read_byte() == FALSE)
  369.         return( FALSE );
  370.  
  371.     if (cchar == DLE)
  372.     {
  373.         if (read_byte() == FALSE)
  374.             return( FALSE );
  375.         cchar &= 0x1F;
  376.         masked = TRUE;
  377.     }
  378.  
  379.     return( TRUE );
  380. }
  381.  
  382. static    int    read_packet (lead_in_seen, from_send_packet)
  383. int    lead_in_seen, from_send_packet;
  384. /*
  385. ** Lead_in_Seen is TRUE if the <DLE><B> has been seen already.
  386. ** from_send_packet is TRUE if called from Send_Packet
  387. **    (causes exit on first error detected)
  388. **
  389. ** Returns True if packet is available from host.
  390. */
  391. {
  392.     int    State, next_seq, block_num, errors, new_cks;
  393.     int    i;
  394.  
  395.     packet_received = FALSE;
  396.     for(i=0; i<buffer_size; i++ )
  397.         r_buffer[i] = 0;
  398.     next_seq = (seq_num +  1) % 10;
  399.     errors = 0;
  400.  
  401.     if (lead_in_seen)        /* Start off on the correct foot */
  402.         State = R_GET_SEQ;
  403.     else
  404.         State = R_GET_DLE;
  405.  
  406.     while (TRUE)
  407.     {
  408.         switch  (State)
  409.         {
  410.             case R_GET_DLE :
  411. /*
  412.                 if (_abort_flag)
  413.                 {
  414.                     send_failure ('A');
  415.                     return( FALSE );
  416.                 }
  417. */
  418.                 if (!read_byte())
  419.                     State = R_TIMED_OUT;
  420.                 else
  421.                     if ((cchar & 0x7F) == DLE)
  422.                         State = R_GET_B;
  423.                     else
  424.                         if ((cchar & 0x7F) == ENQ)
  425.                             State = R_SEND_ACK;
  426.                 break;
  427.  
  428.             case R_GET_B :
  429.                 if (!read_byte())
  430.                     State = R_TIMED_OUT;
  431.                 else
  432.                     if ((cchar & 0x7F) == 'B')
  433.                         State = R_GET_SEQ;
  434.                     else
  435.                         if (cchar == ENQ)
  436.                             State = R_SEND_ACK;
  437.                         else
  438.                             State = R_GET_DLE;
  439.                 break;
  440.  
  441.             case R_GET_SEQ :
  442.                 if (!read_byte())
  443.                     State = R_TIMED_OUT;
  444.                 else
  445.                     if (cchar == ENQ)
  446.                         State = R_SEND_ACK;
  447.                     else
  448.                     {
  449.                         if (Quick_B && Use_CRC)
  450.                             lchecksm = crc_16 = -1;
  451.                         else
  452.                             lchecksm = 0;
  453.  
  454.                         block_num = cchar - '0';
  455.  
  456.                         do_checksum(cchar);
  457.  
  458.                         i = 0;
  459.                         State = R_GET_DATA;
  460.                     }
  461.                 break;
  462.  
  463.             case R_GET_DATA :
  464.                 r_counter = 0;
  465.                 if (!read_masked_byte())
  466.                     State = R_TIMED_OUT;
  467.                 else
  468.                     if ((cchar == ETX) && !masked)
  469.                     {
  470.                         do_checksum(ETX);
  471.                         State = R_GET_CHECKSUM;
  472.                     }
  473.                     else
  474.                     {
  475.                         r_buffer[i] = cchar;
  476.                         i = i + 1;
  477.                         do_checksum(cchar);
  478.                     }
  479.                 break;
  480.  
  481.             case R_GET_CHECKSUM :
  482.                 if (!read_masked_byte())
  483.                     State = R_TIMED_OUT;
  484.                 else
  485.                 {
  486.                     if (Quick_B && Use_CRC)
  487.                     {
  488.                         lchecksm = upd_CRC (cchar);
  489.  
  490.                         if (!read_masked_byte())
  491.                             new_cks = lchecksm ^ 0xFF;
  492.                         else
  493.                         {
  494.                             lchecksm = upd_CRC (cchar);
  495.                             new_cks = 0;
  496.                         }
  497.                     }
  498.                     else
  499.                         new_cks = cchar;
  500.  
  501.                     if (new_cks != lchecksm)
  502.                         State = R_TIMED_OUT;
  503.                     else
  504.                         if (r_buffer[0] == 'F') /* Watch for Failure Packet */
  505.                             State = R_SUCCESS;  /* which is always accepted */
  506.                         else
  507.                             if (block_num == seq_num) /* Watch for dup block */
  508.                                 State = R_SEND_ACK;
  509.                             else
  510.                                 if (block_num != next_seq)
  511.                                     State = R_TIMED_OUT; /* Bad sequence number */
  512.                                 else
  513.                                     State = R_SUCCESS;
  514.                 }
  515.                 break;
  516.  
  517.             case R_TIMED_OUT :
  518.                 errors = errors + 1;
  519.  
  520.                 if ((errors > MAX_ERRORS) || (from_send_packet))
  521.                     return( FALSE );
  522.  
  523.                 lc_put(port, NAK);
  524.  
  525.                 if (from_send_packet)
  526.                     return( FALSE );
  527.  
  528.                 State = R_GET_DLE;
  529.                 break;
  530.  
  531.             case R_SEND_ACK :
  532.                 send_ack();
  533.                 State = R_GET_DLE;        /* wait for the next block */
  534.                 break;
  535.  
  536.             case R_SUCCESS :
  537.                 seq_num = block_num;
  538.                 r_size = i;
  539.                 packet_received = TRUE;
  540.                 return( TRUE );
  541.         }
  542.     }
  543. }
  544.  
  545. static    void    send_data (Buffer_Number)
  546. int    Buffer_Number;
  547. {
  548.     int    i;
  549.     register PACKET    *p;
  550.  
  551.     s_counter = 0;
  552.     p = &SA_Buf [Buffer_Number];
  553.     if (Quick_B && Use_CRC)
  554.         lchecksm = crc_16 = -1;
  555.     else
  556.         lchecksm = 0;
  557.  
  558.     lc_put(port, DLE);
  559.     lc_put(port, 'B');
  560.  
  561.     lc_put(port, p->seq + '0');
  562.     do_checksum(p->seq + '0');
  563.  
  564.     for (i = 0; i<=p->num; i++ )
  565.     {
  566.         send_masked_byte(p->buf[i]);
  567.         do_checksum(p->buf[i]);
  568.     }
  569.  
  570.     lc_put(port, ETX);
  571.     do_checksum (ETX);
  572.  
  573.     if (Quick_B && Use_CRC)
  574.         send_masked_byte (lchecksm >> 8);
  575.  
  576.     send_masked_byte(lchecksm);
  577. }
  578.  
  579. /*
  580. ** ReSync is called to restablish syncronism with the remote.  This is
  581. ** accomplished by sending <ENQ><ENQ> and waiting for the sequence
  582. ** <DLE><d><DLE><d> to be received, ignoring everything else.
  583. **
  584. ** Return is -1 on time out, else the digit <d>.
  585. */
  586. #define    GET_FIRST_DLE        1
  587. #define    GET_FIRST_DIGIT        2
  588. #define    GET_SECOND_DLE        3
  589. #define    GET_SECOND_DIGIT    4
  590.  
  591. static    int    ReSync()
  592. {
  593.     int    State, Digit_1;
  594.  
  595.     lc_put(port, ENQ);     /* Send <ENQ><ENQ> */
  596.     lc_put(port, ENQ);
  597.     State = GET_FIRST_DLE;
  598.  
  599.     while(1)
  600.     {
  601.         switch (State)
  602.         {
  603.             case GET_FIRST_DLE :
  604.                 if( !read_byte() )
  605.                     return( -1 );
  606.                 if( cchar == DLE )
  607.                     State = GET_FIRST_DIGIT;
  608.                 break;
  609.             case GET_FIRST_DIGIT :
  610.                 if( !read_byte() )
  611.                     return( -1 );
  612.                 if( (cchar >= '0') && (cchar <= '9') )
  613.                 {
  614.                     Digit_1 = cchar;
  615.                     State = GET_SECOND_DLE;
  616.                 }
  617.                 break;
  618.             case GET_SECOND_DLE :
  619.                 if( !read_byte() )
  620.                     return( -1 );
  621.                 if( cchar == DLE )
  622.                     State = GET_SECOND_DIGIT;
  623.                 break;
  624.             case GET_SECOND_DIGIT :
  625.                 if( !read_byte() )
  626.                     return( -1 );
  627.                 if( (cchar >= '0') && (cchar <= '9') )
  628.                 {
  629.                     if( Digit_1 == cchar )
  630.                         return( cchar );
  631.                     else
  632.                     {
  633.                         Digit_1 = cchar;
  634.                         State = GET_SECOND_DLE;
  635.                     }
  636.                 }
  637.                 else
  638.                     State = GET_SECOND_DLE;
  639.                 break;
  640.         }
  641.     }
  642. }
  643.  
  644. /*
  645. ** get_ACK is called to wait until the SA_Buf indicated by ack_SA
  646. ** has been ACKed by the host.
  647. */
  648. static    int    get_ACK()
  649. {
  650.     int    State, errors, block_num, i;
  651.     int    Sent_ENQ;
  652.     int    SA_Index;
  653.  
  654.     packet_received = FALSE;
  655.     errors = 0;
  656.     Sent_ENQ = FALSE;
  657.     State = S_GET_DLE;
  658.  
  659.     while( TRUE )
  660.     {
  661.         switch (State) {
  662.         case S_GET_DLE :
  663. /*
  664.             if (_abort_flag)
  665.             {
  666.                 send_failure ('A');
  667.                 return( FALSE );
  668.             }
  669. */
  670.  
  671.             if (!read_byte())
  672.                 State = S_TIMED_OUT;
  673.             else if (cchar == DLE)
  674.                 State = S_GET_NUM;
  675.             else if (cchar == NAK)
  676.             {
  677.                 if (++errors > MAX_ERRORS)
  678.                     return( FALSE );
  679.                 State = S_SEND_ENQ;
  680.             }
  681.             else if (cchar == ETX)
  682.                 State = S_SEND_NAK;
  683.             break;
  684.  
  685.         case S_GET_NUM :
  686.             if (!read_byte())
  687.                 State = S_TIMED_OUT;
  688.             else if ((cchar >= '0') && (cchar <= '9'))
  689.                 State = S_HAVE_ACK;    /* Received ACK */
  690.             else if (cchar == 'B')
  691.                 State = S_GET_PACKET; /* Try to get packet */
  692.             else if (cchar == NAK)
  693.             {
  694.                 if (++errors > MAX_ERRORS)
  695.                     return( FALSE );
  696.                 State = S_SEND_ENQ;
  697.             }
  698.             else
  699.                 State = S_TIMED_OUT;
  700.             break;
  701.  
  702.         case S_GET_PACKET :
  703.             if (read_packet (TRUE, TRUE))
  704.             {
  705.                 if (r_buffer [0] == 'F')
  706.                 {
  707.                     send_ack();
  708.                     return( FALSE );
  709.                 }
  710.                 else
  711.                     return( TRUE );
  712.             }
  713.  
  714.             State = S_TIMED_OUT; /* On a bad receive, try again */
  715.             break;
  716.         case S_HAVE_ACK:
  717.             block_num = cchar - '0';
  718.             if (SA_Buf [ack_SA].seq == block_num)
  719.             {    /* This is the one we're waiting for */
  720.                 ack_SA = incr_SA(ack_SA);
  721.                 SA_Waiting--;
  722.                 return( TRUE );
  723.             }
  724.             else
  725.                 if (SA_Buf [incr_SA (ack_SA)].seq == block_num)
  726.                 {    /* Must have missed an ACK */
  727.                     ack_SA = incr_SA (ack_SA);
  728.                     ack_SA = incr_SA (ack_SA);
  729.                     SA_Waiting -= 2;
  730.                     return( TRUE );
  731.                 }
  732.                 else 
  733.                     if (SA_Buf [ack_SA].seq == incr_seq (block_num))
  734.                     {
  735.                         if( Sent_ENQ )
  736.                             State = S_SEND_DATA;
  737.                         else
  738.                             State = S_GET_DLE;
  739.                     }
  740.                     else
  741.                         State = S_TIMED_OUT;
  742.             Sent_ENQ = FALSE;
  743.             break;
  744.         case S_TIMED_OUT :
  745.             if (++errors > MAX_ERRORS)
  746.                 return( FALSE );
  747.  
  748.             State = S_SEND_ENQ;
  749.             break;
  750.  
  751.         case S_SEND_NAK :
  752.             if (++errors > MAX_ERRORS)
  753.                 return( FALSE );
  754.  
  755.             lc_put(port, NAK);
  756.  
  757.             State = S_GET_DLE;
  758.             break;
  759.  
  760.         case S_SEND_ENQ :
  761.             if (++errors > MAX_ERRORS)
  762.                 return( FALSE );
  763.             cchar = ReSync();
  764.             if( cchar == -1 )
  765.                 State = S_SEND_ENQ;
  766.             else
  767.                 State = S_HAVE_ACK;
  768.             Sent_ENQ = TRUE;
  769.             break;
  770.  
  771.         case S_SEND_DATA :
  772.             SA_Index = ack_SA;
  773.  
  774.             for (i = 1; i<=SA_Waiting; i++ )
  775.             {
  776.                 send_data (SA_Index);
  777.                 SA_Index = incr_SA (SA_Index);
  778.             }
  779.  
  780.             State = S_GET_DLE;
  781.             Sent_ENQ = FALSE;
  782.             break;
  783.         }
  784.     }
  785. } /* get_ACK */
  786.  
  787. static int    send_packet (size)
  788. int    size;
  789. {
  790.     if (SA_Waiting == SA_Max)
  791.         if (!get_ACK())
  792.             return( FALSE );
  793.  
  794.     seq_num = incr_seq (seq_num);
  795.     SA_Buf [fill_SA].seq = seq_num;
  796.     SA_Buf [fill_SA].num = size;
  797.     send_data (fill_SA);
  798.     fill_SA = incr_SA (fill_SA);
  799.     SA_Waiting = SA_Waiting + 1;
  800.     return( TRUE );
  801. }
  802. /*
  803. ** SA_Flush is called after sending the last packet to get host's
  804. ** ACKs on outstanding packets.
  805. */
  806. static    int    SA_Flush()
  807. {
  808.     while( SA_Waiting != 0 )
  809.         if (!get_ACK())
  810.             return( FALSE );
  811.     return( TRUE );
  812. }
  813.  
  814. /* Send_File is called to send a file to the host */
  815. static    int    send_file(name)
  816. char    name[];
  817. {
  818.     int    fd;
  819.     int    n;
  820.     register PACKET    *p;
  821.  
  822.     fd = open(name, (O_BINARY | O_RDONLY));
  823.  
  824.     if (fd < 0)
  825.       {
  826.         send_failure('E');
  827.         wperror("** Cannot find that file **");
  828.         return( FALSE );
  829.     }
  830.  
  831.     do
  832.     {
  833.         p = &SA_Buf [fill_SA];
  834.         p->buf[0] = 'N';
  835.         n = read(fd, &p->buf[1], buffer_size);
  836.  
  837.         if (n > 0)
  838.         {
  839.             if (send_packet (n) == FALSE)
  840.                 return( FALSE );
  841.             wgotoxy(4, 1);
  842.             wprintf("Sent Block: %d", blkct++);
  843.         }
  844.     } while( n == buffer_size );
  845.  
  846.     close (fd);
  847.  
  848.     if (n < 0)
  849.     {
  850.         send_failure ('E');
  851.         wperror("** Read failure...aborting **");
  852.         return(FALSE);
  853.     }
  854.  
  855. /* Inform host that the file was sent */
  856.     p = &SA_Buf [fill_SA];
  857.     p->buf[0] = 'T';
  858.     p->buf[1] = 'C';
  859.  
  860.     if (send_packet(2) == FALSE)
  861.         return( FALSE );
  862.     else
  863.     {
  864.         wputs( "Waiting for host..." );
  865.         if (!SA_Flush())
  866.             return( FALSE );
  867.         return( TRUE );
  868.     }
  869. }
  870.  
  871. /*
  872. ** do_transport_parameters is called when a Packet type of + is received.
  873. ** It sends a packet of our local Quick B parameters and sets the Our_xx
  874. ** parameters to the minimum of the sender's and our own parameters.
  875. */
  876. static    void do_transport_parameters()
  877. {
  878.     register PACKET    *p;
  879.  
  880.     His_WS = r_buffer [1];     /* Pick out Sender's parameters */
  881.     His_WR = r_buffer [2];
  882.     His_BS = r_buffer [3];
  883.     His_CM = r_buffer [4];
  884.  
  885.     p = &SA_Buf [fill_SA];
  886.     p->buf [0] = '+';  /* Prepare to return our own parameters */
  887.     p->buf [1] = DEF_WS;
  888.     p->buf [2] = DEF_WR;
  889.     p->buf [3] = DEF_BS;
  890.     p->buf [4] = DEF_CM;
  891.     p->buf [5] = DEF_DQ;
  892.  
  893.     if (!send_packet (5))
  894.         return;
  895.  
  896.     if (SA_Flush())                 /* Wait for host's ACK on our packet */
  897.     {
  898. /* Take minimal subset of Transport Params. */
  899. /* If he can send ahead, we can receive it. */
  900.         Our_WR = (His_WS < DEF_WR) ? His_WS : DEF_WR;
  901.  
  902. /* If he can receive send ahead, we can send it. */
  903.         Our_WS = (His_WR < DEF_WS) ? His_WR : DEF_WS;
  904.  
  905.         Our_BS = His_BS < DEF_BS ? His_BS : DEF_BS;
  906.  
  907.         Our_CM = His_CM < DEF_CM ? His_CM : DEF_CM;
  908.  
  909.         if (Our_BS == 0)
  910.             Our_BS = 4;    /* Default */
  911.  
  912.         buffer_size = Our_BS * 128;
  913.  
  914.         Quick_B = TRUE;
  915.  
  916.         if (Our_CM == 1)
  917.             Use_CRC = TRUE;
  918.  
  919.         if (Our_WS != 0)
  920.         {
  921.             SA_Enabled = TRUE;
  922.             SA_Max     = MAX_SA;
  923.         }
  924.     }
  925. }
  926.  
  927. /*
  928.   do_application_parameters is called when a ? packet is received.
  929.   This version ignores the host's packet and returns a ? packet
  930.   saying that normal B Protocol File Transfer is supported.
  931.   (Well, actually it says that no extended application packets are
  932.    supported.  The T packet is assumed to be standard.) */
  933.  
  934. static    void    do_application_parameters()
  935. {
  936.     register PACKET    *p;
  937.  
  938.     p = &SA_Buf [fill_SA];
  939.     p->buf[0] = '?';     /* Build the ? packet */
  940.     p->buf[1] = 1;             /* The T packet flag  */
  941.  
  942.     if (send_packet (1))            /* Send the packet    */
  943.         SA_Flush();
  944. }
  945.  
  946. /* Receive_File is called to receive a file from the host */
  947. static    int    receive_file (name)
  948. char    name[];
  949. {
  950.     int    fd;
  951.     unsigned  bytes;
  952.  
  953.     _fmode = O_BINARY;
  954.     fd = creat(name,(S_IREAD | S_IWRITE) );
  955.  
  956.     if (fd < 0)
  957.     {
  958.         wperror("** Cannot open file...aborting **");
  959.         send_failure('E');
  960.         return( FALSE );
  961.     }
  962.  
  963.     send_ack();
  964.  
  965. /* Process each incoming packet until 'TC' packet received or failure */
  966.  
  967.     while( TRUE )
  968.     {
  969.         if (read_packet (FALSE, FALSE))
  970.         {
  971.             switch (r_buffer[0]) {
  972.             case 'N' :
  973.                 bytes = r_size - 1;
  974.  
  975.                 if (write(fd, &r_buffer[1], bytes) != bytes )
  976.                 {
  977.                     wperror("** Write failure...aborting **");
  978.                     close (fd);
  979.                     send_failure ('E');
  980.                     return( FALSE );
  981.                 }
  982.                 send_ack();
  983.                 wgotoxy(4,1);
  984.                 wprintf("Received Block: %d", blkct++);
  985.                 break;
  986.  
  987.             case 'T' :
  988.                 if (r_buffer[1] == 'C')
  989.                 {
  990.                     close(fd);
  991.  
  992.                     send_ack();
  993.                     return( TRUE );
  994.                 }
  995.                 else
  996.                 {
  997.                     wperror("** Invalid termination packet...aborting **");
  998.                     close (fd);
  999.                     send_failure ('N');
  1000.                     return( FALSE );
  1001.                 }
  1002.  
  1003.             case 'F' :
  1004.                 send_ack();
  1005.                 wperror("** Failure packet received...aborting **");
  1006.                 close (fd);
  1007.                 return( FALSE );
  1008.             }
  1009.         }
  1010.          else
  1011.         {
  1012.             wperror("** Failed to receive packet...aborting **");
  1013.             close (fd);
  1014.             return( FALSE );
  1015.         }
  1016.     }
  1017. }
  1018.  
  1019. /*
  1020. ** bp_DLE is called from the main program when the character <DLE> is
  1021. ** received from the host.
  1022. **
  1023. ** This routine calls read_packet and dispatches to the appropriate
  1024. ** handler for the incoming packet.
  1025. */
  1026. void    bp_DLE()
  1027. {
  1028.     int    i;
  1029.     int j;
  1030.     char    filename[255];
  1031.     char    str[2];
  1032. /*
  1033. ** Begin by getting the next character.  If it is <B> then enter the
  1034. ** B_Protocol state.  Otherwise simply return.
  1035. */
  1036.     j = wait(port, 10, 0x00);
  1037.     if (j != 'B')
  1038.         return;
  1039.  
  1040.     strcpy( str, " " );
  1041.  
  1042.     ack_SA  = 0;    /* Initialize Send-ahead variables */
  1043.     fill_SA = 0;
  1044.     SA_Waiting      = 0;
  1045.     blkct = 0;
  1046.  
  1047. /*  <DLE><B> received; begin B Protocol */
  1048.  
  1049.     r_counter   = 0;
  1050.     s_counter   = 0;
  1051.  
  1052.     if (Quick_B)
  1053.     {
  1054.         wputs ("*** Quick B is in effect ***\n");
  1055.  
  1056.         if (Use_CRC)
  1057.             wputs ("*** Using CRC ***\n");
  1058.  
  1059.         if (Our_WS != 0) /* Allow send-ahead if other end agrees */
  1060.             wputs ("*** Send-Ahead enabled ***\n");
  1061.     }
  1062.  
  1063.     if (read_packet (TRUE, FALSE))
  1064.     {
  1065. /* Dispatch on the type of packet just received */
  1066.  
  1067.             switch (r_buffer[0]) {
  1068.         case 'T':     /* File Transfer Application */
  1069.             switch (r_buffer[1]) {
  1070.             case 'D' :    /* downloading */
  1071.                 break;
  1072.             case 'U' :    /* uploading */
  1073.                 break;
  1074.             default :
  1075.                 send_failure('N');
  1076.                 return;
  1077.             }
  1078.  
  1079.             switch (r_buffer[2]) {
  1080.             case 'A':    /* ascii file */
  1081.                 break;
  1082.             case 'B':    /* binary file */
  1083.                 break;
  1084.             default :
  1085.                 send_failure('N');        /* not implemented */
  1086.                 return;
  1087.             }
  1088.  
  1089.             i = 2;
  1090.             strcpy( filename, "" );
  1091.  
  1092.             while( (r_buffer[i] != 0) && (i < r_size) )
  1093.             {
  1094.                 i = i + 1;
  1095.                 str[0] = r_buffer[i];
  1096.                 strcat( filename, str );
  1097.             }
  1098.  
  1099.             if (r_buffer[1] == 'U')
  1100.             {
  1101.                 if( send_file(filename) )
  1102.                     wperror("Transfer completed!" );
  1103.             }
  1104.             else
  1105.             {
  1106.                 if( receive_file(filename) )
  1107.                     wperror("Transfer completed!" );
  1108.             }
  1109.             break;
  1110.  
  1111.         case '+':          /* Received Transport Parameters Packet */
  1112.             do_transport_parameters();
  1113.             break;
  1114.  
  1115.         case '?':          /* Received Application Parameters Packet */
  1116.             do_application_parameters();
  1117.             break;
  1118.  
  1119.         default:    /* Unknown packet; tell host we don't know */
  1120.             send_failure ('N');
  1121.                     break;
  1122.  
  1123.         }  /* of case */
  1124.     }     /* of if read_packet the */
  1125. }
  1126.