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