-- Transport Mechanism: User: main loop of access to mailboxes -- -- [Juniper]<DMS>MS>RetrieveMail.mesa -- Andrew Birrell 21-Jan-81 17:26:03 -- DIRECTORY BodyDefs USING[ ItemHeader, ItemLength, RName, Timestamp ], PupDefs USING[ PupAddress ], RetrieveDefs USING[ AccessProcs, FailureReason, MBXState, ServerState, ServerType ], RetrieveXDefs USING[ FindAddress, GVAccept, GVClose, GVDeleteMessage, GVNextBlock, GVNextItem, GVNextMessage, GVReadTOC, GVStartMessage, GVWriteTOC, Handle, HandleObject, MBXPtr, MTPAccept, MTPClose, MTPNextBlock, MTPNextItem, MTPNextMessage, NoteChangedMBX, noMBX ], String USING[ AppendString ]; RetrieveMail: MONITOR LOCKS handle USING handle: RetrieveXDefs.Handle IMPORTS RetrieveXDefs, String EXPORTS RetrieveDefs, RetrieveXDefs = BEGIN Handle: PUBLIC TYPE = RetrieveXDefs.Handle; HandleObject: PUBLIC TYPE = RetrieveXDefs.HandleObject; MailboxState: PUBLIC ENTRY PROCEDURE[handle: Handle] RETURNS[state: RetrieveDefs.MBXState] = BEGIN ENABLE UNWIND => NULL; DO SELECT handle.mbxState FROM unknown, userOK => WAIT handle.mbxStateChange; ENDCASE => EXIT; ENDLOOP; RETURN[handle.mbxState] END; -- Client access to his mail: -- WrongCallSequence: ERROR = CODE; ServerName: PUBLIC ENTRY PROCEDURE[ handle: Handle, serverName: BodyDefs.RName ] = BEGIN IF handle.currentMBX = RetrieveXDefs.noMBX THEN ERROR WrongCallSequence[]; serverName.length ← 0; String.AppendString[serverName, handle.currentMBX.name]; END; ServerAddress: PUBLIC INTERNAL PROC[handle: RetrieveXDefs.Handle] RETURNS[ PupDefs.PupAddress ] = BEGIN IF handle.currentMBX = RetrieveXDefs.noMBX THEN ERROR WrongCallSequence[]; IF handle.currentMBX.addrState = unknown THEN RetrieveXDefs.FindAddress[handle, handle.currentMBX]; SELECT handle.currentMBX.addrState FROM unknown => ERROR Failed[communicationFailure]; bad => ERROR Failed[noSuchServer]; known => RETURN[handle.currentMBX.addr]; ENDCASE => ERROR; END; NextServer: PUBLIC ENTRY PROCEDURE[handle: Handle] RETURNS[ noMore: BOOLEAN, state: RetrieveDefs.ServerState, procs: RetrieveDefs.AccessProcs ] = BEGIN ENABLE UNWIND => NULL; DO SELECT handle.mbxState FROM unknown, userOK => WAIT handle.mbxStateChange; ENDCASE => EXIT; ENDLOOP; IF handle.currentMBX = RetrieveXDefs.noMBX THEN BEGIN handle.currentMBX ← handle.MBXChain; handle.newPollWanted ← TRUE; BROADCAST handle.pollCond; WHILE handle.newPollWanted DO WAIT handle.mbxStateChange ENDLOOP; END ELSE BEGIN IF handle.currentMBX.type = MTP THEN RetrieveXDefs.MTPClose[handle] ELSE RetrieveXDefs.GVClose[handle]; handle.currentMBX ← handle.currentMBX.next; END; IF handle.currentMBX = RetrieveXDefs.noMBX THEN BEGIN noMore ← TRUE; END ELSE BEGIN noMore ← FALSE; WHILE handle.currentMBX.replyWanted DO WAIT handle.mbxStateChange ENDLOOP; state ← handle.currentMBX.state; IF handle.currentMBX.type = MTP THEN BEGIN handle.state ← beginning; procs ← [ nextMessage: RetrieveXDefs.MTPNextMessage, nextItem: RetrieveXDefs.MTPNextItem, nextBlock: RetrieveXDefs.MTPNextBlock, accept: Accept, extra: MTP[] ]; END ELSE BEGIN handle.header ← [type: LastItem, length: 0]; handle.spareByte ← FALSE; handle.state ← beforeMBX; procs ← [ nextMessage: RetrieveXDefs.GVNextMessage, nextItem: RetrieveXDefs.GVNextItem, nextBlock: RetrieveXDefs.GVNextBlock, accept: Accept, extra: GV[ readTOC: RetrieveXDefs.GVReadTOC, startMessage: RetrieveXDefs.GVStartMessage, writeTOC: RetrieveXDefs.GVWriteTOC, deleteMessage: RetrieveXDefs.GVDeleteMessage ] ]; END; END; END; Accept: ENTRY PROCEDURE[ handle: Handle ] = BEGIN ENABLE UNWIND => NULL; IF handle.currentMBX.type = MTP THEN RetrieveXDefs.MTPAccept[handle] ELSE RetrieveXDefs.GVAccept[handle]; RetrieveXDefs.NoteChangedMBX[handle, handle.currentMBX, empty]; END; Failed: PUBLIC ERROR[why: RetrieveDefs.FailureReason] = CODE; END.