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