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;
Manager data
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[];
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
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;
initialization
myPupRouterSocket.input ← NEW[BufferDefs.QueueObject];
END.