-- Transport Mechanism Mail Server - client reading mail --
-- [Indigo]<Grapevine>MS>Readmail.mesa
-- Andrew Birrell 25-Oct-82 10:53:32 --
DIRECTORY
BodyDefs USING[ maxRNameLength, Password, RName ],
LogDefs USING[ WriteLogEntry],
MailboxDefs USING[ Close, DeleteMessage, FlushAndClose,
InaccessibleArchive, MBXHandle,
NextMessage, Open, ReadTOC, SendBody, WriteTOC ],
NameInfoDefs USING[ AuthenticateInfo, AuthenticateKey ],
PolicyDefs USING [CheckOperation, EndOperation],
ProtocolDefs USING[ Failed, Handle, mailServerOutputSocket,
maxRemarkLength, MSOperation,
ReceiveMSOperation, ReceivePassword,
ReceiveRemark,
ReceiveRName, Remark, SendAck, SendBoolean,
SendByte, SendCount, SendNow, SendRemark ],
PupStream USING[ CreatePupByteStreamListener,
PupAddress, RejectThisRequest, SecondsToTocks ],
RestartDefs USING[] --EXPORT only--,
String USING [EquivalentSubStrings, SubStringDescriptor];
ReadMail: PROGRAM
IMPORTS LogDefs, MailboxDefs, NameInfoDefs, PolicyDefs, ProtocolDefs,
PupStream, String
EXPORTS RestartDefs --PROGRAM-- =
BEGIN
EndsWith: PROC[s: STRING, b: STRING] RETURNS[ BOOLEAN ] =
BEGIN
pattern: String.SubStringDescriptor ← [b, 0, b.length];
target: String.SubStringDescriptor ← [s,s.length-b.length,b.length];
RETURN[ s.length >= b.length
AND String.EquivalentSubStrings[@pattern,@target] ]
END;
Receive: PROCEDURE[ str: ProtocolDefs.Handle, where: PupStream.PupAddress ] =
BEGIN
OPEN ProtocolDefs;
client: BodyDefs.RName = [BodyDefs.maxRNameLength];
state: { closed, open, inMessage } ← closed;
mbx: MailboxDefs.MBXHandle;
found: BOOLEAN ← FALSE;
Open: PROC =
BEGIN
count: CARDINAL;
[found, count, mbx] ← MailboxDefs.Open[client];
IF found THEN state ← open;
ProtocolDefs.SendCount[str,IF found THEN count ELSE 0];
END;
DO ENABLE ProtocolDefs.Failed, MailboxDefs.InaccessibleArchive => EXIT;
op: ProtocolDefs.MSOperation;
op ← ProtocolDefs.ReceiveMSOperation[str !
ProtocolDefs.Failed =>
IF why = noData AND EndsWith[client, ".gv"]
THEN RETRY -- i.e. if caller is an R-Server --];
SELECT op FROM
openMBX =>
BEGIN
key: BodyDefs.Password;
info: NameInfoDefs.AuthenticateInfo;
ProtocolDefs.ReceiveRName[str,client];
key ← ProtocolDefs.ReceivePassword[str, [0,0,0,0] ];
IF state # closed THEN EXIT;
info ← NameInfoDefs.AuthenticateKey[client, key];
ProtocolDefs.SendByte[str, LOOPHOLE[info]];
IF info = individual THEN Open[];
END;
nextMessage =>
BEGIN
msgExists, archived, deleted: BOOLEAN;
IF state = inMessage THEN state ← open;
-- pretend that not found means empty mailbox --
IF found
THEN IF state # open
THEN EXIT
ELSE BEGIN
[msgExists,archived,deleted] ←
MailboxDefs.NextMessage[mbx];
state ← IF deleted THEN open ELSE inMessage;
END
ELSE msgExists ← archived ← deleted ← FALSE;
ProtocolDefs.SendBoolean[str, msgExists];
ProtocolDefs.SendBoolean[str, archived];
ProtocolDefs.SendBoolean[str, deleted];
END;
readTOC =>
BEGIN
remark: ProtocolDefs.Remark = [ProtocolDefs.maxRemarkLength];
IF state # inMessage THEN EXIT;
MailboxDefs.ReadTOC[mbx, remark];
ProtocolDefs.SendRemark[str, remark];
END;
readMessage =>
BEGIN
IF state # inMessage THEN EXIT;
MailboxDefs.SendBody[mbx, str];
END;
writeTOC =>
BEGIN
remark: ProtocolDefs.Remark = [ProtocolDefs.maxRemarkLength];
ProtocolDefs.ReceiveRemark[str, remark];
IF state # inMessage THEN EXIT;
MailboxDefs.WriteTOC[mbx, remark];
ProtocolDefs.SendAck[str];
END;
deleteMessage =>
BEGIN
IF state # inMessage THEN EXIT;
MailboxDefs.DeleteMessage[mbx];
ProtocolDefs.SendAck[str];
END;
flushMBX =>
BEGIN
IF found
THEN BEGIN
IF state = closed THEN EXIT;
MailboxDefs.FlushAndClose[mbx];
state ← closed;
END
ELSE NULL;
ProtocolDefs.SendAck[str];
END;
ENDCASE => EXIT;
ProtocolDefs.SendNow[str];
ENDLOOP;
IF state # closed THEN MailboxDefs.Close[mbx];
str.delete[str];
PolicyDefs.EndOperation[readMail];
END;
ReadMailFilter: PROCEDURE[PupStream.PupAddress] =
BEGIN
IF NOT PolicyDefs.CheckOperation[readMail]
THEN BEGIN
LogDefs.WriteLogEntry["Rejected ReadMail connection"L];
ERROR PupStream.RejectThisRequest["Server full"L];
END
END;
[] ← PupStream.CreatePupByteStreamListener[
ProtocolDefs.mailServerOutputSocket, Receive,
PupStream.SecondsToTocks[120],
ReadMailFilter ];
END.