-- File: EchoServer.mesa, Last Edit: January 30, 1981 3:16 PM -- Please don't forget to update the herald too..... DIRECTORY Ascii USING [CR], InlineDefs USING [MesaToBcplLongNumber], Process USING [Yield], Event USING [Item, Reason, AddNotifier], FormSW USING [ AllocateItemDescriptor, newLine, ClientItemsProcType, ProcType, FindItem, Display, CommandItem, BooleanItem], MsgSW USING [AppendString], Tool USING [Create, MakeSWsProc, MakeMsgSW, MakeFormSW, AddThisSW], ToolWindow USING [TransitionProcType, DisplayProcType, CreateSubwindow], Window USING [Handle, Box, DisplayData, DisplayInvert, DisplayWhite], EchoServerDefs USING [ echoStatsRequest, echoStatsReply, EchoStatsEntry, echoVersion], StatsDefs USING [StatIncr, StatBump, StatGetCounter], PupDefs USING [ PupBuffer, ReturnFreePupBuffer, PupPackageMake, PupPackageDestroy, PupRouterSendThis, ReturnPup, SwapPupSourceAndDest, GetPupContentsBytes, PupSocket, PupSocketMake, PupSocketDestroy, PupSocketKick, veryLongWait], PupTypes USING [echoSoc, fillInPupAddress]; EchoServer: PROGRAM IMPORTS InlineDefs, Process, Event, FormSW, MsgSW, Tool, ToolWindow, Window, StatsDefs, PupDefs EXPORTS EchoServerDefs = 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; eventItem: Event.Item _ [eventMask: 177777B, eventProc: Broom]; EchoServerOn: PUBLIC PROCEDURE = BEGIN IF (useCount _ useCount + 1) = 1 THEN BEGIN 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[]; 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.pupType FROM echoMe => BEGIN b.pupType _ iAmEcho; SwapPupSourceAndDest[b]; PupRouterSendThis[b]; StatsDefs.StatIncr[pupsEchoed]; StatsDefs.StatBump[pupBytesEchoed, GetPupContentsBytes[b]]; showSomething['!]; END; EchoServerDefs.echoStatsRequest => BEGIN OPEN EchoServerDefs; ese: LONG POINTER TO EchoStatsEntry _ LOOPHOLE[@b.pupWords]; ese^ _ [version: echoVersion, pupsEchoed: InlineDefs.MesaToBcplLongNumber[ StatsDefs.StatGetCounter[pupsEchoed]]]; ReturnPup[b, EchoServerDefs.echoStatsReply, 2*SIZE[EchoStatsEntry]]; END; ENDCASE => ReturnFreePupBuffer[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; Window.DisplayData[window, indicatorBox, @pattern, 1] 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 Window.DisplayInvert[boxes, indicatorBox]; END; SetDownBoxes: PROCEDURE = BEGIN indicator _ off; IF boxes # NIL THEN Window.DisplayWhite[boxes, indicatorBox]; END; MakeBoxesSW: PROCEDURE [window: Window.Handle] = BEGIN boxes _ ToolWindow.CreateSubwindow[parent: window, display: DisplayBoxes]; boxes.box.dims.h _ 36; 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: PROCEDURE [why: Event.Reason] = BEGIN SELECT why FROM makeImage, makeCheck => IF running THEN Stopper[]; startImage, restartCheck, continueCheck => IF running THEN Starter[]; ENDCASE => NULL; END; -- initialization tool _ Tool.Create[ name: "Echo Server of January 30, 1981"L, makeSWsProc: MakeSWs, clientTransition: ClientTransition, initialState: inactive]; Event.AddNotifier[@eventItem]; EchoServerOn[]; -- This may be undesirable END.