-- File: PupMiscServer.mesa,  Last Edit: HGM  November 13, 1980  10:14 AM

DIRECTORY
  Process USING [Yield],
  Event USING [Item, Reason, AddNotifier],

  MiscServerDefs,
  PupDefs USING [
    PupBuffer, ReturnFreePupBuffer, veryLongWait, PupSocketKick, PupSocket,
    PupSocketMake, PupSocketDestroy, PupPackageMake, PupPackageDestroy],
  PupTypes USING [fillInPupAddress, miscSrvSoc];

PupMiscServer: PROGRAM IMPORTS Process, Event, PupDefs EXPORTS MiscServerDefs =
  BEGIN OPEN PupDefs;

  useCount: CARDINAL ← 0;
  pleaseStop, running: BOOLEAN ← FALSE;
  miscSocket: PupSocket ← NIL;
  miscFork: PROCESS;

  bootServer: PROCEDURE [PupBuffer] ← IgnoreThisPacket;
  nameServer: PROCEDURE [PupBuffer] ← IgnoreThisPacket;
  directoryServer: PROCEDURE [PupBuffer] ← IgnoreThisPacket;
  timeServer: PROCEDURE [PupBuffer] ← IgnoreThisPacket;

  eventItem: Event.Item ← [eventMask: 177777B, eventProc: Broom];

  PupMiscServerOn: PUBLIC PROCEDURE =
    BEGIN
    IF (useCount ← useCount + 1) = 1 THEN BEGIN running ← TRUE; Starter[]; END;
    END;

  Starter: PROCEDURE =
    BEGIN
    pleaseStop ← FALSE;
    PupDefs.PupPackageMake[];
    miscSocket ← PupSocketMake[
      PupTypes.miscSrvSoc, PupTypes.fillInPupAddress, veryLongWait];
    miscFork ← FORK Misc[];
    END;

  PupMiscServerOff: PUBLIC PROCEDURE =
    BEGIN
    IF useCount # 0 AND (useCount ← useCount - 1) = 0 THEN
      BEGIN running ← FALSE; Stopper[]; END;
    END;

  Stopper: PROCEDURE =
    BEGIN
    pleaseStop ← TRUE;
    PupSocketKick[miscSocket];
    JOIN miscFork[];
    PupSocketDestroy[miscSocket];
    PupDefs.PupPackageDestroy[];
    END;

  IgnoreThisPacket: PUBLIC PROCEDURE [b: PupBuffer] =
    BEGIN ReturnFreePupBuffer[b]; END;

  SetBootServer: PUBLIC PROCEDURE [proc: PROCEDURE [PupBuffer]] =
    BEGIN bootServer ← proc; END;

  SetNameServer: PUBLIC PROCEDURE [proc: PROCEDURE [PupBuffer]] =
    BEGIN nameServer ← proc; END;

  SetDirectoryServer: PUBLIC PROCEDURE [proc: PROCEDURE [PupBuffer]] =
    BEGIN directoryServer ← proc; END;

  SetTimeServer: PUBLIC PROCEDURE [proc: PROCEDURE [PupBuffer]] =
    BEGIN timeServer ← proc; END;

  -- This procedure is the only HOT chunk of code

  Misc: PROCEDURE =
    BEGIN OPEN MiscServerDefs; -- lots of PupType values
    b: PupBuffer;
    UNTIL pleaseStop DO
      IF (b ← miscSocket.get[]) # NIL THEN
	BEGIN
	SELECT b.pupType FROM
	  bootFileSend, microcodeRequest, bootDirReq, bootDirReply,
	    lockBooterRequest, unlockBooterRequest, bootStatsRequest =>
	    bootServer[b];
	  netDirVersion, sendNetDir, lockDirRequest, unlockDirRequest =>
	    directoryServer[b];
	  nameLookup, addressLookup, whoAmI, nameStatsRequest => nameServer[b];
	  dateTextRequest, dateTenexRequest, dateAltoRequest, lockTimeRequest,
	    resetTimeRequest, timeStatsRequest => timeServer[b];
	  ENDCASE => ReturnFreePupBuffer[b];
	END;
      Process.Yield[]; -- avoid hogging machine

      ENDLOOP;
    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

  Event.AddNotifier[@eventItem];
  END.