home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / duucp-1.17 / AU-117b4-src.lha / src / uucico / gio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-28  |  19.7 KB  |  1,081 lines

  1. /*
  2.  *  GIO.C    WINDOWED G PROTOCOL
  3.  *
  4.  *  written from scratch, except the checksum routine which was
  5.  *  rewritten but based on the old one.
  6.  *
  7.  *  WINDOW SIZE:    When changing the window size be sure there
  8.  *            are enough buffers available for pending txs.
  9.  *
  10.  *  GIO.C (c)Copyright 1989, Matthew Dillon, All Rights Reserved
  11.  *  extended to window size of 7 by Jack J. Rouse
  12.  *
  13.  *  Added variable packetsize (SegSize, TxSegSize). <CB>
  14.  *
  15.  */
  16.  
  17. #include "includes.h"
  18.  
  19. typedef unsigned char  ubyte;
  20. typedef unsigned short uword;
  21.  
  22. typedef struct {
  23.     ubyte    Dle;        /*    Literal ASCII DLE                */
  24.     ubyte    K;        /*    data size 2^(K+4) except K=0 means no data  */
  25.     ubyte    CL,CH;        /*    MAGIC - chksum(data) ^ C    */
  26.     ubyte    C;
  27.     ubyte    X;        /*    K ^ C0 ^ C1 ^ C         */
  28. } Frame;
  29.  
  30. typedef struct {
  31.     ubyte    CType;        /*    bits 7-6 of C        */
  32.     ubyte    CCmd;        /*    bits 5-3 of C        */
  33.     ubyte    CSeq;        /*    bits 2-0 of C        */
  34.     ubyte    PLen;        /*    pre-data (2 bytes) for SHORTDATA type */
  35.     ubyte    *Data;        /*    implies CType=LONGDATA or SHORTDATA */
  36.     uword    DLen;        /*    length of data        */
  37. } Packet;
  38.  
  39. Prototype int gwrdata (FILE *);
  40. Prototype int gwrmsg (char *);
  41. Prototype int grddata (FILE *);
  42. Prototype int grdmsg (char *, int);
  43. Prototype int gturnon (int);
  44. Prototype int gturnoff (void);
  45. Prototype void ResetGIO (void);
  46.  
  47. Prototype int ReducedTimeout;
  48.  
  49. int ReducedTimeout;
  50.  
  51. Local char *GetTxBuf (void);
  52. Local int SendDataPacket (unsigned char *, int);
  53. Local int RecvDataPacket (char **);
  54. Local int GetData (int, Packet *);
  55. Local int RecvdAck (char);
  56. Local int WriteCtlPacket (int);
  57. Local int WritePacket (Packet *, int);
  58. Local int ReadPacket (Packet *, int, int);
  59. Local int CheckSum (unsigned char *, int);
  60. Local void FrameToPacket (Frame *, Packet *, unsigned char *);
  61. Local int LenToK (unsigned short);
  62.  
  63. #define SUCCESS 0
  64. #define FAIL    1
  65.  
  66. #define MAGIC        0125252
  67. #define DLE        0x10
  68. #define WINDOWSIZE  7
  69. #define SEGSIZEK    2        /*  64 bytes ??        */
  70. #define SEGSIZEMAX  9        /*  4096 bytes max    <CB> */
  71.  
  72. #define SUB1(var)   (((var)-1)&7)
  73.  
  74. #define CT_CONTROL    (0 << 6)
  75. #define CT_ALTCHN    (1 << 6)
  76. #define CT_LONGDATA    (2 << 6)
  77. #define CT_SHORTDATA    (3 << 6)
  78. #define CT_MASK     (3 << 6)
  79.  
  80. #define CC_CLOSE    (1 << 3)
  81. #define CC_RJ        (2 << 3)
  82. #define CC_SRJ        (3 << 3)
  83. #define CC_RR        (4 << 3)
  84. #define CC_INITC    (5 << 3)
  85. #define CC_INITB    (6 << 3)
  86. #define CC_INITA    (7 << 3)
  87. #define CC_MASK     (7 << 3)
  88.  
  89. #define SEQ_MASK    7
  90.  
  91. #define WAIT_ACK    1
  92. #define WAIT_DATA    2
  93. #define WAIT_CONTROL    3
  94.  
  95. #define MaxPktSize    4096
  96.  
  97. char    RxBuf [MaxPktSize + 4];
  98. char    *TxBuf [8];
  99.  
  100.                 /*  TRANSMIT STAGE        */
  101. char    TxSeq = 0;        /*  Last send packet        */
  102. char    TxPend= 0;        /*  hasn't been acked yet   */
  103. uword    TxWinSize;        /*  1 or 2 (max 7)        */
  104. uword    TxSegSize;        /*  maximum segment size    */
  105. char    TxSegK;         /*  K for TxSegSize        */
  106. Packet    TxPacket[8];        /*  contents of last packet */
  107.  
  108.                 /*  RECEIVE STAGE        */
  109. char    RxSeq = 0;        /*  Last valid recv pkt     */
  110. char    RxRdy = 0;        /*  Has come in..        */
  111. char    RxRetry = 8;
  112. char    RxNotAcked = 0;     /*  We have yet to ack it   */
  113. Packet    RxPacket;        /*  The packet that has come in */
  114.  
  115. Prototype int Tot_Retries;
  116. Prototype int Tot_Packets;
  117.  
  118. int
  119.     Tot_Retries,
  120.     Tot_Packets;
  121.  
  122. void
  123. ResetGIO (void)
  124. {
  125.     TxSeq = 0;
  126.     TxPend= 0;
  127.     TxWinSize = 0;
  128.     TxSegSize = 0;
  129.     TxSegK = 0;
  130.     RxSeq = 0;
  131.     RxRdy = 0;
  132.     RxRetry = 8;
  133.     RxNotAcked = 0;
  134.  
  135.     return;
  136. }
  137.  
  138. /*
  139.  *  Get Transmit Buffer.  Note that some space to the left is available
  140.  */
  141.  
  142. Local
  143. char *
  144. GetTxBuf (void)
  145. {
  146.     static int
  147.         index = 0;
  148.  
  149.     if (++index > TxWinSize)
  150.         index = 0;
  151.  
  152.     if (TxBuf [index] == NULL &&
  153.        (TxBuf [index] = (char *) malloc (MaxPktSize + 4)) == NULL) {
  154.         printf("Out of memory in GetTxBuf.");
  155.         /* could handle this case better, but it should be rare */
  156.         xexit (1);
  157.     }
  158.     return (TxBuf [index] + 2);
  159. }
  160.  
  161. int
  162. gwrdata (FILE *fi)
  163. {
  164.     if (debug > 7)
  165.         printf ("GWRDATA: ");
  166.  
  167.     for (;;) {
  168.         int
  169.             bytes;
  170.         char
  171.             *buf = GetTxBuf ();
  172.  
  173.         if ((bytes = fread (buf, 1, TxSegSize, fi)) <= 0)
  174.             break;
  175.  
  176.         BytesOut += bytes;
  177.  
  178.         if (SendDataPacket (buf, bytes) != SUCCESS) {
  179.             if (debug > 7)
  180.                 printf ("GWR Failed\n");
  181.             return FAIL;
  182.         }
  183.         if (debug > 7)
  184.             printf("\nGWROK ");
  185.     }
  186.  
  187.     {
  188.         char
  189.             *buf = GetTxBuf ();
  190.  
  191.         if (SendDataPacket (buf, 0) != SUCCESS) {
  192.             if (debug > 7)
  193.                 printf ("GWR Failed (last)\n");
  194.             return FAIL;
  195.         }
  196.     }
  197.  
  198.     if (debug > 7)
  199.         printf ("\nGWFile Last Ack\n");
  200.  
  201.     while (TxPend) {
  202.         if (GetData (WAIT_ACK, NULL) == FAIL)
  203.             return FAIL;
  204.     }
  205.  
  206.     if (debug > 7)
  207.         printf ("success\n");
  208.  
  209.     return SUCCESS;
  210. }
  211.  
  212. /*
  213.  *  Write message to the other guy.
  214.  *
  215.  *  NOTE: LONGDATA packets used exclusively and \0 fill to end.
  216.  */
  217.  
  218. int
  219. gwrmsg (char *str)
  220. {
  221.     int
  222.         len = strlen (str) + 1;      /*  type + str + \0  */
  223.  
  224.     if (debug > 7)
  225.         printf ("GWRMSG: %s\n", str);
  226.  
  227.     while (len > TxSegSize) {
  228.         char
  229.             *buf = GetTxBuf ();
  230.  
  231.         movmem (str, buf, TxSegSize);
  232.         if (debug > 7)
  233.             printf ("GWR-SEND %d\n", TxSegSize);
  234.  
  235.         if (SendDataPacket (buf, TxSegSize) != SUCCESS)
  236.             return FAIL;
  237.  
  238.         len -= TxSegSize;
  239.         str += TxSegSize;
  240.     }
  241.  
  242.     /*
  243.      *  Find optimal packet size (remember, we must force LONGDATA
  244.      *
  245.      *  Apparently packet sizes less than the agreed upon size are
  246.      *  not allowed ???
  247.      */
  248.  
  249.     {
  250.         int
  251.             siz = TxSegSize;
  252.         char
  253.             *buf = GetTxBuf ();
  254.  
  255.         if (VarPackets) {
  256.             int
  257.                 k = TxSegK;
  258.  
  259.             while (k > 1 && (siz >> 1) >= len) {
  260.                 --k;
  261.                 siz >>= 1;
  262.             }
  263.         }
  264.  
  265.         if (debug > 7)
  266.             printf ("GWR-FNL %d %d\n", len, siz);
  267.  
  268.         movmem (str, buf, len);
  269.         setmem (buf + len, siz - len, 0);
  270.         if (SendDataPacket (buf, siz) != SUCCESS) {
  271.             if (debug > 7)
  272.                 printf ("GWR-FAIL\n");
  273.             return FAIL;
  274.         }
  275.     }
  276.  
  277.     if (debug > 7)
  278.         printf ("GWR Last Ack\n");
  279.  
  280.     while (TxPend) {
  281.         if (GetData (WAIT_ACK, NULL) == FAIL)
  282.             return(FAIL);
  283.     }
  284.  
  285.     if (debug > 7)
  286.         printf ("success\n");
  287.  
  288.     return SUCCESS;
  289. }
  290.  
  291. int
  292. grddata (FILE *fi)
  293. {
  294.     int
  295.         bytes;
  296.     char
  297.         *buf;
  298.  
  299.     if (debug > 7)
  300.         printf ("GRDDATA\n");
  301.  
  302.     while ((bytes = RecvDataPacket (&buf)) > 0) {
  303.         if (debug > 7)
  304.             printf ("GRDDATA blk %d\n", bytes);
  305.  
  306.         fwrite (buf, 1, bytes, fi); /* FIXME - check result */
  307.         BytesIn += bytes;
  308.     }
  309.  
  310.     if (debug > 7)
  311.         printf ("GRDDATA end %d\n", bytes);
  312.  
  313.     if (bytes < 0)
  314.         return FAIL;
  315.  
  316.     return SUCCESS;
  317. }
  318.  
  319. int
  320. grdmsg (char *buf, int maxlen)
  321. {
  322.     int
  323.         i,
  324.         n,
  325.         slen;
  326.     char
  327.         *ptr;
  328.  
  329.     i = 0;
  330.     if (debug > 7)
  331.         printf ("GRDMSG\n");
  332.  
  333.     while ((n = RecvDataPacket (&ptr)) > 0) {
  334.         ptr [n] = 0;
  335.         slen = strlen (ptr);
  336.         if (slen > maxlen - 1) {
  337.             printf ("GRDMSG: Buffer overflow!\n");
  338.             return FAIL;
  339.         }
  340.         movmem (ptr, buf + i, slen);
  341.         buf [i + slen] = 0;
  342.         if (slen != n)
  343.             break;
  344.         i += slen;
  345.         maxlen -= slen;
  346.     }
  347.  
  348.     if (debug > 7)
  349.         printf ("GRDMSGEND %d (%d) %s\n", n, i, buf);
  350.  
  351.     if (n < 0) {
  352.         buf [0] = 0;
  353.         return FAIL;
  354.     }
  355.  
  356.     return SUCCESS;
  357. }
  358.  
  359. Local
  360. int
  361. SendDataPacket (ubyte *buf, int bytes)
  362. {
  363.     Packet
  364.         P;
  365.  
  366.     /*
  367.      *  If window exhausted we must wait for at least one ack.
  368.      */
  369.  
  370.     while (TxPend == TxWinSize) {
  371.         if (GetData (WAIT_ACK, NULL) == FAIL)
  372.             return FAIL;
  373.     }
  374.  
  375.     TxSeq = (TxSeq + 1) & 7;    /*  next Tx packet  */
  376.  
  377.     /*
  378.      *  Figure out best fit packet size.  Apparently packets smaller
  379.      *  than the agreed upon size are not allowed ???
  380.      */
  381.  
  382.     if (VarPackets) {
  383.         int
  384.             k = TxSegK;
  385.  
  386.         P.DLen = TxSegSize;
  387.         while (k > 1 && P.DLen && (P.DLen >> 1) >= bytes) {
  388.             --k;
  389.             P.DLen >>= 1;
  390.         }
  391.     }
  392.     else
  393.         P.DLen = TxSegSize;
  394.  
  395.     if (bytes < P.DLen) {
  396.         uword
  397.             extra = P.DLen - bytes;
  398.  
  399.         setmem (buf + bytes, extra, 0);
  400.         if (extra <= 127) {
  401.             P.PLen = 1;
  402.             buf [-1] = extra;
  403.         }
  404.         else {
  405.             P.PLen = 2;
  406.             buf [-2] = 0x80 | extra;
  407.             buf [-1] = (extra >> 7);
  408.         }
  409.         P.CType = CT_SHORTDATA;
  410.     }
  411.     else {
  412.         P.PLen = 0;
  413.         P.CType = CT_LONGDATA;
  414.     }
  415.  
  416.     P.CCmd = TxSeq << 3;        /*    transmit sequence number */
  417.     P.CSeq = RxSeq;         /*    last valid received pkt  */
  418.     P.Data = buf;
  419.  
  420.     if (debug > 7)
  421.         printf ("WRITE DATA PACKET txseq=%d rxack=%d\n", TxSeq, P.CSeq);
  422.  
  423. #ifdef NOTDEF
  424.     RxNotAcked = 0;         /*    We've acked the rx packet */
  425. #else
  426.     if (RxNotAcked) {        /*    always send CC_RR packets */
  427.         WriteCtlPacket (CC_RR | RxSeq);
  428.         RxNotAcked = 0;
  429.     }
  430. #endif
  431.  
  432.     TxPacket [TxSeq] = P;
  433.     ++TxPend;
  434.  
  435.     WritePacket (&TxPacket [TxSeq], 1);
  436.     ++Tot_Packets;
  437.  
  438.     return SUCCESS;
  439. }
  440.  
  441. Local
  442. int
  443. RecvDataPacket (char **pbuf)
  444. {
  445.     if (RxRdy == 0) {
  446.         if (GetData (WAIT_DATA, NULL) != SUCCESS)
  447.             return -1;
  448.     }
  449.     *pbuf = RxPacket.Data;
  450.     RxRdy = 0;
  451.  
  452.     return (int) RxPacket.DLen;
  453. }
  454.  
  455. int
  456. gturnon (int master)
  457. {
  458.     Packet
  459.         P;
  460.     int
  461.         retry = 5,
  462.         windowsize = WINDOWSIZE,  /*  our prefered window size      */
  463.         segsize = SEGSIZEK;      /*  our prefered segment size   */
  464.  
  465.     if (WindowSize < windowsize)      /*  command line override      */
  466.         windowsize = WindowSize;
  467.  
  468.     if (SegSize > segsize && SegSize < SEGSIZEMAX)
  469.         segsize = SegSize;      /*  added by <CB> */
  470.  
  471.     if (debug > 0)
  472.         printf ("Proposed SegSize is %d\n", segsize);
  473.  
  474.     if (master) {
  475.         while (retry > 0) {
  476.             WriteCtlPacket (CC_INITA | windowsize);
  477.             if (GetData (WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITA) {
  478.                 if (P.CSeq && P.CSeq < windowsize)
  479.                     windowsize = P.CSeq;
  480.                 break;
  481.             }
  482.             --retry;
  483.         }
  484.         while (retry > 0) {
  485.             WriteCtlPacket (CC_INITB | (segsize - 1));
  486.             if (GetData (WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITB) {
  487.                 if (P.CSeq < segsize - 1)
  488.                     segsize = P.CSeq + 1;
  489.                 break;
  490.             }
  491.             --retry;
  492.         }
  493.         while (retry > 0) {
  494.             WriteCtlPacket (CC_INITC | windowsize);
  495.             if (GetData (WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITC) {
  496.                 if (P.CSeq && P.CSeq < windowsize)
  497.                     windowsize = P.CSeq;
  498.                 break;
  499.             }
  500.             --retry;
  501.         }
  502.     }
  503.     else {
  504.         while (retry > 0) {
  505.             if (GetData (WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITA) {
  506.                 WriteCtlPacket (CC_INITA | windowsize);
  507.                 if (P.CSeq && windowsize > P.CSeq)
  508.                     windowsize = P.CSeq;
  509.                 break;
  510.             }
  511.             --retry;
  512.         }
  513.         while (retry > 0) {
  514.             if (GetData (WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITB) {
  515.                 WriteCtlPacket (CC_INITB | (segsize - 1));
  516.                 if (P.CSeq < segsize - 1)
  517.                     segsize = P.CSeq + 1;
  518.                 break;
  519.             }
  520.             --retry;
  521.         }
  522.         while (retry > 0) {
  523.             if (GetData (WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITC) {
  524.                 WriteCtlPacket (CC_INITC | windowsize);
  525.                 if (P.CSeq && windowsize > P.CSeq)
  526.                     windowsize = P.CSeq;
  527.                 break;
  528.             }
  529.             --retry;
  530.         }
  531.     }
  532.  
  533.     TxSegK = segsize;
  534.     TxSegSize = 1 << (TxSegK + 4);
  535.     TxWinSize = windowsize;
  536.  
  537.     xfer.proto [0] = 'g';
  538.     xfer.proto [1] = TxWinSize;
  539.     xfer.proto [2] = TxSegK;
  540.  
  541.     if (debug > 0) {
  542.         printf ("Window Size is %d\n", TxWinSize);
  543.         printf ("Segment Size is %d (%d bytes)\n", TxSegK, TxSegSize);
  544.     }
  545.  
  546.     if (retry == 0)
  547.         return FAIL;
  548.  
  549.     return SUCCESS;
  550. }
  551.  
  552. int
  553. gturnoff (void)
  554. {
  555.     Packet
  556.         P;
  557.     int
  558.         retry = 5;
  559.  
  560.     if (RxNotAcked) { /* ack last data packet sent (presumably master's HY) */
  561.         WriteCtlPacket (CC_RR | RxSeq);
  562.         RxNotAcked = 0;
  563.     }
  564.  
  565.     while (retry > 0) {
  566.         WriteCtlPacket (CC_CLOSE);
  567.         if (GetData (WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_CLOSE)
  568.             return SUCCESS;
  569.         --retry;
  570.     }
  571.  
  572.     return FAIL;
  573. }
  574.  
  575. /*
  576.  *  GetData()
  577.  *
  578.  *  This is the core of the packet protocol.  As soon as we get a satisfactory
  579.  *  terminating condition we return.  However, on unsatisfactory conditions
  580.  *  such as having to send a reject, we attempt to drain any pending data
  581.  *  (i.e. multiple returned rejects) so we do not do multiple resends.
  582.  *
  583.  *  The resend flag only applies on a failure return.
  584.  */
  585.  
  586. Local
  587. int
  588. GetData (int waitfor, Packet *p)
  589. {
  590.     Packet
  591.         P;
  592.     int
  593.         timeout,
  594.         drainmode = 0;
  595.  
  596.     /*
  597.      *  If we haven't acked the last packet we received we must do
  598.      *  so now before we can expect to receive another one!
  599.      */
  600.  
  601.     if (debug > 7)
  602.         printf ("Get-Data waitfor %s\n", (waitfor == WAIT_ACK) ? "WAIT_ACK" : "WAIT_DATA");
  603.  
  604.     if (waitfor == WAIT_ACK)
  605.         timeout = (PacketTimeout) ? PacketTimeout : 5;
  606.     else
  607.         if (waitfor == WAIT_DATA)
  608.             timeout = (PacketTimeout) ? PacketTimeout * 4 : 20;
  609.         else
  610.             timeout = (PacketTimeout) ? PacketTimeout * 4 : 20;
  611.  
  612.     for (;;) {
  613.         /*
  614.          *  due to confusion on connection termination, we do not wait
  615.          *  around trying to retry the final termination acknowlege.
  616.          */
  617.  
  618.         if (ReducedTimeout) {
  619.             if (RxRetry > 2)
  620.                 RxRetry = 2;
  621.             if (timeout > 5)
  622.                 timeout = 5;
  623.         }
  624.         if (RxNotAcked) {            /*    good, send ack for rx'd pkt */
  625.             WriteCtlPacket (CC_RR | RxSeq);
  626.             RxNotAcked = 0;
  627.         }                    /*    bad, timeout on read        */
  628.         if (ReadPacket (&P, (drainmode) ? 0 : timeout, (waitfor == WAIT_DATA)) == FAIL) {
  629.             drainmode = 0;
  630.  
  631.             /*
  632.              * fail if greater than 20% of packets received are retries.
  633.              */
  634. #define ERROR_THRESHOLD (Tot_Packets < 50 || (Tot_Packets/(Tot_Retries+1)) > 4)
  635.  
  636.             /*
  637.              *  If we have timed out waiting for data then send a reject
  638.              */
  639.  
  640.             if (waitfor == WAIT_DATA && RxRetry && ERROR_THRESHOLD) {
  641.                 --RxRetry;
  642.                 /*
  643.                  * sd: To properly drain on errors I found a small
  644.                  *     delay was needed here.
  645.                  */
  646.                 if (NoDelay == 0)
  647.                     Delay (15);
  648.                 ++Tot_Retries;
  649.  
  650.                 if (debug > 7)
  651.                     printf ("\nWAIT-DATA, TIMEOUT, SEND RJ\n");
  652.  
  653.                 WriteCtlPacket (CC_RJ | RxSeq);
  654.                 continue;
  655.             }
  656.  
  657.             /*
  658.              *  If we have timed out waiting for an ack send the entire
  659.              *  window.  We must send the window sometime and it might as
  660.              *  well be now.
  661.              */
  662.  
  663.             if (waitfor == WAIT_ACK && RxRetry && ERROR_THRESHOLD) {
  664.                 int
  665.                     i;
  666.  
  667.                 if (debug > 7)
  668.                     printf ("RESEND %d packets\n", TxPend);
  669.                 for (i = 1; i <= TxPend; ++i) {
  670.                     Packet
  671.                         *pkt = &TxPacket [(TxSeq - TxPend + i) & 7];
  672.  
  673.                     pkt->CSeq = RxSeq;
  674.                     WritePacket (pkt, 1);
  675.                 }
  676.                 --RxRetry;
  677.                 ++Tot_Retries;
  678.                 continue;
  679.             }
  680.  
  681.             if (debug > 7)
  682.                 printf ("COMPLETE FAILURE RxRetry = %d\n", RxRetry);
  683.  
  684.             return FAIL;
  685.         }
  686.  
  687.         /*
  688.          *  valid packet, terminating condition?
  689.          */
  690.  
  691.         RxRetry = 8;
  692.         switch (P.CType) {
  693.             case CT_CONTROL:
  694.                 switch (P.CCmd) {
  695.                     case CC_CLOSE:    /*  End of communication ... not an ACK!       */
  696.                         if (waitfor == WAIT_CONTROL) {
  697.                             *p = P;
  698.                             return SUCCESS;
  699.                         }
  700.                         return FAIL;
  701.                     case CC_RJ:    /*  Reject packet (P.CSeq == last good packet) */
  702.                         RecvdAck (P.CSeq);
  703.                         drainmode = 1;
  704.                         break;
  705.                     case CC_SRJ:    /*  Selective Reject (P.CSeq == bad packet # ) */
  706.                         return FAIL;
  707.                     case CC_RR:    /*  Ack to packet  (P.CSeq == packet # acked)    */
  708. #ifdef NOTDEF
  709.                         if (P.CSeq == ((TxSeq - TxPend) & 7)) {
  710.                             /*
  711.                              * The CSeq packet was previously acknowledged
  712.                              * The receiver apparently has not seen anything since.
  713.                              * This is the same as a rejection.
  714.                              */
  715.                             goto resend;
  716.                         }
  717. #endif
  718.                         if (RecvdAck (P.CSeq) == SUCCESS && waitfor == WAIT_ACK)
  719.                             return SUCCESS;
  720.                         else
  721.                             drainmode = 1;        /* .19  */
  722.                         break;
  723.                     case CC_INITC:
  724.                     case CC_INITB:
  725.                     case CC_INITA:
  726.                         if (waitfor == WAIT_CONTROL) {
  727.                             *p = P;
  728.                             return SUCCESS;
  729.                         }
  730.                         return FAIL;
  731.                 }
  732.                 break;
  733.             case CT_ALTCHN:
  734.                 printf ("ALTCHN packet ??\n");
  735.                 break;
  736.             case CT_LONGDATA:
  737.             case CT_SHORTDATA:
  738.                 {
  739.                 char
  740.                     rxseq = P.CCmd >> 3;
  741.                 char
  742.                     txack = P.CSeq;
  743.  
  744.                 if (RxRdy == 1) {
  745.                     printf ("Got two receive packets without me acking!\n");
  746.                 }
  747.  
  748.                 if (rxseq == RxSeq) {    /*  already got this packet */
  749.                     RxNotAcked = 1;
  750.                     continue;
  751.                     /*  expected packet?        */
  752.                 }
  753.                 else
  754.                 if (rxseq != ((RxSeq + 1) & 7)) {
  755.                     drainmode = 1;
  756.                     printf ("Received sequence %d, expected %d\n", rxseq, (RxSeq + 1) & 7);
  757.                     break;
  758.                 }
  759.  
  760.                 if (debug > 6)
  761.                     printf ("RECV SEQUENCE %d\n", rxseq);
  762.  
  763.                 RecvdAck (txack);    /*  woa */
  764.  
  765.                 /*
  766.                  *  Delay sending the ACK back in case we can combine
  767.                  *  it with the next transmitted packet.
  768.                  */
  769.  
  770.                 RxNotAcked = 1;     /*  we haven't ack'd the rx packet */
  771.  
  772.                 ++Tot_Packets;
  773.  
  774.                 RxSeq = (RxSeq + 1) & 7;
  775.                 RxRdy = 1;
  776.                 RxPacket = P;
  777.                 if (waitfor == WAIT_DATA)
  778.                     return SUCCESS;
  779.                 if (TxPend == 0 && waitfor == WAIT_ACK)
  780.                     return SUCCESS;
  781.                 }
  782.                 break;
  783.         }
  784.     }
  785.  
  786.     return;
  787. }
  788.  
  789. Local
  790. int
  791. RecvdAck (char seq)
  792. {
  793.     int
  794.         i;
  795.  
  796.     /*
  797.      *  which packet was acked?
  798.      */
  799.  
  800.     for (i = 0; i < TxPend; ++i) {
  801.         if (seq == ((TxSeq - i) & 7))
  802.             break;
  803.     }
  804.  
  805.     if (i && i == TxPend) {
  806.         if (seq != ((TxSeq - TxPend) & 7))
  807.             printf ("He acked the wrong packet! %d expected %d\n", seq, TxSeq);
  808.         return FAIL;
  809.     }
  810.  
  811.     if (debug > 7)
  812.         printf ("TxPend %d -> %d\n", TxPend, i);
  813.  
  814.     TxPend = i;
  815.  
  816.     return SUCCESS;
  817. }
  818.  
  819. Local
  820. int
  821. WriteCtlPacket (int cc)
  822. {
  823.     Packet
  824.         pk;
  825.  
  826.     pk.CType = CT_CONTROL;
  827.     pk.CCmd  = cc & CC_MASK;
  828.     pk.CSeq  = cc & SEQ_MASK;
  829.     pk.PLen  = 0;
  830.     pk.DLen  = 0;
  831.     WritePacket (&pk, 0);
  832.  
  833.     return SUCCESS;
  834. }
  835.  
  836. Local
  837. int
  838. WritePacket (Packet *pk, int async)
  839. {
  840.     Frame
  841.         F;
  842.     uword
  843.         sum;
  844.  
  845.     F.Dle = DLE;
  846.     F.C   = pk->CType | pk->CCmd | pk->CSeq;
  847.     F.K   = 9;
  848.  
  849.     if (pk->CType == CT_SHORTDATA || pk->CType == CT_LONGDATA)
  850.         F.K = LenToK (pk->DLen);
  851.     else
  852.         pk->DLen = 0;
  853.  
  854.     sum = MAGIC - (CheckSum (pk->Data - pk->PLen, pk->DLen) ^ F.C);
  855.  
  856.     F.CH  = sum >> 8;
  857.     F.CL  = sum;
  858.     F.X   = F.K ^ F.CH ^ F.CL ^ F.C;
  859.  
  860.     if (debug > 7)
  861.         printf ("WritePacket: F.K = %d F.C = %d.%d.%d\n", F.K, F.C >> 6, (F.C >> 3) & 7, F.C & 7);
  862.  
  863.     if (async)
  864.         xwritea (&F, sizeof (F));
  865.     else
  866.         xwrite (&F, sizeof (F));      /*  write header      */
  867.  
  868.     if (pk->DLen) {         /*    write data    */
  869.         if (async)
  870.             xwritea (pk->Data - pk->PLen, pk->DLen);
  871.         else
  872.             xwrite (pk->Data - pk->PLen, pk->DLen);
  873.     }
  874.  
  875.     return SUCCESS;
  876. }
  877.  
  878. Local
  879. int
  880. ReadPacket (Packet *pk, int timeout, int delay_flg)
  881. {
  882.     Frame
  883.         F;
  884.     int
  885.         c,
  886.         i = 0;
  887.  
  888.     pk->Data = RxBuf;
  889.     pk->CType = 0xFF;
  890.     pk->CCmd  = 0;
  891.     pk->CSeq  = 0;
  892.  
  893.     if (debug > 7)
  894.         printf ("ReadPacket\n");
  895.  
  896.     while ((c = xgetc (timeout, delay_flg)) != EOF) {
  897.         if (debug > 8)
  898.             printf ("RP %d %02x\n", i, c);
  899.  
  900.         switch(i) {
  901.             case 0:
  902.                 if (c == DLE) {
  903.                     F.Dle = c;
  904.                     ++i;
  905.                     if (timeout == 0)
  906.                         timeout = 1;
  907.                 }
  908.                 break;
  909.             case 1:
  910.                 F.K = c;
  911.                 ++i;
  912.                 if (c == DLE) { /*  K only valid 1-9    */
  913.                     F.Dle = c;
  914.                     i = 1;
  915.                 }
  916.                 else
  917.                     if (c == 0 || c > 9)
  918.                         i = 0;
  919.                 break;
  920.             case 2:
  921.                 F.CL = c;
  922.                 ++i;
  923.                 break;
  924.             case 3:
  925.                 F.CH = c;
  926.                 ++i;
  927.                 break;
  928.             case 4:
  929.                 F.C = c;
  930.                 ++i;
  931.                 break;
  932.             case 5:
  933.                 F.X = c;
  934.                 if (F.X != (F.K ^ F.CH ^ F.CL ^ F.C)) {
  935.                     printf ("F.X failed: %02x %02x\n", F.X, (F.K ^ F.CH ^ F.CL ^ F.C));
  936.                     i = 0;
  937.                 }
  938.                 else {          /*  get data segment if any */
  939.                     ++i;
  940.                 }
  941.                 break;
  942.         }
  943.         if (i == 6)
  944.             break;
  945.     }
  946.  
  947.     if (debug > 7) {
  948.         if (i)
  949.             printf ("RP Hdr i = %d, F.K = %d F.C = %d.%d.%d\n", i, F.K, F.C >> 6, (F.C >> 3) & 7, F.C & 7);
  950.         else
  951.             printf ("RP Hdr <rx timeout>\n");
  952.     }
  953.  
  954.     if (i == 6) {        /*    Receive Data Portion    */
  955.         uword
  956.             n,
  957.             pktsize = 1 << (F.K + 4);
  958.  
  959.         if (F.K == 9)
  960.             pktsize = 0;
  961.  
  962.         if (pktsize > MaxPktSize) {
  963.             printf ("Protocol failure pktsize %d/%d/%d\n", pktsize, TxSegSize, MaxPktSize);
  964.             return FAIL;
  965.         }
  966.         for (n = 0; n < pktsize; ++n) {
  967.             if ((c = xgetc (4, delay_flg)) == EOF)
  968.                 break;
  969.             pk->Data [n] = c;
  970.         }
  971.         if (c != EOF) {
  972.             uword
  973.                 hissum,
  974.                 oursum;
  975.  
  976.             hissum = (F.CH << 8) | F.CL;
  977.             oursum = MAGIC - (CheckSum (pk->Data, pktsize) ^ F.C);
  978.  
  979.             if (debug > 7)
  980.                 printf ("Got Data, checking: %04x %04x\n", hissum, oursum);
  981.  
  982.             if (hissum == oursum) {
  983.                 FrameToPacket (&F, pk, pk->Data);
  984.                 return SUCCESS;
  985.             }
  986.         }
  987.         else {
  988.             FrameToPacket (&F, pk, pk->Data);    /* mainly for pk->CType */
  989.             return FAIL;
  990.         }
  991.     }
  992.     /*
  993.      *  Timeout, retry?
  994.      */
  995.     return FAIL;
  996. }
  997.  
  998. Local
  999. int
  1000. CheckSum (ubyte *s, int n)
  1001. {
  1002.     uword
  1003.         sum,
  1004.         x,
  1005.         t;
  1006.  
  1007.     if (n == 0)
  1008.         return 0;
  1009.     sum = -1;
  1010.     x = 0;
  1011.  
  1012.     while (n) {
  1013.         if (sum & 0x8000)
  1014.             sum = (sum << 1) | 1;
  1015.         else
  1016.             sum = (sum << 1);
  1017.  
  1018.         t = sum;
  1019.         sum += *s++;
  1020.         x += sum ^ n;
  1021.  
  1022.         if (sum <= t)
  1023.             sum ^= x;
  1024.  
  1025.         --n;
  1026.     }
  1027.     return (int) sum;
  1028. }
  1029.  
  1030. Local
  1031. void
  1032. FrameToPacket (Frame *fr, Packet *pk, ubyte *data)
  1033. {
  1034.     pk->CType = fr->C & CT_MASK;
  1035.     pk->CCmd  = fr->C & CC_MASK;
  1036.     pk->CSeq  = fr->C & SEQ_MASK;
  1037.  
  1038.     switch (pk->CType) {
  1039.         case CT_LONGDATA:
  1040.             pk->DLen = 1 << (fr->K + 4);
  1041.             break;
  1042.         case CT_SHORTDATA:
  1043.             pk->DLen = 1 << (fr->K + 4);
  1044.             if (pk->Data [0] & 0x80) {
  1045.                 pk->DLen -= (pk->Data[0] & 0x7F) | (pk->Data[1] << 7);
  1046.                 pk->Data += 2;
  1047.             }
  1048.             else {
  1049.                 pk->DLen -= *pk->Data;
  1050.                 ++pk->Data;
  1051.             }
  1052.             break;
  1053.         default:
  1054.             pk->DLen = 0;
  1055.             break;
  1056.     }
  1057.  
  1058.     return;
  1059. }
  1060.  
  1061. Local
  1062. int
  1063. LenToK (uword bytes)
  1064. {
  1065.     uword
  1066.         n = 32,
  1067.         k = 1;
  1068.  
  1069.     while (n < bytes) {
  1070.         n <<= 1;
  1071.         ++k;
  1072.     }
  1073.  
  1074.     if (k > 8) {
  1075.         printf ("Soft error, LenToK: %d %d %d\n", bytes, n, k);
  1076.         k = 8;
  1077.     }
  1078.  
  1079.     return (int) k;
  1080. }
  1081.