DIRECTORY BasicTime, Commander, Convert, IO, NetAddressing, Process, PupStream, PupStreamCellarWindow, RemoteViewersHostBackdoor, Rope, TypeScript, ViewerClasses, ViewerOps; RemoteViewersHostSpy: CEDAR PROGRAM IMPORTS BasicTime, Commander, Convert, IO, NetAddressing, Process, PupStream, PupStreamCellarWindow, RemoteViewersHostBackdoor, Rope, TypeScript, ViewerOps = BEGIN Viewer: TYPE ~ ViewerClasses.Viewer; STREAM: TYPE ~ IO.STREAM; ROPE: TYPE ~ Rope.ROPE; Stats: TYPE ~ PupStreamCellarWindow.Stats; StatsLabels: TYPE ~ PupStreamCellarWindow.StatsLabels; StatsInfoList: TYPE = LIST OF StatsInfoObject; StatsInfoObject: TYPE = RECORD [inLabel, outLabel: ROPE, index: INT ¬ -1]; updateInterval: INT ¬ 15; -- seconds between updates script: Viewer ¬ NIL; statsInfoList: StatsInfoList ¬ LIST [ ["packetsPushed", "snd"], ["inOrderPackets", "rcv"], ["packetsRetransmitted", "rtr"], ["oldPackets", "dup"], ["resourceLimitsErrors", "res"] ]; DoViewer: PROC [stream: STREAM, address: NetAddressing.Address] ~ { PutRope[IO.PutFR["Connection Established from: %g", [rope[NetAddressing.FormatAddress[address, FALSE]]]]]; IF address.kind # pup THEN { PutRope["Sorry, no Stats available for this transport.\n"]; RETURN; }; {ENABLE IO.Error, PupStream.StreamClosing => CONTINUE; prevStats: Stats ¬ PupStreamCellarWindow.GetStreamStats[stream]; DO Process.PauseMsec[updateInterval*1000]; PupStream.CheckConnection[stream]; {stats: Stats ¬ PupStreamCellarWindow.GetStreamStats[stream]; PutRope[CreateStatsRope[stream, stats, prevStats]]; prevStats ¬ stats; }ENDLOOP; }; PutRope["Connection Closed since last sampling.\n"]; RETURN}; CreateStatsRope: PROC [stream: STREAM, stats, prevStats: Stats] RETURNS [rope: ROPE] ~ { FOR info: StatsInfoList ¬ statsInfoList, info.rest WHILE info # NIL DO IF info.first.index < 0 THEN LOOP; rope ¬ Rope.Cat[rope, IO.PutFR["%g: %g/%g", [rope[info.first.outLabel]], [cardinal[stats[info.first.index]-prevStats[info.first.index]]], [cardinal[stats[info.first.index]]]]]; IF info.rest # NIL THEN rope ¬ Rope.Cat[rope, ", "]; ENDLOOP; RETURN}; PutRope: PROC [rope: ROPE, stampIt: BOOL ¬ TRUE] ~ { IF script = NIL OR script.destroyed THEN RETURN; IF stampIt THEN rope ¬ Rope.Cat[IO.PutFR["%g: ", [rope[Convert.RopeFromTime[from: BasicTime.Now[], start: hours, end: seconds, includeDayOfWeek: FALSE, useAMPM: TRUE, includeZone: FALSE]]]], rope]; script.name ¬ rope; TypeScript.PutRope[script, rope]; TypeScript.PutChar[script, '\n]; ViewerOps.PaintViewer[script, caption]; }; HostStatsProc: Commander.CommandProc = { GetViewer[]; RETURN}; GetViewer: PROC ~ { IF script # NIL AND script.destroyed THEN { script ¬ NIL; }; IF script = NIL THEN { s: Viewer ~ TypeScript.Create[info: [name: "Host Spy", label: "Host Spy", column: right, iconic: TRUE]]; ViewerOps.SetOpenHeight[s, -12]; ViewerOps.OpenIcon[icon: s, bottom: FALSE]; script ¬ s; }; }; SetUpStatsInfoList: PROC ~ { statsLabels: StatsLabels ¬ PupStreamCellarWindow.GetStreamStatsLabels[]; GetIndex: PROC [label: ROPE] RETURNS [index: INT ¬ -1] ~ { FOR i: CARDINAL IN [0..statsLabels.length) DO IF Rope.Equal[s1: label, s2: statsLabels[i], case: FALSE] THEN RETURN[i]; ENDLOOP; }; FOR info: StatsInfoList ¬ statsInfoList, info.rest WHILE info # NIL DO info.first.index ¬ GetIndex[info.first.inLabel]; ENDLOOP; }; Start: PROC ~ { SetUpStatsInfoList[]; RemoteViewersHostBackdoor.SetSpy[DoViewer]; Commander.Register[key: "HostSpy", proc: HostStatsProc, doc: "Create a viewer for spying on the host side of a RemoteTerminal session."]; RETURN}; Start[]; END. „ RemoteViewersHostSpy.mesa Copyright Σ 1990, 1992 by Xerox Corporation. All rights reserved. Wes Irish, March 10, 1989 10:07:58 am PST Last tweaked by Mike Spreitzer on September 12, 1990 11:55 am PDT ["funnyPacketType", "funnyPacketType"], ["acksDefered", "acksDefered"], ["oldAcks", "oldAcks"], ["futurePackets", "futurePackets"], ["clumpsRetransmitted", "clumpsRetransmitted"], Κd•NewlineDelimiter –(cedarcode) style™codešœ™Kšœ Οeœ7™BKšœ)™)K™A—K˜šΟk œ žœ‚˜­K˜—K˜šΟnœžœž˜#Kšžœ žœr˜›K˜—K˜Kšž˜K˜Kšœžœ˜$Kšžœžœžœžœ˜Kšžœžœžœ˜K˜Kšœžœ˜*Kšœ žœ%˜6K˜Kšœžœžœžœ˜.š œžœžœžœ žœ˜JK˜—KšœžœΟc˜5K˜Kšœžœ˜K˜šœžœ˜%Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜Kšœ'™'Kšœ™Kšœ™Kšœ#™#Kšœ/™/K˜K˜—šΠbnœžœ žœ%˜CKšœžœUžœ˜jšžœžœ˜Kšœ;˜;Kšžœ˜K˜—Kšœžœžœ#žœ˜6K˜@šž˜K˜'K˜"K˜=Kšœ3˜3K˜Kšœžœ˜ —K˜Kšœ4˜4Kšžœ˜K˜—š ‘œžœ žœžœžœ˜Xšžœ0žœžœž˜FKšžœžœžœ˜"Kšœžœ˜˜°Kšžœ žœžœ˜4Kšžœ˜—Kšžœ˜K˜—š ‘œžœžœ žœžœ˜4Kš žœ žœžœžœžœ˜0Kš žœ žœžœožœ žœžœ ˜ΕK˜Kšœ!˜!Kšœ ˜ Kšœ'˜'K˜K˜—•StartOfExpansionL -- [cmd: Commander.Handle] RETURNS [result: REF ANY _ NIL, msg: ROPE _ NIL]šΟb œ˜(K˜ Kšžœ˜K˜—š‘ œžœ˜šžœ žœžœžœ˜+Kšœ žœ˜ K˜—šžœ žœžœ˜Kšœbžœ˜iK˜ Kšœ$žœ˜+K˜ K˜—K˜K˜—š‘œžœ˜K˜Hš Ÿœžœ žœžœ žœ ˜:šžœžœžœž˜-K–-[s1: ROPE, s2: ROPE, case: BOOL _ TRUE]šžœ1žœžœžœ˜IKšžœ˜—K˜—šžœ0žœžœž˜FK˜0Kšžœ˜—K˜K˜—šŸœžœ˜Kšœ˜Kšœ+˜+K–x[key: ROPE, proc: Commander.CommandProc, doc: ROPE _ NIL, clientData: REF ANY _ NIL, interpreted: BOOL _ TRUE]˜‰Kšžœ˜—K˜K˜K˜Kšžœ˜—…— άΔ