-- 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