Skip to content

Commit

Permalink
Merge pull request #9 from lyft/swift-3.0
Browse files Browse the repository at this point in the history
update to Swift 3.0
  • Loading branch information
dduan authored Oct 10, 2016
2 parents 6c2be21 + d90d6c9 commit 6575f91
Show file tree
Hide file tree
Showing 17 changed files with 228 additions and 218 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
All notable changes to this project will be documented in this file.
`Kronos` adheres to [Semantic Versioning](http://semver.org/).

## [0.2.0](https://github.com/lyft/Kronos/releases/tag/0.2.0)
- Added Swift 3 support

## [0.1.1](https://github.com/lyft/Kronos/releases/tag/0.1.1)
- Added IPv6 support

Expand Down
2 changes: 1 addition & 1 deletion Kronos.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'Kronos'
s.version = '0.1.2'
s.version = '0.2.0'
s.license = { :type => 'Apache License, Version 2.0', :file => 'LICENSE' }
s.summary = 'Elegant NTP client in Swift'
s.homepage = 'https://github.com/lyft/Kronos'
Expand Down
12 changes: 6 additions & 6 deletions Kronos.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -187,11 +187,11 @@
TargetAttributes = {
C20174821BD5509D00E4FE18 = {
CreatedOnToolsVersion = 7.0;
LastSwiftMigration = 0800;
LastSwiftMigration = 0810;
};
C201748C1BD5509D00E4FE18 = {
CreatedOnToolsVersion = 7.0;
LastSwiftMigration = 0800;
LastSwiftMigration = 0810;
};
};
};
Expand Down Expand Up @@ -356,7 +356,7 @@
PRODUCT_NAME = Kronos;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 2.3;
SWIFT_VERSION = 3.0;
TVOS_DEPLOYMENT_TARGET = 9.0;
};
name = Debug;
Expand All @@ -379,7 +379,7 @@
PRODUCT_BUNDLE_IDENTIFIER = com.Lyft.Kronos;
PRODUCT_NAME = Kronos;
SKIP_INSTALL = YES;
SWIFT_VERSION = 2.3;
SWIFT_VERSION = 3.0;
TVOS_DEPLOYMENT_TARGET = 9.0;
};
name = Release;
Expand All @@ -394,7 +394,7 @@
PRODUCT_BUNDLE_IDENTIFIER = com.Lyft.KronosTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 2.3;
SWIFT_VERSION = 3.0;
};
name = Debug;
};
Expand All @@ -407,7 +407,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.Lyft.KronosTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 2.3;
SWIFT_VERSION = 3.0;
};
name = Release;
};
Expand Down
2 changes: 1 addition & 1 deletion Resources/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0.1</string>
<string>0.2.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
Expand Down
16 changes: 8 additions & 8 deletions Sources/Clock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ public struct Clock {
private static var stableTime: TimeFreeze?

/// The most accurate timestamp that we have so far (nil if no synchronization was done yet)
public static var timestamp: NSTimeInterval? {
public static var timestamp: TimeInterval? {
return self.stableTime?.adjustedTimestamp
}

/// The most accurate date that we have so far (nil if no synchronization was done yet)
public static var now: NSDate? {
return self.timestamp.map { NSDate(timeIntervalSince1970: $0) }
public static var now: Date? {
return self.timestamp.map { Date(timeIntervalSince1970: $0) }
}

/// Syncs the clock using NTP. Note that the full synchronization could take a few seconds. The given
Expand All @@ -39,22 +39,22 @@ public struct Clock {
/// - parameter completion: A closure that will be called after _all_ the NTP calls are finished.
/// - parameter first: A closure that will be called after the first valid date is calculated.
public static func sync(from pool: String = "time.apple.com", samples: Int = 4,
first: ((date: NSDate, offset: NSTimeInterval) -> Void)? = nil,
completion: ((date: NSDate?, offset: NSTimeInterval?) -> Void)? = nil)
first: ((Date, TimeInterval) -> Void)? = nil,
completion: ((Date?, TimeInterval?) -> Void)? = nil)
{
self.reset()

NTPClient().queryPool(pool, numberOfSamples: samples) { offset, done, total in
NTPClient().query(pool: pool, numberOfSamples: samples) { offset, done, total in
if let offset = offset {
self.stableTime = TimeFreeze(offset: offset)

if done == 1, let now = self.now {
first?(date: now, offset: offset)
first?(now, offset)
}
}

if done == total {
completion?(date: self.now, offset: offset)
completion?(self.now, offset)
}
}
}
Expand Down
40 changes: 22 additions & 18 deletions Sources/DNSResolver.swift
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import Foundation

private let kCopyNoOperation = unsafeBitCast(0, CFAllocatorCopyDescriptionCallBack.self)
private let kCopyNoOperation = unsafeBitCast(0, to: CFAllocatorCopyDescriptionCallBack.self)
private let kDefaultTimeout = 8.0

final class DNSResolver {
private var completion: ([InternetAddress] -> Void)?
private var timer: NSTimer?
private var completion: (([InternetAddress]) -> Void)?
private var timer: Timer?

private init() {}

Expand All @@ -16,17 +16,20 @@ final class DNSResolver {
/// - parameter timeout: The connection timeout.
/// - parameter completion: A completion block that will be called both on failure and success with a list
/// of IPs.
static func resolve(host host: String, timeout: NSTimeInterval = kDefaultTimeout,
completion: [InternetAddress] -> Void)
static func resolve(host: String, timeout: TimeInterval = kDefaultTimeout,
completion: @escaping ([InternetAddress]) -> Void)
{
let callback: CFHostClientCallBack = { host, hostinfo, error, info in
let retainedSelf = Unmanaged<DNSResolver>.fromOpaque(COpaquePointer(info))
guard let info = info else {
return
}
let retainedSelf = Unmanaged<DNSResolver>.fromOpaque(info)
let resolver = retainedSelf.takeUnretainedValue()
resolver.timer?.invalidate()
resolver.timer = nil

var resolved: DarwinBoolean = false
guard let addresses = CFHostGetAddressing(host, &resolved) where resolved else {
guard let addresses = CFHostGetAddressing(host, &resolved), resolved.boolValue else {
resolver.completion?([])
retainedSelf.release()
return
Expand All @@ -35,7 +38,8 @@ final class DNSResolver {
let IPs = (addresses.takeUnretainedValue() as NSArray)
.flatMap { $0 as? NSData }
.flatMap { data -> InternetAddress? in
let socketAddress = UnsafePointer<sockaddr_storage>(data.bytes)
let socketAddress = data.bytes.bindMemory(to: sockaddr_storage.self,
capacity: data.length)
return InternetAddress(storage: socketAddress)
}

Expand All @@ -47,17 +51,17 @@ final class DNSResolver {
resolver.completion = completion

let retainedClosure = Unmanaged.passRetained(resolver).toOpaque()
var clientContext = CFHostClientContext(version: 0, info: UnsafeMutablePointer<Void>(retainedClosure),
var clientContext = CFHostClientContext(version: 0, info: UnsafeMutableRawPointer(retainedClosure),
retain: nil, release: nil, copyDescription: kCopyNoOperation)

let hostReference = CFHostCreateWithName(kCFAllocatorDefault, host).takeUnretainedValue()
let hostReference = CFHostCreateWithName(kCFAllocatorDefault, host as CFString).takeUnretainedValue()
CFHostSetClient(hostReference, callback, &clientContext)
CFHostScheduleWithRunLoop(hostReference, CFRunLoopGetCurrent(), kCFRunLoopCommonModes)
CFHostStartInfoResolution(hostReference, .Addresses, nil)
CFHostScheduleWithRunLoop(hostReference, CFRunLoopGetCurrent(), CFRunLoopMode.commonModes.rawValue)
CFHostStartInfoResolution(hostReference, .addresses, nil)

resolver.timer = NSTimer.scheduledTimerWithTimeInterval(timeout, target: resolver,
selector: #selector(DNSResolver.onTimeout),
userInfo: hostReference, repeats: false)
resolver.timer = Timer.scheduledTimer(timeInterval: timeout, target: resolver,
selector: #selector(DNSResolver.onTimeout),
userInfo: hostReference, repeats: false)
}

@objc
Expand All @@ -73,9 +77,9 @@ final class DNSResolver {
return
}

let hostReference = unsafeBitCast(userInfo, CFHost.self)
CFHostCancelInfoResolution(hostReference, .Addresses)
CFHostUnscheduleFromRunLoop(hostReference, CFRunLoopGetCurrent(), kCFRunLoopCommonModes)
let hostReference = unsafeBitCast(userInfo, to: CFHost.self)
CFHostCancelInfoResolution(hostReference, .addresses)
CFHostUnscheduleFromRunLoop(hostReference, CFRunLoopGetCurrent(), CFRunLoopMode.commonModes.rawValue)
CFHostSetClient(hostReference, nil, nil)
}
}
48 changes: 21 additions & 27 deletions Sources/InternetAddress.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,31 @@ import Foundation
/// - IPv6: An Internet Address of type IPv6 (e.g.: '::1').
/// - IPv4: An Internet Address of type IPv4 (e.g.: '127.0.0.1').
enum InternetAddress: Hashable {
case IPv6(sockaddr_in6)
case IPv4(sockaddr_in)
case ipv6(sockaddr_in6)
case ipv4(sockaddr_in)

/// Human readable host represetnation (e.g. '192.168.1.1' or 'ab:ab:ab:ab:ab:ab:ab:ab').
var host: String? {
switch self {
case IPv6(var address):
var buffer = [CChar](count: Int(INET6_ADDRSTRLEN), repeatedValue: 0)
case .ipv6(var address):
var buffer = [CChar](repeating: 0, count: Int(INET6_ADDRSTRLEN))
inet_ntop(AF_INET6, &address.sin6_addr, &buffer, socklen_t(INET6_ADDRSTRLEN))
return String.fromCString(buffer)
return String(cString: buffer)

case IPv4(var address):
var buffer = [CChar](count: Int(INET_ADDRSTRLEN), repeatedValue: 0)
case .ipv4(var address):
var buffer = [CChar](repeating: 0, count: Int(INET_ADDRSTRLEN))
inet_ntop(AF_INET, &address.sin_addr, &buffer, socklen_t(INET_ADDRSTRLEN))
return String.fromCString(buffer)
return String(cString: buffer)
}
}

/// The protocol family that should be used on the socket creation for this address.
var family: Int32 {
switch self {
case .IPv4:
case .ipv4:
return PF_INET

case .IPv6:
case .ipv6:
return PF_INET6
}
}
Expand All @@ -39,19 +39,17 @@ enum InternetAddress: Hashable {
}

init?(storage: UnsafePointer<sockaddr_storage>) {
if storage == nil {
return nil
}

switch Int32(storage.memory.ss_family) {
switch Int32(storage.pointee.ss_family) {
case AF_INET:
let address = UnsafeMutablePointer<sockaddr_in>(storage)
self = IPv4(address.memory)
self = storage.withMemoryRebound(to: sockaddr_in.self, capacity: 1) { address in
InternetAddress.ipv4(address.pointee)
}

case AF_INET6:
let address = UnsafeMutablePointer<sockaddr_in6>(storage)
self = IPv6(address.memory)

self = storage.withMemoryRebound(to: sockaddr_in6.self, capacity: 1) { address in
InternetAddress.ipv6(address.pointee)
}
default:
return nil
}
Expand All @@ -64,17 +62,13 @@ enum InternetAddress: Hashable {
/// - returns: An address struct wrapped into a CFData type.
func addressData(withPort port: Int) -> CFData {
switch self {
case IPv6(var address):
case .ipv6(var address):
address.sin6_port = in_port_t(port).bigEndian
return withUnsafePointer(&address) { pointer -> CFData in
CFDataCreate(kCFAllocatorDefault, UnsafePointer<UInt8>(pointer), sizeofValue(address))
}
return NSData(bytes: &address, length: MemoryLayout<sockaddr_in6>.size) as CFData

case IPv4(var address):
case .ipv4(var address):
address.sin_port = in_port_t(port).bigEndian
return withUnsafePointer(&address) { pointer -> CFData in
CFDataCreate(kCFAllocatorDefault, UnsafePointer<UInt8>(pointer), sizeofValue(address))
}
return NSData(bytes: &address, length: MemoryLayout<sockaddr_in>.size) as CFData
}
}
}
Expand Down
14 changes: 7 additions & 7 deletions Sources/NSMutableData+Bytes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ extension NSData {
let hexArray = Array(hex.characters)
var bytes: [UInt8] = []

for index in 0.stride(to: hexArray.count, by: 2) {
for index in stride(from: 0, to: hexArray.count, by: 2) {
guard let byte = UInt8("\(hexArray[index])\(hexArray[index + 1])", radix: 16) else {
return nil
}
Expand All @@ -29,7 +29,7 @@ extension NSData {
/// - parameter index: The index of the byte to be retrieved. Note that this should never be >= length.
///
/// - returns: The byte located at position `index`.
func getByte(atIndex index: Int) -> Int8 {
func getByte(at index: Int) -> Int8 {
var data: Int8 = 0
self.getBytes(&data, range: NSRange(location: index, length: 1))
return data
Expand All @@ -41,7 +41,7 @@ extension NSData {
/// 3.
///
/// - returns: The unsigned int located at position `index`.
func getUnsignedInteger(atIndex index: Int, bigEndian: Bool = true) -> UInt32 {
func getUnsignedInteger(at index: Int, bigEndian: Bool = true) -> UInt32 {
var data: UInt32 = 0
self.getBytes(&data, range: NSRange(location: index, length: 4))
return bigEndian ? data.bigEndian : data.littleEndian
Expand All @@ -53,7 +53,7 @@ extension NSData {
/// 7.
///
/// - returns: The unsigned long integer located at position `index`.
func getUnsignedLong(atIndex index: Int, bigEndian: Bool = true) -> UInt64 {
func getUnsignedLong(at index: Int, bigEndian: Bool = true) -> UInt64 {
var data: UInt64 = 0
self.getBytes(&data, range: NSRange(location: index, length: 8))
return bigEndian ? data.bigEndian : data.littleEndian
Expand All @@ -67,22 +67,22 @@ extension NSMutableData {
/// - parameter data: The byte to be appended.
func append(byte data: Int8) {
var data = data
self.appendBytes(&data, length: 1)
self.append(&data, length: 1)
}

/// Appends the given unsigned integer (32 bits; 4 bytes) into the receiver NSData.
///
/// - parameter data: The unsigned integer to be appended.
func append(unsignedInteger data: UInt32, bigEndian: Bool = true) {
var data = bigEndian ? data.bigEndian : data.littleEndian
self.appendBytes(&data, length: 4)
self.append(&data, length: 4)
}

/// Appends the given unsigned long (64 bits; 8 bytes) into the receiver NSData.
///
/// - parameter data: The unsigned long to be appended.
func append(unsignedLong data: UInt64, bigEndian: Bool = true) {
var data = bigEndian ? data.bigEndian : data.littleEndian
self.appendBytes(&data, length: 8)
self.append(&data, length: 8)
}
}
Loading

0 comments on commit 6575f91

Please sign in to comment.