Skip to content

Instantly share code, notes, and snippets.

@agentk
Created August 2, 2016 14:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save agentk/99fd9a3732aac169b17ae390d411ddb7 to your computer and use it in GitHub Desktop.
Save agentk/99fd9a3732aac169b17ae390d411ddb7 to your computer and use it in GitHub Desktop.
import Foundation
enum HostResult {
case success([String])
case failure(String)
var description: String {
switch self {
case let .success(addresses): return "\(addresses)"
case let .failure(error): return "\(error)"
}
}
}
// https://developer.apple.com/library/mac/documentation/CoreFoundation/Reference/CFStreamConstants/index.html#//apple_ref/doc/constant_group/CFStream_Error_Domain_Constants_CFHost_
extension CFStreamError {
var description: String {
switch (domain, error) {
case (CFIndex(kCFStreamErrorDomainNetDB), EAI_NONAME):
return "NetDB error: hostname nor servname provided, or not known"
default:
return "error \(error) domain \(domain)"
}
}
}
func stringForIPAddress(address: NSData) -> String? {
var hostBuf = Array<Int8>(repeating: 0, count: Int(NI_MAXHOST))
if getnameinfo(
UnsafePointer<sockaddr>(address.bytes), socklen_t(address.length),
&hostBuf, socklen_t(hostBuf.count),
nil, 0,
NI_NUMERICHOST | NI_NUMERICSERV) != 0 {
return nil
}
return String(cString: hostBuf)
}
func lookupAddresses(name: String) -> HostResult {
let host = CFHostCreateWithName(kCFAllocatorDefault, name).takeRetainedValue()
var error = CFStreamError()
let didStart = CFHostStartInfoResolution(host, .addresses, &error)
if error.error != 0 {
return .failure("😡 \(error.description)")
}
if !didStart {
return .failure("❌ Failed to start info resolution")
}
var resolved = DarwinBoolean(false)
guard let dataArray = (CFHostGetAddressing(host, &resolved)?.takeUnretainedValue() as [AnyObject]?) as? [NSData] else {
return .failure("💣 Error getting addresses")
}
return .success(dataArray.flatMap { stringForIPAddress(address: $0) })
}
// ---------------------------------------
lookupAddresses(name: "localhost") // -> ["::1", "127.0.0.1"]
lookupAddresses(name: "google.com") // -> ["216.58.220.142"]
lookupAddresses(name: "facebook.com") // -> ["69.171.230.68"]
lookupAddresses(name: "v6.google.com") // -> "😡 NetDB error: hostname nor servname provided, or not known"
lookupAddresses(name: "v6.vvv.facebook.com") // -> "😡 NetDB error: hostname nor servname provided, or not known"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment