GVProtocol.mesa - subroutines for mail and reg server protocols
Copyright © 1985 by Xerox Corporation. All rights reserved.
Andrew Birrell June 22, 1983 6:02 pm
Levin, September 22, 1983 10:38 am
Hal Murray, May 12, 1986 9:57:44 pm PDT
DIRECTORY
Endian USING [HWORD],
GVBasics USING [Connect, ItemHeader, GVString, oldestTime, Password, Remark, RName, Timestamp],
GVNames USING [RSOperation],
IO USING [STREAM, UnsafeBlock],
Pup USING [Address, Socket],
Rope USING [ROPE];
GVProtocol: CEDAR DEFINITIONS = {
SetTestingMode: PROC;
set sockets for test-only mode
GVSocket: TYPE = { -- socket numbers are hidden, because they differ in testing mode
none, -- use socket number in host address
RSEnquiry, -- database operations
RSPoll, -- "are you there" probes
Lily, -- Lily terminal service
MSPoll, -- "are you there" probes
MSForward, -- internal forwarding protocol
MSSend, -- mail submission protocol
MSRetrieve -- mail retrieval
};
GetSocket: PROC [gv: GVSocket] RETURNS [Pup.Socket];
endSST: [0..256) = 1;
BSP "mark" byte used in Server-Server and ReadMail protocols
IsLocal: PROC [addr: Pup.Address] RETURNS [BOOLEAN ];
Whether the address is on this host
Handle: TYPE = IO.STREAM;
FailureReason: TYPE = { communicationError, noData, protocolError, clientError };
"communicationError" means some error pup arrived; "noData" means the stream is still there, but no data; "protocolError" means we cant understand him
Failed: SIGNAL [why: FailureReason, text: Rope.ROPE];
may be raised by any of the following procedures,
except DestroyStream.
CreateStream: PROC [host: Pup.Address, socket: GVSocket, secs: INT ← 120 ]
RETURNS[ Handle ];
Create stream, with given timeout for data
SendNow: PROC [str: Handle];
Close: PROC [str: Handle];
The following procedures provide type-safe access to the communication protocols. Note that sending characters directly on the stream is not always correct if they have one of these types. These procedures implement any conversion needed between Cedar internal representation and the Grapevine protocols.
SendAck: PROC [str: Handle];
ReceiveAck: PROC [str: Handle];
SendBoolean: PROC [str: Handle, bool: BOOL];
ReceiveBoolean: PROC [str: Handle] RETURNS [BOOL];
Byte: TYPE = [0..256);
SendByte: PROC [str: GVProtocol.Handle, byte: Byte];
ReceiveByte: PROC [str: GVProtocol.Handle] RETURNS [byte: Byte];
SendCount: PROC [str: Handle, count: Endian.HWORD];
ReceiveCount: PROC [str: Handle] RETURNS [count: Endian.HWORD];
SendItemHeader: PROC [str: Handle, header: GVBasics.ItemHeader];
transmits the header.
ReceiveItemHeader: PROC [str: Handle] RETURNS [header: GVBasics.ItemHeader];
receive header of item from stream.
SendTimestamp: PROC [str: Handle, stamp: GVBasics.Timestamp];
sends a Timestamp value over the stream.
ReceiveTimestamp: PROC [str: Handle] RETURNS [stamp: GVBasics.Timestamp];
receives a timestamp from the stream.
SendPassword: PROC [str: Handle, pw: GVBasics.Password];
ReceivePassword: PROC [str: Handle] RETURNS[pw: GVBasics.Password];
SendRC: PROC [str: Handle, rc: ReturnCode];
sends a return code value over the stream.
ReceiveRC: PROC [str: Handle] RETURNS [rc: ReturnCode];
receives a return code value from the stream.
SendMSOperation: PROC [str: Handle, op: MSOperation];
ReceiveMSOperation: PROC [str: Handle] RETURNS [op: MSOperation];
SendRSOperation: PROC [str: Handle, op: GVNames.RSOperation];
ReceiveRSOperation: PROC [str: Handle] RETURNS [op: GVNames.RSOperation];
SendBytes: PROC [str: GVProtocol.Handle, block: IO.UnsafeBlock];
ReceiveBytes: UNSAFE PROC [str: GVProtocol.Handle, block: IO.UnsafeBlock];
StringSize: PROC [str: GVBasics.GVString] RETURNS [INT];
the number of words occupied by protocol representation of a string
SendRName: PROC [str: Handle, name: GVBasics.RName];
transmits the contents of the R-Name.
ReceiveRName: PROC [str: Handle] RETURNS [GVBasics.RName];
SendConnect: PROC [str: Handle, connect: GVBasics.Connect];
sends the connect-site name as a Mesa string. "connect.length" should be < maxConnectLength
ReceiveConnect: PROC [str: Handle] RETURNS [GVBasics.Connect];
SendRemark: PROC [str: Handle, remark: GVBasics.Remark];
-- sends the remark as a Mesa string. "remark.length" should be < maxRemarkLength --
ReceiveRemark: PROC [str: Handle] RETURNS[GVBasics.Remark];
ReceiveGVString: PROC [str: GVProtocol.Handle] RETURNS[GVBasics.GVString];
Receive a string in GV protocol format
ReceiveFunnyString: PROC [str: Handle] RETURNS [GVBasics.RName];
Skip maxLength when sent in the middle of a bigger thing.
This is only used by GVNamesImpl to get the Remark and Connect fields.
SendGVString: PROC [str: GVProtocol.Handle, rope: GVBasics.GVString];
Send a string in GV protocol format.
SendRope: PROC [str: GVProtocol.Handle, rope: Rope.ROPE];
Send the characters of the rope with no extra protocol information
Enquire: PROC [
str: Handle,
op: GVNames.RSOperation,
name: GVBasics.RName,
oldStamp: GVBasics.Timestamp ← GVBasics.oldestTime]
RETURNS [rc: ReturnCode, stamp: GVBasics.Timestamp];
Sends an enquiry on the stream
ReceiveRList: PROC [str: Handle, work: PROC [GVBasics.RName] ];
receives a sequence of R-Names from the stream, calling "work" for each R-Name.
MSOperation: TYPE = MACHINE DEPENDENT {
openMBX(0),
nextMessage(1),
readTOC(2),
readMessage(3),
writeTOC(4),
deleteMessage(5),
flushMBX(6),
restartMBX(7),
startSend(20),
addRecipient(21),
checkValidity(22),
startItem(23),
addToItem(24),
send(26),
expand(27),
getStamp(28),
(255)
};
RNameType: TYPE = MACHINE DEPENDENT {
status of an RName, given in an R-Server reply.
group(0), -- group of names
individual(1), -- person or machine
notFound(2), -- the R-Name does not exist
dead(3), -- the R-Name has been deleted from the database
(255) };
Code: TYPE = MACHINE DEPENDENT {
result of an R-Server operation.
done(0), -- operation succeeded
noChange(1), -- enquiry: given stamp was still valid
update: operation wouldn't change the database
outOfDate(2), -- update: more recent info was in database (!)
NotAllowed(3), -- update: operation prevented by access controls
BadOperation(4), -- unknown operation number
BadProtocol(5), -- protocol violation (e.g. list out of order)
BadRName(6), -- R-Name does not exist or has wrong type
BadPassword(7), -- what it says
WrongServer(8), -- the R-Name's registry is not in this R-Server
AllDown(9), -- remote R-Server was down for ACL enquiry
(255) };
ReturnCode: TYPE = MACHINE DEPENDENT RECORD [
code: Code, type: RNameType];
}.