-- File: PupListeners.mesa - last edit: -- AOF 17-Feb-88 15:22:39 -- SMA 1-Sep-83 20:56:59 -- Copyright (C) 1983, 1986, 1988 by Xerox Corporation. All rights reserved. DIRECTORY Process USING [Detach], Runtime USING [GlobalFrame], Stream USING [Handle], PrincOpsMinus USING [NewSelf], PupRouterDefs USING [GetFirstPupSocket, PupRouterSocket], PupPktDefs USING [PupPktStreamMake, PupPktStream], PupStream USING [ PupByteStreamMake, PupListener, PupListenerObject, RejectThisRequest], PupDefs USING [ PupAddress, PupBuffer, PupSocketID, Tocks, PupRouterSendThis, SendErrorPup, SwapPupSourceAndDest, PupSocket, PupSocketMake, ReturnBuffer, PupSocketKick, PupSocketDestroy, veryLongWait, SetPupContentsBytes, AppendStringBodyToPupBuffer], PupTypes USING [fillInPupAddress]; PupListeners: MONITOR IMPORTS Runtime, PrincOpsMinus, Process, PupRouterDefs, PupPktDefs, PupStream, PupDefs EXPORTS PupPktDefs, PupStream = BEGIN OPEN PupRouterDefs, PupDefs; -- Manager data Listen: PROCEDURE [local: PupSocketID] ← RealListen; -- The procedure variable for getting linkage to the instance's RealListen. free: LONG POINTER TO FRAME[PupListeners] ← LOOPHOLE[Runtime.GlobalFrame[LOOPHOLE[Listen]]]; GetInstance: ENTRY PROCEDURE RETURNS [him: LONG POINTER TO FRAME[PupListeners]] = BEGIN IF free = NIL THEN BEGIN him ← --NEW PupListeners-- PrincOpsMinus.NewSelf[]; START him; -- Do initialization code RETURN; END; him ← free; free ← free.next; END; FreeInstance: ENTRY PROCEDURE [him: LONG POINTER TO FRAME[PupListeners]] = BEGIN him.next ← free; free ← him; END; next: LONG POINTER TO FRAME[PupListeners] ← NIL; myPupListener: PupStream.PupListenerObject ← LOOPHOLE[Listen]; socket: PupSocket; timeout: Tocks; stop: BOOLEAN; proc: PROCESS; who: PROCEDURE [LONG 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 [PupStream.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 [PupStream.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 [PupStream.PupListener] = BEGIN him: LONG 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: PupStream.PupListener] = BEGIN him: LONG POINTER TO FRAME[PupListeners] ← LOOPHOLE[Runtime.GlobalFrame[ LOOPHOLE[listener↑]]]; him.stop ← TRUE; PupSocketKick[him.socket]; JOIN him.proc; PupSocketDestroy[him.socket]; FreeInstance[him]; END; RealListen: PROCEDURE [local: PupSocketID] = BEGIN soc: PupRouterSocket; arg: LONG UNSPECIFIED; b: PupBuffer; UNTIL stop DO b ← socket.get[]; IF b # NIL THEN BEGIN SELECT b.pup.pupType FROM rfc => BEGIN OPEN PupStream; FOR soc ← GetFirstPupSocket[], soc.next UNTIL soc = NIL DO -- check for duplicate IF soc.remote # b.pup.source THEN LOOP; IF soc.id # b.pup.pupID THEN LOOP; b.pup.address ← soc.local; SwapPupSourceAndDest[b]; PupRouterSendThis[b]; EXIT; ENDLOOP; IF soc = NIL THEN BEGIN -- not a duplicate, make a new connection him: PupAddress ← b.pup.address; check[ him ! PupStream.RejectThisRequest => BEGIN b.pup.pupType ← abort; SwapPupSourceAndDest[b]; SetPupContentsBytes[b, 2]; AppendStringBodyToPupBuffer[b, error]; PupRouterSendThis[b]; GOTO Reject; END]; SELECT kind FROM pkt => arg ← PupPktDefs.PupPktStreamMake[ local, him, timeout, alreadyOpened, b.pup.pupID]; byte => arg ← PupStream.PupByteStreamMake[ local, him, timeout, alreadyOpened, b.pup.pupID]; ENDCASE => ERROR; PupDefs.ReturnBuffer[b]; Process.Detach[FORK who[arg, him]]; END; EXITS Reject => NULL; END; echoMe => BEGIN b.pup.pupType ← iAmEcho; SwapPupSourceAndDest[b]; PupRouterSendThis[b]; END; ENDCASE => SendErrorPup[b, LOOPHOLE[100B], "RFC expected"L]; END; ENDLOOP; END; END. LOG 19-May-83 9:59:26 By: SMA Action: Converted to new BufferMgr. 11-Jul-83 17:17:36 By: SMA Action: Changes for 32-bit procs. 1-Sep-83 20:57:12 By: SMA Action: Fixed initialized <free>. 2-Sep-86 14:44:19 By: AOF Action: New Buffer mgmt package. 17-Feb-88 15:22:07 By: AOF Action: Patch for compiler bug NEWing self.