-- file: SetTime.mesa
-- edited by Levin, August 11, 1980 5:55 PM
-- edited by Brotz, November 12, 1981 2:40 PM

DIRECTORY
DMSTimeDefs USING [HardwareTime, MapPackedTimeToTimeZoneString, PackedTime,
WestEast],
inD: FROM "InteractorDefs" USING [],
intCommon USING [lastMinuteSeconds, secondsLastChecked, timeHouse],
ProcessDefs USING [Detach],
PupDefs USING [GetFreePupBuffer, MsToTocks, PupAddress, PupBuffer,
PupRouterBroadcastThis, PupSocket, PupSocketDestroy, PupSocketMake,
ReturnFreePupBuffer, SetPupContentsBytes, UniqueLocalPupSocketID],
PupTypes USING [fillInPupAddress, miscSrvSoc, PupAddress],
TimeDefs USING [CurrentDayTime, currentParameters, currentTime, PackedTime,
UnpackDT, WestEast];

SetTime: PROGRAM
IMPORTS DMSTimeDefs, intC: intCommon, ProcessDefs, PupDefs, TimeDefs
EXPORTS DMSTimeDefs, inD =

BEGIN
OPEN PupDefs, PupTypes;

-- Purpose: determines correct time by probing the network.

Msec: TYPE = CARDINAL;

timeCheckIntervalMs: Msec = 1000;

timeTries: CARDINAL = 5;


SetTime: PUBLIC PROCEDURE = {ProcessDefs.Detach[FORK DoSetTime]};


SetLaurelTime: PUBLIC PROCEDURE =
BEGIN
pt: DMSTimeDefs.PackedTime;
nSlopSeconds: CARDINAL;
pt.lc ← TimeDefs.CurrentDayTime[];
nSlopSeconds ← TimeDefs.UnpackDT[pt.lc].second;
-- Set intC.lastMinuteSeconds so that DMSTime will not be called for at least 15
-- seconds; This may cause the time to not be updated for a whole minute + 14
-- seconds.
intC.secondsLastChecked ← intC.lastMinuteSeconds ←
pt.lowbits - nSlopSeconds + (IF nSlopSeconds > 45 THEN 60 ELSE 0);
DMSTimeDefs.MapPackedTimeToTimeZoneString[pt, intC.timeHouse.text];
intC.timeHouse.houseRefresher[intC.timeHouse];
END; -- of SetLaurelTime --


DoSetTime: PROCEDURE =
BEGIN
timeSocket: PupSocket;
garbageAddress: PupAddress = fillInPupAddress;
timeSocket ← PupSocketMake[local: UniqueLocalPupSocketID[], remote: garbageAddress,
ticks: MsToTocks[timeCheckIntervalMs]];
THROUGH [0..timeTries) DO IF TryTime[timeSocket] THEN EXIT; ENDLOOP;
SetLaurelTime[];
PupSocketDestroy[timeSocket];
END; -- of DoSetTime --


TryTime: PROCEDURE [timeSocket: PupSocket] RETURNS[responseReceived: BOOLEAN] =
BEGIN
packet: PupBuffer ← GetFreePupBuffer[];
ResponsePacketData: TYPE = MACHINE DEPENDENT RECORD
[gmtSeconds: DMSTimeDefs.HardwareTime,
direction: DMSTimeDefs.WestEast,
zoneHours: [0..177B], zoneMinutes: [0..377B],
beginDST: WORD,
endDST: WORD];
timeInfo: POINTER TO ResponsePacketData;
responseReceived ← FALSE;
packet.pupType ← dateAltoRequest;
SetPupContentsBytes[packet,0];
packet.dest.socket ← miscSrvSoc;
packet.source ← timeSocket.getLocalAddress[];
PupRouterBroadcastThis[packet];
-- packet has been handed off, now wait for response.
UNTIL responseReceived OR (packet ← timeSocket.get[]) = NIL DO
IF packet.pupType = dateAltoIs THEN
BEGIN
OPEN timeInfo;
timeInfo ← LOOPHOLE[@packet.pupBody];
TimeDefs.currentParameters↑
← [direction, zoneHours, 0, beginDST, 0, zoneMinutes, endDST];
TimeDefs.currentTime↑ ← gmtSeconds;
responseReceived ← TRUE;
END;
ReturnFreePupBuffer[packet];
ENDLOOP;
END; -- of TryTime --


END. -- of SetTime --