-- 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.