home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / auucp+-1.02 / fuucp_plus_src.lzh / uucico / gio.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-11-21  |  18.5 KB  |  938 lines

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