-- File: PupEchoServer.mesa - last edit: -- AOF 3-Feb-88 11:33:27 -- WIrish 5-Feb-88 12:42:58 -- HGM 25-Jun-85 1:13:07 -- Copyright (C) 1983, 1985, 1988 by Xerox Corporation. All rights reserved. DIRECTORY Ascii USING [CR], Display USING [Bitmap, Invert, replaceFlags, White], Event USING [aboutToSwap], EventTypes USING [aboutToBoot, aboutToBootPhysicalVolume], FormSW USING [ AllocateItemDescriptor, newLine, ClientItemsProcType, ProcType, FindItem, Display, CommandItem, BooleanItem], MsgSW USING [AppendString], Process USING [Yield], Runtime USING [GetBcdTime], String USING [AppendString], Supervisor USING [ AddDependency, AgentProcedure, CreateSubsystem, RemoveDependency, SubsystemHandle], Time USING [Append, Unpack], Tool USING [Create, MakeSWsProc, MakeMsgSW, MakeFormSW, AddThisSW], ToolWindow USING [CreateSubwindow, DisplayProcType, nullBox, TransitionProcType], Window USING [Handle, Box], PupWireFormat USING [MesaToBcplLongNumber], PupEchoServerDefs USING [ echoStatsRequest, echoStatsReply, EchoStatsEntry, echoVersion], Stats USING [StatIncr, StatBump, StatGetCounter], PupDefs USING [ PupBuffer, PupPackageMake, PupPackageDestroy, ReturnBuffer, PupRouterSendThis, ReturnPup, SwapPupSourceAndDest, GetPupContentsBytes, PupSocket, PupSocketMake, PupSocketDestroy, PupSocketKick, veryLongWait], PupTypes USING [echoSoc, fillInPupAddress]; PupEchoServer: PROGRAM IMPORTS Display, Event, FormSW, MsgSW, Runtime, String, Supervisor, Time, Process, Tool, ToolWindow, PupWireFormat, Stats, PupDefs EXPORTS PupEchoServerDefs = BEGIN OPEN PupDefs; useCount, hits: CARDINAL ¬ 0; pleaseStop, running, verbose: BOOLEAN ¬ FALSE; echoFork: PROCESS; echoSocket: PupSocket; showSomething: PROCEDURE [CHARACTER] ¬ DummyEchoHook; tool, msg, form, boxes: Window.Handle ¬ NIL; broom: Supervisor.SubsystemHandle = Supervisor.CreateSubsystem[Broom]; EchoServerOn: PUBLIC PROCEDURE = BEGIN IF (useCount ¬ useCount + 1) = 1 THEN BEGIN Supervisor.AddDependency[client: broom, implementor: Event.aboutToSwap]; running ¬ TRUE; Starter[]; END; UpdatePicture[]; END; Starter: PROCEDURE = BEGIN pleaseStop ¬ FALSE; [] ¬ PupDefs.PupPackageMake[]; echoSocket ¬ PupSocketMake[ PupTypes.echoSoc, PupTypes.fillInPupAddress, veryLongWait]; echoFork ¬ FORK Echoer[]; END; EchoServerOff: PUBLIC PROCEDURE = BEGIN IF useCount # 0 AND (useCount ¬ useCount - 1) = 0 THEN BEGIN running ¬ FALSE; Stopper[]; Supervisor.RemoveDependency[client: broom, implementor: Event.aboutToSwap]; END; UpdatePicture[]; END; Stopper: PROCEDURE = BEGIN pleaseStop ¬ TRUE; PupSocketKick[echoSocket]; JOIN echoFork[]; PupSocketDestroy[echoSocket]; PupDefs.PupPackageDestroy[]; END; UpdatePicture: PROCEDURE = BEGIN IF running THEN SetupBoxes[] ELSE SetDownBoxes[]; IF form = NIL THEN RETURN; FormSW.FindItem[form, startIX].flags.invisible ¬ running; FormSW.FindItem[form, stopIX].flags.invisible ¬ ~running; FormSW.Display[form]; END; Echoer: PROCEDURE = BEGIN b: PupBuffer; UNTIL pleaseStop DO IF (b ¬ echoSocket.get[]) # NIL THEN BEGIN SELECT b.pup.pupType FROM echoMe => BEGIN Stats.StatIncr[pupsEchoed]; Stats.StatBump[pupBytesEchoed, GetPupContentsBytes[b]]; b.pup.pupType ¬ iAmEcho; SwapPupSourceAndDest[b]; PupRouterSendThis[b]; showSomething['!]; END; PupEchoServerDefs.echoStatsRequest => BEGIN OPEN PupEchoServerDefs; ese: LONG POINTER TO EchoStatsEntry ¬ LOOPHOLE[@b.pup.pupWords]; ese­ ¬ [ version: echoVersion, pupsEchoed: PupWireFormat.MesaToBcplLongNumber[ Stats.StatGetCounter[pupsEchoed]]]; ReturnPup[ b, PupEchoServerDefs.echoStatsReply, 2*SIZE[EchoStatsEntry]]; END; ENDCASE => ReturnBuffer[b]; END; Process.Yield[]; -- avoid hogging machine ENDLOOP; END; DummyEchoHook: PUBLIC PROCEDURE [c: CHARACTER] = {}; RealEchoHook: PUBLIC PROCEDURE [c: CHARACTER] = BEGIN s: STRING = [2]; IF boxes # NIL THEN FlipBoxes[]; IF msg = NIL OR ~verbose THEN RETURN; s[0] ¬ c; s.length ¬ 1; IF ((hits ¬ hits + 1) MOD 50) = 0 THEN {s[1] ¬ Ascii.CR; s.length ¬ 2; }; MsgSW.AppendString[msg, s]; END; indicator: {off, left, right} ¬ off; indicatorBox: Window.Box = [[25, 10], [16, 16]]; DisplayBoxes: ToolWindow.DisplayProcType = BEGIN pattern: ARRAY [0..1] OF ARRAY [0..8) OF WORD; left: WORD = 177400B; right: WORD = 000377B; SELECT indicator FROM left => pattern ¬ [ALL[left], ALL[right]]; right => pattern ¬ [ALL[right], ALL[left]]; off => pattern ¬ [ALL[0], ALL[0]]; ENDCASE; Display.Bitmap[window, indicatorBox, [@pattern, 0, 0], 16, Display.replaceFlags] END; SetupBoxes: PROCEDURE = BEGIN indicator ¬ left; IF boxes # NIL THEN DisplayBoxes[boxes]; END; FlipBoxes: PROCEDURE = BEGIN SELECT indicator FROM left => indicator ¬ right; off, right => indicator ¬ left; ENDCASE; IF boxes # NIL THEN Display.Invert[boxes, indicatorBox]; END; SetDownBoxes: PROCEDURE = BEGIN indicator ¬ off; IF boxes # NIL THEN Display.White[boxes, indicatorBox]; END; MakeBoxesSW: PROCEDURE [window: Window.Handle] = BEGIN box: Window.Box ¬ ToolWindow.nullBox; box.dims.h ¬ 36; boxes ¬ ToolWindow.CreateSubwindow[parent: window, display: DisplayBoxes, box: box]; Tool.AddThisSW[window: window, sw: boxes, swType: vanilla]; END; Start: FormSW.ProcType = BEGIN EchoServerOn[]; END; Stop: FormSW.ProcType = BEGIN EchoServerOff[]; END; MakeSWs: Tool.MakeSWsProc = BEGIN msg ¬ Tool.MakeMsgSW[window: window, lines: 3]; form ¬ Tool.MakeFormSW[window: window, formProc: MakeForm]; MakeBoxesSW[window]; END; startIX: CARDINAL = 0; stopIX: CARDINAL = 1; MakeForm: FormSW.ClientItemsProcType = BEGIN nParams: CARDINAL = 3; items ¬ FormSW.AllocateItemDescriptor[nParams]; items[0] ¬ FormSW.CommandItem[ tag: "Start"L, proc: Start, place: FormSW.newLine, invisible: running]; items[1] ¬ FormSW.CommandItem[ tag: "Stop"L, proc: Stop, place: FormSW.newLine, invisible: ~running]; items[2] ¬ FormSW.BooleanItem[tag: "Verbose"L, switch: @verbose]; RETURN[items, TRUE]; END; ClientTransition: ToolWindow.TransitionProcType = BEGIN IF new = inactive THEN msg ¬ form ¬ boxes ¬ NIL; showSomething ¬ IF new = active THEN RealEchoHook ELSE DummyEchoHook; END; Broom: Supervisor.AgentProcedure = BEGIN SELECT event FROM EventTypes.aboutToBoot, EventTypes.aboutToBootPhysicalVolume => IF running THEN Stopper[]; ENDCASE => NULL; END; Init: PROCEDURE = BEGIN herald: LONG STRING = [100]; String.AppendString[herald, "Pup EchoServer of "L]; Time.Append[herald, Time.Unpack[Runtime.GetBcdTime[]]]; tool ¬ Tool.Create[ name: herald, makeSWsProc: MakeSWs, clientTransition: ClientTransition, initialState: inactive]; END; Init[]; EchoServerOn[]; -- This may be undesirable END.