-- File: PupListeners.mesa - last edit:
-- AOF 17-Feb-88 15:22:39
-- SMA 1-Sep-83 20:56:59
-- Copyright (C) 1983, 1986, 1988 by Xerox Corporation. All rights reserved.
DIRECTORY
Process USING [Detach],
Runtime USING [GlobalFrame],
Stream USING [Handle],
PrincOpsMinus USING [NewSelf],
PupRouterDefs USING [GetFirstPupSocket, PupRouterSocket],
PupPktDefs USING [PupPktStreamMake, PupPktStream],
PupStream USING [
PupByteStreamMake, PupListener, PupListenerObject, RejectThisRequest],
PupDefs USING [
PupAddress, PupBuffer, PupSocketID, Tocks, PupRouterSendThis, SendErrorPup,
SwapPupSourceAndDest, PupSocket, PupSocketMake, ReturnBuffer,
PupSocketKick, PupSocketDestroy, veryLongWait, SetPupContentsBytes,
AppendStringBodyToPupBuffer],
PupTypes USING [fillInPupAddress];
PupListeners: MONITOR
IMPORTS
Runtime, PrincOpsMinus, Process, PupRouterDefs, PupPktDefs, PupStream,
PupDefs
EXPORTS PupPktDefs, PupStream =
BEGIN OPEN PupRouterDefs, PupDefs;
-- Manager data
Listen: PROCEDURE [local: PupSocketID] ← RealListen;
-- The procedure variable for getting linkage to the instance's RealListen.
free: LONG POINTER TO FRAME[PupListeners] ←
LOOPHOLE[Runtime.GlobalFrame[LOOPHOLE[Listen]]];
GetInstance: ENTRY PROCEDURE RETURNS [him: LONG POINTER TO FRAME[PupListeners]] =
BEGIN
IF free = NIL THEN
BEGIN
him ← --NEW PupListeners-- PrincOpsMinus.NewSelf[];
START him; -- Do initialization code
RETURN;
END;
him ← free;
free ← free.next;
END;
FreeInstance: ENTRY PROCEDURE [him: LONG POINTER TO FRAME[PupListeners]] =
BEGIN him.next ← free; free ← him; END;
next: LONG POINTER TO FRAME[PupListeners] ← NIL;
myPupListener: PupStream.PupListenerObject ← LOOPHOLE[Listen];
socket: PupSocket;
timeout: Tocks;
stop: BOOLEAN;
proc: PROCESS;
who: PROCEDURE [LONG 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 [PupStream.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 [PupStream.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 [PupStream.PupListener] =
BEGIN
him: LONG 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: PupStream.PupListener] =
BEGIN
him: LONG POINTER TO FRAME[PupListeners] ← LOOPHOLE[Runtime.GlobalFrame[
LOOPHOLE[listener↑]]];
him.stop ← TRUE;
PupSocketKick[him.socket];
JOIN him.proc;
PupSocketDestroy[him.socket];
FreeInstance[him];
END;
RealListen: PROCEDURE [local: PupSocketID] =
BEGIN
soc: PupRouterSocket;
arg: LONG UNSPECIFIED;
b: PupBuffer;
UNTIL stop DO
b ← socket.get[];
IF b # NIL THEN
BEGIN
SELECT b.pup.pupType FROM
rfc =>
BEGIN OPEN PupStream;
FOR soc ← GetFirstPupSocket[], soc.next UNTIL soc = NIL DO
-- check for duplicate
IF soc.remote # b.pup.source THEN LOOP;
IF soc.id # b.pup.pupID THEN LOOP;
b.pup.address ← soc.local;
SwapPupSourceAndDest[b];
PupRouterSendThis[b];
EXIT;
ENDLOOP;
IF soc = NIL THEN
BEGIN -- not a duplicate, make a new connection
him: PupAddress ← b.pup.address;
check[
him !
PupStream.RejectThisRequest =>
BEGIN
b.pup.pupType ← abort;
SwapPupSourceAndDest[b];
SetPupContentsBytes[b, 2];
AppendStringBodyToPupBuffer[b, error];
PupRouterSendThis[b];
GOTO Reject;
END];
SELECT kind FROM
pkt =>
arg ← PupPktDefs.PupPktStreamMake[
local, him, timeout, alreadyOpened, b.pup.pupID];
byte =>
arg ← PupStream.PupByteStreamMake[
local, him, timeout, alreadyOpened, b.pup.pupID];
ENDCASE => ERROR;
PupDefs.ReturnBuffer[b];
Process.Detach[FORK who[arg, him]];
END;
EXITS Reject => NULL;
END;
echoMe =>
BEGIN
b.pup.pupType ← iAmEcho;
SwapPupSourceAndDest[b];
PupRouterSendThis[b];
END;
ENDCASE => SendErrorPup[b, LOOPHOLE[100B], "RFC expected"L];
END;
ENDLOOP;
END;
END.
LOG
19-May-83 9:59:26 By: SMA Action: Converted to new BufferMgr.
11-Jul-83 17:17:36 By: SMA Action: Changes for 32-bit procs.
1-Sep-83 20:57:12 By: SMA Action: Fixed initialized <free>.
2-Sep-86 14:44:19 By: AOF Action: New Buffer mgmt package.
17-Feb-88 15:22:07 By: AOF Action: Patch for compiler bug NEWing self.