-- Copyright (C) 1984, 1985 by Xerox Corporation. All rights reserved.
-- OthelloOpsTime.mesa, HGM, 3-Jul-85 0:57:47
DIRECTORY
Buffer USING [NSBuffer],
Environment,
NSConstants USING [timeServerSocket],
NSTypes USING [wordsPerExchangeHeader],
OthelloOps USING [TimeServerErrorType],
ProcessorFace USING [GreenwichMeanTime, SetGreenwichMeanTime],
Socket USING [
BroadcastAddressFromSocket, ChannelHandle,
Create, Delete, GetPacket, GetPacketBytes, GetSendBuffer,
BroadcastPacketToAllConnectedNets, ReturnBuffer, SetDestination,
SetPacketWords, SetWaitTime, TimeOut],
System USING [
gmtEpoch, GetGreenwichMeanTime, GreenwichMeanTime,
LocalTimeParameters, NetworkAddress, nullSocketNumber, WestEast],
TimeServerFormat USING [TSPacket, WireToGMT, Version];
OthelloOpsTime: PROGRAM
IMPORTS ProcessorFace, Socket, System, TimeServerFormat
EXPORTS OthelloOps =
BEGIN
IsTimeValid: PUBLIC PROC RETURNS [valid: BOOLEAN] = {
RETURN[System.GetGreenwichMeanTime[]#System.gmtEpoch]};
SetProcessorTime: PUBLIC PROC [time: System.GreenwichMeanTime] = {
ProcessorFace.SetGreenwichMeanTime[time]};
TimeServerError: PUBLIC ERROR [error: OthelloOps.TimeServerErrorType] = CODE;
GetTimeFromTimeServer: PUBLIC PROC RETURNS[
serverTime: System.GreenwichMeanTime,
serverLTPs: System.LocalTimeParameters] = {
isValid: BOOLEAN;
[isValid, serverTime, serverLTPs] ← GetNSTime[];
IF ~isValid THEN ERROR TimeServerError[noResponse];
RETURN};
GetNSTime: PROC RETURNS [
valid: BOOLEAN ← FALSE, time: System.GreenwichMeanTime,
ltp: System.LocalTimeParameters] =
BEGIN
wordsInRequest: CARDINAL = SIZE[timeRequest TimeServerFormat.TSPacket];
wordsInAnswer: CARDINAL = SIZE[timeResponse TimeServerFormat.TSPacket];
request: LONG POINTER TO timeRequest TimeServerFormat.TSPacket;
answer: LONG POINTER TO timeResponse TimeServerFormat.TSPacket;
soc: Socket.ChannelHandle;
soc ← Socket.Create[socket: System.nullSocketNumber, receive: 1];
Socket.SetWaitTime[soc, 700]; -- milli-seconds
FOR i: CARDINAL IN [0..3) DO
him: System.NetworkAddress ← Socket.BroadcastAddressFromSocket[
NSConstants.timeServerSocket];
b: Buffer.NSBuffer ← Socket.GetSendBuffer[soc];
Socket.SetDestination[b, him];
b.ns.packetType ← packetExchange;
b.ns.exchangeID ← [0, i];
b.ns.exchangeType ← timeService;
request ← LOOPHOLE[@b.ns.exchangeBody];
request↑ ← [TimeServerFormat.Version, timeRequest[]];
Socket.SetPacketWords[b, NSTypes.wordsPerExchangeHeader + wordsInRequest];
Socket.BroadcastPacketToAllConnectedNets[soc, b];
DO
b ← Socket.GetPacket[soc ! Socket.TimeOut => EXIT];
answer ← LOOPHOLE[@b.ns.exchangeBody];
SELECT TRUE FROM
b.ns.packetType # packetExchange
OR Socket.GetPacketBytes[b] # 2*(NSTypes.wordsPerExchangeHeader + wordsInAnswer)
OR (b.ns.exchangeType # timeService)
OR answer.version # TimeServerFormat.Version
OR answer.type # timeResponse => NULL;
ENDCASE =>
BEGIN OPEN t: LOOPHOLE[time, Environment.LongNumber];
valid ← TRUE;
time ← TimeServerFormat.WireToGMT[answer.time];
ltp ← [
zone: answer.zoneH,
direction: answer.zoneS,
zoneMinutes: answer.zoneM,
beginDST: answer.beginDST,
endDST: answer.endDST];
Socket.ReturnBuffer[b];
GOTO Done;
END;
Socket.ReturnBuffer[b];
ENDLOOP;
REPEAT Done => NULL;
ENDLOOP;
Socket.Delete[soc];
END;
END....