/*++ Copyright (c) 1996 Microsoft Corporation Module Name: PROTOCOL.H Abstract: Another Reliable Protocol - CPP implementation Author: Aaron Ogus (aarono) Environment: Win32/COM Revision History: Date Author Description ====== ====== ============================================================ 12/10/96 aarono Original 2/11/97 aarono Removed channel from header, now rides in body of 1st packet. along with the length field. 3/12/97 aarono channel is gone, not relevant to transport protocol, can be prepended to messages that want it. Length field is gone, not required. 6/6/98 aarono Turn on throttling and windowing - fix some definitions --*/ #ifndef _PROTOCOL_H_ #define _PROTOCOL_H_ #pragma pack(push,1) typedef unsigned char byte; typedef unsigned short word; typedef unsigned int dword; // // ARP - Another Reliable Protocol - Packet Definitions // // Terminology // // message - an arbitrary sized chunk of data // to be sent from one computer to a another over // the available media. // // packet - a piece of a message broken down // for the media, including protocol information // to allow the message to be reconstructed at // the other end. // // frame - an instance of a packet. // // Assumptions: // // All values on the wire are little endian. // // This protocol allows packets to arrive out of // order but is optimized for the in-order case. // #define EXT 0x80 /* EXTENSION BIT */ #define BIG 0x40 /* BIG HEADERS (FAST MEDIA) */ #define CMD 0x20 /* COMMAND FRAME */ #define STA 0x10 #define EOM 0x08 /* END OF MESSAGE */ #define SAK 0x04 /* SEND ME AN ACK */ #define ACK 0x02 /* ACKNOWLEDGE FRAME */ #define RLY 0x01 /* RELIABLE FRAME */ // Shifts used in small extended fields. #define nNACK_MSK 0x60 #define nNACK_SHIFT 5 #define CMD_MSK 0x1F #define IDMSK (pCmdInfo->IDMSK) #define SEQMSK (pCmdInfo->SEQMSK) // Note: abort packets contain serial numbers but no sequence numbers. // the nACK field can be used to abort many messages at the same // time. (using ABORT2 or ABORT3). Also just the messageid is // provided in the abort case. typedef struct _Packet1 { // simple small -I- frame byte flags; byte messageid; byte sequence; byte serial; byte data[0]; } Packet1, *pPacket1; typedef struct _Packet2 { // simple large -I- frame byte flags; word messageid; word sequence; byte serial; byte data[0]; } Packet2, *pPacket2; typedef struct { byte flag1; // header flags byte flag2; // extended flags for small hdr/command for lrg byte flag3; // nNACK for large hdr. byte pad; // make it a dword. } FLAGS, *pFLAGS; // different frame components that may be part of any // frame. type 1 - small frames, type 2 - large frames // // ACKNOWLEDGE information // typedef struct _ACK1 { byte messageid; byte sequence; byte serial; dword bytes; // bytes received from remote dword time; // time when bytes received was this value } ACK1, *pACK1; typedef struct _ACK2 { word messageid; word sequence; byte serial; dword bytes; // bytes received from remote dword time; // remote time when bytes receive was this value } ACK2, *pACK2; // // ABORT // typedef struct _ABT1 { byte messageid; byte sequence; } ABT1, *pABT1; typedef struct _ABT2 { word messageid; word sequence; } ABT2, *pABT2; // // MISSING packet information // typedef struct _NACK1 { byte messageid; byte sequence; dword bytes; // bytes received from remote dword time; // remote time when bytes received was this value byte mask[0]; } NACK1, *pNACK1; typedef struct _NACK2 { word messageid; word sequence; dword bytes; // bytes received from remote dword time; // remote time when bytes received was this value byte mask[0]; } NACK2, *pNACK2; // // COMMAND information (including -I- frames) // typedef struct _CMD1 { byte messageid; byte sequence; byte serial; byte data[0]; } CMD1, *pCMD1; typedef struct _CMD2 { word messageid; word sequence; byte serial; byte data[0]; } CMD2, *pCMD2; #pragma pack(pop) #endif /*============================================================================== Protocol Operational description ================================ Characteristics: ---------------- The ARP protocol provides for reliable and non-reliable packet delivery over an existing non-reliable (datagram) protocol. It is assumed that packet length information and addressing information is carried by the datagram protocol and these fields are therefore ambiguous and excluded from ARP. ARP is optimized to provide a minimum of overhead in the case of low bandwidth links. The overhead per-packet is 3 bytes. ARP's default command is the delivery of I frames. This avoids the need for a command field in the protocol header for the most common frame type. ARP does segmentation and reassembly on large datagram messages. This allows for datagram delivery of messages larger than 1 packet. ARP does a hybrid of windowing with selective NACK of missing packets, allowing optimal operation on both good and weak links, regardless of latency. ARP assigns each frame a serial number that is used in the ACK responses. This allows the protocol to keep up to date latency information as well as recognize which packet is being responded to in a retry situation. The serial number allows the protocol to adjust timeouts reliably. ARP allows multiple messages to be sent concurrently. Having multiple messages prevents the system from blocking on retry from a single packet transmission failure. It also allows better use of available bandwidth since the protocol does not wait for the ACK from one message before sending the next. {FUTURE: What about packet sub-allocation? Bandwidth allocation?} Header Description: ------------------- Flags: +-----+-----+-----+-----+-----+-----+-----+-----+ | EXT | BIG | CMD | STA | EOM | SAK | ACK | RLY | +-----+-----+-----+-----+-----+-----+-----+-----+ Extended Flags: Small: +-----+-----+-----+-----+-----+-----+-----+-----+ | EXT | nNACK | COMMAND | +-----+-----+-----+-----+-----+-----+-----+-----+ Big: +-----+-----------------------------------------+ | EXT | COMMAND | (only if CMD & BIG set) +-----+-----------------------------------------+ | EXT | nNACK | +-----+-----------------------------------------+ Flags: STA - start of a message. EOM - this bit is set when the packet is the last packet of a message ACK - used to signify that this is an ACK packet, otherwise a COMMAND - if nACK != 0, the ACK is informative only. i.e - tells client last ACKed frame that instigated the nACK to update latency information. An ACK without nACK indicates all frames up to the ACK frame were successfully received. Any bit set in the nACK mask indicates a missing frame, any 0 bit indicates a frame that was successfully received. SAK - when this bit is set, the receiver must send an ACK packet for this packet. RLY - indicates that this message is being delivered reliably. BIG - when this bit is set, the packets are in large format TYPE 3. CMD - command frame. When this bit is set, the packet contains a command. If there is no COMMAND field it is an I frame. EXT - when the BIG bit is not set, indicates extended flags are present. Extended Flags: nNACK - if non-zero indicates presence of nNACK byte masks. The NACK field consists of a sequence number followed by nNACK byte masks. Each bit in the mask represents a packet after the packet specified in the sequence number. The packet in the sequence number is also being NACKed. Command: The command field is used to specify protocol subcommands. The following are defined. Commands larger than 15 require BIG packets. Commands that require responses include the response in the ACK packet. All protocol commands are unreliable. Each command has its own messageid sequence and serial. This means commands can be of arbitrary length. The Response to a command is also a command. 0000 0 - Default - I Frame or ACK/NACK (nACK != 0) 0001 1 - ABORT 0010 2 - Ping - send packet back to sender. 0011 3 - Ping Response - a message being returned. 0100 4 - GetTime - Get the tick count. 0101 5 - Get Time Response - Response to the Get Time request. 0110 6 - SetTime - Set the tick count. 0111 7 - Set Time Response - Response to the Set Time request. Rule for processing EXT bits. If a byte in the flags has the high bit set, there is one more byte. Ignore any bits beyond what you know how to process. Sample Packets: =============== Time setting algorithm? Bandwidth Calculations? Scheduling? Window Size? Interpacket wait? Send Queue Management? Command for selective NACK. RLY bit separates 2 streams - reliable/datagram. For piggyback ACK this means reliable piggyback ACKs are only on reliable streams and datagram piggyback ACKs are only on non-reliable streams. ==============================================================================*/ #ifdef __DPMESS_INCLUDED__ #define MAX_SEND_HEADER (sizeof(Packet2)+sizeof(MSG_PROTOCOL)) // leave space for a 128 bit NACK message, this is the maximum window we ever allow #define MAX_SYS_HEADER (sizeof(NACK2)+(128/8)+sizeof(MSG_PROTOCOL)) #endif