-- Copyright (C) 1983, 1985 by Xerox Corporation. All rights reserved.
-- VoiceForwardingNoDisk.mesa, WIrish, 24-Apr-87 11:55:52
-- From: PupBootServerNoDisk.mesa, HGM, 9-May-86 16:14:32
DIRECTORY
Ascii USING [CR],
CmFile USING [Handle, TableError],
Event USING [aboutToSwap],
EventTypes USING [aboutToBoot, aboutToBootPhysicalVolume],
Heap USING [systemZone],
Process USING [Yield],
Put USING [Text],
String USING [AppendChar, AppendNumber, AppendString],
StringLookUp USING [noMatch],
Supervisor USING [
AddDependency, AgentProcedure, CreateSubsystem, RemoveDependency,
SubsystemHandle],
Token USING [FreeTokenString, Item, Octal],
Buffer USING [ReturnBuffer],
Indirect USING [Close, NextValue, OpenSection],
PupDefs USING [
GetPupAddress,
PupBuffer, PupNameTrouble, PupPackageMake, PupRouterSendThis,
PupSocket, PupSocketDestroy, PupSocketKick, PupSocketMake, Tocks, veryLongWait],
PupRouterDefs USING [NetworkContext],
PupTypes USING [fillInPupAddress, PupAddress, PupNetID, rpcpSoc];
VoiceForwardingNoDisk: MONITOR
IMPORTS
CmFile, Event, Heap, Indirect, Process, Put,
String, Supervisor, Token,
Buffer, PupDefs
EXPORTS =
BEGIN
broom: Supervisor.SubsystemHandle = Supervisor.CreateSubsystem[Broom];
z: UNCOUNTED ZONE = Heap.systemZone;
remote: Chain ← NIL;
pleaseStop: BOOLEAN ← FALSE;
Chain: TYPE = LONG POINTER TO ChainSlot;
ChainSlot: TYPE = RECORD [
next: Chain,
source: PupTypes.PupNetID,
dest: PupTypes.PupAddress,
target: LONG STRING];
VFRunning: PUBLIC BOOLEAN ← FALSE;
useCount: CARDINAL ← 0;
VoiceForwardingOn: PUBLIC ENTRY PROCEDURE =
BEGIN
IF (useCount ← useCount + 1) = 1 THEN
BEGIN
Supervisor.AddDependency[client: broom, implementor: Event.aboutToSwap];
VFRunning ← TRUE;
Starter[];
END;
END;
Starter: PROCEDURE =
BEGIN
ScanParameterFile[];
StartListener[];
END;
VoiceForwardingOff: PUBLIC ENTRY PROCEDURE =
BEGIN
IF useCount # 0 AND (useCount ← useCount - 1) = 0 THEN
BEGIN
VFRunning ← FALSE;
Stopper[];
Supervisor.RemoveDependency[client: broom, implementor: Event.aboutToSwap];
END;
END;
Stopper: INTERNAL PROCEDURE =
BEGIN
StopListener[];
ForgetParameters[];
END;
VoiceForwarding: PUBLIC PROCEDURE [b: PupDefs.PupBuffer] =
BEGIN
ForwardThisOne[b];
END;
ForwardThisOne: PROCEDURE [b: PupDefs.PupBuffer] =
BEGIN
context: PupRouterDefs.NetworkContext = b.context;
IF b.pup.source.net = 0 THEN b.pup.source.net ← [context.pupNetNumber];
FOR finger: Chain ← remote, finger.next UNTIL finger = NIL DO
IF context.pupNetNumber = finger.source THEN
BEGIN
IF finger.dest = PupTypes.fillInPupAddress THEN EXIT;
b.pup.dest.net ← finger.dest.net;
b.pup.dest.host ← finger.dest.host;
PupDefs.PupRouterSendThis[b];
RETURN;
END;
ENDLOOP;
Buffer.ReturnBuffer[b];
END;
voice60Soc: PupDefs.PupSocket ← NIL;
rpcpSoc: PupDefs.PupSocket ← NIL;
voice60Fork: PROCESS;
rpcpFork: PROCESS;
StartListener: PUBLIC PROCEDURE =
BEGIN
pleaseStop ← FALSE;
[] ← PupDefs.PupPackageMake[];
voice60Soc ← PupDefs.PupSocketMake[
[0, 60B], PupTypes.fillInPupAddress, PupDefs.veryLongWait];
voice60Fork ← FORK Voice[];
rpcpSoc ← PupDefs.PupSocketMake[
PupTypes.rpcpSoc, PupTypes.fillInPupAddress, PupDefs.veryLongWait];
rpcpFork ← FORK Rpcp[];
END;
StopListener: PUBLIC PROCEDURE =
BEGIN
pleaseStop ← TRUE;
PupDefs.PupSocketKick[voice60Soc];
JOIN voice60Fork[];
PupDefs.PupSocketDestroy[voice60Soc];
PupDefs.PupSocketKick[rpcpSoc];
JOIN rpcpFork[];
PupDefs.PupSocketDestroy[rpcpSoc];
END;
Voice: PROCEDURE =
BEGIN
b: PupDefs.PupBuffer;
UNTIL pleaseStop DO
IF (b ← voice60Soc.get[]) # NIL THEN VoiceForwarding[b];
Process.Yield[]; -- avoid hogging machine
ENDLOOP;
END;
Rpcp: PROCEDURE =
BEGIN
b: PupDefs.PupBuffer;
UNTIL pleaseStop DO
IF (b ← rpcpSoc.get[]) # NIL THEN VoiceForwarding[b];
Process.Yield[]; -- avoid hogging machine
ENDLOOP;
END;
ScanParameterFile: PROCEDURE =
BEGIN
cmFile: CmFile.Handle;
Option: TYPE = {remote};
NextValue: PROCEDURE [
h: CmFile.Handle, table: LONG DESCRIPTOR FOR ARRAY Option OF LONG STRING]
RETURNS [Option] = LOOPHOLE[Indirect.NextValue];
optionTable: ARRAY Option OF LONG STRING ← [remote: "Remote"L];
cmFile ← Indirect.OpenSection["VoiceForwarding"L];
IF cmFile = NIL THEN RETURN;
DO
option: Option;
option ← NextValue[
cmFile, DESCRIPTOR[optionTable] !
CmFile.TableError =>
BEGIN
IF name[0] # '; THEN Message["Unrecognized parameter: ", name];
RETRY;
END];
SELECT option FROM
LOOPHOLE[StringLookUp.noMatch] => EXIT;
remote =>
BEGIN
source: PupTypes.PupNetID = [Token.Octal[cmFile]];
temp: LONG STRING ← Token.Item[cmFile, FALSE];
new: Chain ← z.NEW[ChainSlot];
new↑ ← [NIL, source, PupTypes.fillInPupAddress, z.NEW[StringBody[temp.length]]];
String.AppendString[new.target, temp];
[] ← Token.FreeTokenString[temp];
PupDefs.GetPupAddress[@new.dest, new.target ! PupDefs.PupNameTrouble => CONTINUE];
IF remote = NIL THEN remote ← new
ELSE
BEGIN
FOR finger: Chain ← remote, finger.next DO
IF finger.next = NIL THEN
BEGIN
finger.next ← new;
EXIT;
END;
ENDLOOP;
END;
MessageNet["Forwarding Voice requests from net "L, new.source, " to "L, new.target];
END;
ENDCASE => ERROR;
ENDLOOP;
Indirect.Close[cmFile];
END;
ForgetParameters: PROCEDURE =
BEGIN
UNTIL remote = NIL DO
temp: Chain ← remote;
remote ← remote.next;
z.FREE[@temp.target];
z.FREE[@temp];
ENDLOOP;
END;
MessageNet: PROCEDURE [one: LONG STRING, net: CARDINAL, three, four: LONG STRING] =
BEGIN
two: STRING = [20];
String.AppendNumber[two, net, 8];
Message[one, two, three, four];
END;
Message: PROCEDURE [one, two, three, four: LONG STRING ← NIL] =
BEGIN
text: STRING = [200];
String.AppendString[text, one];
IF two # NIL THEN String.AppendString[text, two];
IF three # NIL THEN String.AppendString[text, three];
IF four # NIL THEN String.AppendString[text, four];
LogString[text];
END;
LogString: PROCEDURE [text: LONG STRING] =
BEGIN
String.AppendChar[text, '.];
String.AppendChar[text, Ascii.CR];
Put.Text[NIL, text];
END;
Broom: ENTRY Supervisor.AgentProcedure =
BEGIN
SELECT event FROM
EventTypes.aboutToBoot, EventTypes.aboutToBootPhysicalVolume =>
IF VFRunning THEN Stopper[];
ENDCASE => NULL;
END;
-- initialization
VoiceForwardingOn[];
END.