home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 098.lha / quickb.c < prev    next >
Text File  |  1986-11-20  |  26KB  |  1,108 lines

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