diff --git a/TunnelKit/Sources/AppExtension/ConnectionStrategy.swift b/TunnelKit/Sources/AppExtension/ConnectionStrategy.swift index 1b6769e..5c7c31b 100644 --- a/TunnelKit/Sources/AppExtension/ConnectionStrategy.swift +++ b/TunnelKit/Sources/AppExtension/ConnectionStrategy.swift @@ -116,11 +116,11 @@ private extension NEProvider { switch endpointProtocol.socketType { case .udp: let impl = createUDPSession(to: endpoint, from: nil) - return NEUDPInterface(impl: impl) + return NEUDPSocket(impl: impl) case .tcp: let impl = createTCPConnection(to: endpoint, enableTLS: false, tlsParameters: nil, delegate: nil) - return NETCPInterface(impl: impl) + return NETCPSocket(impl: impl) } } } diff --git a/TunnelKit/Sources/AppExtension/GenericSocket.swift b/TunnelKit/Sources/AppExtension/GenericSocket.swift index 58eddb7..5c6a87e 100644 --- a/TunnelKit/Sources/AppExtension/GenericSocket.swift +++ b/TunnelKit/Sources/AppExtension/GenericSocket.swift @@ -9,7 +9,7 @@ import Foundation protocol LinkProducer { - func link() -> LinkInterface + func link(withMTU mtu: Int) -> LinkInterface } protocol GenericSocketDelegate: class { diff --git a/TunnelKit/Sources/AppExtension/Transport/NETCPInterface.swift b/TunnelKit/Sources/AppExtension/Transport/NETCPInterface.swift index 06358ca..95977f9 100644 --- a/TunnelKit/Sources/AppExtension/Transport/NETCPInterface.swift +++ b/TunnelKit/Sources/AppExtension/Transport/NETCPInterface.swift @@ -12,16 +12,13 @@ import SwiftyBeaver private let log = SwiftyBeaver.self -class NETCPInterface: NSObject, GenericSocket, LinkInterface { +class NETCPSocket: NSObject, GenericSocket { private static var linkContext = 0 private let impl: NWTCPConnection - private let maxPacketSize: Int - - init(impl: NWTCPConnection, maxPacketSize: Int? = nil) { + init(impl: NWTCPConnection) { self.impl = impl - self.maxPacketSize = maxPacketSize ?? (512 * 1024) isActive = false isShutdown = false } @@ -58,13 +55,13 @@ class NETCPInterface: NSObject, GenericSocket, LinkInterface { return } } - impl.addObserver(self, forKeyPath: #keyPath(NWTCPConnection.state), options: [.initial, .new], context: &NETCPInterface.linkContext) - impl.addObserver(self, forKeyPath: #keyPath(NWTCPConnection.hasBetterPath), options: .new, context: &NETCPInterface.linkContext) + impl.addObserver(self, forKeyPath: #keyPath(NWTCPConnection.state), options: [.initial, .new], context: &NETCPSocket.linkContext) + impl.addObserver(self, forKeyPath: #keyPath(NWTCPConnection.hasBetterPath), options: .new, context: &NETCPSocket.linkContext) } func unobserve() { - impl.removeObserver(self, forKeyPath: #keyPath(NWTCPConnection.state), context: &NETCPInterface.linkContext) - impl.removeObserver(self, forKeyPath: #keyPath(NWTCPConnection.hasBetterPath), context: &NETCPInterface.linkContext) + impl.removeObserver(self, forKeyPath: #keyPath(NWTCPConnection.state), context: &NETCPSocket.linkContext) + impl.removeObserver(self, forKeyPath: #keyPath(NWTCPConnection.hasBetterPath), context: &NETCPSocket.linkContext) } func shutdown() { @@ -76,17 +73,17 @@ class NETCPInterface: NSObject, GenericSocket, LinkInterface { guard impl.hasBetterPath else { return nil } - return NETCPInterface(impl: NWTCPConnection(upgradeFor: impl)) + return NETCPSocket(impl: NWTCPConnection(upgradeFor: impl)) } - func link() -> LinkInterface { - return self + func link(withMTU mtu: Int) -> LinkInterface { + return NETCPLink(impl: impl) } // MARK: Connection KVO (any queue) override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { - guard (context == &NETCPInterface.linkContext) else { + guard (context == &NETCPSocket.linkContext) else { super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) return } @@ -148,12 +145,28 @@ class NETCPInterface: NSObject, GenericSocket, LinkInterface { break } } +} + +class NETCPLink: LinkInterface { + private let impl: NWTCPConnection + + private let maxPacketSize: Int + + init(impl: NWTCPConnection, maxPacketSize: Int? = nil) { + self.impl = impl + self.mtu = .max + self.maxPacketSize = maxPacketSize ?? (512 * 1024) + } // MARK: LinkInterface let isReliable: Bool = true - let mtu: Int = .max + var remoteAddress: String? { + return (impl.remoteAddress as? NWHostEndpoint)?.hostname + } + + let mtu: Int var packetBufferSize: Int { return maxPacketSize @@ -206,7 +219,7 @@ class NETCPInterface: NSObject, GenericSocket, LinkInterface { } } -extension NETCPInterface { +extension NETCPSocket { override var description: String { guard let hostEndpoint = impl.endpoint as? NWHostEndpoint else { return impl.endpoint.description diff --git a/TunnelKit/Sources/AppExtension/Transport/NEUDPInterface.swift b/TunnelKit/Sources/AppExtension/Transport/NEUDPInterface.swift index 2650844..20814df 100644 --- a/TunnelKit/Sources/AppExtension/Transport/NEUDPInterface.swift +++ b/TunnelKit/Sources/AppExtension/Transport/NEUDPInterface.swift @@ -12,16 +12,13 @@ import SwiftyBeaver private let log = SwiftyBeaver.self -class NEUDPInterface: NSObject, GenericSocket, LinkInterface { +class NEUDPSocket: NSObject, GenericSocket { private static var linkContext = 0 private let impl: NWUDPSession - private let maxDatagrams: Int - - init(impl: NWUDPSession, maxDatagrams: Int? = nil) { + init(impl: NWUDPSession) { self.impl = impl - self.maxDatagrams = maxDatagrams ?? 200 isActive = false isShutdown = false @@ -58,13 +55,13 @@ class NEUDPInterface: NSObject, GenericSocket, LinkInterface { return } } - impl.addObserver(self, forKeyPath: #keyPath(NWUDPSession.state), options: [.initial, .new], context: &NEUDPInterface.linkContext) - impl.addObserver(self, forKeyPath: #keyPath(NWUDPSession.hasBetterPath), options: .new, context: &NEUDPInterface.linkContext) + impl.addObserver(self, forKeyPath: #keyPath(NWUDPSession.state), options: [.initial, .new], context: &NEUDPSocket.linkContext) + impl.addObserver(self, forKeyPath: #keyPath(NWUDPSession.hasBetterPath), options: .new, context: &NEUDPSocket.linkContext) } func unobserve() { - impl.removeObserver(self, forKeyPath: #keyPath(NWUDPSession.state), context: &NEUDPInterface.linkContext) - impl.removeObserver(self, forKeyPath: #keyPath(NWUDPSession.hasBetterPath), context: &NEUDPInterface.linkContext) + impl.removeObserver(self, forKeyPath: #keyPath(NWUDPSession.state), context: &NEUDPSocket.linkContext) + impl.removeObserver(self, forKeyPath: #keyPath(NWUDPSession.hasBetterPath), context: &NEUDPSocket.linkContext) } func shutdown() { @@ -75,17 +72,17 @@ class NEUDPInterface: NSObject, GenericSocket, LinkInterface { guard impl.hasBetterPath else { return nil } - return NEUDPInterface(impl: NWUDPSession(upgradeFor: impl)) + return NEUDPSocket(impl: NWUDPSession(upgradeFor: impl)) } - func link() -> LinkInterface { - return self + func link(withMTU mtu: Int) -> LinkInterface { + return NEUDPLink(impl: impl, mtu: mtu) } // MARK: Connection KVO (any queue) override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { - guard (context == &NEUDPInterface.linkContext) else { + guard (context == &NEUDPSocket.linkContext) else { super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) return } @@ -150,12 +147,28 @@ class NEUDPInterface: NSObject, GenericSocket, LinkInterface { break } } +} + +class NEUDPLink: LinkInterface { + private let impl: NWUDPSession + + private let maxDatagrams: Int + + init(impl: NWUDPSession, mtu: Int, maxDatagrams: Int? = nil) { + self.impl = impl + self.mtu = mtu + self.maxDatagrams = maxDatagrams ?? 200 + } // MARK: LinkInterface let isReliable: Bool = false - let mtu: Int = 1000 + var remoteAddress: String? { + return (impl.resolvedEndpoint as? NWHostEndpoint)?.hostname + } + + let mtu: Int var packetBufferSize: Int { return maxDatagrams @@ -191,7 +204,7 @@ class NEUDPInterface: NSObject, GenericSocket, LinkInterface { } } -extension NEUDPInterface { +extension NEUDPSocket { override var description: String { guard let hostEndpoint = impl.endpoint as? NWHostEndpoint else { return impl.endpoint.description diff --git a/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift b/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift index 199068a..760e753 100644 --- a/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift +++ b/TunnelKit/Sources/AppExtension/TunnelKitProvider+Configuration.swift @@ -125,8 +125,8 @@ extension TunnelKitProvider { /// The optional CA certificate to validate server against. Set to `nil` to disable CA validation (default). public var ca: Certificate? - /// The MTU of the tunnel. - public var mtu: NSNumber + /// The MTU of the link. + public var mtu: Int /// Enables LZO framing (deprecated). // @available(*, deprecated) @@ -214,7 +214,7 @@ extension TunnelKitProvider { self.cipher = cipher self.digest = digest self.ca = ca - mtu = providerConfiguration[S.mtu] as? NSNumber ?? 1500 + mtu = providerConfiguration[S.mtu] as? Int ?? 1250 LZOFraming = providerConfiguration[S.LZOFraming] as? Bool ?? false renegotiatesAfterSeconds = providerConfiguration[S.renegotiatesAfter] as? Int @@ -310,7 +310,7 @@ extension TunnelKitProvider { public let ca: Certificate? /// - Seealso: `TunnelKitProvider.ConfigurationBuilder.mtu` - public let mtu: NSNumber + public let mtu: Int /// - Seealso: `TunnelKitProvider.ConfigurationBuilder.LZOFraming` public let LZOFraming: Bool diff --git a/TunnelKit/Sources/AppExtension/TunnelKitProvider.swift b/TunnelKit/Sources/AppExtension/TunnelKitProvider.swift index 9ff5a66..18b3433 100644 --- a/TunnelKit/Sources/AppExtension/TunnelKitProvider.swift +++ b/TunnelKit/Sources/AppExtension/TunnelKitProvider.swift @@ -335,10 +335,10 @@ extension TunnelKitProvider: GenericSocketDelegate { return } if proxy.canRebindLink() { - proxy.rebindLink(socket.link()) + proxy.rebindLink(socket.link(withMTU: cfg.mtu)) reasserting = false } else { - proxy.setLink(socket.link()) + proxy.setLink(socket.link(withMTU: cfg.mtu)) } } @@ -446,7 +446,6 @@ extension TunnelKitProvider: SessionProxyDelegate { let newSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: tunnel) newSettings.ipv4Settings = ipv4Settings newSettings.dnsSettings = dnsSettings - newSettings.mtu = cfg.mtu setTunnelNetworkSettings(newSettings, completionHandler: completionHandler) } diff --git a/TunnelKitTests/AppExtensionTests.swift b/TunnelKitTests/AppExtensionTests.swift index 58a6f70..16dcd2c 100644 --- a/TunnelKitTests/AppExtensionTests.swift +++ b/TunnelKitTests/AppExtensionTests.swift @@ -59,7 +59,7 @@ class AppExtensionTests: XCTestCase { XCTAssertEqual(proto?.providerConfiguration?[K.cipherAlgorithm] as? String, cfg.cipher.rawValue) XCTAssertEqual(proto?.providerConfiguration?[K.digestAlgorithm] as? String, cfg.digest.rawValue) XCTAssertEqual(proto?.providerConfiguration?[K.ca] as? String, cfg.ca?.pem) - XCTAssertEqual(proto?.providerConfiguration?[K.mtu] as? NSNumber, cfg.mtu) + XCTAssertEqual(proto?.providerConfiguration?[K.mtu] as? Int, cfg.mtu) XCTAssertEqual(proto?.providerConfiguration?[K.renegotiatesAfter] as? Int, cfg.renegotiatesAfterSeconds) XCTAssertEqual(proto?.providerConfiguration?[K.debug] as? Bool, cfg.shouldDebug) XCTAssertEqual(proto?.providerConfiguration?[K.debugLogKey] as? String, cfg.debugLogKey)