-- Copyright (C) 1981, 1984, 1985 by Xerox Corporation. All rights reserved. -- MiscSoc.mesa, Transport Mechanism Mail Server - Miscellaneous socket communication -- -- HGM: 18-Sep-85 6:42:09 -- Randy Gobbel 29-May-81 14:44:13 -- -- Andrew Birrell 13-Jan-81 11:15:27 -- -- Mark Johnson May 28, 1981 2:29 PM -- -- Hankins 2-Oct-84 11:30:32 DIRECTORY BodyDefs USING [maxRNameLength, RName], Buffer USING [AccessHandle, GetBuffer, MakePool, ReturnBuffer], Heap USING [systemZone], Inline USING [LongCOPY], LogDefs USING [WriteLogEntry], MailboxDefs USING [Poll], PolicyDefs USING [ProdServersPause, CheckOperation], Process USING [Detach, SecondsToTicks, SetTimeout], ProtocolDefs USING [Init, mailServerPollingSocket], PupDefs USING [ AppendHostName, GetPupContentsBytes, PupBuffer, PupRouterSendThis, PupSocket, PupSocketMake, SetPupContentsWords, SwapPupSourceAndDest, veryLongWait], PupTypes USING [echoSoc, fillInSocketID, PupAddress], RestartDefs USING [], ServerDefs USING [ EnumerateAll, NoSuchServer, ServerAddr, ServerHandle, ServerNotUp, ServerUp, UpServer], SiteCacheDefs USING [SingleFlush], String USING [AppendString]; MiscSoc: MONITOR IMPORTS Buffer, Heap, Inline, LogDefs, MailboxDefs, PolicyDefs, Process, ProtocolDefs, PupDefs, ServerDefs, SiteCacheDefs, String EXPORTS RestartDefs --PROGRAM-- = BEGIN bufferPool: Buffer.AccessHandle; poll: PupDefs.PupSocket ← NIL; prod: PupDefs.PupSocket ← NIL; echo: PupDefs.PupSocket ← NIL; UnexpectedTimeout: ERROR = CODE; AcceptPoll: PROCEDURE = BEGIN DO b: PupDefs.PupBuffer = poll.get[]; IF b = NIL THEN ERROR UnexpectedTimeout[]; SELECT b.pup.pupType FROM mailCheckLaurel => PutBuffer[b]; echoMe => BEGIN IF ~PolicyDefs.CheckOperation[serverInput, FALSE] THEN -- Don't answer unless we are accepting forwarded mail to avoid -- false hopes (and thrashing) on other servers. BEGIN Buffer.ReturnBuffer[b]; LOOP; END; PupDefs.SwapPupSourceAndDest[b]; b.pup.pupType ← iAmEcho; PupDefs.PupRouterSendThis[b]; END; LOOPHOLE[215B] => PutBuffer[b]; ENDCASE => Buffer.ReturnBuffer[b]; ENDLOOP; END; WorkOnPoll: PROCEDURE = BEGIN DO b: PupDefs.PupBuffer = GetBuffer[]; SELECT b.pup.pupType FROM mailCheckLaurel => BEGIN pLength: CARDINAL = PupDefs.GetPupContentsBytes[b]; IF pLength > BodyDefs.maxRNameLength THEN b.pup.pupType ← mailNotNew ELSE BEGIN client: BodyDefs.RName = [BodyDefs.maxRNameLength]; Inline.LongCOPY[ from: @(b.pup.pupString), to: @(client.text), nwords: (1 + pLength) / 2]; client.length ← pLength; b.pup.pupType ← IF MailboxDefs.Poll[client] THEN mailIsNew ELSE mailNotNew; END; PupDefs.SwapPupSourceAndDest[b]; PupDefs.SetPupContentsWords[b, 0]; PupDefs.PupRouterSendThis[b]; END; LOOPHOLE[215B] => CacheFlushRequest[b]; ENDCASE => ERROR; ENDLOOP; END; flushing: BOOLEAN ← FALSE; buffersFlushed, clumpsFlushed: LONG CARDINAL ← 0; theBuffer: PupDefs.PupBuffer ← NIL; waitingForBuffer: CONDITION; PutBuffer: ENTRY PROC [b: PupDefs.PupBuffer] = BEGIN IF theBuffer # NIL AND ~flushing THEN WAIT waitingForBuffer; IF theBuffer # NIL THEN BEGIN Buffer.ReturnBuffer[b]; buffersFlushed ← buffersFlushed.SUCC; IF ~flushing THEN clumpsFlushed ← clumpsFlushed.SUCC; flushing ← TRUE; RETURN; END; theBuffer ← b; NOTIFY waitingForBuffer; flushing ← FALSE; END; GetBuffer: ENTRY PROC RETURNS [b: PupDefs.PupBuffer] = BEGIN WHILE theBuffer = NIL DO WAIT waitingForBuffer; ENDLOOP; b ← theBuffer; theBuffer ← NIL; NOTIFY waitingForBuffer; END; CacheFlushRequest: PROCEDURE [b: PupDefs.PupBuffer] = BEGIN name: LONG STRING = LOOPHOLE[@(b.pup.pupWords)]; IF name.length <= BodyDefs.maxRNameLength THEN BEGIN log: LONG STRING ← Heap.systemZone.NEW[StringBody[200]]; SiteCacheDefs.SingleFlush[name]; String.AppendString[log, "Cache-Flush request for "L]; String.AppendString[log, name]; String.AppendString[log, " from "]; PupDefs.AppendHostName[log, b.pup.source]; LogDefs.WriteLogEntry[log]; Heap.systemZone.FREE[@log]; END; Buffer.ReturnBuffer[b]; END; PollForUpServer: PROCEDURE [server: ServerDefs.ServerHandle] = BEGIN ENABLE BEGIN ServerDefs.NoSuchServer => GOTO NoSuchServer; ServerDefs.ServerNotUp => GOTO ServerNotUp; END; IF NOT ServerDefs.ServerUp[server] THEN BEGIN dest: PupTypes.PupAddress ← ServerDefs.ServerAddr[server]; b: PupDefs.PupBuffer ← Buffer.GetBuffer[ type: pup, aH: bufferPool, function: send]; PupDefs.SetPupContentsWords[b, 0]; b.pup.pupType ← echoMe; b.pup.pupID.a ← LOOPHOLE[server]; b.pup.pupID.b ← LOOPHOLE[server]; dest.socket ← IF server.leaf THEN PupTypes.echoSoc ELSE ProtocolDefs.mailServerPollingSocket; prod.setRemoteAddress[dest]; prod.put[b]; END; EXITS NoSuchServer => NULL; ServerNotUp => NULL; END; ProdServers: PROC = BEGIN DO PolicyDefs.ProdServersPause[]; ServerDefs.EnumerateAll[PollForUpServer]; ENDLOOP; END; ProdReply: PROCEDURE = BEGIN DO b: PupDefs.PupBuffer = prod.get[]; IF b = NIL THEN ERROR UnexpectedTimeout[]; SELECT b.pup.pupType FROM iAmEcho => BEGIN maybe: ServerDefs.ServerHandle = LOOPHOLE[b.pup.pupID.a]; Work: PROCEDURE [really: ServerDefs.ServerHandle] = BEGIN IF really = maybe THEN ServerDefs.UpServer[really]; END; ServerDefs.EnumerateAll[Work]; Buffer.ReturnBuffer[b]; END; ENDCASE => Buffer.ReturnBuffer[b]; ENDLOOP; END; Echo: PROCEDURE = BEGIN DO b: PupDefs.PupBuffer = echo.get[]; IF b = NIL THEN ERROR UnexpectedTimeout[]; SELECT b.pup.pupType FROM echoMe => BEGIN PupDefs.SwapPupSourceAndDest[b]; b.pup.pupType ← iAmEcho; PupDefs.PupRouterSendThis[b]; END; ENDCASE => Buffer.ReturnBuffer[b]; ENDLOOP; END; MiscSoc1: PUBLIC PROC = BEGIN Process.SetTimeout[@waitingForBuffer, Process.SecondsToTicks[5]]; ProtocolDefs.Init[]; END; MiscSoc2: PUBLIC PROC = BEGIN bufferPool ← Buffer.MakePool[send: 1, receive: 0]; poll ← PupDefs.PupSocketMake[ProtocolDefs.mailServerPollingSocket, , PupDefs.veryLongWait]; prod ← PupDefs.PupSocketMake[PupTypes.fillInSocketID, , PupDefs.veryLongWait]; echo ← PupDefs.PupSocketMake[PupTypes.echoSoc, , PupDefs.veryLongWait]; Process.Detach[FORK AcceptPoll[]]; Process.Detach[FORK WorkOnPoll[]]; Process.Detach[FORK ProdReply[]]; Process.Detach[FORK Echo[]]; Process.Detach[FORK ProdServers[]]; END; END.