-- File: PupListeners.mesa, Last Edit: HGM January 24, 1981 2:23 PM
DIRECTORY
Process USING [Detach],
Runtime USING [GlobalFrame],
Stream USING [Handle],
PupRouterDefs USING [GetFirstPupSocket, PupRouterSocket],
PupPktDefs USING [PupPktStreamMake, PupPktStream],
PupStream USING [
PupByteStreamMake, PupListener, PupListenerObject, RejectThisRequest],
PupDefs USING [
PupAddress, PupBuffer, PupSocketID, Tocks, PupRouterSendThis, SendErrorPup,
SwapPupSourceAndDest, ReturnFreePupBuffer, PupSocket, PupSocketMake,
PupSocketKick, PupSocketDestroy, veryLongWait, SetPupContentsBytes,
AppendStringBodyToPupBuffer],
PupTypes USING [fillInPupAddress];
PupListeners: MONITOR
IMPORTS Runtime, Process, PupRouterDefs, PupPktDefs, PupStream, PupDefs
EXPORTS PupPktDefs, PupStream =
BEGIN OPEN PupRouterDefs, PupStream, PupDefs;
-- Manager data
free: POINTER TO FRAME [PupListeners] ← LOOPHOLE[Runtime.GlobalFrame[Listen]];
GetInstance: ENTRY PROCEDURE RETURNS [him: POINTER TO FRAME[PupListeners]] =
BEGIN
IF free=NIL THEN
BEGIN
him ← NEW PupListeners;
START him; -- Do initialization code
RETURN;
END;
him ← free;
free ← free.next;
END;
FreeInstance: ENTRY PROCEDURE [him: POINTER TO FRAME[PupListeners]] =
BEGIN
him.next ← free;
free ← him;
END;
next: POINTER TO FRAME [PupListeners] ← NIL;
myPupListener: PupListenerObject ← LOOPHOLE[Listen];
socket: PupSocket;
timeout: Tocks;
stop: BOOLEAN;
proc: PROCESS;
who: PROCEDURE [UNSPECIFIED, PupAddress];
check: PROCEDURE [PupAddress];
Kind: TYPE = {pkt, byte};
kind: Kind;
DontReject: PUBLIC PROCEDURE [PupAddress] = BEGIN END;
CreatePupByteStreamListener: PUBLIC PROCEDURE [
local: PupSocketID, proc: PROCEDURE [Stream.Handle, PupAddress], ticks: Tocks,
filter: PROCEDURE [PupAddress]] RETURNS [PupListener] =
BEGIN RETURN[CreatePupListener[local, proc, ticks, byte, filter]]; END;
CreatePupPktStreamListener: PUBLIC PROCEDURE [
local: PupSocketID, proc: PROCEDURE [PupPktDefs.PupPktStream, PupAddress],
ticks: Tocks, filter: PROCEDURE [PupAddress]] RETURNS [PupListener] =
BEGIN RETURN[CreatePupListener[local, proc, ticks, pkt, filter]]; END;
CreatePupListener: PROCEDURE [
local: PupSocketID, w: PROCEDURE [UNSPECIFIED, PupAddress], ticks: Tocks,
k: Kind, f: PROCEDURE [PupAddress]] RETURNS [PupListener] =
BEGIN
him: POINTER TO FRAME[PupListeners] ← GetInstance[];
him.socket ← PupSocketMake[local, PupTypes.fillInPupAddress, veryLongWait];
him.kind ← k;
him.who ← w;
him.check ← f;
him.timeout ← ticks;
him.stop ← FALSE;
him.proc ← FORK him.Listen[local];
RETURN[@him.myPupListener];
END;
DestroyPupListener: PUBLIC PROCEDURE [listener: PupListener] =
BEGIN
him: POINTER TO FRAME[PupListeners] ← LOOPHOLE[Runtime.GlobalFrame[
listener↑]];
him.stop ← TRUE;
PupSocketKick[him.socket];
JOIN him.proc;
PupSocketDestroy[him.socket];
FreeInstance[him];
END;
Listen: PROCEDURE [local: PupSocketID] =
BEGIN
soc: PupRouterSocket;
arg: UNSPECIFIED;
b: PupBuffer;
UNTIL stop DO
b ← socket.get[];
IF b # NIL THEN
BEGIN
SELECT b.pupType FROM
rfc =>
BEGIN OPEN PupStream;
FOR soc ← GetFirstPupSocket[], soc.next UNTIL soc = NIL DO
-- check for duplicate
IF soc.remote # b.source THEN LOOP;
IF soc.id # b.pupID THEN LOOP;
b.address ← soc.local;
SwapPupSourceAndDest[b];
PupRouterSendThis[b];
EXIT;
ENDLOOP;
IF soc = NIL THEN
BEGIN -- not a duplicate, make a new connection
him: PupAddress ← b.address;
check[
him !
RejectThisRequest =>
BEGIN
b.pupType ← abort;
SwapPupSourceAndDest[b];
SetPupContentsBytes[b, 2];
AppendStringBodyToPupBuffer[b, error];
PupRouterSendThis[b];
GOTO Reject;
END];
ReturnFreePupBuffer[b];
SELECT kind FROM
pkt =>
arg ← PupPktDefs.PupPktStreamMake[
local, him, timeout, alreadyOpened, b.pupID];
byte =>
arg ← PupByteStreamMake[
local, him, timeout, alreadyOpened, b.pupID];
ENDCASE => ERROR;
Process.Detach[FORK who[arg, him]];
END;
EXITS Reject => NULL;
END;
echoMe =>
BEGIN
b.pupType ← iAmEcho;
SwapPupSourceAndDest[b];
PupRouterSendThis[b];
END;
ENDCASE => SendErrorPup[b, LOOPHOLE[100B], "RFC expected"L];
END;
ENDLOOP;
END;
-- initialization
END. -- of PupListeners