124 lines
4.7 KiB
Swift
124 lines
4.7 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the SwiftNIO open source project
|
|
//
|
|
// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors
|
|
// Licensed under Apache License v2.0
|
|
//
|
|
// See LICENSE.txt for license information
|
|
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
|
|
// swift-tools-version:4.0
|
|
//
|
|
// swift-tools-version:4.0
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
import Darwin
|
|
import Foundation
|
|
import NIO
|
|
import Network
|
|
|
|
extension IPv4Address {
|
|
/// Create an `IPv4Address` object from a `sockaddr_in`.
|
|
internal init(fromSockAddr sockAddr: sockaddr_in) {
|
|
var localAddr = sockAddr
|
|
self = withUnsafeBytes(of: &localAddr.sin_addr) {
|
|
precondition($0.count == 4)
|
|
let addrData = Data(bytes: $0.baseAddress!, count: $0.count)
|
|
return IPv4Address(addrData)!
|
|
}
|
|
}
|
|
}
|
|
|
|
extension IPv6Address {
|
|
internal init(fromSockAddr sockAddr: sockaddr_in6) {
|
|
var localAddr = sockAddr
|
|
|
|
// TODO: We should check whether we can reliably pull an interface declaration out
|
|
// here to be more useful.
|
|
self = withUnsafeBytes(of: &localAddr.sin6_addr) {
|
|
precondition($0.count == 16)
|
|
let addrData = Data(bytes: $0.baseAddress!, count: $0.count)
|
|
return IPv6Address(addrData)!
|
|
}
|
|
}
|
|
}
|
|
|
|
extension NWEndpoint {
|
|
/// Create an `NWEndpoint` value from a NIO `SocketAddress`.
|
|
internal init(fromSocketAddress socketAddress: SocketAddress) {
|
|
switch socketAddress {
|
|
case .unixDomainSocket(let uds):
|
|
var address = uds.address
|
|
let path: String = withUnsafeBytes(of: &address.sun_path) { ptr in
|
|
let ptr = ptr.baseAddress!.bindMemory(to: UInt8.self, capacity: 104)
|
|
return String(cString: ptr)
|
|
}
|
|
self = NWEndpoint.unix(path: path)
|
|
case .v4(let v4Addr):
|
|
let v4Address = IPv4Address(fromSockAddr: v4Addr.address)
|
|
let port = NWEndpoint.Port(rawValue: UInt16(socketAddress.port!))!
|
|
self = NWEndpoint.hostPort(host: .ipv4(v4Address), port: port)
|
|
case .v6(let v6Addr):
|
|
let v6Address = IPv6Address(fromSockAddr: v6Addr.address)
|
|
let port = NWEndpoint.Port(rawValue: UInt16(socketAddress.port!))!
|
|
self = NWEndpoint.hostPort(host: .ipv6(v6Address), port: port)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TODO: We'll want to get rid of this when we support returning NWEndpoint directly from
|
|
// the various address-handling functions.
|
|
extension SocketAddress {
|
|
internal init(fromNWEndpoint endpoint: NWEndpoint) throws {
|
|
switch endpoint {
|
|
case .hostPort(.ipv4(let host), let port):
|
|
var addr = sockaddr_in()
|
|
addr.sin_family = sa_family_t(AF_INET)
|
|
addr.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
|
|
addr.sin_port = port.rawValue.bigEndian
|
|
host.rawValue.withUnsafeBytes {
|
|
precondition($0.count == 4)
|
|
memcpy(&addr.sin_addr, $0.baseAddress!, 4)
|
|
}
|
|
self = .init(addr, host: host.debugDescription)
|
|
case .hostPort(.ipv6(let host), let port):
|
|
var addr = sockaddr_in6()
|
|
addr.sin6_family = sa_family_t(AF_INET6)
|
|
addr.sin6_port = port.rawValue.bigEndian
|
|
addr.sin6_len = UInt8(MemoryLayout<sockaddr_in6>.size)
|
|
host.rawValue.withUnsafeBytes {
|
|
precondition($0.count == 16)
|
|
memcpy(&addr.sin6_addr, $0.baseAddress!, 16)
|
|
}
|
|
self = .init(addr, host: host.debugDescription)
|
|
case .unix(let path):
|
|
self = try .init(unixDomainSocketPath: path)
|
|
case .service:
|
|
preconditionFailure("Cannot represent service addresses in SocketAddress")
|
|
case .hostPort(_, _):
|
|
preconditionFailure("Cannot represent unknown host in SocketAddress")
|
|
@unknown default:
|
|
preconditionFailure("cannot create SocketAddress from unknown representation")
|
|
}
|
|
}
|
|
}
|
|
|
|
internal extension SocketAddress {
|
|
/// Change the port on this `SocketAddress` to a new value.
|
|
mutating func newPort(_ port: UInt16) {
|
|
switch self {
|
|
case .v4(let addr):
|
|
var address = addr.address
|
|
address.sin_port = port.bigEndian
|
|
self = SocketAddress(address, host: addr.host)
|
|
case .v6(let addr):
|
|
var address = addr.address
|
|
address.sin6_port = port.bigEndian
|
|
self = SocketAddress(address, host: addr.host)
|
|
case .unixDomainSocket:
|
|
preconditionFailure("Cannot set new port on UDS")
|
|
}
|
|
}
|
|
}
|