-- File: PupSockets.mesa, Last Edit: HGM March 14, 1981 11:50 AM DIRECTORY Process USING [SetTimeout, DisableTimeout], Runtime 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, Runtime, CommUtilDefs, PupRouterDefs, PupDefs EXPORTS PupRouterDefs, PupDefs SHARES BufferDefs = BEGIN OPEN PupRouterDefs, PupDefs; -- Manager data free: POINTER TO FRAME[PupSockets] _ LOOPHOLE[Runtime.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: PupSocketObject _ [ -- data for the client put: Put, get: Get, setRemoteAddress: SetRemoteAddress, getLocalAddress: GetLocalAddress]; dontWait, kick: BOOLEAN _ FALSE; myPupRouterSocket: PupRouterSocketObject; PupSocketMake: PUBLIC PROCEDURE [ local: PupSocketID, remote: PupAddress, ticks: Tocks, id: Pair] RETURNS [PupSocket] = 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 PROCEDURE [local, remote: PupAddress, ticks: Tocks] RETURNS [PupSocket] = BEGIN him: POINTER TO FRAME[PupSockets] _ GetInstance[]; -- We need to check local to verify that it is valid 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 PROCEDURE [s: PupSocket] = BEGIN him: POINTER TO FRAME[PupSockets] _ LOOPHOLE[Runtime.GlobalFrame[s.put]]; kick _ TRUE; NOTIFY him.myPupRouterSocket.ready; END; PupSocketDestroy: PUBLIC PROCEDURE [s: PupSocket] = BEGIN him: POINTER TO FRAME[PupSockets] _ LOOPHOLE[Runtime.GlobalFrame[s.put]]; PupRouterForgetAboutSocket[@him.myPupRouterSocket]; FreeInstance[him]; END; Get: ENTRY PROCEDURE RETURNS [b: PupBuffer] = 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 PROCEDURE [a: PupAddress] = BEGIN myPupRouterSocket.remote _ a; END; GetLocalAddress: ENTRY PROCEDURE RETURNS [PupAddress] = BEGIN RETURN[myPupRouterSocket.local]; END; -- initialization END.