-- 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.