-- File: PupListeners.mesa, Last Edit: 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