PupListeners.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Andrew Birrell May 12, 1983 10:56 am
DIRECTORY
IO USING [STREAM],
Process USING [Detach],
PupRouterDefs USING [GetFirstPupSocket, PupRouterSocket],
PupStream USING [ PupByteStreamMake, RejectThisRequest],
PupDefs USING [PupAddress, PupBuffer, PupSocketID, Tocks, PupRouterSendThis, SendErrorPup, SwapPupSourceAndDest, ReturnFreePupBuffer, PupSocket, PupSocketMake, PupSocketKick, PupSocketDestroy, veryLongWait, SetPupContentsBytes, AppendRopeToPupBuffer],
PupTypes USING [fillInPupAddress];
PupListeners: MONITOR
IMPORTS Process, PupRouterDefs, PupStream, PupDefs
EXPORTS PupStream =
BEGIN OPEN PupRouterDefs, PupStream, PupDefs;
PupListener: TYPE = REF PupListenerObject;
PupListenerObject: PUBLIC TYPE = RECORD[
socket: PupSocket,
timeout: Tocks,
stop: BOOLEAN,
who: PROCEDURE [IO.STREAM, PupAddress],
check: PROCEDURE [PupAddress],
proc: PROCESS
];
DontReject: PUBLIC SAFE PROCEDURE [PupAddress] = CHECKED BEGIN END;
CreatePupByteStreamListener: PUBLIC SAFE PROCEDURE [
local: PupSocketID, proc: PROCEDURE [IO.STREAM, PupAddress], ticks: Tocks,
filter: PROCEDURE [PupAddress]] RETURNS [PupListener] =
TRUSTED BEGIN
him: PupListener = NEW[PupListenerObject];
him.socket ← PupSocketMake[local, PupTypes.fillInPupAddress, veryLongWait];
him.timeout ← ticks;
him.stop ← FALSE;
him.who ← proc;
him.check ← filter;
him.proc ← FORK Listen[him, local];
RETURN[him];
END;
DestroyPupListener: PUBLIC SAFE PROCEDURE [listener: PupListener] =
TRUSTED BEGIN
listener.stop ← TRUE;
PupSocketKick[listener.socket];
JOIN listener.proc;
PupSocketDestroy[listener.socket];
END;
Listen: PROCEDURE [listener: PupListener, local: PupSocketID] =
BEGIN
soc: PupRouterSocket;
arg: IO.STREAM;
b: PupBuffer;
UNTIL listener.stop DO
b ← listener.socket.get[];
IF b # NIL THEN
BEGIN
SELECT b.pupType FROM
rfc =>
BEGIN OPEN PupStream;
FOR soc ← GetFirstPupSocket[], soc.next UNTIL soc = NIL DO
check for duplicate
IF soc.remote # b.source THEN LOOP;
IF soc.id # b.pupID THEN LOOP;
b.address ← soc.local;
SwapPupSourceAndDest[b];
PupRouterSendThis[b];
EXIT;
ENDLOOP;
IF soc = NIL THEN
BEGIN -- not a duplicate, make a new connection
him: PupAddress ← b.address;
listener.check[
him !
RejectThisRequest =>
BEGIN
b.pupType ← abort;
SwapPupSourceAndDest[b];
SetPupContentsBytes[b, 2];
AppendRopeToPupBuffer[b, error];
PupRouterSendThis[b];
GOTO Reject;
END];
ReturnFreePupBuffer[b];
arg ← PupByteStreamMake[ local, him, listener.timeout, alreadyOpened, b.pupID];
Process.Detach[FORK listener.who[arg, him]];
END;
EXITS Reject => NULL;
END;
echoMe =>
BEGIN
b.pupType ← iAmEcho;
SwapPupSourceAndDest[b];
PupRouterSendThis[b];
END;
ENDCASE => SendErrorPup[b, LOOPHOLE[100B], "RFC expected"];
END;
ENDLOOP;
END;
initialization
END. -- of PupListeners