-- Copyright (C) 1983, 1985 by Xerox Corporation. All rights reserved.
-- PupEchoServer.mesa, HGM, 25-Jun-85 1:13:07
-- Please don't forget to update the herald too.....
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],
Supervisor USING [
AddDependency, AgentProcedure, CreateSubsystem, RemoveDependency,
SubsystemHandle],
Tool USING [Create, MakeSWsProc, MakeMsgSW, MakeFormSW, AddThisSW],
ToolWindow USING [CreateSubwindow, DisplayProcType, nullBox, TransitionProcType],
Window USING [Handle, Box],
Buffer USING [ReturnBuffer],
PupWireFormat USING [MesaToBcplLongNumber],
PupEchoServerDefs USING [
echoStatsRequest, echoStatsReply, EchoStatsEntry, echoVersion],
Stats USING [StatIncr, StatBump, StatGetCounter],
PupDefs USING [
PupBuffer, PupPackageMake, PupPackageDestroy,
PupRouterSendThis, ReturnPup, SwapPupSourceAndDest, GetPupContentsBytes,
PupSocket, PupSocketMake, PupSocketDestroy, PupSocketKick, veryLongWait],
PupTypes USING [echoSoc, fillInPupAddress];
PupEchoServer: PROGRAM
IMPORTS
Display, Event, FormSW, MsgSW, Supervisor, Process, Tool, ToolWindow,
Buffer, 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 => Buffer.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: STRING = "Pup EchoServer of 25-Jun-85 1:13:03"L;
tool ← Tool.Create[
name: herald, makeSWsProc: MakeSWs,
clientTransition: ClientTransition, initialState: inactive];
END;
Init[];
EchoServerOn[]; -- This may be undesirable
END.