-- TimeServer.mesa -- BLyon, January 16, 1981 5:16 PM -- HGM, February 10, 1981 6:34 PM DIRECTORY BufferDefs USING [BufferAccessHandle, OisBuffer], InlineDefs USING [BcplLongNumber, MesaToBcplLongNumber], TimeDefs USING [WestEast], Clock USING [GetTimeParms, TimeParameters], StatsDefs USING [StatCounterIndex, StatIncr, StatsStringToIndex], TimeServerDefs USING [], Router USING [FindMyHostID, XmitStatus], Socket USING [ Abort, ChannelAborted, ChannelHandle, Create, defaultWaitTime, Delete, PutPacket, GetPacket, SetWaitTime, TimeOut, WaitTime], SocketInternal USING [GetBufferPool, SocketHandle], System USING [GetGreenwichMeanTime], OISCP USING [ReturnFreeOisBuffer, SetOisPacketTextLength, unknownNetID], OISCPConstants USING [timeServerSocket], SpecialSystem USING [NetworkAddress, SocketNumber]; TimeServer: PROGRAM IMPORTS InlineDefs, Clock, StatsDefs, System, OISCP, Router, Socket, SocketInternal EXPORTS TimeServerDefs, System, Socket SHARES BufferDefs = BEGIN -- Krock to make TYPEs work ok ChannelHandle: PUBLIC TYPE = SocketInternal.SocketHandle; NetworkAddress: PUBLIC TYPE = SpecialSystem.NetworkAddress; -- These should move to OISCPTypes timeRequest: CARDINAL = 1; timeResponse: CARDINAL = 2; cH: Socket.ChannelHandle; localAddr: NetworkAddress; timeServerFork: PROCESS; timerTimeout: Socket.WaitTime = Socket.defaultWaitTime; statPilot: PUBLIC StatsDefs.StatCounterIndex; CreateServer: PUBLIC PROCEDURE = BEGIN localAddr ← [net: OISCP.unknownNetID, host: Router.FindMyHostID[], socket: OISCPConstants.timeServerSocket]; cH ← Socket.Create[localAddr, 0, 2, 0, FALSE]; timeServerFork ← FORK TimeServer[]; END; DeleteServer: PUBLIC PROCEDURE = BEGIN Socket.Abort[cH]; JOIN timeServerFork; Socket.Delete[cH]; END; TimeServer: PROCEDURE = BEGIN b: BufferDefs.OisBuffer; pool: BufferDefs.BufferAccessHandle ← SocketInternal.GetBufferPool[cH]; Socket.SetWaitTime[cH, timerTimeout]; DO b ← NIL; b ← Socket.GetPacket[ cH ! Socket.TimeOut => RETRY; Socket.ChannelAborted => GOTO GoAway]; SELECT LOOPHOLE[b.status, Router.XmitStatus] FROM goodCompletion => BEGIN -- ID is in b.oisWords[0..2), type is in word 2 IF b.ois.oisWords[2] = timeRequest THEN BEGIN target: LONG POINTER TO WireTimeFormat = LOOPHOLE[@b.ois.oisWords[3]]; parms: Clock.TimeParameters ← Clock.GetTimeParms[]; target↑ ← [time: InlineDefs.MesaToBcplLongNumber[ System.GetGreenwichMeanTime[]], zoneS: IF parms.zone > 0 THEN west ELSE east, zoneH: ABS[parms.zone], zoneM: parms.minutes, beginDST: parms.beginDst, endDST: parms.endDst]; b.ois.destination ← b.ois.source; b.ois.oisWords[2] ← timeResponse; OISCP.SetOisPacketTextLength[b, 2*(3 + SIZE[WireTimeFormat])]; Socket.PutPacket[cH, b ! Socket.ChannelAborted => CONTINUE]; StatsDefs.StatIncr[statPilot]; LOOP; END; END; ENDCASE; OISCP.ReturnFreeOisBuffer[b]; REPEAT GoAway => NULL; ENDLOOP; END; WireTimeFormat: TYPE = RECORD [ time: InlineDefs.BcplLongNumber, -- word 0 and 1 zoneS: TimeDefs.WestEast, -- start of word 2 zoneH: [0..177B], zoneM: [0..377B], -- end of word 2 beginDST: WORD, -- word 3 endDST: WORD, -- word 4 spare: ARRAY [5..8) OF WORD ← ALL[0]]; -- NB: There is no check for: -- 1) The OISCP package is turned on -- 2) Our clock is reasonable -- AutoStartup via START traps statPilot ← StatsDefs.StatsStringToIndex["Pilot Date Requests"]; CreateServer[]; END.