//===----------------------------------------------------------------------===// // // 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 // //===----------------------------------------------------------------------===// #if canImport(Network) 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.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.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") } } } #endif