-- Transport Mechanism Mail Server - input from other GV servers --

-- [Juniper]<DMS>MS>ReceiveInput.mesa

-- Randy Gobbel		19-May-81 18:47:09 --
-- Andrew Birrell	12-Jan-81 16:09:58 --

DIRECTORY
BodyDefs	USING[ maxRNameLength, RName, Timestamp ],
HeapDefs	USING[ ObjectNumber, HeapAbandonWrite, HeapStartWrite,
                       HeapWriteData, ReceiveObj, HeapEndWrite,
                       GetWriterOffset, WriterHandle ],
LogDefs		USING[ WriteChar, WriteLogEntry ],
NameInfoDefs	USING[ IsMemberDirect ],
PolicyDefs	USING [CheckOperation, EndOperation],
ProtocolDefs	USING[ AppendTimestamp, Failed, Handle,
                       mailServerServerSocket, ReceiveRName,
                       ReceiveTimestamp, SendAck, SendNow ],
PupDefs		USING[ AppendHostName, PupAddress, SecondsToTocks ],
PupStream	USING[ CreatePupByteStreamListener, RejectThisRequest ],
RestartDefs	USING[] --EXPORT only--,
SLDefs		USING[ SLHeader, SLWrite ],
String		USING[ AppendLongDecimal, AppendString ],
Time	USING[ Current ];

ReceiveInput: PROGRAM
   IMPORTS HeapDefs, LogDefs, NameInfoDefs, PolicyDefs, ProtocolDefs,
           PupDefs, PupStream, SLDefs, String, Time
   EXPORTS RestartDefs --PROGRAM-- =

BEGIN

Filter: PROCEDURE[ from: PupDefs.PupAddress ] =
   BEGIN
   IF NOT PolicyDefs.CheckOperation[serverInput]
   THEN BEGIN
        LogDefs.WriteLogEntry["Rejected ServerInput connection"L];
        ERROR PupStream.RejectThisRequest["Server full"L]
        END;
   END;

Receiver: PROCEDURE[ str: ProtocolDefs.Handle,
                     fromAddr: PupDefs.PupAddress ] =
   BEGIN
   OPEN ProtocolDefs;

   fromName: BodyDefs.RName = [BodyDefs.maxRNameLength];

   ReceiveRName[str, fromName ! Failed => GOTO badName ];
   IF NameInfoDefs.IsMemberDirect["*.MS"L, fromName] # yes
   THEN GOTO badName;

   DO BEGIN
         bodyHandle: HeapDefs.WriterHandle = HeapDefs.HeapStartWrite[body];
         SLhandle:   HeapDefs.WriterHandle = HeapDefs.HeapStartWrite[SLinput];
         Accept: PROCEDURE[ obj: HeapDefs.ObjectNumber ] =
            BEGIN SLDefs.SLWrite[obj, SLhandle, input] END;
         header: SLDefs.SLHeader;
         header.received.host ← fromAddr.host;
         header.received.net ←  fromAddr.net;
         header.received.time ← Time.Current[];
         header.server ← NIL;
         BEGIN
            ENABLE Failed => GOTO bad;
            header.created ← ProtocolDefs.ReceiveTimestamp[str];
            HeapDefs.HeapWriteData[SLhandle,
                                   [@header, SIZE[SLDefs.SLHeader] ] ];
            HeapDefs.ReceiveObj[SLhandle, str];
            HeapDefs.ReceiveObj[bodyHandle, str];
            LogReceived[header.created, fromName,
                        HeapDefs.GetWriterOffset[bodyHandle] ];
            LogDefs.WriteChar['S];
            HeapDefs.HeapEndWrite[bodyHandle, Accept];
         EXITS bad =>
            BEGIN
            HeapDefs.HeapAbandonWrite[bodyHandle];
            HeapDefs.HeapAbandonWrite[SLhandle];
            EXIT
            END;
         END;
      END;
      BEGIN
         ENABLE ProtocolDefs.Failed => EXIT;
         ProtocolDefs.SendAck[str]; -- all is on disk --
         ProtocolDefs.SendNow[str];
      END;

      -- wait for sender to start a new message, possibly --
   ENDLOOP;

   PolicyDefs.EndOperation[serverInput];
   str.delete[str];

   EXITS
      badName =>
         BEGIN
         PolicyDefs.EndOperation[serverInput];
         str.delete[str];
         LogBad[fromAddr];
         END;
   END;

LogReceived: PROC[created: BodyDefs.Timestamp, from: BodyDefs.RName,
                  words: LONG CARDINAL] =
   BEGIN
   log: STRING = [128];
   String.AppendString[log, "Received "L];
   ProtocolDefs.AppendTimestamp[log, created];
   String.AppendString[log, " from "L];
   String.AppendString[log, from];
   String.AppendString[log, ": "L];
   String.AppendLongDecimal[log,words];
   String.AppendString[log, " words"L];
   LogDefs.WriteLogEntry[log];
   END;

LogBad: PROC[fromAddr: PupDefs.PupAddress] =
   BEGIN
   log: STRING = [128];
   String.AppendString[log, "Illegal MS-input request from host "L];
   PupDefs.AppendHostName[log, fromAddr];
   END;

[] ← PupStream.CreatePupByteStreamListener[
        ProtocolDefs.mailServerServerSocket, Receiver,
        PupDefs.SecondsToTocks[60],
        Filter ];


END.