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