home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Utilities / Mac⁄gnuucp 6.14 / source / gio.c.recent < prev    next >
Encoding:
Text File  |  1993-08-08  |  32.6 KB  |  1,204 lines  |  [TEXT/R*ch]

  1. /*
  2.     $Header: gio.c,v 1.19 90/02/28 04:15:27 gnu Exp $
  3.     Copyright 1990 Free Software Foundation, Inc.x
  4.  
  5.     This program is free software; you can redistribute it and/or modify
  6.     it under the terms of the GNU General Public License as published by
  7.     the Free Software Foundation; either version 1, or (at your option)
  8.     any later version.
  9.  
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU General Public License
  16.     along with this program; if not, write to the Free Software
  17.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19.  
  20.     "G-protocol" module for error-checked serial communications for uucp.
  21.  
  22.     Derived from:
  23.     uuslave.c    1.7 08/12/85 14:04:20
  24.     which came from the ACGNJ BBS system at +1 201 753 9758.  Original
  25.     author unknown.
  26. */
  27.  
  28. #ifndef lint
  29. char gio_version[] = "Version Fort Pond Research-6.12";
  30. #endif
  31.  
  32. #include "includes.h"        /* All the system header files */
  33. #include "uucp.h"
  34. #include "sysdep.h"
  35.  
  36. extern int errno;
  37.  
  38. int connection_closing = FALSE;
  39. /*
  40.  
  41.  
  42. This program implements the uucp (Unix-to-Unix CoPy) protocol as a
  43. slave (the recipient of a phone call from another Unix system) or, now,
  44. a master (the originator of a phone call).  This
  45. protocol is used to transfer mail, files, and Usenet news from Unix
  46. machine to Unix machine.  UUCP comes with Unix (unless you get a
  47. sleazeoid version like Xenix, where they charge you extra for it).  You
  48. can buy a commercial program for MSDOS, called UULINK, which also
  49. implements this protocol.  UULINK costs $300 and you don't get sources,
  50. though.
  51.  
  52. The protocol requires a full 8-bit data path with no characters inserted
  53. or deleted (e.g. ^S and ^Q are used as DATA characters).  Simple serial
  54. ports and modems do this; most complicated networks do not, at least without
  55. setting up odd modes and such.  Telenet's PC Pursuit works though.
  56.  
  57. The basic flow of the protocol is that the calling machine will send down
  58. a line of text saying what it wants to do (send a file, receive a file,
  59. or hang up).  (The lines of text are encapsulated into packets; see below.)
  60. The called machine responds with a "yes" or "no" answer, and if the answer
  61. was yes, it sends or receives the file.  Files are terminated with a
  62. packet containing 0 bytes of data.  Then the system that received the file
  63. sends a "copy succeeded" or "copy failed" line to the other end, and 
  64. they go back to "what do we do now".  A request to hang up should be
  65. answered "no" if the called machine has some mail or files it wants to
  66. send to the calling machine; the two machines reverse roles and the calling
  67. machine goes into "what do we do now".  If a hangup request is answered "yes",
  68. the call is terminated.
  69.  
  70. The data flow described above is actually sent in packets containing
  71. checksums and acknowledgements.  Each packet can either hold a short
  72. control message (e.g. an ack) or a data block.  The data blocks are
  73. numbered with a 3-bit counter, and sent with a checksum.  If the sender
  74. has not received an acknowledgement for a data block within a certain
  75. time, it retransmits the block.  The size of a data block is negotiated
  76. at the start of a call.  To send a block with fewer bytes, a "short
  77. data" block is sent, which is just as big as a "long data" block, but
  78. contains a 1- or 2-byte count of "how many bytes in this block are just
  79. padding".  This is a cute trick since it always works (e.g. if you want
  80. to send 1023 out of 1024 bytes, you only need one byte for the count;
  81. while if you want to send 1 byte out of 1024 then you have enough space
  82. for the count to be 2 bytes).
  83.  
  84. The short control messages are used to start the call and negotiate the
  85. packet size and the "window size", to acknowledge or reject packets,
  86. and to terminate the packet protocol at the end of a call.  The window
  87. size is how many packets one side can send before it will stop and wait
  88. for an acknowledgement from the other side.  A window size of 1 makes
  89. for a half-duplex protocol (which is what gio.c currently implements),
  90. but also makes it easy to implement on micros that don't handle serial
  91. lines with interrupts.  In window 1, you just keep sending the same
  92. packet until the other side acknowledges it.  Unix traditionally uses a
  93. window size of 3, because Greg Chesson didn't have an environment where
  94. a larger window did any good.  Modern buffered (internally half duplex)
  95. modems and packet switching networks provide such an environment, so we
  96. offer a window size of 7, the maximum.  This gives much better
  97. throughput, but requires full duplex serial port handling and more
  98. complicated acknowledgement strategies.
  99.  
  100. At the low level, full 8-bit bytes are sent out and received on an async serial
  101. port.  The received data is scanned for a DLE (hex 10) which indicates the
  102. start of a packet, and the next 5 bytes are read and checked.  If they
  103. pass, this is a good packet and it is acted upon.  (If it's a data
  104. packet, we have to read in and check the data part too.)  If the checks
  105. fail, all the bytes read so far should be scanned for another DLE.
  106.  
  107. FIXME: Think about how to do data transfers in BOTH directions
  108. simultaneously, without completely botching the structure of the
  109. code.  We should be able to move news/mail both ways at once.
  110.  
  111. FIXME:  Check the ack strategy to make sure we are kicking the other
  112. side with acks whenever necessary.
  113.  
  114. FIXME:  Support some real timeouts for chars that are less than
  115. the send-expect timeouts and which don't kill the protocol.
  116. */
  117.  
  118.  
  119. /*
  120.  * UUCP "g" procotol definitions
  121.  */
  122. #define    MAGIC    0125252        /* checksum is subtracted from this */
  123.  
  124. /*
  125.  * What is sent from one machine to the other is a control byte and
  126.  * sometimes a data block following.
  127.  * A packet is just this, with a frame around the control byte and the
  128.  * data, if any, after the frame.  The frame is 6 bytes long, and looks like:
  129.  *    DLE K C0 C1 C X
  130.  * where:
  131.  *    DLE is a literal ASCII DLE (Data Link Escape) character
  132.  *    K is binary, 9 for a control packet, or the packet size log 2, minus 4
  133.  *        e.g. K = 2 means 64 byte packet since  (K+4) is  6 or 64.
  134.  *                              2         2
  135.  *    C0 and C1 are low, high order checksums for the entire data section, or
  136.  *        are low, high order of (MAGIC minus the control byte).
  137.  *    C is the control byte for the message.
  138.  *    X is the xor of K, C0, C1, and C.
  139.  * If a packet does not satisfy all of the above checks, it is invalid.
  140.  */
  141. #define    DLE    0x10        /* Start of packet indicator */
  142.  
  143. #define    DLEBYTE        0    /* Byte offset from DLE to DLE */
  144. #define    LENBYTE        1    /* Byte offset from DLE to length */
  145. #define    CHKBYTE1    2    /* Byte offset from DLE to checksum byte 1 */
  146. #define    CHKBYTE2    3    /* Byte offset from DLE to checksum byte 2 */
  147. #define    CBYTE        4    /* Byte offset from DLE to control */
  148. #define    FRAMEBYTE    5    /* Byte offset from DLE to end of frame */
  149. #define    XORBYTE        5    /* Byte offset from DLE to xor-checksum */
  150. #define    SHORTLEN1    6    /* Byte offset from DLE to len of shortdata */
  151. #define    SHORTLEN2    7    /* Byte offset from DLE to 2ndlen of shortdat */
  152.  
  153. #define    FRAMELEN    6    /* Length of whole frame (except data) */
  154.  
  155. #define    KCONTROL    9    /* K value for control packets */
  156.  
  157. /*
  158.  * A control byte is split into three bit fields: type, x, and y.
  159.  *     TT XXX YYY
  160.  * Here are the types:
  161.  */
  162. #define    TYPESHIFT    6    /* Offset of TYPE in control byte */
  163. #define    XXXSHIFT    3    /* Offset of XXX  in control byte */
  164. #define YYYSHIFT    0    /* Offset of YYY  in control byte */
  165.  
  166. #define    TYPEMASK    0x03    /* Mask for field size */
  167. #define    XXXMASK        0x07
  168. #define    YYYMASK        0x07
  169.  
  170. #define    CONTROL        0    /* Control message */
  171. #define    ALTCHN        1    /* Alternate channel message, unused in UUCP */
  172. #define    LONGDATA    2    /* Long data block -- full size spec'd by K */
  173. #define    SHORTDATA    3    /* Short data block -- first byte or two is
  174.                    count.  Full K-size packet is sent, even
  175.                    though the useful data is shorter. */
  176.  
  177. char *tt_pr[] = {"CONTROL", "ALTCHN", "LONGDATA", "SHORTDATA"};
  178.  
  179. /* If TT == CONTROL (also K will == KCONTROL) then
  180.    the x field is:             and the Y field means: */
  181. #define    CLOSE    1    /* End of communication */
  182. #define    RJ    2    /* Reject packet    last good packet # seen */
  183. #define    SRJ    3    /* Selective reject    seq # of bad packet, resend
  184.                SRJ is not used by UUCP. */
  185. #define    RR    4    /* Receiver Ready    last good packet # seen */
  186. #define    INITC    5    /* Init phase C        window size to hand sender */
  187. #define    INITB    6    /* Init phase B        max data segment size (K val)
  188.                         to hand sender */
  189. #define    INITA    7    /* Init phase A        window size to hand sender */
  190.  
  191. char *ctrl_pr[] = {"*ZERO*",
  192.     "CLOSE", "RJ", "SRJ", "RR", "INITC", "INITB", "INITA"};
  193.  
  194. /*
  195.  * If TT == LONGDATA or SHORTDATA then x field is the sequence # of this packet
  196.  * and y field is the last good packet # seen.
  197.  *
  198.  * In both data and RJ/RR packets, the "last good packet # seen" starts off
  199.  * as zero.
  200.  */
  201.  
  202.  
  203. #define    MAX_PACKET 64
  204.  
  205. unsigned char    msgi[MAX_PACKET+SLOP];    /* Incoming packet */
  206. unsigned char    msgout[8][MAX_PACKET+SLOP];    /* Outgoing packets #0 to #7 */
  207. unsigned char    ctlout[FRAMELEN];    /* Outgoing control packet */
  208.  
  209. int    msgsize,            /* Size of data part of msg */
  210.     tt, xxx, yyy,            /* Fields from control byte */
  211.     rseq,                /* Last good packet # we received */
  212.     his_rseq,            /* Last good packet # HE received */
  213.     wseq;                /* Next packet # we will send */
  214.  
  215. #define NOOP 0
  216. #define ACK_MSG 1
  217. #define RETRANS_MSG 2
  218.  
  219. int    need_write = NOOP;            /* Flag: need to write (an ack or
  220.                        data packet) to let the other side
  221.                        know what we're up to */
  222.  
  223. int    reject;                /* Packet # to reject or NOREJECT */
  224. #define    NOREJECT    -1
  225.  
  226. /* Segments are encoded as (log2 length) - 3, except in INITB packet */
  227. /* FIXME window size */
  228. #define    MAX_WINDOW    7
  229. #ifdef BUFFEREDIO
  230. int wndsiz = MAX_WINDOW;    /* Ask for window of maximum # packets */
  231. #else
  232. int wndsiz = 1            /* Ask for window of 1 messages flying */
  233. #endif
  234. int segsiz = 2;            /* Ask for 64 byte messages */
  235. int sendseg = 2;        /* Size segments other guy wants to see */
  236. int sendwin = 1;        /* Size window other guy wants to see */
  237.  
  238. int sendbytes;            /* sendseg, in bytes */
  239.  
  240. #define s_or_f int
  241.  
  242. void DEBUG_DATA (int data);
  243. void
  244. DEBUG_DATA(data)
  245. int data;
  246. {
  247.     if (isprint((char)data))
  248.         putchar((char)data);
  249.      else
  250.         putchar(' ');
  251.      }
  252.         
  253. int
  254. pktchksum(unsigned char *msg, int bytes);
  255. void
  256. update_rseq(unsigned char *msgo);
  257.  
  258. static int segbytes[10] = {    /* K value (encoded segment size) */
  259.         -1,        /* 0 */
  260.         32,        /* 1 */
  261.         64,        /* 2 */
  262.         128,        /* 3 */
  263.         256,        /* 4 */
  264.         512,        /* 5 */
  265.         1024,        /* 6 */
  266.         2048,        /* 7 */
  267.         4096,        /* 8 */
  268.         0,        /* 9 = KCONTROL */
  269. };
  270.  
  271. /* s_or_f inpkt();
  272. int pktchksum();
  273. int chksum(); */
  274.  
  275.  
  276. /*
  277.  * Low level output routines.  These send packets without checking
  278.  * whether they got properly received.
  279.  *
  280.  * writeframe():
  281.  *
  282.  * Finish off an outgoing frame in msgo and queue it up to be written
  283.  * to the serial port.
  284.  *
  285.  * This routine is called to send each and every packet.
  286.  *
  287.  * Note that with this setup, we may hang in the xwrite() below
  288.  * looking for outgoing buffer space, even though there are input
  289.  * characters (packets) that we could process if we would look for
  290.  * them.  This may want to be fixed FIXME.
  291.  */
  292. s_or_f
  293. writeframe(cksm, msgo)
  294.     int cksm;
  295.     unsigned char *msgo;
  296. {
  297.     int status, maxlen;
  298.     
  299.     msgo[DLEBYTE]  = (unsigned char)DLE;
  300.     msgo[CHKBYTE1] = (unsigned char)cksm;
  301.     msgo[CHKBYTE2] = (unsigned char)(cksm >> 8);
  302.     msgo[XORBYTE]  = msgo[1] ^ msgo[2] ^ msgo[3] ^ msgo[4];
  303.  
  304.     maxlen = segbytes[msgo[LENBYTE]] + FRAMELEN;
  305.  
  306.     if (DEBUG_LEVEL(9)) {
  307.         int i;
  308.  
  309.         printf("T ");
  310.         for (i = 0; i < maxlen; i++)
  311.             DEBUG_DATA(msgo[i]);
  312.         putchar('\n');
  313.     }
  314.     if (DEBUG_LEVEL(6)) {
  315.         int t, x, y;
  316.  
  317.         t = (msgo[CBYTE] >> TYPESHIFT) & TYPEMASK;
  318.         x = (msgo[CBYTE] >> XXXSHIFT) & XXXMASK;
  319.         y = (msgo[CBYTE] >> YYYSHIFT) & YYYMASK;
  320.         if (t == CONTROL)
  321.             printf("Sent: CONTROL %s %d\n",
  322.                 ctrl_pr[x], y);
  323.         else
  324.             printf("Sent: %s %d %d\n",
  325.                 tt_pr[t], x, y);
  326.     }
  327.  
  328.     /* Actually write it out the serial port */
  329.     {
  330.         char orig;
  331.         char did_it = 0;
  332.         int rand_val = rand();
  333.         int type_val = (msgo[CBYTE] >> TYPESHIFT) & TYPEMASK;
  334.         if ((type_val ==  LONGDATA) && 
  335.             rand_val <= (int)0)
  336.             {
  337.                 did_it = 1;
  338.                 orig = msgo[10];
  339.                 msgo[10] = 44;
  340.                 }
  341.     status = xwrite((char *)msgo, maxlen);
  342.     if (did_it == 1)
  343.             {
  344.                 msgo[10] = orig;
  345.                 did_it = 0;
  346.                 }
  347.         }
  348.     if (status != maxlen) {
  349.         if (DEBUG_LEVEL(0)) {
  350.             printf("xmit %d bytes failed, status %d, errno %d\n", 
  351.                 maxlen, status, errno);
  352.         }
  353.         return FAIL;        /* Write failed */
  354.     }
  355.  
  356.     need_write = NOOP;
  357.     return SUCCESS;
  358. }
  359.  
  360.  
  361. /*
  362.  * Send an ack.  If the ack would be for packet N and we have seen a garbled
  363.  * copy of the next packet, send a reject acknowledging packet N rather than a
  364.  * regular acknowledgement of packet N.  It's not clear what uucp's strategy
  365.  * for this is, let's see how this one does.  FIXME.
  366.  */
  367. s_or_f
  368. ackmsg()
  369. {
  370.  
  371.     if (connection_closing == TRUE) return(SUCCESS);
  372.     ctlout[LENBYTE] = (unsigned char)KCONTROL;
  373.     if (reject == rseq)
  374.        ctlout[CBYTE] = (unsigned char)((CONTROL << TYPESHIFT) |
  375.                        (RJ      << XXXSHIFT) |
  376.                        (reject  << YYYSHIFT) );
  377.     else
  378.        ctlout[CBYTE] = (unsigned char)((CONTROL << TYPESHIFT) | 
  379.                        (RR      << XXXSHIFT) | 
  380.                        (rseq    << YYYSHIFT) );
  381.     reject = NOREJECT;
  382.     return writeframe((int)(MAGIC - ctlout[CBYTE]), ctlout);
  383. }
  384.  
  385.  
  386. /* Send a control message other than an ack */
  387. s_or_f
  388. ctlmsg(byte)
  389. char byte;
  390. {
  391.  
  392.     ctlout[LENBYTE] = (unsigned char)KCONTROL;
  393.     ctlout[CBYTE] = (unsigned char)((CONTROL << TYPESHIFT) | byte);
  394.     return writeframe((int)(MAGIC - ctlout[CBYTE]), ctlout);
  395. }
  396.  
  397.  
  398. /*
  399.  * Medium level output routine.  This sends a short or long data packet
  400.  * and figures out when to retransmit and/or insert acknowledgements as
  401.  * needed.
  402.  */
  403. s_or_f
  404. sendpacket(s, n, sorl)
  405.     char *s;
  406.     int n;
  407.     int sorl;            /* SHORTDATA or LONGDATA */
  408. {
  409.     int offset, difflen;
  410.     unsigned char *msgo;
  411.  
  412.     while (((wseq - his_rseq) & MAX_WINDOW) >= sendwin) {
  413.         /*
  414.          * Better get the earlier packet(s) sent and ack'd first 
  415.          * to make room for this one in the window.
  416.          */
  417.         if (inpkt() != SUCCESS) 
  418.             {
  419.                 return FAIL;
  420.                 }
  421.         switch (tt) {
  422.         default:
  423.         unexp:
  424.             DEBUG(0, "Unexpected pkt received in sendpacket\n", 0);
  425.             return FAIL;        /* Unsupported - yet */
  426.  
  427.         case CONTROL:    
  428.             switch (xxx) {
  429.             default:
  430.                 goto unexp;    /* Bad packet type */
  431.  
  432.             case RJ:        /* Reject prev pkt */
  433.             case RR:        /* OK but no data */
  434.                 break;        /* These are OK */
  435.             }
  436.         }
  437.     }
  438.  
  439.     msgo = msgout[wseq];        /* Pick a place to put the datapacket */
  440.  
  441.     /* FIXME, is this bzero burning a lot of time?  For completely full
  442.        long-data packets, we can skip it. */
  443.     bzero((char *)(msgo+FRAMELEN), sendbytes);
  444.  
  445.     /* FIXME, we might consider shrinking the send segment size to
  446.        match the data size... dunno if this will break Unix uucp. */
  447.     msgo[LENBYTE] = (unsigned char)sendseg;
  448.     msgo[CBYTE] = (unsigned char)((sorl << TYPESHIFT) |
  449.                       (wseq << XXXSHIFT) | 
  450.                       (rseq << YYYSHIFT) );
  451.  
  452.     switch(sorl) {
  453.     case LONGDATA:
  454.     default:
  455.         if (n > sendbytes) abort();
  456.         offset = FRAMELEN;
  457.         break;
  458.  
  459.     case SHORTDATA:
  460.         difflen = sendbytes - n;
  461.         if (difflen < 1) abort();
  462.         offset = FRAMELEN+1;
  463.         if (difflen <= 127) {
  464.             /* One byte count */
  465.             msgo[SHORTLEN1] = (unsigned char)difflen;
  466.         } else {
  467.             /* low byte, with 0x80 on, then high byte */
  468.             msgo[SHORTLEN1] = (unsigned char)(0x80 | difflen);
  469.             msgo[SHORTLEN2] = (unsigned char)(difflen >> 7);
  470.             offset = FRAMELEN+2;
  471.         }
  472.     }
  473.  
  474.     bcopy(s, (char *)(msgo+offset), n);        /* Move the data */
  475.  
  476.     wseq = (wseq + 1) & MAX_WINDOW;        /* Bump sent pkt sequence # */
  477.     return writeframe(pktchksum(msgo, sendbytes), msgo);
  478. }
  479.  
  480. /*
  481.  * Update the received sequence number in packets that we retransmit.
  482.  */
  483. void
  484. update_rseq(msgo)
  485.     unsigned char *msgo;
  486. {
  487.     msgo[CBYTE] = (msgo[CBYTE] & ~(MAX_WINDOW << YYYSHIFT))
  488.             | (rseq << YYYSHIFT);
  489.     /* writeframe() will recalculate the xor checksum. */
  490. }
  491.  
  492. /*
  493.  * Medium level input routine.
  494.  *
  495.  * Read a packet from the serial port.  Handle acknowledgements and
  496.  * retransmissions.
  497.  * Return FAIL if other side went away, SUCCESS if good packet received.
  498.  *
  499.  * With window size of 1, we send a packet and then receive one.
  500.  * FIXME, when we implement a larger window size, this routine will become
  501.  * more complicated and callers will not be able to depend on msgo[]
  502.  * being sent and acknowledged when it returns.
  503.  */
  504. s_or_f
  505. inpkt()
  506. {
  507.     int data, count, need;
  508.     register int i;
  509.     unsigned short pktsum, oursum;
  510.     unsigned char *msgo;
  511.     /*
  512.      * Next vars are for re-queueing received chars to rescan them
  513.      * for a valid packet after an error.
  514.      */
  515.     int queued = -1;  /* <0: off, 0: just finished, >0: # chars pending */
  516.     unsigned char *qp;
  517.     static unsigned char qbuf[sizeof msgi];    /* This is static for machines
  518.                            where 4K on the stack is too much */
  519. #    define    bad(str) { if (DEBUG_LEVEL(6)) printf str; goto oops; }
  520.     if (need_write == NOOP) goto again;
  521.     /* if (need_write == ACK_MSG) goto ack_msg; This doesn't work right */
  522.     /* if (need_write == RETRANS_MSG) goto xmit; */
  523. xmit:
  524.     /*
  525.      * We have encountered a garbled packet or a timeout, or need an ack.
  526.      * 
  527.      * If we have any outstanding unacknowledged data, send the next
  528.      * unack'd packet.  If we have no outstanding data, send an RR or
  529.      * an RJ (as decided by ackmsg()).
  530.      */
  531.     if (wseq != ((his_rseq +1) & MAX_WINDOW)) 
  532.         {
  533.             int tmp_rseq;
  534.             tmp_rseq = his_rseq + 1;
  535. xmit_again:
  536.             /* msgo = msgout[(tmp_rseq + 1) & MAX_WINDOW]; JIM */
  537.             msgo = msgout[(tmp_rseq) & MAX_WINDOW];
  538.             update_rseq(msgo);
  539.             if (writeframe(pktchksum(msgo, sendbytes)
  540.                             /* msgo[CHKBYTE1]|(msgo[CHKBYTE2]>>8) */, msgo)
  541.                 != SUCCESS)
  542.                 {
  543.                     DEBUG(6, "write failed\n", 0);
  544.                     return FAIL;        /* Write failed */
  545.                     }
  546.             tmp_rseq = (tmp_rseq + 1) & MAX_WINDOW;
  547.             if (wseq != tmp_rseq) goto xmit_again;
  548.             } 
  549.         else
  550. ack_msg: 
  551.             {
  552.                 if (ackmsg() != SUCCESS)
  553.                     {
  554.                         DEBUG(6, "ack failed\n", 0);
  555.                         return FAIL;        /* Write failed */
  556.                         }
  557.                 }
  558.  
  559. again:
  560.     count = 0;
  561.  
  562.     DEBUG(9, "R ", 0);
  563.  
  564.     while (1) {
  565.         if (queued >= 0) {
  566.             /*
  567.              * Process some stuff from a string.
  568.              * If we just finished the last char queued, and
  569.              * we are still scanning for a DLE, re-xmit our
  570.              * last packet before we continue reading.
  571.              * On the other hand, if we have a valid packet
  572.              * header accumulating, just keep reading the serial
  573.              * port.
  574.              */
  575.             if (--queued < 0) {
  576.                 if (count == 0) {
  577.                     DEBUG(6, "End queue.  Re-xmit.\n", 0);
  578.                     goto xmit; /* No packet comin' in */
  579.                 } else {
  580.                     DEBUG(6,"End queue.  Keep reading\n",0);
  581.                     goto readser; /* Seems to be sumpin' */
  582.                 }
  583.             }
  584.             data = *qp++;        /* Just grab from queue */
  585.         } else {
  586. readser:
  587.             /* FIXME, suck in data in chunks into qbuf */
  588.             data = xgetc();
  589.             if (data == EOF) 
  590.                 {
  591.                     DEBUG(6, "EOF while getc'ing.\n", 0);
  592.                     break;
  593.                     }
  594.         }
  595.  
  596.         if (DEBUG_LEVEL(9))
  597.             DEBUG_DATA(data);
  598.  
  599.         switch (count)
  600.         {
  601.         case DLEBYTE:
  602.             /* Look for DLE */
  603.             if (data == DLE)
  604.                 msgi[count++] = (unsigned char)DLE;
  605.             break;
  606.  
  607.         case LENBYTE:
  608.             /* Check length byte */
  609.             if (data > KCONTROL || data == 0)
  610.                 bad(("packet size"));
  611.             if (segbytes[data] > MAX_PACKET) {
  612.                 bad(("packet too long for buffer"));
  613.  
  614.                 /*
  615.                  * Error recovery.
  616.                  *
  617.                  * First diagnose problem with current pkt.
  618.                  * Then scan that packet to see if perhaps
  619.                  * we have been looking at garbage and the
  620.                  * real packet is "inside" the garbage.
  621.                  * If so, rescan from the next DLE.  If not,
  622.                  * scan further input, or xmit a packet or
  623.                  * ack and then handle further input.
  624.                  */
  625.         oops:
  626.                 if (DEBUG_LEVEL(5))
  627.                     printf(": bad packet\n");
  628.  
  629.                 if (DEBUG_LEVEL(6) && count > CBYTE) {
  630.                     if (tt == CONTROL)
  631.                         printf("Bad:  CONTROL %s %d\n",
  632.                             ctrl_pr[xxx], yyy);
  633.                     else
  634.                         printf("Bad:  %s %d %d\n",
  635.                             tt_pr[tt], xxx, yyy);
  636.                 }
  637.  
  638.                 /* See if any DLEs in the bad packet */
  639.                 /* Skip 0, we know that's a DLE */
  640.                 for (i = DLEBYTE+1; i < count; i++) {
  641.                     if (msgi[i] == DLE) {
  642.                         /* Reprocess from the DLE.
  643.                          * if queued, back up the q.
  644.                          * if not, make one.
  645.                          */
  646.                         if (queued >= 0) {
  647.                             queued += count - i;
  648.                             qp -= count - i;
  649.                     DEBUG(2,"Backup and rescan queue\n", 0);
  650.                         } else {
  651.                             bcopy((char *)(msgi+i),
  652.                                   (char *)qbuf,
  653.                                   count - i);
  654.                             qp = qbuf;
  655.                             queued = count - i;
  656.                     DEBUG(2,"Queue and rescan input\n", 0);
  657.                         }
  658.                         goto again;
  659.                     }
  660.                 }
  661.  
  662.                 if (queued >= 0) {
  663.                     DEBUG(2, "Continue scan\n", 0);
  664.                     goto again;
  665.                 } else {
  666.                     DEBUG(2, "Re-xmit previous packet\n",0);
  667.                     goto xmit;    /* Xmit then rcv */
  668.                 }
  669.             }
  670.             msgi[count++] = (unsigned char)data;    /* Save it */
  671.             if (data > segsiz && data != KCONTROL) 
  672.                 bad(("packet larger than negotiated"));
  673.             msgsize = segbytes[data];    /* Save Packet size */
  674.             need = FRAMELEN + msgsize;
  675.             break;
  676.  
  677.         case CBYTE:
  678.             /* Break up control byte as well as storing it */
  679.             msgi[count++] = data;        /* Save it */
  680.             tt  = (data >> TYPESHIFT) & TYPEMASK;
  681.             xxx = (data >> XXXSHIFT ) & XXXMASK;
  682.             yyy = (data >> YYYSHIFT ) & YYYMASK;
  683.  
  684.             /* Now check it a bit */
  685.             switch (tt) {        /* Switch on msg type */
  686.             case CONTROL:
  687.                 /* Control msg must have KCONTROL size */
  688.                 if (msgsize != 0) bad(("K versus Control"));
  689.                 break;
  690.             
  691.             case ALTCHN:
  692.                 bad(("ALTCHN received")); /* Unsupported */
  693.  
  694.             case SHORTDATA:
  695.             case LONGDATA:
  696.                 if (msgsize == 0) bad (("KCONTROL with data"));
  697.                 break;
  698.             }
  699.             break;
  700.  
  701.         case FRAMEBYTE:
  702.             /* See whole frame, check it a bit. */
  703.             msgi[count++] = (unsigned char)data;
  704.             if (data != (msgi[1] ^ msgi[2] ^ msgi[3] ^ msgi[4]))
  705.                 bad(("frame checksum"));
  706.             pktsum = msgi[CHKBYTE1] + (msgi[CHKBYTE2] << 8);
  707.  
  708.             if (tt == CONTROL) {
  709.                 /* Check checksum for control packets */
  710.                 oursum = MAGIC - msgi[CBYTE];
  711.                 if (pktsum != oursum)
  712.                     bad(("control checksum"));
  713.                 /*
  714.                  * We have a full control packet.
  715.                  * Update received seq number for the ones
  716.                  * that carry one.
  717.                  */
  718.                 switch (xxx) {
  719.                 /* We don't implement SRJ, nor does Unix */
  720.                 case SRJ:
  721.                     bad(("SRJ received"));
  722.                 case RJ:
  723.                     if (((wseq - yyy) & MAX_WINDOW)
  724.                               > sendwin) {
  725. /* Atari ST cpp has problems with macro args broken across lines.
  726.  * That's why funny indent here. */
  727. bad (("RJ out of window, yyy=%d wseq=%d\n", yyy, wseq));
  728.                     }
  729.                     his_rseq = (yyy) & MAX_WINDOW;
  730.                     need_write = RETRANS_MSG;
  731.                     break;
  732.                 case RR:
  733.                     if (((wseq - yyy) & MAX_WINDOW)
  734.                               > sendwin) {
  735. bad (("RR out of window, yyy=%d wseq=%d\n", yyy, wseq));
  736.                     }
  737.                     /*
  738.                      * This is an experiment.  The
  739.                      * packet protocol paper claims
  740.                      * that "Packets must arrive in
  741.                      * sequence number order and are
  742.                      * only acknowledged in order."
  743.                      */
  744.                     if (yyy != his_rseq &&
  745.                         yyy != ((his_rseq+1) & MAX_WINDOW)) {
  746.                     his_rseq = yyy;
  747. bad(("RR not sequential, yyy=%d, wseq=%d, his_rseq=%d\n", yyy, wseq, his_rseq));
  748.                     }
  749.                     his_rseq = yyy;
  750.                     /* printf("RR: yyy=%d, wseq=%d\n", (int)yyy, (int)wseq); */
  751.                 }
  752.                 goto done;
  753.             } else {
  754.                 /*
  755.                  * Received frame of data packet.
  756.                  *
  757.                  * Now that the xor checksum has been verified,
  758.                  * we can believe the acknowledgement (if
  759.                  * any) in it.
  760.                  */
  761.                 if (((xxx - rseq) & MAX_WINDOW) > wndsiz) {
  762. bad (("data out of window, xxx=%d rseq=%d", xxx, rseq));
  763.                 }
  764.                 if (((wseq - yyy) & MAX_WINDOW) > sendwin) {
  765. bad (("data ack out of window, yyy=%d wseq=%d", yyy, wseq));
  766.                 }
  767.                 /*
  768.                  * This is an experiment.  The
  769.                  * packet protocol paper claims
  770.                  * that "Packets must arrive in
  771.                  * sequence number order and are
  772.                  * only acknowledged in order."
  773.                  */
  774.                 if (yyy != his_rseq &&
  775.                     yyy != ((his_rseq) & MAX_WINDOW) ) {
  776. bad(("data ack not sequential, yyy=%d, wseq=%d, his_rseq=%d", yyy, wseq, his_rseq));
  777.                 }
  778.                 his_rseq = yyy;
  779.             }
  780.             break;
  781.  
  782.         default:
  783.             msgi[count++] = (unsigned char)data;
  784.             if (count >= need) {
  785.                 /* We have received a full data packet */
  786.                 oursum = pktchksum(msgi, msgsize);
  787.                 if (pktsum != oursum) {
  788.                     /* Send a reject on this pkt */
  789.                     reject = xxx - 1;
  790. bad(("\ndata checksum in packet %x, ours=%x", pktsum, oursum));
  791.                     }
  792.                 if (xxx != ((rseq+1) & MAX_WINDOW)) {
  793. bad(("Not next packet xxx=%d rseq=%d\n", xxx, rseq));
  794.                 }
  795.         done:
  796.                 if (DEBUG_LEVEL(9))
  797.                     putchar('\n');
  798.                 if (DEBUG_LEVEL(6)) {
  799.                     if (tt == CONTROL)
  800.                         {
  801.                             if (xxx == CLOSE) 
  802.                                 {
  803.                                     wseq = (his_rseq + 1) & MAX_WINDOW;
  804.                                     connection_closing = TRUE;
  805.                                     }
  806.                             printf("Rcvd: CONTROL %s %d\n",
  807.                                 ctrl_pr[xxx], yyy);
  808.                             }
  809.                     else
  810.                         printf("Rcvd: %s %d %d\n",
  811.                             tt_pr[tt], xxx, yyy);
  812.                 }
  813.                 need_write = ACK_MSG;
  814.                 return SUCCESS;
  815.             }
  816.             break;
  817.         }
  818.     }
  819.     DEBUG(6, " EOF\n", 0);
  820.     return FAIL;
  821. }
  822.  
  823. /*
  824.  * Calculate the checksum of a packet.
  825.  * This code has been modified to work on systems where bytes are not 8
  826.  * bits and shorts are not 16 bits.  *Please* let me know if it does
  827.  * not work on your system, no matter what the byte size.
  828.  *
  829.  * To determine whether this still works with shorts larger than 16 bits,
  830.  * just uncomment the "#define short int" below.
  831.  */
  832. #define    HIGHBIT16    0x8000
  833. #define    JUST16BITS    0xFFFF
  834. #define    JUST8BITS    0x00FF
  835.  
  836. int
  837. pktchksum(msg, bytes)
  838.     unsigned char *msg;
  839.     int bytes;
  840. {
  841.     return (JUST16BITS &
  842.         (MAGIC - (chksum(&msg[6], bytes) ^ (JUST8BITS & msg[4]))));
  843.     
  844. }
  845.  
  846.  
  847. int
  848. chksum(s,n)
  849. register unsigned char *s;
  850. register n;
  851. {
  852. /* For debugging the checksum on PDP-10s, uncomment the following line
  853.  * and the line at the bottom of the function. */
  854. /* #define short int */
  855.     register short sum;
  856.     register unsigned short t;
  857.     register short x;
  858.  
  859.     sum = (-1) & JUST16BITS;
  860.     x = 0;
  861.     do {
  862.         /* Rotate "sum" left by 1 bit, in a 16-bit barrel */
  863.         if (sum & HIGHBIT16)
  864.         {
  865.             sum = (1 + (sum << 1)) & JUST16BITS;
  866.         }
  867.         else
  868.             sum <<= 1;
  869.         t = sum;
  870.         sum = (sum + (*s++ & JUST8BITS)) & JUST16BITS;
  871.         x += sum ^ n;
  872.         if ((unsigned short)sum <= t)
  873.             sum = (sum ^ x) & JUST16BITS;
  874.     } while (--n > 0);
  875.  
  876.     return(sum);
  877. /* End of debugging check */
  878. /* #undef short    */
  879. }
  880.  
  881.  
  882. /*
  883.  * Medium level packet driver input routine.
  884.  *
  885.  * Read a data packet from the other side.  If called twice in succession,
  886.  * we send an ack of the previous packet.  Otherwise we tend to piggyback
  887.  * the acks on data packets.
  888.  *
  889.  * Result is SUCCESS if we got a data packet, FAIL if we got some other kind,
  890.  * or a hangup timeout.
  891.  */
  892. s_or_f
  893. indata()
  894. {
  895.  
  896.     while (1) {
  897.         if (inpkt() != SUCCESS) 
  898.             {
  899.                 DEBUG(6, "inpkt failing\n", 0);
  900.                 return FAIL;
  901.                 }
  902.         switch (tt) {
  903.         case ALTCHN:
  904.             DEBUG(6, "ALTCHN unsupported\n", 0);
  905.             return FAIL;        /* Unsupported - yet */
  906.  
  907.         case LONGDATA:
  908.         case SHORTDATA:
  909.             /*
  910.              * We got a data packet.  That's what we want,
  911.              * so return.
  912.              */
  913.             rseq = xxx;        /* Packet correctly received */
  914.             return SUCCESS;        /* We are done. */
  915.  
  916.         case CONTROL:    
  917.             switch (xxx) {
  918.             default:
  919.                 DEBUG(6, "Bad packet type\n", 0);
  920.                 return FAIL;    /* Bad packet type */
  921.  
  922.             case RJ:        /* Reject prev pkt */
  923.                 {
  924.                     break;
  925.                     }
  926.             case RR:        /* OK but no data */
  927.                 {
  928.                     break;
  929.                     }        /* Ack and try again */
  930.             }
  931.         }
  932.     }
  933. }
  934.  
  935.  
  936.  
  937. /*
  938.  * Open a conversation in the g protocol.  Medium level routine.
  939.  *
  940.  * We need to both send and receive each packet type in turn.
  941.  * If this sequence falters, we start over at INITA, trying a few more times.
  942.  *
  943.  * Returns SUCCESS for success, FAIL for failure.
  944.  */
  945. s_or_f
  946. gturnon(mastermode/* , fd*/)
  947.     int mastermode;        /* 1 for master, 0 for slave */
  948.     /* int fd; */            /* File descriptor to operate on */
  949. {
  950.     int tries = 0;
  951.     int step = 0;
  952.     static int which[] = {INITA, INITA, INITB, INITB, INITC, INITC};
  953.  
  954.     /* initialize protocol globals, e.g. packet sequence numbers */
  955.  
  956.     rseq = 0;        /* Last good packet # we have seen from him */
  957.     wseq = 1;        /* Next packet # we will send */
  958.     his_rseq = 0;        /* Last good Packet # he has seen from us */
  959.     reject = NOREJECT;    /* Don't reject first packet */
  960.  
  961.     if (mastermode) goto master_start;
  962.  
  963.     while (++tries <= 8) {
  964.         /* Receive an initialization packet and handle it */
  965.         if (inpkt() == SUCCESS && tt == CONTROL && xxx == which[step]) {
  966.             switch (xxx) {
  967.             /* Remember we've seen it, grab value */
  968.             case INITA:
  969.             do_inita:
  970.                 sendwin = yyy;
  971.                 DEBUG(6, "INITA SENDWIN: %d\n", sendwin);
  972.                 break;
  973.             case INITB:
  974.                 /*
  975.                  * Get preferred packet size for other guy,
  976.                  * but don't overrun our buffer space.
  977.                  * The encoded segment size is off-by-1 from
  978.                  * the one used in the K field in each packet.
  979.                  */
  980.                 do {
  981.                     sendseg = yyy+1;
  982.                     sendbytes = segbytes[sendseg];
  983.                 } while (sendbytes > MAX_PACKET && --yyy);
  984.                 DEBUG(6, "INITB sendbytes: %d\n", sendbytes);
  985.                 break;
  986.             case INITC:
  987.                 sendwin = yyy;
  988.                 DEBUG(6, "INITC SENDWIN: %d\n", sendwin);
  989.                 break;
  990.             }
  991.             if (++step >= 6)        /* Move forward */
  992.                 return SUCCESS;        /* We are done */
  993.         } else {
  994.             /* Start over, sigh */
  995.             step = 0;
  996.             if (xxx == INITA)    /* Start with his inita */
  997.                 goto do_inita;
  998.         }
  999.  
  1000. master_start:
  1001.         /*
  1002.          * Transmit an initialization packet.
  1003.          */
  1004.         switch (which[step]) {
  1005.         case INITA:
  1006.             ctlmsg((INITA << XXXSHIFT) | wndsiz);
  1007.             break;
  1008.         case INITB:
  1009.             ctlmsg((INITB << XXXSHIFT) | (segsiz - 1));
  1010.             break;
  1011.         case INITC:
  1012.             ctlmsg((INITC << XXXSHIFT) | wndsiz);
  1013.             break;
  1014.         }
  1015.         if (++step >= 6)
  1016.             return SUCCESS;        /* We are done */
  1017.     }
  1018.     return FAIL;                /* Failure */
  1019. }
  1020.  
  1021.  
  1022. /*
  1023.  * Turn off conversation in the G protocol.  Medium level routine.
  1024.  */
  1025. s_or_f
  1026. gturnoff()
  1027. {
  1028.     int tries = 0;
  1029. #    define TURNOFF_TRIES    19
  1030.     /* Loop til all prevous data's been ack'd */
  1031.     need_write = NOOP;
  1032.     while ((wseq != ((his_rseq + 1) & MAX_WINDOW)) || 
  1033.            (tt != CONTROL && xxx != CLOSE)) 
  1034.         {
  1035.         if (++tries > TURNOFF_TRIES) return FAIL;
  1036.         ackmsg();
  1037.         if (inpkt() != SUCCESS) return FAIL;
  1038.     }
  1039.     tries = 0;
  1040.     do {
  1041.         if (++tries > TURNOFF_TRIES) return FAIL;
  1042.         ctlmsg(CLOSE << XXXSHIFT);
  1043.         if (inpkt() != SUCCESS)
  1044.             return FAIL;
  1045.     } while (tt != CONTROL && xxx != CLOSE);
  1046.  
  1047.     return SUCCESS;
  1048. }
  1049.  
  1050.  
  1051. /*
  1052.  * Read a message from the other side.
  1053.  *
  1054.  * Messages are always contained in LONGDATA packets.  If a message is
  1055.  * longer than a single packet, only the last packet will contain a null
  1056.  * character.  Keep catenating them until you see the null.
  1057.  *
  1058.  * Return SUCCESS or FAIL.  If the received message is longer than our
  1059.  * buffer, we eat the whole message, but return FAIL once it ends.
  1060.  */
  1061. s_or_f
  1062. grdmsg(str, fn)
  1063.     char *str;    /* Buffer to put it in, sized MAXMSGLEN */
  1064.     int fn;        /* File descriptor to read it from */
  1065. {
  1066.     unsigned msglen;
  1067.     unsigned totlen = 0;
  1068.     unsigned oldlen;
  1069.  
  1070.     str[0] = '\0';        /* No command yet */
  1071.     do {
  1072.         if (indata() != SUCCESS || tt != LONGDATA) {
  1073.             DEBUG(5, "grdmsg failing\n", 0);
  1074.             return FAIL;
  1075.         }
  1076.         msgi[FRAMELEN+msgsize] = '\0';    /* Null terminate packet */
  1077.         msglen = strlen((char *)(msgi+6));
  1078.         oldlen = totlen;
  1079.         totlen += msglen;
  1080.  
  1081.         /* Tack on to command */
  1082.         if (totlen < MAXMSGLEN) {
  1083.             strcat(str+oldlen,(char *)&msgi[FRAMELEN]);
  1084.         }
  1085.     } while (msglen == msgsize);    /* Loop if no null in pkt */
  1086.  
  1087.     if (DEBUG_LEVEL(5) && (totlen >= MAXMSGLEN)) {
  1088.         printf("grdmsg: message overflow: size=%d, max=%d\n", totlen, 
  1089.             MAXMSGLEN);
  1090.     }
  1091.  
  1092.     return (totlen < MAXMSGLEN)? SUCCESS: FAIL;
  1093. }
  1094.  
  1095.  
  1096. /*
  1097.  * Write a message to the other side.
  1098.  *
  1099.  * We write the first (or only) packet from our local bufr[], the
  1100.  * rest comes straight out of the caller's string.
  1101.  */
  1102. s_or_f
  1103. gwrmsg(type, str, fn)
  1104.     char type;
  1105.     char *str;
  1106.     int fn;
  1107. {
  1108.     char bufr[MAX_PACKET];
  1109.     char *ptr;
  1110.     int thislen, totlen;
  1111.     
  1112.     bufr[0] = type;
  1113.     totlen = strlen(str) + 1;
  1114.     if (totlen > MAXMSGLEN) abort();
  1115.     strncpy(&bufr[1], str, sendbytes-1);
  1116.     ptr = bufr;
  1117.     
  1118.     for (;;) {
  1119.         thislen = totlen;
  1120.         if (thislen > sendbytes) thislen = sendbytes;
  1121.         if (sendpacket(ptr, thislen, LONGDATA) != SUCCESS)
  1122.             return FAIL;
  1123.         totlen -= sendbytes;
  1124.         if (totlen < 0) break;
  1125.         if (ptr == bufr)    ptr = str + (sendbytes - 1);
  1126.         else            ptr += sendbytes;
  1127.     }
  1128.  
  1129.     return SUCCESS;
  1130. }
  1131.  
  1132. /*
  1133.  * Write a file to the other side.
  1134.  */
  1135. s_or_f
  1136. gwrdata(file, fn)
  1137.     FILE *file;        /* File to be sent */
  1138.     int fn;            /* fd of serial line */
  1139. {
  1140.     char dskbuf[MAX_PACKET];    /* Disk I/O buffer */
  1141.     int count;
  1142.  
  1143.     do {
  1144.         count = fread(dskbuf, sizeof (char), sendbytes, file);
  1145.         /* if (count < 0) return FAIL; */ /* FIXME, should send EOF */
  1146.         if ferror(file) return FAIL;
  1147.         if (sendpacket(dskbuf, count,
  1148.             (count == sendbytes)? LONGDATA: SHORTDATA) != SUCCESS)
  1149.                 return FAIL;
  1150.     } while (count);
  1151.     need_write = NOOP;
  1152.     return SUCCESS;
  1153. }
  1154.  
  1155. /*
  1156.  * Read a file from the other side.
  1157.  */
  1158. s_or_f
  1159. grddata(fn, file)
  1160.     int fn;            /* File desc of serial line */
  1161.     FILE *file;        /* stdio file ptr of file to read into */
  1162. {
  1163.     int offset;
  1164.     int status;
  1165.     int error = 0;
  1166.  
  1167.     do {
  1168.         /* Read a packet, handle the data in it */
  1169.         if (indata() != SUCCESS)
  1170.             return FAIL;
  1171.  
  1172.         switch (tt) {
  1173.         case LONGDATA:
  1174.             /* FIXME, check this write */
  1175.             ackmsg();        /* Send ack early, before
  1176.                            disk write */
  1177.             offset = FRAMELEN;
  1178.             goto writeit;
  1179.         case SHORTDATA:
  1180.             if (msgi[SHORTLEN1] & 0x80) {
  1181.                 msgsize -=
  1182.                   (msgi[SHORTLEN2] << 7) | (127&msgi[SHORTLEN1]);
  1183.                 offset = FRAMELEN+2;
  1184.             } else {
  1185.                 msgsize -= msgi[SHORTLEN1];
  1186.                 offset = FRAMELEN+1;
  1187.             }
  1188.  
  1189.         writeit:
  1190.             /* FIXME:
  1191.              * Consider skipping further writing if error != 0 */
  1192.             if (msgsize != 0) {
  1193.                 status = fwrite((char *) &msgi[offset],
  1194.                             sizeof (char), msgsize, file);
  1195.                 if (status != msgsize) error++;
  1196.             }
  1197.             break;
  1198.         }
  1199.     } while (msgsize != 0);
  1200.  
  1201.     return error? FAIL: SUCCESS;
  1202. }
  1203.  
  1204.