<> <> DIRECTORY GermSwap USING [switches], PupDefs USING [PupAddress, PupBuffer, PupRouterSendThis, PupSocket, PupSocketDestroy, PupSocketKick, PupSocketMake, ReturnFreePupBuffer, ReturnPup, SwapPupSourceAndDest, veryLongWait], PupTypes USING [echoSoc, fillInPupAddress], PupEchoServer USING [echoStatsReply, echoStatsRequest, EchoStatsEntry, echoVersion], PupWireFormat USING [MesaToBcplLongNumber]; PupEchoServerImpl: CEDAR MONITOR IMPORTS GermSwap, PupDefs, PupWireFormat EXPORTS PupEchoServer = BEGIN <> pupsEchoed: INT _ 0; pleaseStopServer: BOOLEAN _ FALSE; server: PROCESS _ NIL; serverSoc: PupDefs.PupSocket _ NIL; Start: PUBLIC ENTRY PROC = { IF server # NIL THEN RETURN; pleaseStopServer _ FALSE; server _ FORK Server[]; }; Stop: PUBLIC ENTRY PROC = TRUSTED { IF server = NIL THEN RETURN; pleaseStopServer _ TRUE; IF server # NIL THEN {PupDefs.PupSocketKick[serverSoc]; JOIN server; }; server _ NIL; }; Server: PROC = TRUSTED { serverSoc _ PupDefs.PupSocketMake[ PupTypes.echoSoc, PupTypes.fillInPupAddress, PupDefs.veryLongWait]; UNTIL pleaseStopServer DO b: PupDefs.PupBuffer _ serverSoc.get[]; IF b # NIL THEN { SELECT b.pupType FROM echoMe => { b.pupType _ iAmEcho; PupDefs.SwapPupSourceAndDest[b]; PupDefs.PupRouterSendThis[b]; pupsEchoed _ pupsEchoed.SUCC; }; PupEchoServer.echoStatsRequest => { EchoStatsEntry: TYPE = PupEchoServer.EchoStatsEntry; ese: LONG POINTER TO EchoStatsEntry _ LOOPHOLE[@b.pupWords]; ese^ _ [ version: PupEchoServer.echoVersion, pupsEchoed: PupWireFormat.MesaToBcplLongNumber[pupsEchoed]]; PupDefs.ReturnPup[ b, PupEchoServer.echoStatsReply, 2*SIZE[EchoStatsEntry]]; }; ENDCASE => PupDefs.ReturnFreePupBuffer[b]; }; ENDLOOP; PupDefs.PupSocketDestroy[serverSoc]; serverSoc _ NIL; }; IF ~GermSwap.switches[c] THEN Start[]; END.