Commit
This commit is contained in:
68
Carthage/Checkouts/TrueTime.swift/Sources/NTPResponse.swift
vendored
Normal file
68
Carthage/Checkouts/TrueTime.swift/Sources/NTPResponse.swift
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
//
|
||||
// NTPResponse.swift
|
||||
// TrueTime
|
||||
//
|
||||
// Created by Michael Sanders on 10/14/16.
|
||||
// Copyright © 2016 Instacart. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct NTPResponse {
|
||||
let packet: ntp_packet_t
|
||||
let responseTime: Int64
|
||||
let receiveTime: timeval
|
||||
init?(packet: ntp_packet_t, responseTime: Int64, receiveTime: timeval = .now()) {
|
||||
self.packet = packet
|
||||
self.responseTime = responseTime
|
||||
self.receiveTime = receiveTime
|
||||
guard isValidResponse else { return nil }
|
||||
}
|
||||
|
||||
// See https://en.wikipedia.org/wiki/Network_Time_Protocol#Clock_synchronization_algorithm
|
||||
var offset: Int64 {
|
||||
let T = offsetValues
|
||||
return ((T[1] - T[0]) + (T[2] - T[3])) / 2
|
||||
}
|
||||
|
||||
var delay: Int64 {
|
||||
let T = offsetValues
|
||||
return (T[3] - T[0]) - (T[2] - T[1])
|
||||
}
|
||||
|
||||
var networkDate: Date {
|
||||
let interval = TimeInterval(milliseconds: responseTime + offset)
|
||||
return Date(timeIntervalSince1970: interval)
|
||||
}
|
||||
}
|
||||
|
||||
func bestTime(fromResponses times: [[FrozenNetworkTime]]) -> FrozenNetworkTime? {
|
||||
let bestTimes = times.map { serverTimes -> FrozenNetworkTime? in
|
||||
serverTimes.min { $0.serverResponse.delay < $1.serverResponse.delay }
|
||||
}.compactMap { $0 }.sorted { $0.serverResponse.offset < $1.serverResponse.offset }
|
||||
|
||||
return bestTimes.isEmpty ? nil : bestTimes[bestTimes.count / 2]
|
||||
}
|
||||
|
||||
private extension NTPResponse {
|
||||
var isValidResponse: Bool {
|
||||
return packet.stratum > 0 && packet.stratum < 16 &&
|
||||
packet.root_delay.durationInMilliseconds < maxRootDispersion &&
|
||||
packet.root_dispersion.durationInMilliseconds < maxRootDispersion &&
|
||||
packet.client_mode == ntpModeServer &&
|
||||
packet.leap_indicator != leapIndicatorUnknown &&
|
||||
abs(receiveTime.milliseconds - packet.originate_time.milliseconds - delay) < maxDelayDelta
|
||||
}
|
||||
|
||||
var offsetValues: [Int64] {
|
||||
return [packet.originate_time.milliseconds,
|
||||
packet.receive_time.milliseconds,
|
||||
packet.transmit_time.milliseconds,
|
||||
responseTime]
|
||||
}
|
||||
}
|
||||
|
||||
private let maxRootDispersion: Int64 = 100
|
||||
private let maxDelayDelta: Int64 = 100
|
||||
private let ntpModeServer: UInt8 = 4
|
||||
private let leapIndicatorUnknown: UInt8 = 3
|
Reference in New Issue
Block a user