-- File: PupListeners.mesa, Last Edit: HGM January 24, 1981 2:23 PM DIRECTORY Process USING [Detach], Runtime USING [GlobalFrame], Stream USING [Handle], PupRouterDefs USING [GetFirstPupSocket, PupRouterSocket], PupPktDefs USING [PupPktStreamMake, PupPktStream], PupStream USING [ PupByteStreamMake, PupListener, PupListenerObject, RejectThisRequest], PupDefs USING [ PupAddress, PupBuffer, PupSocketID, Tocks, PupRouterSendThis, SendErrorPup, SwapPupSourceAndDest, ReturnFreePupBuffer, PupSocket, PupSocketMake, PupSocketKick, PupSocketDestroy, veryLongWait, SetPupContentsBytes, AppendStringBodyToPupBuffer], PupTypes USING [fillInPupAddress]; PupListeners: MONITOR IMPORTS Runtime, Process, PupRouterDefs, PupPktDefs, PupStream, PupDefs EXPORTS PupPktDefs, PupStream = BEGIN OPEN PupRouterDefs, PupStream, PupDefs; -- Manager data free: POINTER TO FRAME [PupListeners] _ LOOPHOLE[Runtime.GlobalFrame[Listen]]; GetInstance: ENTRY PROCEDURE RETURNS [him: POINTER TO FRAME[PupListeners]] = BEGIN IF free=NIL THEN BEGIN him _ NEW PupListeners; START him; -- Do initialization code RETURN; END; him _ free; free _ free.next; END; FreeInstance: ENTRY PROCEDURE [him: POINTER TO FRAME[PupListeners]] = BEGIN him.next _ free; free _ him; END; next: POINTER TO FRAME [PupListeners] _ NIL; myPupListener: PupListenerObject _ LOOPHOLE[Listen]; socket: PupSocket; timeout: Tocks; stop: BOOLEAN; proc: PROCESS; who: PROCEDURE [UNSPECIFIED, PupAddress]; check: PROCEDURE [PupAddress]; Kind: TYPE = {pkt, byte}; kind: Kind; DontReject: PUBLIC PROCEDURE [PupAddress] = BEGIN END; CreatePupByteStreamListener: PUBLIC PROCEDURE [ local: PupSocketID, proc: PROCEDURE [Stream.Handle, PupAddress], ticks: Tocks, filter: PROCEDURE [PupAddress]] RETURNS [PupListener] = BEGIN RETURN[CreatePupListener[local, proc, ticks, byte, filter]]; END; CreatePupPktStreamListener: PUBLIC PROCEDURE [ local: PupSocketID, proc: PROCEDURE [PupPktDefs.PupPktStream, PupAddress], ticks: Tocks, filter: PROCEDURE [PupAddress]] RETURNS [PupListener] = BEGIN RETURN[CreatePupListener[local, proc, ticks, pkt, filter]]; END; CreatePupListener: PROCEDURE [ local: PupSocketID, w: PROCEDURE [UNSPECIFIED, PupAddress], ticks: Tocks, k: Kind, f: PROCEDURE [PupAddress]] RETURNS [PupListener] = BEGIN him: POINTER TO FRAME[PupListeners] _ GetInstance[]; him.socket _ PupSocketMake[local, PupTypes.fillInPupAddress, veryLongWait]; him.kind _ k; him.who _ w; him.check _ f; him.timeout _ ticks; him.stop _ FALSE; him.proc _ FORK him.Listen[local]; RETURN[@him.myPupListener]; END; DestroyPupListener: PUBLIC PROCEDURE [listener: PupListener] = BEGIN him: POINTER TO FRAME[PupListeners] _ LOOPHOLE[Runtime.GlobalFrame[ listener^]]; him.stop _ TRUE; PupSocketKick[him.socket]; JOIN him.proc; PupSocketDestroy[him.socket]; FreeInstance[him]; END; Listen: PROCEDURE [local: PupSocketID] = BEGIN soc: PupRouterSocket; arg: UNSPECIFIED; b: PupBuffer; UNTIL stop DO b _ 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; check[ him ! RejectThisRequest => BEGIN b.pupType _ abort; SwapPupSourceAndDest[b]; SetPupContentsBytes[b, 2]; AppendStringBodyToPupBuffer[b, error]; PupRouterSendThis[b]; GOTO Reject; END]; ReturnFreePupBuffer[b]; SELECT kind FROM pkt => arg _ PupPktDefs.PupPktStreamMake[ local, him, timeout, alreadyOpened, b.pupID]; byte => arg _ PupByteStreamMake[ local, him, timeout, alreadyOpened, b.pupID]; ENDCASE => ERROR; Process.Detach[FORK 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"L]; END; ENDLOOP; END; -- initialization END. -- of PupListeners