home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 272.lha / xprquickb / protocol.c < prev    next >
C/C++ Source or Header  |  1989-08-05  |  25KB  |  1,118 lines

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