The `g' protocol is a packet based flow controlled error correcting protocol that requires an eight bit clear connection. It is the original UUCP protocol, and is supported by all UUCP implementations. Many implementations of it are only able to support small window and packet sizes, specifically a window size of 3 and a packet size of 64 bytes, but the protocol itself can support up to a window size of 7 and a packet size of 4096 bytes. Complaints about the inefficiency of the `g' protocol generally refer to specific implementations, rather than to the correctly implemented protocol.
The `g' protocol was originally designed for general packet drivers, and thus contains some features that are not used by UUCP, including an alternate data channel and the ability to renegotiate packet and window sizes during the communication session.
The `g' protocol is spoofed by many Telebit modems. When spoofing is in effect, each Telebit modem uses the `g' protocol to communicate with the attached computer, but the data between the modems is sent using a Telebit proprietary error correcting protocol. This allows for very high throughput over the Telebit connection, which, because it is half-duplex, would not normally be able to handle the `g' protocol very well at all. When a Telebit is spoofing the `g' protocol, it forces the packet size to be 64 bytes and the window size to be 3.
This discussion of the `g' protocol explains how it works, but does not discuss useful error handling techniques. Some discussion of this can be found in Jamie E. Hanrahan's paper, cited above (see section UUCP Protocol Sources).
All `g' protocol communication is done with packets. Each packet begins with a six byte header. Control packets consist only of the header. Data packets contain additional data.
The header is as follows:
The control byte in the header is composed of three bit fields, referred
to here as tt (two bits), xxx (three bits) and yyy
(three bits). The control is ttxxxyyy, or (tt
<< 6) + (xxx << 3) + yyy
.
The TT field takes on the following values:
l -
b1
valid bytes of data in the data field, beginning with the
second byte. If b1 >= 128
, let b2 be the second byte
in the data field. Then there are l - ((b1 & 0x7f) +
(b2 << 7))
valid bytes of data in the data field, beginning with
the third byte. In all cases l bytes of data are sent (and all
data bytes participate in the checksum calculation) but some of the
trailing bytes may be dropped by the receiver. The xxx and
yyy fields are described below.
In a data packet (short or not) the xxx field gives the sequence number of the packet. Thus sequence numbers can range from 0 to 7, inclusive. The yyy field gives the sequence number of the last correctly received packet.
Each communication direction uses a window which indicates how many unacknowledged packets may be transmitted before waiting for an acknowledgement. The window may range from 1 to 7, and may be different in each direction. For example, if the window is 3 and the last packet acknowledged was packet number 6, packet numbers 7, 0 and 1 may be sent but the sender must wait for an acknowledgement before sending packet number 2. This acknowledgement could come as the yyy field of a data packet, or as the yyy field of a `RJ' or `RR' control packet (described below).
Each packet must be transmitted in order (the sender may not skip sequence numbers). Each packet must be acknowledged, and each packet must be acknowledged in order.
In a control packet, the xxx field takes on the following values:
To compute the checksum, call the control byte (the fifth byte in the header) c.
The checksum of a control packet is simply 0xaaaa - c
.
The checksum of a data packet is 0xaaaa - (check ^
c)
, where ^
denotes exclusive or, and check is the
result of the following routine as run on the contents of the data field
(every byte in the data field participates in the checksum, even for a
short data packet). Below is the routine used by an early version of
Taylor UUCP; it is a slightly modified version of a routine which John
Gilmore patched from G.L. Chesson's original paper. The z
argument points to the data and the c
argument indicates how much
data there is.
int igchecksum (z, c) register const char *z; register int c; { register unsigned int ichk1, ichk2; ichk1 = 0xffff; ichk2 = 0; do { register unsigned int b; /* Rotate ichk1 left. */ if ((ichk1 & 0x8000) == 0) ichk1 <<= 1; else { ichk1 <<= 1; ++ichk1; } /* Add the next character to ichk1. */ b = *z++ & 0xff; ichk1 += b; /* Add ichk1 xor the character position in the buffer counting from the back to ichk2. */ ichk2 += ichk1 ^ c; /* If the character was zero, or adding it to ichk1 caused an overflow, xor ichk2 to ichk1. */ if (b == 0 || (ichk1 & 0xffff) < b) ichk1 ^= ichk2; } while (--c > 0); return ichk1 & 0xffff; }
When the `g' protocol is started, the calling UUCP sends an `INITA' control packet with the window size it wishes the called UUCP to use. The called UUCP responds with an `INITA' packet with the window size it wishes the calling UUCP to use. Pairs of `INITB' and `INITC' packets are then similarly exchanged. When these exchanges are completed, the protocol is considered to have been started.
Note that the window and packet sizes are not a negotiation. Each system announces the window and packet size which the other system should use. It is possible that different window and packet sizes will be used in each direction. The protocol works this way on the theory that each system knows how much data it can accept without getting overrun. Therefore, each system tells the other how much data to send before waiting for an acknowledgement.
When a UUCP package transmits a command, it sends one or more data packets. All the data packets will normally be complete, although some UUCP packages may send the last one as a short packet. The command string is sent with a trailing null byte, to let the receiving package know when the command is finished. Some UUCP packages require the last byte of the last packet sent to be null, even if the command ends earlier in the packet. Some packages may require all the trailing bytes in the last packet to be null, but I have not confirmed this.
When a UUCP package sends a file, it will send a sequence of data packets. The end of the file is signalled by a short data packet containing zero valid bytes (it will normally be preceeded by a short data packet containing the last few bytes in the file).
Note that the sequence numbers cover the entire communication session, including both command and file data.
When the protocol is shut down, each UUCP package sends a `CLOSE' control packet.
Go to the first, previous, next, last section, table of contents.