-- File: GateControlServer.mesa, Last Edit: HGM February 5, 1981 12:08 AM DIRECTORY InlineDefs USING [MesaToBcplLongNumber], Process USING [Detach], StringDefs USING [BcplSTRING], Time USING [Current], Window USING [Handle], George USING [CountFreeDiskPages], StatsDefs, GateDefs USING [GetVersionText], GateControlDefs USING [ gateControlStatsSend, gateControlStatsAck, gateControlStatsNak, gateControlExamine, gateControlDeposit, gateControlRestart, gateControlHalt, GateControlStatsEntry, gateControlVersion, RestartGateway, HaltGateway], PupDefs USING [ PupAddress, PupBuffer, ReturnFreePupBuffer, GetPupContentsBytes, SetPupContentsWords, PupRouterSendThis, SwapPupSourceAndDest, PupSocket, PupSocketMake, veryLongWait], BufferDefs USING [BuffersLeft], PupTypes USING [fillInPupAddress]; GateControlServer: PROGRAM IMPORTS InlineDefs, George, Process, Time, GateDefs, GateControlDefs, StatsDefs, PupDefs, BufferDefs EXPORTS GateControlDefs = BEGIN OPEN StatsDefs, PupDefs; msg: PUBLIC Window.Handle ← NIL; version: STRING ← GateDefs.GetVersionText[]; statsCounters: POINTER TO ARRAY StatCounterIndex OF LONG CARDINAL = StatsGetCounters[]; soc: PupSocket; GateControlServerOn: PUBLIC PROCEDURE = BEGIN Process.Detach[FORK Server[]]; END; Server: PROCEDURE = BEGIN b: PupBuffer; soc ← PupSocketMake[[31415, 9265], PupTypes.fillInPupAddress, veryLongWait]; DO -- forever IF (b ← soc.get[]) # NIL THEN BEGIN OPEN GateControlDefs; IF b.pupID.a # 27182 THEN GOTO Ignore; SELECT b.pupType FROM gateControlStatsSend => BEGIN gse: LONG POINTER TO GateControlStatsEntry; now: LONG CARDINAL ← Time.Current[]; StatsDefs.StatUpdate[]; -- be sure statSeconds is up-to-date IF GetPupContentsBytes[b] # 0 THEN GOTO Ignore; gse ← LOOPHOLE[@b.pupBody]; -- Beware: Constructor needs space for a copy on the frame gse.version ← GateControlDefs.gateControlVersion; gse.startTime ← InlineDefs.MesaToBcplLongNumber[ -- we can't just save the start time since we might not know the time yet LOOPHOLE[LOOPHOLE[now, LONG INTEGER] - statsCounters[statSeconds]]]; gse.ftpStatus ← 0; gse.freeBuffers ← BufferDefs.BuffersLeft[] + 2; gse.freeDiskPages ← George.CountFreeDiskPages[]; CopyString[version, @gse.versionText]; -- This sends more than we need to SetPupContentsWords[b, SIZE[GateControlStatsEntry]]; GOTO Send; END; gateControlExamine => BEGIN p: POINTER TO ARRAY [0..0) OF WORD ← LOOPHOLE[b.pupWords[0]]; i, words: CARDINAL; StatsDefs.StatUpdate[]; -- might look at the time IF GetPupContentsBytes[b] # 2*2 THEN GOTO Ignore; words ← b.pupWords[1]; FOR i IN [0..words) DO b.pupWords[2 + i] ← p[i]; ENDLOOP; SetPupContentsWords[b, (words + 2)]; GOTO Send; END; gateControlDeposit => BEGIN -- I hope you know what you are doing p: POINTER TO ARRAY [0..0) OF WORD ← LOOPHOLE[b.pupWords[0]]; i, words: CARDINAL; words ← b.pupWords[1]; IF GetPupContentsBytes[b] # 2*(words + 2) THEN GOTO Ignore; FOR i IN [0..b.pupWords[1]) DO p[i] ← b.pupWords[2 + i]; ENDLOOP; SetPupContentsWords[b, 0]; GOTO Send; END; gateControlRestart => BEGIN GateControlDefs.RestartGateway[b]; SetPupContentsWords[b, 0]; GOTO Send; END; gateControlHalt => BEGIN GateControlDefs.HaltGateway[b]; SetPupContentsWords[b, 0]; GOTO Send; END; ENDCASE => GOTO Reject; EXITS Send => BEGIN -- pupLength already setup b.pupType ← gateControlStatsAck; SwapPupSourceAndDest[b]; PupRouterSendThis[b]; END; Reject => BEGIN b.pupType ← GateControlDefs.gateControlStatsNak; SetPupContentsWords[b, 0]; SwapPupSourceAndDest[b]; PupRouterSendThis[b]; END; Ignore => BEGIN ReturnFreePupBuffer[b]; END; END; ENDLOOP; END; CopyString: PROCEDURE [s: STRING, d: LONG POINTER TO StringDefs.BcplSTRING] = BEGIN i: CARDINAL; d.length ← s.length; FOR i IN [0..s.length) DO d.char[i] ← s[i]; ENDLOOP; END; -- initialization GateControlServerOn[]; END.