<> <> <> <> <> 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 = { OPEN PupRouterDefs, PupDefs; <> InstancePtr: TYPE = POINTER TO FRAME[PupSockets]; free: InstancePtr _ LOOPHOLE[PrincOpsUtils.GlobalFrame[LOOPHOLE[PupSocketMake]]]; <> <<>> GetInstance: ENTRY PROC RETURNS [him: InstancePtr] = { IF free = NIL THEN { him _ NEW PupSockets; START him; -- Do initialization code RETURN; }; him _ free; free _ free.next; }; FreeInstance: ENTRY PROC [him: InstancePtr] = { him.next _ free; free _ him; }; PupSocketMake: PUBLIC SAFE PROC [local: PupSocketID, remote: PupAddress, ticks: Tocks, id: Pair] RETURNS [PupSocket] = TRUSTED { RETURN [PupSocketCommon[GetLocalPupAddress[local, remote], remote, ticks, id]]; }; PupSocketMakeFull: PUBLIC SAFE PROC [local, remote: PupAddress, ticks: Tocks] RETURNS [PupSocket] = TRUSTED { RETURN [PupSocketCommon[local, remote, ticks, [0,0]]]; }; PupSocketCommon: PROC [local, remote: PupAddress, ticks: Tocks, id: Pair] RETURNS [PupSocket] = { him: InstancePtr _ GetInstance[]; <> him.myPupRouterSocket.local _ local; him.myPupRouterSocket.remote _ remote; him.myPupRouterSocket.id _ id; him.dontWait _ 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]; }; PupSocketKick: PUBLIC ENTRY SAFE PROC [s: PupSocket] = TRUSTED { him: InstancePtr _ LOOPHOLE[PrincOpsUtils.GlobalFrame[LOOPHOLE[s.put]]]; him.kick _ TRUE; NOTIFY him.myPupRouterSocket.ready; }; PupSocketDestroy: PUBLIC SAFE PROC [s: PupSocket] = TRUSTED { him: InstancePtr _ LOOPHOLE[PrincOpsUtils.GlobalFrame[LOOPHOLE[s.put]]]; PupRouterForgetAboutSocket[@him.myPupRouterSocket]; FreeInstance[him]; }; <> Get: ENTRY SAFE PROC RETURNS [b: PupBuffer] = TRUSTED { ENABLE UNWIND => NULL; IF ~dontWait AND myPupRouterSocket.input.length = 0 THEN { IF ~kick THEN WAIT myPupRouterSocket.ready[]; }; 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; }; Put: PROC [b: PupBuffer] = { b.dest _ myPupRouterSocket.remote; b.source _ myPupRouterSocket.local; PupRouterSendThis[b]; }; SetRemoteAddress: ENTRY SAFE PROC [a: PupAddress] = TRUSTED { myPupRouterSocket.remote _ a; }; GetLocalAddress: ENTRY SAFE PROC RETURNS [PupAddress] = TRUSTED { RETURN[myPupRouterSocket.local]; }; <> myPupSocket: PupSocket = NEW[PupSocketObject _ [ put: Put, get: Get, setRemoteAddress: SetRemoteAddress, getLocalAddress: GetLocalAddress] ]; dontWait, kick: BOOL _ FALSE; next: InstancePtr _ NIL; myPupRouterSocket: PupRouterSocketObject; myPupRouterSocket.input _ NEW[BufferDefs.QueueObject]; }.