-- File: NetWatcher.mesa, Last Edit: HGM February 4, 1981 11:11 AM -- Please don't forget to update the herald.... DIRECTORY Process USING [Detach, SetTimeout, MsecToTicks, Yield], String USING [AppendChar, AppendString, AppendNumber], Time USING [AppendCurrent], System USING [GreenwichMeanTime, GetGreenwichMeanTime], Put USING [Line], Tool USING [Create, MakeSWsProc, MakeMsgSW], ToolWindow USING [TransitionProcType], Window USING [Handle], NameServerDefs USING [BumpCacheSize, PupDirServerOn, PupNameServerOn], PupDefs USING [defaultNumberOfNetworks, PupAddressLookup, PupNameTrouble], PupRouterDefs USING [ RoutingTableEntry, RoutingTableObject, GetRoutingTableEntry, maxHop]; NetWatcher: MONITOR IMPORTS Process, String, Time, Put, System, Tool, NameServerDefs, PupDefs, PupRouterDefs = BEGIN seconds: CARDINAL _ 5; oldPupRouting: ARRAY [0..maxNets] OF PupRouterDefs.RoutingTableObject; maxNets: CARDINAL = PupDefs.defaultNumberOfNetworks; msg: Window.Handle _ NIL; pleaseStop, running: BOOLEAN _ FALSE; Init: PROCEDURE = BEGIN herald: STRING = "Net Watcher of February 4, 1981"L; [] _ Tool.Create[ name: herald, makeSWsProc: MakeSWs, clientTransition: ClientTransition]; Process.Detach[FORK Watch[]]; END; Watch: ENTRY PROCEDURE = BEGIN time: System.GreenwichMeanTime _ System.GetGreenwichMeanTime[]; pause: CONDITION; Process.SetTimeout[@pause, Process.MsecToTicks[500]]; InitializeThings[]; UNTIL pleaseStop DO WHILE (System.GetGreenwichMeanTime[] - time) < seconds DO WAIT pause; ENDLOOP; time _ System.GetGreenwichMeanTime[]; CheckNetState[]; THROUGH [0..100) DO Process.Yield[]; ENDLOOP; ENDLOOP; END; InitializeThings: PROCEDURE = BEGIN FOR net: CARDINAL IN (0..maxNets] DO rte: PupRouterDefs.RoutingTableEntry _ PupRouterDefs.GetRoutingTableEntry[ [net]]; IF rte = NIL OR rte.hop > PupRouterDefs.maxHop THEN oldPupRouting[net].network _ NIL ELSE oldPupRouting[net] _ rte^; ENDLOOP; BEGIN wordsPerNet: CARDINAL = 20; wordsPerPath: CARDINAL = 40; NameServerDefs.BumpCacheSize[25*wordsPerNet + 3*wordsPerPath]; NameServerDefs.PupDirServerOn[]; NameServerDefs.PupNameServerOn[]; END; END; CheckNetState: INTERNAL PROCEDURE = BEGIN FOR net: CARDINAL IN (0..maxNets] DO rte: PupRouterDefs.RoutingTableEntry _ PupRouterDefs.GetRoutingTableEntry[ [net]]; rto: PupRouterDefs.RoutingTableObject; -- It would be nice if there were a simple way to do this atomically IF rte # NIL THEN rto _ rte^; IF (rte = NIL AND oldPupRouting[net].network = NIL) OR (rto.network = NIL AND oldPupRouting[net].network = NIL) OR (rto.hop > PupRouterDefs.maxHop AND oldPupRouting[net].network = NIL) OR (oldPupRouting[net].network = rto.network AND oldPupRouting[net].route = rto.route AND oldPupRouting[net].hop = rto.hop) THEN LOOP; BEGIN text: STRING = [100]; via: STRING = [20]; Time.AppendCurrent[text]; String.AppendString[text, " "L]; PupDefs.PupAddressLookup[ text, [[net], [0], [0, 0]] ! PupDefs.PupNameTrouble => BEGIN String.AppendNumber[text, net, 8]; String.AppendString[text, "##"L]; CONTINUE; END]; String.AppendString[text, " is "L]; SELECT TRUE FROM rte = NIL, rto.network = NIL, rto.hop > PupRouterDefs.maxHop => String.AppendString[text, "unreachable"L]; (rto.route = 0) => String.AppendString[text, "directly connected"L]; ENDCASE => BEGIN String.AppendNumber[text, rto.hop, 10]; String.AppendString[text, " hop"L]; IF rto.hop # 1 THEN String.AppendChar[text, 's]; String.AppendString[text, " via "L]; PupDefs.PupAddressLookup[ via, [[rto.network.netNumber.b], [rto.route], [0, 0]] ! PupDefs.PupNameTrouble => BEGIN String.AppendNumber[text, rto.network.netNumber.b, 8]; String.AppendChar[text, '#]; String.AppendNumber[text, rto.route, 8]; String.AppendChar[text, '#]; CONTINUE; END]; String.AppendString[text, via]; END; String.AppendChar[text, '.]; IF rte = NIL OR rto.hop > PupRouterDefs.maxHop THEN oldPupRouting[net].network _ NIL ELSE oldPupRouting[net] _ rto; LogString[text]; END; WaitTwoSeconds[]; ENDLOOP; END; WaitTwoSeconds: INTERNAL PROCEDURE = BEGIN pause: CONDITION; Process.SetTimeout[@pause, Process.MsecToTicks[2000]]; THROUGH [0..1000) DO Process.Yield[]; ENDLOOP; -- and more if things are busy WAIT pause; END; LogString: PROCEDURE [text: STRING] = BEGIN IF msg # NIL THEN Put.Line[msg, text]; Put.Line[NIL, text]; END; MakeSWs: Tool.MakeSWsProc = BEGIN msg _ Tool.MakeMsgSW[window: window, lines: 5]; END; ClientTransition: ToolWindow.TransitionProcType = BEGIN IF new = inactive THEN msg _ NIL; END; -- initialization Init[]; END.