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
Server data (global)
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.