-- File: PupSockets.mesa, Last Edit: HGM October 16, 1979 9:33 PM
-- Copyright Xerox Corporation 1979, 1980
-- This module does everything connected with an instance of a PupSocket. (Which isn’t very much.) For now, there is no need to get fancy, so we create a new copy of this module for each PupSocket that we make, and UnNew it when we are through with it. A cache of the last few might speed things up if that ever becomes interesting. We could also use ourself as the first PupSocket to save a few words of core.
DIRECTORY
CommUtilDefs: FROM "CommUtilDefs" USING [
GlobalFrame, UnNew, SetTimeout, GetReturnFrame],
PupRouterDefs: FROM "PupRouterDefs" USING [
PupRouterForgetAboutSocket, PupRouterKnowAboutSocket,
routerLock, PupRouterSocketObject],
PupDefs: FROM "PupDefs" USING [
GetLocalPupAddress, DequeuePup, PupAddress, PupBuffer,
PupRouterSendThis, PupSocket, PupSocketID, Pair, PupSocketObject,
Tocks, veryLongWait, veryShortWait],
DriverDefs: FROM "DriverDefs" USING [doDebug],
BufferDefs: FROM "BufferDefs",
PupTypes: FROM "PupTypes";
PupSockets: MONITOR LOCKS PupRouterDefs.routerLock
IMPORTS CommUtilDefs, PupRouterDefs, PupDefs
EXPORTS PupRouterDefs, PupDefs
SHARES BufferDefs =
BEGIN OPEN PupRouterDefs, PupDefs;
myPupSocket: PupSocketObject ← [ -- data for the client
put: Put,
get: Get,
setRemoteAddress: SetRemoteAddress,
getLocalAddress: GetLocalAddress ];
dontWait: BOOLEAN ← FALSE;
myPupRouterSocket: PupRouterSocketObject;
-- For now, don’t try to be fancy, just create a copy.
PupSocketMake: PUBLIC PROCEDURE [
local: PupSocketID, remote: PupAddress, ticks: Tocks, id: Pair]
RETURNS [PupSocket] =
BEGIN
him: POINTER TO FRAME[PupSockets] ← NEW PupSockets;
START him; -- Do initialization code
him.myPupRouterSocket.local ← GetLocalPupAddress[local,@remote];
him.myPupRouterSocket.remote ← remote;
him.myPupRouterSocket.id ← id;
PupRouterKnowAboutSocket[@him.myPupRouterSocket];
SELECT ticks FROM
veryShortWait => dontWait ← TRUE;
veryLongWait => NULL;
ENDCASE => CommUtilDefs.SetTimeout[@him.myPupRouterSocket.ready,ticks];
RETURN[@him.myPupSocket];
END;
PupSocketKick: PUBLIC ENTRY PROCEDURE [s: PupSocket] =
BEGIN
him: POINTER TO FRAME[PupSockets] ← CommUtilDefs.GlobalFrame[s.put];
NOTIFY him.myPupRouterSocket.ready;
END;
PupSocketDestroy: PUBLIC PROCEDURE [s: PupSocket] =
BEGIN
him: POINTER TO FRAME[PupSockets] ← CommUtilDefs.GlobalFrame[s.put];
PupRouterForgetAboutSocket[@him.myPupRouterSocket];
CommUtilDefs.UnNew[him];
END;
Get: ENTRY PROCEDURE RETURNS [b: PupBuffer] =
BEGIN
IF ~dontWait AND myPupRouterSocket.input.length=0 THEN
BEGIN ENABLE UNWIND => NULL; -- we might get aborted
WAIT myPupRouterSocket.ready;
END;
IF myPupRouterSocket.input.length=0 THEN RETURN[NIL];
b ← PupDefs.DequeuePup[@myPupRouterSocket.input];
IF DriverDefs.doDebug AND b#NIL THEN
b.debug ← CommUtilDefs.GetReturnFrame[].accesslink;
END;
Put: PROCEDURE [b: PupBuffer] =
BEGIN
b.dest ← myPupRouterSocket.remote;
b.source.socket ← myPupRouterSocket.local.socket;
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. -- of PupSockets module