DIRECTORY Basics USING [BITAND, bytesPerWord], Endian USING [bytesPerFWord, bytesPerHWord, FWORD, HWORD], CommBuffer USING [Overhead], Pup USING [Address, Host, Net], PupType USING [bytesInPupHeader, bytesOfPupOverhead, ErrorCode, HeaderWithoutChecksum, maxNewGatewayBytes, maxOldGatewayBytes, Type]; PupBuffer: CEDAR DEFINITIONS IMPORTS Basics = { BYTE: TYPE = [0..100H); HWORD: TYPE = Endian.HWORD; FWORD: TYPE = Endian.FWORD; maxOldGatewayBytes: NAT = PupType.maxOldGatewayBytes; maxNewGatewayBytes: NAT = PupType.maxNewGatewayBytes; maxDataBytes: NAT = 1500-PupType.bytesOfPupOverhead; maxDataHWords: NAT = maxDataBytes/Endian.bytesPerHWord; maxDataFWords: NAT = maxDataBytes/Endian.bytesPerFWord; ByteAlloc: TYPE = [0..maxDataBytes); HWordAlloc: TYPE = [0..maxDataHWords); FWordAlloc: TYPE = [0..maxDataFWords); ByteIndex: TYPE = [0..maxDataBytes]; HWordIndex: TYPE = [0..maxDataHWords]; FWordIndex: TYPE = [0..maxDataFWords]; StringIndex: TYPE = [0..maxDataBytes-stringOverheadBytes); AbortIndex: TYPE = [0..maxDataBytes-abortOverheadBytes); ErrorIndex: TYPE = [0..maxDataBytes-errorOverheadBytes); Buffer: TYPE = REF BufferObject; PupBufferPointer: TYPE = LONG POINTER TO BufferObject; -- Needed by Stupid Debugger BufferObject: TYPE = MACHINE DEPENDENT RECORD [ ovh: CommBuffer.Overhead, byteLength: HWORD, -- includes header and software checksum hopCount: [0..16), spares: [0..16), type: PupType.Type, id: FWORD, dest, source: Pup.Address, body: SELECT OVERLAID * FROM bytes => [ byte: PACKED ARRAY ByteAlloc OF BYTE ], chars => [ char: PACKED ARRAY ByteAlloc OF CHAR ], hWords => [ hWord: ARRAY HWordAlloc OF HWORD ], fWords => [ fWord: ARRAY FWordAlloc OF FWORD ], string => [ string: RECORD [ length: HWORD, maxLength: HWORD, text: PACKED ARRAY StringIndex OF CHAR ] ], rfc => [ address: Pup.Address ], ack => [ maxBytesPerPup: HWORD, maxPupsAhead: HWORD, maxBytesAhead: HWORD], abort => [ abort: RECORD [ code: HWORD, text: PACKED ARRAY AbortIndex OF CHAR ] ], error => [ error: RECORD [ header: PupType.HeaderWithoutChecksum, code: PupType.ErrorCode, options: HWORD, text: PACKED ARRAY ErrorIndex OF CHAR ] ], addresses => [ addresses: ARRAY AddressAlloc OF Pup.Address ], echoStats => [ echoStats: EchoStatsResponse], fileLookupReply => [ fileLookupReply: FileLookupReply ], routing => [ routing: ARRAY RoutingEntryAlloc OF RoutingInfoResponse ], time => [ time: TimeResponse ], ENDCASE ]; noChecksum: Endian.HWORD = 0FFFFH; RoundUpForChecksum: PROC [bytes: NAT] RETURNS [NAT] = INLINE { RETURN[Basics.BITAND[(bytes+1), 0FFFEH]]; }; WordsWithoutChecksum: PROC [bytes: NAT] RETURNS [words: NAT] = INLINE { RETURN[(bytes-1)/Endian.bytesPerHWord]; }; stringOverheadBytes: NAT = 2*Endian.bytesPerHWord; abortOverheadBytes: NAT = 1*Endian.bytesPerHWord; errorOverheadBytes: NAT = PupType.bytesInPupHeader + SIZE[PupType.ErrorCode, Basics.bytesPerWord] + 1*Endian.bytesPerHWord; bytesPerAddress: NAT = SIZE[Pup.Address, Basics.bytesPerWord]; maxAddresses: NAT = maxOldGatewayBytes/bytesPerAddress; AddressAlloc: TYPE = [0..maxAddresses); echoStatsVersion: NAT = 1; EchoStatsResponse: TYPE = MACHINE DEPENDENT RECORD [ version: HWORD, pupsEchoed: FWORD ]; FileLookupReply: TYPE = MACHINE DEPENDENT RECORD [ version: HWORD, createTime: FWORD, length: FWORD ]; bytesPerRoutingInfoResponse: NAT = SIZE[RoutingInfoResponse, Basics.bytesPerWord]; maxRoutingEntrys: NAT = maxOldGatewayBytes/bytesPerRoutingInfoResponse; RoutingEntryAlloc: TYPE = [0..maxRoutingEntrys); RoutingInfoResponse: TYPE = MACHINE DEPENDENT RECORD [ net: Pup.Net, viaNet: Pup.Net, viaHost: Pup.Host, hop: BYTE ]; TimeResponse: TYPE = MACHINE DEPENDENT RECORD [ time: FWORD, direction: { west(0), east(1) }, zone: [0..127], zoneMinutes: [0..255], beginDST, endDST: HWORD ]; }.  PupBuffer.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Hal Murray, June 2, 1986 11:18:46 am PDT Buffer size constants This is what the type checker uses for things that live in our buffers. Gateways currently support 532. Making this bigger is the first step towards making things go much faster. "1500" is really Driver.dataBytesInBuffer, but we don't want that compilation dependency. Beware: round down to maxXxxGatewayBytes if you are going through a gateway. Including these types here means we have to recompile a whole lot to experiment with bigger buffers. Using these types lets the Compiler avoid a lot of bounds checking. Buffer layout Do not NEW your own BufferObjects. Next is a copy of the Header defined in PupType. If we used that directly you would have to say b.pup.type instead of just b.type. software checksum (1 HWORD) comes after all the data Software checksums Round up to include the garbage byte if this is an odd length packet. Total words is (bytes+2-1)/2, but we want 1 less than that. Length calculations for error/abort Pups (and string body) Record layouts for bodys of Pups This is a collection of all the record layouts used in raw Pups. Collecting so many things here adds to the recompilation problems if anything changes but it avoids LOOPHOLEs and collects these specifications as a documentation aid. Bugs or oversights can be fixed with a LOOPHOLE. That's actually reasonably safe if you consistently include something like the following right after you get a buffer. (Beware of NIL faults.) foo: LONG POINTER TO Record _ LOOPHOLE[@b.body]; The following sections are sorted alphabetically, but you have to guess which keyword to use. Addresses - response from name server Echo server - statistics File Lookup Routing info Time server ΚΠ˜codešœ™Kšœ Οmœ1™Kšœ-˜-Kšœ8˜8Kšœžœžœ˜GKšœ˜Kšž˜—Kšœžœ™4šœ˜K˜———™šœžœ ˜"K˜—š Οnœžœ žœžœžœžœ˜>Kšžœžœ˜,K™EK˜—š ‘œžœ žœžœ žœžœ˜GKšžœ$˜*Kšœ;™;K˜——™:Kšœžœ˜2Kšœžœ˜1šœžœžœB˜{K˜——™ Kšœ₯Οsœ;™θšœ'žœ™ΏKšœ0™0K™—K™]—™%Kšœžœžœ#˜>Kšœžœ&˜7šœžœ˜'K˜——™Kšœžœ˜š œžœžœž œžœ˜4Kšœ žœ˜šœ žœ˜K˜———™ š œžœžœž œžœ˜2Kšœ žœ˜Kšœ ž˜šœžœ˜K˜———™ Kšœžœžœ+˜RKšœžœ2˜GKšœžœ˜0š œžœžœž œžœ˜6šœ7žœ˜>K˜———™ š œžœžœž œžœ˜/Kšœžœ˜ Kšœ ˜ K˜K˜šœžœ˜K˜—K˜——šœ˜K˜——…—Ύš