-- Copyright (C) 1981, 1983, 1984  by Xerox Corporation. All rights reserved. 
-- ReceiveInput.mesa, Transport Mechanism Mail Server - input from other GV servers --

-- HGM, 18-Nov-84  0:34:08
-- Andrew Birrell	12-Jan-81 16:09:58 --
-- Mike Schroeder	25-Jan-83 16:11:56 --

DIRECTORY
  BodyDefs USING [maxRNameLength, RName, Timestamp],
  HeapDefs USING [
    ObjectNumber, HeapAbandonWrite, HeapStartWrite, HeapWriteData, ReceiveObj,
    HeapEndWrite, GetWriterOffset, WriterHandle],
  LogDefs USING [ShowLine, 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, AppendNumber, 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
      s: STRING = [100];
      String.AppendString[s, "Rejected ServerInput connection from "L];
      String.AppendNumber[s, from.net, 8];
      String.AppendString[s, "#"L];
      String.AppendNumber[s, from.host, 8];
      String.AppendString[s, "#"L];
      LogDefs.ShowLine[s];
      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, "Server input from "L];
    String.AppendString[log, from];
    String.AppendString[log, ": "L];
    ProtocolDefs.AppendTimestamp[log, created];
    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.