-- Transport Mechanism Mail Server - algorithm to process forward queue -- -- [ReadForward]<Grapevine>MS>ReadForward.mesa -- Randy Gobbel 19-May-81 11:57:02 -- -- Andrew Birrell 29-Dec-81 14:53:38 -- DIRECTORY BodyDefs USING[ RName ], BufferDefs, HeapDefs USING[ ObjectNumber, HeapReadData, HeapStartRead, ReaderHandle, HeapEndRead, SendObj ], LocalNameDefs USING[ ReadMSName ], LogDefs USING[ WriteLogEntry ], PolicyDefs USING[ EndOperation, WaitOperation], Process USING[ Detach ], ProtocolDefs USING[ AppendTimestamp, CreateStream, DestroyStream, Failed, Handle, Password, ReceiveAck, SendRName, SendTimestamp ], RestartDefs USING[ ], ServerDefs USING[ ServerAddr, ServerHandle, ServerNotUp, ServerUp, DownServer, NoSuchServer ], SLDefs USING[ GetCount, SLHeader, SLStartRead, SLReadHandle, SLEndRead, SLTransfer ], String USING[ AppendString ]; ReadForward: PROGRAM IMPORTS HeapDefs, LocalNameDefs, LogDefs, PolicyDefs, Process, ProtocolDefs, ServerDefs, SLDefs, String EXPORTS RestartDefs --PROGRAM-- = BEGIN NoRecipients: ERROR = CODE; --not caught; should not occur-- ForeignServer: ERROR = CODE; --not caught; should not occur-- ForwardMain: PROCEDURE = BEGIN -- multiple instantiations of this procedure are allowed -- DO BEGIN str: ProtocolDefs.Handle ← NIL; SLobj: HeapDefs.ReaderHandle; SLhandle: SLDefs.SLReadHandle; bodyObj: HeapDefs.ObjectNumber; slHeader: SLDefs.SLHeader; outcome: {ok, down} ← ok; [SLhandle, bodyObj, SLobj] ← SLDefs.SLStartRead[forward]; PolicyDefs.WaitOperation[readForward]; BEGIN -- read SL header -- ended: BOOLEAN; used: CARDINAL; [ended,used] ← HeapDefs.HeapReadData[SLobj, [@slHeader,SIZE[SLDefs.SLHeader]] ]; IF ended THEN ERROR NoRecipients[]; END; --MTP--IF slHeader.server.type = foreign THEN ERROR ForeignServer[]; IF NOT ServerDefs.ServerUp[slHeader.server] THEN { HeapDefs.HeapEndRead[SLobj]; outcome ← down } ELSE BEGIN str ← ProtocolDefs.CreateStream[ ServerDefs.ServerAddr[slHeader.server ! ServerDefs.ServerNotUp, ServerDefs.NoSuchServer => GOTO noAddr ] ! ProtocolDefs.Failed => GOTO noStr ]; BEGIN ENABLE ProtocolDefs.Failed => { HeapDefs.HeapEndRead[SLobj]; GOTO wentDown }; myName: BodyDefs.RName; myKey: ProtocolDefs.Password; [name:myName, key:myKey,password:] ← LocalNameDefs.ReadMSName[]; ProtocolDefs.SendRName[str, myName]; ProtocolDefs.SendTimestamp[str, slHeader.created]; END; BEGIN ENABLE ProtocolDefs.Failed => GOTO wentDown; HeapDefs.SendObj[SLobj, str]; HeapDefs.SendObj[HeapDefs.HeapStartRead[bodyObj], str]; ProtocolDefs.ReceiveAck[str]; END; ProtocolDefs.DestroyStream[str]; EXITS noAddr => { HeapDefs.HeapEndRead[SLobj]; outcome ← down }; noStr => BEGIN HeapDefs.HeapEndRead[SLobj]; ServerDefs.DownServer[slHeader.server]; outcome ← down; END; wentDown => BEGIN ProtocolDefs.DestroyStream[str]; ServerDefs.DownServer[slHeader.server]; outcome ← down; END; END; BEGIN log: STRING = [128]; String.AppendString[log, "Forwarded "L]; ProtocolDefs.AppendTimestamp[log, slHeader.created]; String.AppendString[log, " to "L]; WITH slHeader.server.name SELECT FROM rName => String.AppendString[log, value]; ENDCASE; IF outcome # ok THEN String.AppendString[log, ": failed"L]; LogDefs.WriteLogEntry[log]; END; SELECT outcome FROM ok => SLDefs.SLEndRead[SLhandle]; down => SLDefs.SLTransfer[SLhandle, input]; ENDCASE => ERROR; END; PolicyDefs.EndOperation[readForward]; ENDLOOP; END; ForwardRestart: PROCEDURE = BEGIN -- on restart, must transfer everything to input, since ServerHandles -- are no longer valid -- THROUGH [1..SLDefs.GetCount[forward]] DO BEGIN handle: SLDefs.SLReadHandle; body: HeapDefs.ObjectNumber; SL: HeapDefs.ReaderHandle; [handle, body, SL] ← SLDefs.SLStartRead[forward]; HeapDefs.HeapEndRead[SL]; SLDefs.SLTransfer[handle, input]; END; ENDLOOP; END; ForwardRestart[]; Process.Detach[ FORK ForwardMain[] ]; END.