<> <> <> DIRECTORY Process USING [SetTimeout, DisableTimeout], PrincOpsUtils USING [GlobalFrame], CommFlags USING [doDebug], CommUtilDefs USING [EnableAborts, GetReturnFrame], PupRouterDefs USING [ PupRouterForgetAboutSocket, PupRouterKnowAboutSocket, routerLock, PupRouterSocketObject], PupDefs USING [ GetLocalPupAddress, DequeuePup, PupAddress, PupBuffer, PupRouterSendThis, PupSocket, PupSocketID, Pair, PupSocketObject, Tocks, veryLongWait, veryShortWait], BufferDefs, PupTypes; PupSockets: MONITOR LOCKS PupRouterDefs.routerLock IMPORTS Process, PrincOpsUtils, CommUtilDefs, PupRouterDefs, PupDefs EXPORTS PupRouterDefs, PupDefs SHARES BufferDefs = BEGIN OPEN PupRouterDefs, PupDefs; <> free: POINTER TO FRAME[PupSockets] _ LOOPHOLE[PrincOpsUtils.GlobalFrame[ PupSocketMake]]; GetInstance: ENTRY PROCEDURE RETURNS [him: POINTER TO FRAME[PupSockets]] = BEGIN IF free = NIL THEN BEGIN him _ NEW PupSockets; START him; -- Do initialization code RETURN; END; him _ free; free _ free.next; END; FreeInstance: ENTRY PROCEDURE [him: POINTER TO FRAME[PupSockets]] = BEGIN him.next _ free; free _ him; END; next: POINTER TO FRAME[PupSockets] _ NIL; myPupSocket: PupSocket = NEW[PupSocketObject _ [ -- data for the client put: Put, get: Get, setRemoteAddress: SetRemoteAddress, getLocalAddress: GetLocalAddress] ]; dontWait, kick: BOOLEAN _ FALSE; myPupRouterSocket: PupRouterSocketObject; PupSocketMake: PUBLIC SAFE PROCEDURE [ local: PupSocketID, remote: PupAddress, ticks: Tocks, id: Pair] RETURNS [PupSocket] = TRUSTED BEGIN him: POINTER TO FRAME[PupSockets] _ GetInstance[]; him.myPupRouterSocket.local _ GetLocalPupAddress[local, remote]; him.myPupRouterSocket.remote _ remote; him.myPupRouterSocket.id _ id; him.kick _ FALSE; PupRouterKnowAboutSocket[@him.myPupRouterSocket]; SELECT ticks FROM veryShortWait => dontWait _ TRUE; veryLongWait => Process.DisableTimeout[@him.myPupRouterSocket.ready]; ENDCASE => Process.SetTimeout[@him.myPupRouterSocket.ready, ticks]; CommUtilDefs.EnableAborts[@him.myPupRouterSocket.ready]; RETURN[him.myPupSocket]; END; PupSocketMakeFull: PUBLIC SAFE PROCEDURE [local, remote: PupAddress, ticks: Tocks] RETURNS [PupSocket] = TRUSTED BEGIN him: POINTER TO FRAME[PupSockets] _ GetInstance[]; <> him.myPupRouterSocket.local _ local; him.myPupRouterSocket.remote _ remote; him.myPupRouterSocket.id _ [0,0]; him.kick _ FALSE; PupRouterKnowAboutSocket[@him.myPupRouterSocket]; SELECT ticks FROM veryShortWait => dontWait _ TRUE; veryLongWait => Process.DisableTimeout[@him.myPupRouterSocket.ready]; ENDCASE => Process.SetTimeout[@him.myPupRouterSocket.ready, ticks]; CommUtilDefs.EnableAborts[@him.myPupRouterSocket.ready]; RETURN[him.myPupSocket]; END; PupSocketKick: PUBLIC ENTRY SAFE PROCEDURE [s: PupSocket] = TRUSTED BEGIN him: POINTER TO FRAME[PupSockets] _ LOOPHOLE[PrincOpsUtils.GlobalFrame[s.put]]; kick _ TRUE; NOTIFY him.myPupRouterSocket.ready; END; PupSocketDestroy: PUBLIC SAFE PROCEDURE [s: PupSocket] = TRUSTED BEGIN him: POINTER TO FRAME[PupSockets] _ LOOPHOLE[PrincOpsUtils.GlobalFrame[s.put]]; PupRouterForgetAboutSocket[@him.myPupRouterSocket]; FreeInstance[him]; END; Get: ENTRY SAFE PROCEDURE RETURNS [b: PupBuffer] = TRUSTED BEGIN IF ~dontWait AND myPupRouterSocket.input.length = 0 THEN BEGIN IF ~kick THEN WAIT myPupRouterSocket.ready [ ! UNWIND => NULL]; END; kick _ FALSE; IF myPupRouterSocket.input.length = 0 THEN RETURN[NIL]; b _ PupDefs.DequeuePup[myPupRouterSocket.input]; IF CommFlags.doDebug AND b # NIL THEN b.debug _ CommUtilDefs.GetReturnFrame[].accesslink; END; Put: PROCEDURE [b: PupBuffer] = BEGIN b.dest _ myPupRouterSocket.remote; b.source _ myPupRouterSocket.local; PupRouterSendThis[b]; END; SetRemoteAddress: ENTRY SAFE PROCEDURE [a: PupAddress] = TRUSTED BEGIN myPupRouterSocket.remote _ a; END; GetLocalAddress: ENTRY SAFE PROCEDURE RETURNS [PupAddress] = TRUSTED BEGIN RETURN[myPupRouterSocket.local]; END; <> myPupRouterSocket.input _ NEW[BufferDefs.QueueObject]; END.