home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / TELECOM / UUCP_Blars.lzh / dcpgpkt.c < prev    next >
Text File  |  1991-09-08  |  18KB  |  851 lines

  1. /*
  2.  * dcpgpkt.c
  3.  *
  4.  * Revised edition of dcp
  5.  *
  6.  * Stuart Lynne May/87
  7.  *
  8.  * Copyright (c) Richard H. Lamb 1985, 1986, 1987
  9.  * Changes Copyright (c) Stuart Lynne 1987
  10.  * Ported to OS-9/68000:  Wolfgang Ocker    January 1988
  11.  */
  12.  
  13. /*
  14.  * "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987
  15.  * 3-window "g" ptotocol
  16.  * Thanks got to John Gilmore for sending me a copy of Greg Chesson's
  17.  * UUCP protocol description-- Obviously invaluable
  18.  * Thanks also go to Andrew Tannenbaum for the section on Siding window
  19.  * protocols with a program example in his "Computer Networks" book
  20.  */
  21.  
  22. /*
  23.  * included adaptive error counting (weo, 26/05/88)
  24.  */
  25.  
  26. #include "dcp.h"
  27.  
  28. #define PKTSIZE 64
  29. #define PKTSIZ2 2
  30. #define HDRSIZE 6
  31. #define MAXTRY  4
  32.  
  33. #define MAXERR  50      /* Dont want to quit in a middle of a long file*/
  34. #define SUBERR  5       /* minus 5 errors per successfull transmit */
  35. #define TIMEOUT 6       /* could be longer */
  36. #define KPKT    1024/PKTSIZE
  37. #define POK     -1
  38.  
  39. #define SWINDOW 3       /* fixed now, U make it variable */
  40. #define RWINDOW 3
  41. #define NBUF    8       /* always SAME as MAXSEQ ? */
  42. #define MAXSEQ  8
  43.  
  44. #define between(a,b,c) ((a<=b && b<c) || (c<a && a<=b) || (b<c && c<a))
  45.  
  46. /*
  47.  * packet defines
  48.  */
  49. static int           rwl, swl, swu, rwu, nerr, totnerr, nbuffers;
  50. static int           npkt, irec, timeout, GOT_SYNC, GOT_HDR;
  51. static int           fseq[NBUF], outlen[NBUF], inlen[NBUF], arr[NBUF];
  52. static char          outbuf[NBUF][PKTSIZE+1], inbuf[NBUF][PKTSIZE+1];
  53. static unsigned char grpkt[HDRSIZE+1];
  54. static long          ftimer[NBUF], acktmr, naktmr, rdtmr;
  55.  
  56.  
  57. /*
  58.  * g o p e n p k
  59.  *
  60.  * Sub sub sub packet handler
  61.  */
  62. gopenpk()
  63. {
  64.   int  i, j, n1, n2, len;
  65.   char tmp[PKTSIZE+1];
  66.  
  67.   pktsize = PKTSIZE;      /* change it later after the init */
  68.   msgtime = MSGTIME;      /* not sure I need this for "g" proto */
  69.  
  70.   /*
  71.    * initialize proto parameters
  72.    */
  73.   swl = totnerr = nerr = nbuffers = npkt = 0;
  74.   swl = swu = 1;
  75.   rwl = 0;
  76.   rwu = RWINDOW - 1;
  77.  
  78.   for (i = 0; i < NBUF; i++) {
  79.     ftimer[i] = 0;
  80.     arr[i]    = FALSE;
  81.   }
  82.  
  83.   GOT_SYNC = GOT_HDR = FALSE;
  84.  
  85.   /*
  86.    * 3-way handshake
  87.    */
  88.   timeout = 2;            /* want some timeout capability here */
  89.   gspack(7, 0, 0, 0, tmp);
  90.  
  91. rsrt:
  92.   if (nerr >= MAXERR)
  93.     return(-1);
  94.  
  95.   /* INIT sequence. Easy fix for variable pktsize and windows.
  96.    * I didnt since all the machines I talk to use W=3 PKTSZ=64
  97.    * If you do this make sure to reflect the changes in "grpack"
  98.    * and "gspack"
  99.    */
  100.   switch (grpack(&n1, &n2, &len, tmp)) {
  101.     case 7:
  102.       gspack(6, 0, 0, 0, tmp);
  103.       if ((nerr -= SUBERR) < 0)
  104.         nerr = 0;
  105.       goto rsrt;
  106.  
  107.     case 6:
  108.       if ((nerr -= SUBERR) < 0)
  109.         nerr = 0;
  110.       gspack(5, 0, 0, 0, tmp);
  111.       goto rsrt;
  112.  
  113.     case 5:
  114.       if ((nerr -= SUBERR) < 0)
  115.         nerr = 0;
  116.       break;
  117.  
  118.     default:
  119.       nerr++;
  120.       totnerr++;
  121.       gspack(7, 0, 0, 0, tmp);
  122.       goto rsrt;
  123.   }
  124.  
  125.   nerr = totnerr = 0;
  126.   return(0);                      /* channel open */
  127. }
  128.  
  129.  
  130. /*
  131.  * g c l o s e p k
  132.  */
  133. gclosepk()
  134. {
  135.   int  i;
  136.   char tmp[PKTSIZE+1];
  137.  
  138.   timeout = 2;
  139.  
  140.   for (i = 0; i < MAXTRY; i++) {
  141.     gspack(CLOSE, 0, 0, 0, tmp);
  142.  
  143.     if (gmachine() == CLOSE)
  144.       break;
  145.   }
  146.  
  147.   printmsg(0, "number of errors %d (%d) and pkts xfered %d", totnerr, nerr,
  148.            npkt);
  149.   return(0);
  150. }
  151.  
  152.  
  153. /*
  154.  * g g e t p k t
  155.  *
  156.  * Gets no more than a packet's worth of data from
  157.  * the "packet i/o state machine". May have to
  158.  * periodically run the pkt machine to get some
  159.  * packets.
  160.  *
  161.  * on input:  don't care   getpkt(data,&len)  char *data int len
  162.  * on return: data+\0 and length in len. ret(0) if alls well
  163.  *            ret(-1) if problems (fail).
  164.  */
  165. ggetpkt(cdata, len)
  166.   char *cdata;
  167.   int  *len;
  168. {
  169.   int i2, ttmp;
  170.  
  171.   irec    = 1;
  172.   timeout = 2;
  173.  
  174.   rdtmr = time(&ttmp);              /* setup read timeout */
  175.  
  176.   /*
  177.    * Wait for the desired packet
  178.    */
  179.   while ((arr[rwl]) == FALSE)
  180.     if (gmachine() != POK)
  181.       return(-1);
  182.  
  183.   rdtmr = 0;                        /* disable read timeout */
  184.  
  185.   /*
  186.    * Got a packet
  187.    */
  188.   i2   = rwl;               /* <-- mod(,rwindow) for larger than 8 seq no.s */
  189.   *len = inlen[i2];
  190.   
  191.   memcpy(cdata, inbuf[i2], *len);
  192.  
  193.   arr[i2] = FALSE;
  194.   rwu = (1 + rwu) % MAXSEQ;         /* bump rec window */
  195.   npkt++;
  196.   return(0);
  197. }
  198.  
  199.  
  200. /*
  201.  * s e n d p k t
  202.  *
  203.  * Put at most a packet's worth of data  in the pkt state
  204.  * machine for xmission.
  205.  * May have to run the pkt machine a few times to get
  206.  * an available output slot.
  207.  *
  208.  * on input: char *data int len,flg; len=length of data in data.
  209.  *           flg=2 just send the packet with no wait for ack.
  210.  *           flg>0 zero out the unused part of the buffer. (for UUCP "msg"
  211.  *                                                                   pkts)
  212.  *           flg=0 normal data
  213.  * return:   ret(0) if alls well ret(-1) if problems (fail)
  214.  *
  215.  */
  216. gsendpkt(cdata, len, flg)
  217.   char *cdata;
  218.   int  len, flg;
  219. {
  220.   register int i, i1;
  221.   long         ttmp;
  222.  
  223.   irec = 0;
  224.   timeout = 0;                        /* non-blocking reads */
  225.  
  226.   /*
  227.    * Wait for input i.e. if weve sent SWINDOW pkts and none have been
  228.    * acked, wait for acks
  229.    */
  230.   while (nbuffers >= SWINDOW)
  231.     if (gmachine() != POK)
  232.       return(-1);
  233.  
  234.   i1 = swu;       /* <-- If we ever have more than 8 seq no.s, must mod() here */
  235.  
  236.   /*
  237.    * Place packet in table and mark unacked
  238.    * fill with zeros or not
  239.    */
  240.   if (flg) {
  241.     strcpy(outbuf[i1], cdata);
  242.     len = PKTSIZE;
  243.  
  244.     for (i = strlen(cdata); i < len; i++)
  245.       outbuf[i1][i] = '\0';
  246.   }
  247.   else {
  248.     memcpy(outbuf[i1], cdata, len);
  249.     outbuf[i1][len] = '\0';
  250.   }
  251.  
  252.   /*
  253.    * mark packet
  254.    */
  255.   outlen[i1] = len;
  256.   ftimer[i1] = time(&ttmp);
  257.   fseq[i1]   = swu;
  258.   swu        = (1 + swu) % MAXSEQ;      /* bump send window */
  259.  
  260.   nbuffers++;
  261.   npkt++;
  262.  
  263.   /*
  264.    * send it
  265.    */
  266.   gspack(DATA, rwl, fseq[i1], outlen[i1], outbuf[i1]);
  267.  
  268.   /*
  269.    * send it once then let the pkt machine take it
  270.    */
  271.   return(0);
  272. }
  273.  
  274.  
  275. /*
  276.  * g m a c h i n e
  277.  *
  278.  * Idealy we would like to fork this process off in an infinite loop
  279.  * and send and rec pkts thru "inbuf" and "outbuf". Cant do this in MS-DOS 
  280.  * so we setup "getpkt" and "sendpkt" to call this routine often and return
  281.  * only when the input buffer is empty thus "blocking" the pkt-machine task. 
  282.  */
  283. gmachine()
  284. {
  285.   register int i1, i2;
  286.   int          rack, rseq, rlen, dflg;
  287.   char         rdata[PKTSIZE+1];
  288.   long int     ttmp, itmp;
  289.   
  290. reply:
  291.   printmsg(6, "*send %d<W<%d, rec %d<W<%d, err %d (%d)", swl, swu, rwl,
  292.            rwu, totnerr, nerr);
  293.  
  294.   /*
  295.    * waiting for ACKs for swl to swu-1. Next pkt to send=swu
  296.    * rwl=expected pkt
  297.    */
  298.   printmsg(7, "Kbytes transfered %d errors %d (%d)\r", npkt / KPKT,
  299.            totnerr, nerr);
  300.  
  301.   if (nerr >= MAXERR)
  302.     goto close;
  303.  
  304.   dflg = 0;
  305.  
  306.   switch (grpack(&rack, &rseq, &rlen, rdata)) {
  307.     case CLOSE:
  308.       if ((nerr -= SUBERR) < 0)
  309.         nerr = 0;
  310.  
  311.       printmsg(5, "**got CLOSE");
  312.       goto close;
  313.  
  314.     case NAK:
  315.       nerr++;
  316.       totnerr++;
  317.       acktmr = naktmr = 0;                  /* stop ack/nak timer */
  318.       printmsg(5, "**got NAK %d", rack);
  319.  
  320.       /*
  321.        * As mentioned by Dave Arnold, rack contains the last CORRECT
  322.        * received package. So we have to resend starting at
  323.        * (rack + 1) % MAXSEQ.
  324.        */
  325.       rack = (1 + rack) % MAXSEQ;           /* IS THIS A BUG (weo)? */
  326.  
  327. nloop:
  328.       if (between(swl, rack, swu)) {        /* resend rack->(swu-1) */
  329.         i1 = rack;
  330.  
  331.         gspack(DATA, rwl, rack, outlen[i1], outbuf[i1]);
  332.         printmsg(5, "***resent %d", rack);
  333.         ftimer[i1] = time(&ttmp);
  334.         rack = (1 + rack) % MAXSEQ;
  335.         goto nloop;
  336.       }
  337.  
  338.       if (dflg)
  339.         return(POK);
  340.  
  341.       goto reply;                           /* any other stuff ? */
  342.  
  343.     case EMPTY:
  344.       printmsg(5, "**got EMPTY");
  345.       itmp = time(&ttmp);
  346.  
  347.       if (acktmr)
  348.         if ((itmp - acktmr) >= TIMEOUT) {   /* ack timed out*/
  349.           gspack(ACK, rwl, 0, 0, rdata);
  350.           acktmr = itmp;
  351.         }
  352.   
  353.       if (naktmr)
  354.         if ((itmp - naktmr) >= TIMEOUT) {   /* nak timed out*/
  355.           gspack(NAK, rwl, 0, 0, rdata);
  356.           naktmr = itmp;
  357.         }
  358.  
  359.       if (rdtmr)
  360.         if ((itmp - rdtmr) >= TIMEOUT) {    /* read timed out*/
  361.           nerr++;
  362.           totnerr++;
  363.           gspack(NAK, rwl, 0, 0, rdata);
  364.           rdtmr = itmp;
  365.           goto reply;
  366.         }
  367.   
  368.       /*
  369.        * resend any timed out un-acked pkts
  370.        */
  371.       for (i2 = swl; between(swl, i2, swu); i2 = (1 + i2) % MAXSEQ)  {
  372.         acktmr = naktmr = 0; /* reset ack/nak */
  373.         i1 = i2;
  374.         printmsg(5, "--->seq,elapst %d %ld", i2, (itmp - ftimer[i1]));
  375.  
  376.         if ((itmp - ftimer[i1]) >= TIMEOUT) {
  377.           printmsg(5, "***timeout %d", i2);
  378.  
  379.           /*
  380.            * since "g" is "go-back-N", when we time out we
  381.            * must send the last N pkts in order. The generalized
  382.            * sliding window scheme relaxes this reqirment
  383.            */
  384.           nerr++;
  385.           totnerr++;
  386.           dflg = 1;                         /* same hack */
  387.           rack = i2;
  388.           goto nloop;
  389.         }
  390.       }
  391.  
  392.       return(POK);
  393.  
  394.     case ACK:
  395.       if ((nerr -= SUBERR) < 0)
  396.         nerr = 0;
  397.       printmsg(5, "**got ACK %d", rack);
  398.       acktmr = naktmr = 0;                  /* disable ack/nak's */
  399.  
  400.     aloop:
  401.       if (between(swl, rack, swu)) {        /* S<-- -->(S+W-1)%8 */
  402.         printmsg(5, "***ACK %d", swl);
  403.         ftimer[swl] = 0;
  404.         nbuffers--;
  405.         swl = (1 + swl) % MAXSEQ;
  406.         dflg = 1;                           /* same hack, sl */
  407.         goto aloop;
  408.       }
  409.  
  410.       if (dflg)
  411.         return(POK);                        /* hack for non-mtask sys's */
  412.  
  413.       /*
  414.        * to empty "inbuf[]"
  415.        */
  416.       goto reply;
  417.  
  418.     case DATA:
  419.       if ((nerr -= SUBERR) < 0)
  420.         nerr = 0;
  421.  
  422.       printmsg(5, "**got DATA %d %d", rack, rseq);
  423.       i1 = (1 + rwl) % MAXSEQ; /* (R+1)%8 <-- -->(R+W)%8 */
  424.       i2 = (1 + rwu) % MAXSEQ;
  425.  
  426.       if (between(i1, rseq, i2)) {
  427.         if (i1 == rseq) {
  428.           i1        = rseq;
  429.           arr[i1]   = TRUE;
  430.           inlen[i1] = rlen;
  431.  
  432.           memcpy(inbuf[i1], rdata, rlen);
  433.  
  434.           rwl = (rwl + 1) % MAXSEQ;
  435.           printmsg(5, "***ACK d %d", rwl);
  436.           gspack(ACK, rwl, 0, 0, rdata);
  437.           acktmr = time(&ttmp);     /* enable ack/nak tmout*/
  438.           dflg = 1;                 /* return to caller when finished */
  439.           /*
  440.            * in a mtask system, unneccesary
  441.            */
  442.         }
  443.         else {
  444.           nerr++;
  445.           totnerr++;
  446.           printmsg(5, "***unexpect %d ne %d", rseq, rwl);
  447.         }
  448.       }
  449.       else {
  450.         nerr++;
  451.         totnerr++;
  452.         printmsg(5, "***wrong seq %d", rseq);
  453.       }
  454.  
  455.       goto aloop;
  456.  
  457.     case ERROR:
  458.       nerr++;
  459.       totnerr++;
  460.       printmsg(5, "**got BAD CHK");
  461.       gspack(NAK, rwl, 0, 0, rdata);
  462.  
  463.       naktmr = time(&ttmp); /* set nak timer */
  464.       printmsg(5, "***NAK d %d", rwl);
  465.       goto reply;
  466.  
  467.     default:
  468.       printmsg(5, "**got SCREW UP");
  469.       goto reply;                           /* ignore it */
  470.   }
  471.  
  472. close:
  473.   gspack(CLOSE, 0, 0, 0, rdata);
  474.   return(CLOSE);
  475. }
  476.  
  477.  
  478.  
  479. /*
  480.  * g s p a c k
  481.  *
  482.  * Framming, send a packet
  483.  * nt2=type nt3=pkrec nt4=pksent len=length<=PKTSIZE cnt1= data * ret(0) always
  484.  */
  485. gspack(nt2, nt3, nt4, len, cnt1)
  486.   int  nt2, nt3, nt4, len;
  487.   char cnt1[];
  488. {
  489.   register unsigned int check, i;
  490.   unsigned char         c2, pkt[HDRSIZE+1], dpkerr[10];
  491.  
  492.   if (len > 64)
  493.     len = 64;
  494.  
  495.   if (len == 0)
  496.     cnt1[0] = '\0';
  497.  
  498.   /*
  499.    * Link testing mods- create artificial errors
  500.    *
  501.    * printf("**n:normal,e:error,l:lost,p:partial,h:bad header,s:new seq--> ");
  502.    *
  503.    * gets(dpkerr);
  504.    *
  505.    * if(dpkerr[0] == 's') { sscanf(&dpkerr[1],"%d",&nt4); }
  506.    */
  507.   /*
  508.    * End Link testing mods
  509.    */
  510.  
  511.   printmsg(5, "send packet type %d, num=%d, n=%d, len=%d", nt2, nt3, nt4, len);
  512.   printmsg(5, "data =\n|%.64s|", cnt1);
  513.  
  514.   c2     = '\0';
  515.   pkt[0] = '\020';
  516.   pkt[4] = nt2 << 3;
  517.   nt2    &= 7;
  518.  
  519.   switch (nt2) {
  520.     case 1:
  521.       break;                          /* stop protocol */
  522.  
  523.     case 2:
  524.       pkt[4] += nt3;
  525.       break;                          /* reject        */
  526.  
  527.     case 3:
  528.       break;
  529.  
  530.     case 4:
  531.       pkt[4] += nt3;
  532.       break;                          /* ack          */
  533.  
  534.     case 5:
  535.       pkt[4] += SWINDOW;
  536.       break;                          /* 3 windows */
  537.  
  538.     case 6:
  539.       pkt[4] += 1;
  540.       break;                          /* pktsiz = 64 (1) */
  541.       
  542.     case 7:
  543.       pkt[4] += SWINDOW;
  544.       break;                          /* 3 windows */
  545.  
  546.     case 0:
  547.       pkt[4] += 0x80 + nt3 + (nt4 << 3);
  548.       c2     = (PKTSIZE - len) & 0xff;
  549.  
  550.       /*
  551.        * havn't set it up for VERY LONG pkts with a few
  552.        * bytes yet (-128)
  553.        */
  554.       if (c2) {                       /* short packet handling */
  555.         pkt[4] += 0x40;               /* if len < PKTSIZE */
  556.  
  557.         for (i = PKTSIZE - 1; i > 0; i--)
  558.           cnt1[i] = cnt1[i-1];
  559.  
  560.         cnt1[0] = c2;
  561.       }
  562.  
  563.       break;
  564.   }
  565.  
  566.   pkt[4] &= 0xff;
  567.  
  568.   if (nt2) {
  569.     pkt[1] = 9;                       /* control packet size = 0 (9) */
  570.     check  = (0xaaaa - pkt[4]) & 0xffff;
  571.   }
  572.   else {
  573.     pkt[1] = PKTSIZ2;                 /* data packet size = 64 (2) */
  574.     check  = checksum(cnt1, PKTSIZE);
  575.     i      = pkt[4];                  /* got to do this on PC for ex-or high bits */
  576.     i      &= 0xff;
  577.     check  = (check ^ i) & 0xffff;
  578.     check  = (0xaaaa - check) & 0xffff;
  579.   }
  580.  
  581.   pkt[2] = check & 0xff;
  582.   pkt[3] = (check >> 8) & 0xff;
  583.   pkt[5] = (pkt[1] ^ pkt[2] ^ pkt[3] ^ pkt[4]) & 0xff;
  584.  
  585.   /*
  586.    * More Link testing MODS
  587.    *
  588.    *
  589.    * switch(dpkerr[0]) {
  590.    *   case 'e':
  591.    *     cnt1[10] = -cnt1[10];
  592.    *     break;
  593.    *   case 'h':
  594.    *    pkt[5] = -pkt[5];
  595.    *    break;
  596.    *   case 'l':
  597.    *     return;
  598.    *   case 'p':
  599.    *     swrite(pkt, HDRSIZE);
  600.    *     if(pkt[1] != 9)
  601.    *       swrite(cnt1, PKTSIZE-3);
  602.    *     return;
  603.    *   default:
  604.    *     break;
  605.    * }
  606.    */
  607.   /*
  608.    * End Link Testing Mods
  609.    */
  610.  
  611.   swrite(pkt, HDRSIZE);                   /* header is 6-bytes long */
  612.  
  613.   /*
  614.    * write(flog, pkt, HDRSIZE);
  615.    */
  616.  
  617.   if (pkt[1] != 9) {
  618.     swrite(cnt1, PKTSIZE);                /* data is always 64 bytes long */
  619.     /*
  620.      * write(flog, cnt1, PKTSIZE);
  621.      */
  622.   }
  623. }
  624.  
  625.  
  626. /*
  627.  * g r p a c k
  628.  *
  629.  * read packet
  630.  *
  631.  * on return: nt3=pkrec nt4=pksent len=length <=PKTSIZE  cnt1=data *
  632.  * ret(type) ok; ret(EMPTY) input buf empty; ret(ERROR) bad header;
  633.  *          ret(EMPTY) lost pkt timeout; ret(ERROR) checksum error;ret(-5) ?
  634.  * NOTE :
  635.  *  sread(buf,n,timeout)
  636.  *  while(TRUE) {
  637.  *    if(# of chars available >= n) (without dec internal counter)
  638.  *      read n chars into buf (decrenent internal char counter)
  639.  *      break
  640.  *    else
  641.  *      if(time>timeout) break
  642.  *    }
  643.  *  return(# of chars available)
  644.  */
  645. grpack(nt3, nt4, len, cnt1)
  646.   int  *nt3, *nt4, *len;
  647.   char cnt1[];
  648. {
  649.   unsigned int  nt1, check, checkchk, i;
  650.   unsigned char c, c2;
  651.   register int  ii;
  652.  
  653.   if (GOT_SYNC)
  654.     goto get_hdr;
  655.  
  656.   if (GOT_HDR)
  657.     goto get_data;
  658.  
  659.   c = '\0';
  660.  
  661.   while ((c & 0x7f) != '\020')
  662.     if (sread(&c, 1, timeout) == 0)
  663.       return(EMPTY);
  664.  
  665.   GOT_SYNC = TRUE;
  666.  
  667. get_hdr:
  668.   if (sread(&grpkt[1], HDRSIZE - 1, timeout) < (HDRSIZE - 1))
  669.     return(EMPTY);
  670.  
  671.   GOT_SYNC = FALSE;
  672.  
  673.   /*
  674.    * i = grpkt[1] ^ grpkt[2] ^ grpkt[3] ^ grpkt[4] ^ grpkt[5];
  675.    */
  676.  
  677.    i = (unsigned) grpkt[1] ^ (unsigned) grpkt[2] ^
  678.        (unsigned) grpkt[3] ^ (unsigned) grpkt[4] ^
  679.        (unsigned) grpkt[5];
  680.  
  681.   i &= 0xff;
  682.   printmsg(10, "prpkt %02x %02x %02x %02x %02x .. %02x ",
  683.            grpkt[1], grpkt[2], grpkt[3], grpkt[4], grpkt[5], i);
  684.  
  685.   if (i) {                                /*  bad header */
  686.     printmsg(0, "****bad header****");
  687.     /*
  688.      * I'm not sure whether "g" considers it an empty or error
  689.      */
  690.     printmsg(0, "prpkt %02x %02x %02x %02x %02x .. %02x ",
  691.            grpkt[1], grpkt[2], grpkt[3], grpkt[4], grpkt[5], i);
  692.     return ERROR;
  693.   }
  694.  
  695.   GOT_HDR = TRUE;
  696.   if ((grpkt[1] &= 0x7f) == 9) {        /* control packet */
  697.     *len       = 0;
  698.     c          = grpkt[4] & 0xff;
  699.     nt1        = c >> 3;
  700.     *nt3       = c & 7;
  701.     *nt4       = 0;
  702.     check      = 0;
  703.     checkchk   = 0;
  704.     cnt1[*len] = '\0';
  705.     GOT_HDR    = FALSE;
  706.   }
  707.   else {                                /* data packet */
  708.     if (grpkt[1] != PKTSIZ2)
  709.       return(-5);                       /* can't handle other than 64*/
  710.  
  711. get_data:
  712.     if (sread(cnt1, PKTSIZE, timeout) < PKTSIZE)
  713.       return(EMPTY);
  714.  
  715.     GOT_HDR   = FALSE;
  716.     nt1       = 0;
  717.     c2        = grpkt[4] & 0xff;
  718.     c         = c2 & 0x3f;
  719.     *nt4      = c >> 3;
  720.     *nt3      = c & 7;
  721.     i         = grpkt[3];
  722.     i         = (i << 8) & 0xff00;
  723.     check     = grpkt[2];
  724.     check     = i | (check & 0xff);
  725.     checkchk  = checksum(cnt1, PKTSIZE);
  726.     i         = grpkt[4] | 0x80;
  727.     i        &= 0xff;
  728.     checkchk  = 0xaaaa - (checkchk ^ i);
  729.     checkchk &= 0xffff;
  730.  
  731.     if (checkchk != check) {
  732.       printmsg(4, "***checksum error***");
  733.       return(ERROR);
  734.     }
  735.  
  736.     *len = PKTSIZE;
  737.     /*
  738.      * havn't set it up for very long pkts yet (>128) RH Lamb
  739.      */
  740.     if (c2 & 0x40) {
  741.       ii   = (cnt1[0] & 0xff);
  742.       *len = (*len - ii) & 0xff;
  743.  
  744.       for (ii = 0; ii < *len; ii++)
  745.         cnt1[ii] = cnt1[ii+1];
  746.     }
  747.  
  748.    cnt1[*len] = '\0';
  749.   }
  750.  
  751.   printmsg(5, "rec  packet type %d, num=%d, n=%d, len=%d", nt1, *nt3, *nt4, *len);
  752.   printmsg(6, "  checksum rec = %x comp = %x, data=\n|%s|", check, checkchk, cnt1);
  753.  
  754.   ii = nt1;
  755.   return(ii);
  756. }
  757.  
  758. /*
  759.  * c h e c k s u m
  760.  */
  761. unsigned checksum(data, len)
  762.   int  len;
  763.   char data[];
  764. {
  765.   register unsigned int i, j, tmp, chk1, chk2;
  766.   
  767.   chk1 = 0xffff;
  768.   chk2 = 0;
  769.   j    = len;
  770.  
  771.   for (i = 0; i < len; i++) {
  772.     if (chk1 & 0x8000) {
  773.       chk1 <<= 1;
  774.       chk1++;
  775.     }
  776.     else
  777.       chk1 <<= 1;
  778.   
  779.     tmp  = chk1;
  780.     chk1 += (data[i] & 0xff);
  781.     chk2 += chk1 ^ j;
  782.   
  783.     if ((chk1 & 0xffff) <= (tmp & 0xffff))
  784.       chk1 ^= chk2;
  785.  
  786.     j--;
  787.   }
  788.  
  789.   return(chk1 & 0xffff);
  790. }
  791.  
  792. /*
  793.  * g w r m s g
  794.  *
  795.  * send a null terminated string out
  796.  */
  797. gwrmsg(typ, buf)
  798.   char typ;
  799.   char *buf;      /* null terminated */
  800. {
  801. }
  802.  
  803. /*
  804.  * g r d m s g
  805.  *
  806.  * read a null terminated string
  807.  */
  808. grdmsg(buf)
  809.   char *buf;
  810. {
  811. }
  812.  
  813. /*
  814.  * g w r d a t a
  815.  *
  816.  * read a file and send it out
  817.  */
  818. gwrdata(f)
  819. {
  820. }
  821.  
  822. /*
  823.  * g r r d a t a
  824.  *
  825.  * read in data and send to file
  826.  */
  827. grrdata(f)
  828. {
  829. }
  830.  
  831.  
  832. /*
  833.  * g r d b l k
  834.  *
  835.  * read a block of data in
  836.  */
  837. grdblk(blk, len)
  838. {
  839. }
  840.  
  841. /*
  842.  * g w r b l k
  843.  *
  844.  * write out a block of data
  845.  */
  846. gwrblk(blk, len)
  847. {
  848. }
  849.  
  850.  
  851.