Commit
This commit is contained in:
240
Carthage/Checkouts/TrueTime.swift/Sources/NTPExtensions.swift
vendored
Normal file
240
Carthage/Checkouts/TrueTime.swift/Sources/NTPExtensions.swift
vendored
Normal file
@ -0,0 +1,240 @@
|
||||
//
|
||||
// NTPExtensions.swift
|
||||
// TrueTime
|
||||
//
|
||||
// Created by Michael Sanders on 7/10/16.
|
||||
// Copyright © 2016 Instacart. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public extension timeval {
|
||||
static func uptime() -> timeval {
|
||||
let now = timeval.now()
|
||||
var boottime = timeval()
|
||||
var mib: [CInt] = [CTL_KERN, KERN_BOOTTIME]
|
||||
var size = MemoryLayout.stride(ofValue: boottime)
|
||||
withFatalErrno { sysctl(&mib, 2, &boottime, &size, nil, 0) }
|
||||
return timeval(tv_sec: now.tv_sec - boottime.tv_sec, tv_usec: now.tv_usec - boottime.tv_usec)
|
||||
}
|
||||
|
||||
var milliseconds: Int64 {
|
||||
return Int64(tv_sec) * Int64(MSEC_PER_SEC) + Int64(tv_usec) / Int64(USEC_PER_MSEC)
|
||||
}
|
||||
}
|
||||
|
||||
extension timeval {
|
||||
static func now() -> timeval {
|
||||
var tv = timeval()
|
||||
withFatalErrno { gettimeofday(&tv, nil) }
|
||||
return tv
|
||||
}
|
||||
}
|
||||
|
||||
// Represents an amount of time since the NTP epoch, January 1, 1900.
|
||||
// https://en.wikipedia.org/wiki/Network_Time_Protocol#Timestamps
|
||||
protocol NTPTimeType {
|
||||
associatedtype ValueType: UnsignedInteger
|
||||
init(whole: ValueType, fraction: ValueType)
|
||||
var whole: ValueType { get }
|
||||
var fraction: ValueType { get }
|
||||
}
|
||||
|
||||
protocol NTPTimevalConvertible: NTPTimeType {}
|
||||
|
||||
extension NTPTimeType {
|
||||
// Interprets the receiver as an elapsed time in milliseconds.
|
||||
var durationInMilliseconds: Int64 {
|
||||
return Int64(whole) * Int64(MSEC_PER_SEC) +
|
||||
fractionInMicroseconds / Int64(USEC_PER_MSEC)
|
||||
}
|
||||
|
||||
var fractionInMicroseconds: Int64 {
|
||||
return Int64(fraction) / Int64(1<<32 / USEC_PER_SEC)
|
||||
}
|
||||
}
|
||||
|
||||
extension NTPTimevalConvertible {
|
||||
init(timeSince1970 time: timeval) {
|
||||
precondition(time.tv_sec >= 0 && time.tv_usec >= 0, "Time must be positive \(time)")
|
||||
self.init(whole: ValueType(UInt64(time.tv_sec) + UInt64(secondsFrom1900To1970)),
|
||||
fraction: ValueType(UInt64(time.tv_usec) * UInt64(1<<32 / USEC_PER_SEC)))
|
||||
}
|
||||
|
||||
var milliseconds: Int64 {
|
||||
return (Int64(whole) - secondsFrom1900To1970) * Int64(MSEC_PER_SEC) +
|
||||
fractionInMicroseconds / Int64(USEC_PER_MSEC)
|
||||
}
|
||||
}
|
||||
|
||||
extension ntp_time32_t: NTPTimeType {}
|
||||
extension ntp_time64_t: NTPTimevalConvertible {}
|
||||
|
||||
extension TimeInterval {
|
||||
init(milliseconds: Int64) {
|
||||
self = Double(milliseconds) / Double(MSEC_PER_SEC)
|
||||
}
|
||||
|
||||
init(_ timestamp: timeval) {
|
||||
self = Double(timestamp.tv_sec) + Double(timestamp.tv_usec) / Double(USEC_PER_SEC)
|
||||
}
|
||||
}
|
||||
|
||||
protocol ByteRepresentable {
|
||||
init()
|
||||
}
|
||||
|
||||
extension ByteRepresentable {
|
||||
var data: Data {
|
||||
var buffer = self
|
||||
return Data(bytes: &buffer, count: MemoryLayout.size(ofValue: buffer))
|
||||
}
|
||||
}
|
||||
|
||||
extension ntp_packet_t: ByteRepresentable {}
|
||||
extension sockaddr_in: ByteRepresentable {}
|
||||
extension sockaddr_in6: ByteRepresentable {}
|
||||
extension sockaddr_in6: CustomStringConvertible {
|
||||
public var description: String {
|
||||
var buffer = [Int8](repeating: 0, count: Int(INET6_ADDRSTRLEN))
|
||||
var addr = sin6_addr
|
||||
inet_ntop(AF_INET6, &addr, &buffer, socklen_t(INET6_ADDRSTRLEN))
|
||||
|
||||
let host = String(cString: buffer)
|
||||
let port = Int(sin6_port)
|
||||
return "\(host):\(port)"
|
||||
}
|
||||
}
|
||||
|
||||
extension sockaddr_in: CustomStringConvertible {
|
||||
public var description: String {
|
||||
let host = String(cString: inet_ntoa(sin_addr))
|
||||
let port = Int(sin_port)
|
||||
return "\(host):\(port)"
|
||||
}
|
||||
}
|
||||
|
||||
extension HostResolver: CustomStringConvertible {
|
||||
var description: String {
|
||||
return "\(type(of: self))(host: \(host), port: \(port) timeout: \(timeout))"
|
||||
}
|
||||
}
|
||||
|
||||
extension NTPConnection: CustomStringConvertible {
|
||||
var description: String {
|
||||
return "\(type(of: self))(socketAddress: \(address), " +
|
||||
"timeout: \(timeout), " +
|
||||
"maxRetries: \(maxRetries))"
|
||||
}
|
||||
}
|
||||
|
||||
extension FrozenNetworkTime: CustomStringConvertible {
|
||||
var description: String {
|
||||
return "\(type(of: self))(time: \(time), " +
|
||||
"uptime: \(uptime.milliseconds) ms, " +
|
||||
"serverResponse: \(serverResponse), " +
|
||||
"startTime: \(startTime.milliseconds) ms, " +
|
||||
"sampleSize: \((sampleSize ?? 0)), " +
|
||||
"host: \(host ?? "nil"))"
|
||||
}
|
||||
}
|
||||
|
||||
extension NTPResponse: CustomStringConvertible {
|
||||
var description: String {
|
||||
return "\(type(of: self))(packet: \(packet.description), " +
|
||||
"responseTime: \(responseTime) ms, " +
|
||||
"receiveTime: \(receiveTime.milliseconds) ms)"
|
||||
}
|
||||
}
|
||||
|
||||
extension ntp_packet_t: CustomStringConvertible {
|
||||
public var description: String {
|
||||
let referenceTime = reference_time.milliseconds
|
||||
let originateTime = originate_time.milliseconds
|
||||
let receiveTime = receive_time.milliseconds
|
||||
let transmitTime = transmit_time.milliseconds
|
||||
return "\(type(of: self))(client_mode: \(client_mode.description), " +
|
||||
"version_number: \(version_number.description), " +
|
||||
"leap_indicator: \(leap_indicator.description), " +
|
||||
"stratum: \(stratum.description), " +
|
||||
"poll: \(poll.description), " +
|
||||
"precision: \(precision.description), " +
|
||||
"root_delay: \(root_delay), " +
|
||||
"root_dispersion: \(root_dispersion), " +
|
||||
"reference_id: \(reference_id), " +
|
||||
"reference_time: \(referenceTime) ms, " +
|
||||
"originate_time: \(originateTime) ms, " +
|
||||
"receive_time: \(receiveTime) ms, " +
|
||||
"transmit_time: \(transmitTime) ms)"
|
||||
}
|
||||
}
|
||||
|
||||
extension ntp_packet_t {
|
||||
var timeDescription: String {
|
||||
return "\(type(of: self))(reference_time: + \(reference_time.milliseconds) ms, " +
|
||||
"originate_time: \(originate_time.milliseconds) ms, " +
|
||||
"receive_time: \(receive_time.milliseconds) ms, " +
|
||||
"transmit_time: \(transmit_time.milliseconds) ms)"
|
||||
}
|
||||
}
|
||||
|
||||
extension String {
|
||||
var localized: String {
|
||||
return Bundle.main.localizedString(forKey: self, value: "", table: "TrueTime")
|
||||
}
|
||||
}
|
||||
|
||||
extension TrueTimeError: CustomStringConvertible {
|
||||
public var description: String {
|
||||
switch self {
|
||||
case .cannotFindHost: return "The connection failed because the host could not be found.".localized
|
||||
case .dnsLookupFailed: return "The connection failed because the DNS lookup failed.".localized
|
||||
case .timedOut: return "The connection timed out.".localized
|
||||
case .offline: return "The connection failed because the device is not connected to the internet.".localized
|
||||
case .badServerResponse: return "The connection received an invalid server response.".localized
|
||||
case .noValidPacket: return "No valid NTP packet was found.".localized
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension NSError {
|
||||
convenience init(errno code: Int32) {
|
||||
var userInfo: [String: AnyObject]?
|
||||
if let description = String(validatingUTF8: strerror(code)) {
|
||||
userInfo = [NSLocalizedDescriptionKey: description as AnyObject]
|
||||
}
|
||||
self.init(domain: NSPOSIXErrorDomain, code: Int(code), userInfo: userInfo)
|
||||
}
|
||||
|
||||
convenience init(trueTimeError: TrueTimeError) {
|
||||
self.init(domain: TrueTimeErrorDomain, code: trueTimeError.rawValue, userInfo: [
|
||||
NSLocalizedDescriptionKey: trueTimeError.description
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
func withErrno<X: SignedInteger>(_ block: () -> X) throws -> X {
|
||||
let result = block()
|
||||
if result < 0 {
|
||||
throw NSError(errno: errno)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Equivalent to `withErrno` but asserts at runtime.
|
||||
// Useful when `errno` can only be used to indicate programmer error.
|
||||
@discardableResult
|
||||
func withFatalErrno<X: SignedInteger>(_ block: () -> X) -> X {
|
||||
// swiftlint:disable force_try
|
||||
return try! withErrno(block)
|
||||
// swiftlint:enable force_try
|
||||
}
|
||||
|
||||
// Number of seconds between Jan 1, 1900 and Jan 1, 1970
|
||||
// 70 years plus 17 leap days
|
||||
private let secondsFrom1900To1970: Int64 = ((365 * 70) + 17) * 24 * 60 * 60
|
||||
|
||||
// swiftlint:disable identifier_name
|
||||
let MSEC_PER_SEC: UInt64 = 1000
|
||||
let USEC_PER_MSEC: UInt64 = 1000
|
||||
// swiftlint:enable identifier_name
|
Reference in New Issue
Block a user