Files
swift-mirror/stdlib/public/Darwin/Network/NWParameters.swift
Mike Ash fa5888fb3f [Stdlib][Overlays] Rename various classes to avoid conflicting ObjC names.
Old Swift and new Swift runtimes and overlays need to coexist in the same process. This means there must not be any classes which have the same ObjC runtime name in old and new, because the ObjC runtime doesn't like name collisions.

When possible without breaking source compatibility, classes were renamed in Swift, which results in a different ObjC name.

Public classes were renamed only on the ObjC side using the @_objcRuntimeName attribute.

This is similar to the work done in pull request #19295. That only renamed @objc classes. This renames all of the others, since even pure Swift classes still get an ObjC name.

rdar://problem/46646438
2019-01-15 12:21:20 -05:00

506 lines
17 KiB
Swift

//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2018 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
/// An NWParameters object contains the parameters necessary to create
/// a network connection or listener. NWParameters include any preferences for
/// network paths (such as required, prohibited, and preferred networks, and local
/// endpoint requirements); preferences for data transfer and quality of service;
/// and the protocols to be used for a connection along with any protocol-specific
/// options.
// NOTE: older overlays had Network.NWParameters as the ObjC name.
// The two must coexist, so it was renamed. The old name must not be
// used in the new runtime. _TtC7Network13_NWParameters is the
// mangled name for Network._NWParameters.
@_objcRuntimeName(_TtC7Network13_NWParameters)
@available(macOS 10.14, iOS 12.0, watchOS 5.0, tvOS 12.0, *)
public final class NWParameters : CustomDebugStringConvertible {
public var debugDescription: String {
return String("\(self.nw)")
}
internal let nw : nw_parameters_t
/// Creates a parameters object that is configured for TLS and TCP. The caller can use
/// the default configuration for TLS and TCP, or set specific options for each protocol,
/// or disable TLS.
///
/// - Parameter tls: TLS options or nil for no TLS
/// - Parameter tcp: TCP options. Defaults to NWProtocolTCP.Options() with no options overridden.
/// - Returns: NWParameters object that can be used for creating a connection or listener
public convenience init(tls: NWProtocolTLS.Options?, tcp: NWProtocolTCP.Options = NWProtocolTCP.Options()) {
self.init()
let protocolStack = self.defaultProtocolStack
protocolStack.transportProtocol = tcp
if let tls = tls {
protocolStack.applicationProtocols = [tls]
} else {
protocolStack.applicationProtocols = []
}
}
/// Creates a parameters object that is configured for DTLS and UDP. The caller can use
/// the default configuration for DTLS and UDP, or set specific options for each protocol,
/// or disable TLS.
///
/// - Parameter dtls: DTLS options or nil for no DTLS
/// - Parameter udp: UDP options. Defaults to NWProtocolUDP.Options() with no options overridden.
/// - Returns: NWParameters object that can be used for create a connection or listener
public convenience init(dtls: NWProtocolTLS.Options?, udp: NWProtocolUDP.Options = NWProtocolUDP.Options()) {
self.init()
let protocolStack = self.defaultProtocolStack
protocolStack.transportProtocol = udp
if let dtls = dtls {
protocolStack.applicationProtocols = [dtls]
} else {
protocolStack.applicationProtocols = []
}
}
/// Creates a generic NWParameters object. Note that in order to use parameters
/// with a NWConnection or a NetworkListener, the parameters must have protocols
/// added into the defaultProtocolStack. Clients using standard protocol
/// configurations should use init(tls:tcp:) or init(dtls:udp:).
public init() {
self.nw = nw_parameters_create()
}
private init(nw: nw_parameters_t) {
self.nw = nw
}
/// Default set of parameters for TLS over TCP
/// This is equivalent to calling init(tls:NWProtocolTLS.Options(), tcp:NWProtocolTCP.Options())
public class var tls: NWParameters {
return NWParameters(tls:NWProtocolTLS.Options())
}
/// Default set of parameters for DTLS over UDP
/// This is equivalent to calling init(dtls:NWProtocolTLS.Options(), udp:NWProtocolUDP.Options())
public class var dtls: NWParameters {
return NWParameters(dtls:NWProtocolTLS.Options())
}
/// Default set of parameters for TCP
/// This is equivalent to calling init(tls:nil, tcp:NWProtocolTCP.Options())
public class var tcp: NWParameters {
return NWParameters(tls:nil)
}
/// Default set of parameters for UDP
/// This is equivalent to calling init(dtls:nil, udp:NWProtocolUDP.Options())
public class var udp: NWParameters {
return NWParameters(dtls:nil)
}
/// Require a connection to use a specific interface, or fail if not available
public var requiredInterface: NWInterface? {
set {
if let interface = newValue {
nw_parameters_require_interface(self.nw, interface.nw)
} else {
nw_parameters_require_interface(self.nw, nil)
}
}
get {
if let interface = nw_parameters_copy_required_interface(self.nw) {
return NWInterface(interface)
} else {
return nil
}
}
}
/// Require a connection to use a specific interface type, or fail if not available
public var requiredInterfaceType: NWInterface.InterfaceType {
set {
nw_parameters_set_required_interface_type(self.nw, newValue.nw)
}
get {
return NWInterface.InterfaceType(nw_parameters_get_required_interface_type(self.nw))
}
}
/// Define one or more interfaces that a connection will not be allowed to use
public var prohibitedInterfaces: [NWInterface]? {
set {
nw_parameters_clear_prohibited_interfaces(self.nw)
if let prohibitedInterfaces = newValue {
for prohibitedInterface in prohibitedInterfaces {
nw_parameters_prohibit_interface(self.nw, prohibitedInterface.nw)
}
}
}
get {
var interfaces = [NWInterface]()
nw_parameters_iterate_prohibited_interfaces(self.nw) { (interface) in
interfaces.append(NWInterface(interface))
return true
}
return interfaces
}
}
/// Define one or more interface types that a connection will not be allowed to use
public var prohibitedInterfaceTypes: [NWInterface.InterfaceType]? {
set {
nw_parameters_clear_prohibited_interface_types(self.nw)
if let prohibitedInterfaceTypes = newValue {
for prohibitedInterfaceType in prohibitedInterfaceTypes {
nw_parameters_prohibit_interface_type(self.nw, prohibitedInterfaceType.nw)
}
}
}
get {
var interfaceTypes = [NWInterface.InterfaceType]()
nw_parameters_iterate_prohibited_interface_types(self.nw) { (interfaceType) in
interfaceTypes.append(NWInterface.InterfaceType(interfaceType))
return true
}
return interfaceTypes
}
}
/// Disallow connection from using interfaces considered expensive
public var prohibitExpensivePaths: Bool {
set {
nw_parameters_set_prohibit_expensive(self.nw, newValue)
}
get {
return nw_parameters_get_prohibit_expensive(self.nw)
}
}
/// If true, a direct connection will be attempted first even if proxies are configured. If the direct connection
/// fails, connecting through the proxies will still be attempted.
public var preferNoProxies: Bool {
set {
nw_parameters_set_prefer_no_proxy(self.nw, newValue)
}
get {
return nw_parameters_get_prefer_no_proxy(self.nw)
}
}
/// Force a specific local address to be used. This value is nil by
/// default, in which case the system selects the most appropriate
/// local address and selects a local port.
public var requiredLocalEndpoint: NWEndpoint? {
set {
if let endpoint = newValue {
nw_parameters_set_local_endpoint(self.nw, endpoint.nw)
} else {
nw_parameters_set_local_endpoint(self.nw, nil)
}
}
get {
if let endpoint = nw_parameters_copy_local_endpoint(self.nw) {
return NWEndpoint(endpoint)
} else {
return nil
}
}
}
/// Allow multiple connections to use the same local address and port
/// (SO_REUSEADDR and SO_REUSEPORT).
public var allowLocalEndpointReuse: Bool {
set {
nw_parameters_set_reuse_local_address(self.nw, newValue)
}
get {
return nw_parameters_get_reuse_local_address(self.nw)
}
}
/// Cause an NWListener to only advertise services on the local link,
/// and only accept connections from the local link.
public var acceptLocalOnly: Bool {
set {
nw_parameters_set_local_only(self.nw, newValue)
}
get {
return nw_parameters_get_local_only(self.nw)
}
}
/// Allow the inclusion of peer-to-peer interfaces when
/// listening or establishing outbound connections. This parameter
/// will not take effect if a specific interface is required.
/// This parameter is applicable when advertising a Bonjour service
/// on a listener, or connecting to a Bonjour service.
public var includePeerToPeer: Bool {
set {
nw_parameters_set_include_peer_to_peer(self.nw, newValue)
}
get {
return nw_parameters_get_include_peer_to_peer(self.nw)
}
}
/// The ServiceClass represents the network queuing priority to use
/// for traffic generated by a NWConnection.
public enum ServiceClass {
/// Default priority traffic
case bestEffort
/// Bulk traffic, or traffic that can be de-prioritized behind foreground traffic
case background
/// Interactive video traffic
case interactiveVideo
/// Interactive voice traffic
case interactiveVoice
/// Responsive data
case responsiveData
/// Signaling
case signaling
internal var nw: nw_service_class_t {
switch self {
case .bestEffort:
return Network.nw_service_class_best_effort
case .background:
return Network.nw_service_class_background
case .interactiveVideo:
return Network.nw_service_class_interactive_video
case .interactiveVoice:
return Network.nw_service_class_interactive_voice
case .responsiveData:
return Network.nw_service_class_responsive_data
case .signaling:
return Network.nw_service_class_signaling
}
}
internal init(_ nw: nw_service_class_t) {
switch nw {
case Network.nw_service_class_best_effort:
self = .bestEffort
case Network.nw_service_class_background:
self = .background
case Network.nw_service_class_interactive_video:
self = .interactiveVideo
case Network.nw_service_class_interactive_voice:
self = .interactiveVoice
case Network.nw_service_class_responsive_data:
self = .responsiveData
case Network.nw_service_class_signaling:
self = .signaling
default:
self = .bestEffort
}
}
}
public var serviceClass: NWParameters.ServiceClass {
set {
nw_parameters_set_service_class(self.nw, newValue.nw)
}
get {
return NWParameters.ServiceClass(nw_parameters_get_service_class(self.nw))
}
}
/// Multipath services represent the modes of multipath usage that are
/// allowed for connections.
public enum MultipathServiceType {
/// No multipath transport will be attempted
case disabled
/// Only use the expensive interface when the when the primary one is not available
case handover
/// Use the expensive interface more aggressively to reduce latency
case interactive
/// Use all available interfaces to provide the highest throughput and lowest latency
case aggregate
internal var nw: nw_multipath_service_t {
switch self {
case .disabled:
return Network.nw_multipath_service_disabled
case .handover:
return Network.nw_multipath_service_handover
case .interactive:
return Network.nw_multipath_service_interactive
case .aggregate:
return Network.nw_multipath_service_aggregate
}
}
internal init(_ nw: nw_multipath_service_t) {
switch nw {
case Network.nw_multipath_service_disabled:
self = .disabled
case Network.nw_multipath_service_handover:
self = .handover
case Network.nw_multipath_service_interactive:
self = .interactive
case Network.nw_multipath_service_aggregate:
self = .aggregate
default:
self = .disabled
}
}
}
public var multipathServiceType: NWParameters.MultipathServiceType {
set {
nw_parameters_set_multipath_service(self.nw, newValue.nw)
}
get {
return NWParameters.MultipathServiceType(nw_parameters_get_multipath_service(self.nw))
}
}
/// Use fast open for an outbound NWConnection, which may be done at any
/// protocol level. Use of fast open requires that the caller send
/// idempotent data on the connection before the connection may move
/// into ready state. As a side effect, this may implicitly enable
/// fast open for protocols in the stack, even if they did not have
/// fast open explicitly enabled on them (such as the option to enable
/// TCP Fast Open).
public var allowFastOpen: Bool {
set {
nw_parameters_set_fast_open_enabled(self.nw, newValue)
}
get {
return nw_parameters_get_fast_open_enabled(self.nw)
}
}
/// Allow or prohibit the use of expired DNS answers during connection establishment.
/// If allowed, a DNS answer that was previously returned may be re-used for new
/// connections even after the answers are considered expired. A query for fresh answers
/// will be sent in parallel, and the fresh answers will be used as alternate addresses
/// in case the expired answers do not result in successful connections.
/// By default, this value is .systemDefault, which allows the system to determine
/// if it is appropriate to use expired answers.
public enum ExpiredDNSBehavior {
/// Let the system determine whether or not to allow expired DNS answers
case systemDefault
/// Explicitly allow the use of expired DNS answers
case allow
/// Explicitly prohibit the use of expired DNS answers
case prohibit
internal var nw: nw_parameters_expired_dns_behavior_t {
switch self {
case .systemDefault:
return Network.nw_parameters_expired_dns_behavior_default
case .allow:
return Network.nw_parameters_expired_dns_behavior_allow
case .prohibit:
return Network.nw_parameters_expired_dns_behavior_prohibit
}
}
internal init(_ nw: nw_parameters_expired_dns_behavior_t) {
switch nw {
case Network.nw_parameters_expired_dns_behavior_default:
self = .systemDefault
case Network.nw_parameters_expired_dns_behavior_allow:
self = .allow
case Network.nw_parameters_expired_dns_behavior_prohibit:
self = .prohibit
default:
self = .systemDefault
}
}
}
public var expiredDNSBehavior: NWParameters.ExpiredDNSBehavior {
set {
nw_parameters_set_expired_dns_behavior(self.nw, newValue.nw)
}
get {
return NWParameters.ExpiredDNSBehavior(nw_parameters_get_expired_dns_behavior(self.nw))
}
}
/// A ProtocolStack contains a list of protocols to use for a connection.
/// The members of the protocol stack are NWProtocolOptions objects, each
/// defining which protocol to use within the stack along with any protocol-specific
/// options. Each stack includes an array of application-level protocols, a single
/// transport-level protocol, and an optional internet-level protocol. If the internet-
/// level protocol is not specified, any available and applicable IP address family
/// may be used.
// Set the ObjC name of this class to be nested in the customized ObjC
// name of NWParameters.
@_objcRuntimeName(_TtCC7Network13_NWParameters13ProtocolStack)
public class ProtocolStack {
public var applicationProtocols: [NWProtocolOptions] {
set {
nw_protocol_stack_clear_application_protocols(self.nw)
for applicationProtocol in newValue.reversed() {
nw_protocol_stack_prepend_application_protocol(self.nw, applicationProtocol.nw)
}
}
get {
var applicationProtocols = [NWProtocolOptions]()
nw_protocol_stack_iterate_application_protocols(self.nw) { (protocolOptions) in
let applicationDefinition = nw_protocol_options_copy_definition(protocolOptions)
if (nw_protocol_definition_is_equal(applicationDefinition, NWProtocolTLS.definition.nw)) {
applicationProtocols.append(NWProtocolTLS.Options(protocolOptions))
}
}
return applicationProtocols
}
}
public var transportProtocol: NWProtocolOptions? {
set {
if let transport = newValue {
nw_protocol_stack_set_transport_protocol(self.nw, transport.nw)
}
}
get {
if let transport = nw_protocol_stack_copy_transport_protocol(nw) {
let transportDefinition = nw_protocol_options_copy_definition(transport)
if (nw_protocol_definition_is_equal(transportDefinition, NWProtocolTCP.definition.nw)) {
return NWProtocolTCP.Options(transport)
} else if (nw_protocol_definition_is_equal(transportDefinition, NWProtocolUDP.definition.nw)) {
return NWProtocolUDP.Options(transport)
}
}
return nil
}
}
public var internetProtocol: NWProtocolOptions? {
set {
// Not currently allowed
return
}
get {
if let ip = nw_protocol_stack_copy_internet_protocol(nw) {
if (nw_protocol_definition_is_equal(nw_protocol_options_copy_definition(ip), NWProtocolIP.definition.nw)) {
return NWProtocolIP.Options(ip)
}
}
return nil
}
}
internal let nw: nw_protocol_stack_t
internal init(_ nw: nw_protocol_stack_t) {
self.nw = nw
}
}
/// Every NWParameters has a default protocol stack, although it may start out empty.
public var defaultProtocolStack: NWParameters.ProtocolStack {
get {
return NWParameters.ProtocolStack(nw_parameters_copy_default_protocol_stack(self.nw))
}
}
/// Perform a deep copy of parameters
public func copy() -> NWParameters {
return NWParameters(nw: nw_parameters_copy(self.nw))
}
}