From 6208fe8e2133c20d054b7526ecda8ce791a7f3a7 Mon Sep 17 00:00:00 2001 From: Davide De Rosa Date: Fri, 24 Aug 2018 12:31:08 +0200 Subject: [PATCH 1/3] Split GenericSocket and LinkInterface Keep socket and link logic separated. Allows for setting MTU specifically for the link. - UDP: hardcoded 1000 - TCP: ignored (.max) --- .../Sources/AppExtension/GenericSocket.swift | 2 +- .../Transport/NETCPInterface.swift | 29 ++++++++++++++----- .../Transport/NEUDPInterface.swift | 29 ++++++++++++++----- .../AppExtension/TunnelKitProvider.swift | 4 +-- 4 files changed, 45 insertions(+), 19 deletions(-) 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..62943b7 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 NETCPInterface: 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 } @@ -79,8 +76,8 @@ class NETCPInterface: NSObject, GenericSocket, LinkInterface { return NETCPInterface(impl: NWTCPConnection(upgradeFor: impl)) } - func link() -> LinkInterface { - return self + func link(withMTU mtu: Int) -> LinkInterface { + return NETCPLinkInterface(impl: impl) } // MARK: Connection KVO (any queue) @@ -148,12 +145,28 @@ class NETCPInterface: NSObject, GenericSocket, LinkInterface { break } } +} + +class NETCPLinkInterface: 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 diff --git a/TunnelKit/Sources/AppExtension/Transport/NEUDPInterface.swift b/TunnelKit/Sources/AppExtension/Transport/NEUDPInterface.swift index 2650844..8f37c05 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 NEUDPInterface: 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 @@ -78,8 +75,8 @@ class NEUDPInterface: NSObject, GenericSocket, LinkInterface { return NEUDPInterface(impl: NWUDPSession(upgradeFor: impl)) } - func link() -> LinkInterface { - return self + func link(withMTU mtu: Int) -> LinkInterface { + return NEUDPLinkInterface(impl: impl, mtu: mtu) } // MARK: Connection KVO (any queue) @@ -150,12 +147,28 @@ class NEUDPInterface: NSObject, GenericSocket, LinkInterface { break } } +} + +class NEUDPLinkInterface: 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 diff --git a/TunnelKit/Sources/AppExtension/TunnelKitProvider.swift b/TunnelKit/Sources/AppExtension/TunnelKitProvider.swift index 9ff5a66..f8a623c 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: 1000)) reasserting = false } else { - proxy.setLink(socket.link()) + proxy.setLink(socket.link(withMTU: 1000)) } } From 54cc811e4771830f51a7fe3b1dc467366dae6a70 Mon Sep 17 00:00:00 2001 From: Davide De Rosa Date: Fri, 24 Aug 2018 12:33:52 +0200 Subject: [PATCH 2/3] Use MTU configuration for the link instead Raise default link MTU from 1000 to 1250. Keep default for tunnel MTU. --- .../AppExtension/TunnelKitProvider+Configuration.swift | 8 ++++---- TunnelKit/Sources/AppExtension/TunnelKitProvider.swift | 5 ++--- TunnelKitTests/AppExtensionTests.swift | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) 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 f8a623c..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(withMTU: 1000)) + proxy.rebindLink(socket.link(withMTU: cfg.mtu)) reasserting = false } else { - proxy.setLink(socket.link(withMTU: 1000)) + 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) From c4b0964c3c7a1b12137be96e6471940302ec6b7c Mon Sep 17 00:00:00 2001 From: Davide De Rosa Date: Fri, 24 Aug 2018 12:44:17 +0200 Subject: [PATCH 3/3] Improve split naming *Socket + *Link --- .../AppExtension/ConnectionStrategy.swift | 4 ++-- .../Transport/NETCPInterface.swift | 20 +++++++++---------- .../Transport/NEUDPInterface.swift | 20 +++++++++---------- 3 files changed, 22 insertions(+), 22 deletions(-) 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/Transport/NETCPInterface.swift b/TunnelKit/Sources/AppExtension/Transport/NETCPInterface.swift index 62943b7..95977f9 100644 --- a/TunnelKit/Sources/AppExtension/Transport/NETCPInterface.swift +++ b/TunnelKit/Sources/AppExtension/Transport/NETCPInterface.swift @@ -12,7 +12,7 @@ import SwiftyBeaver private let log = SwiftyBeaver.self -class NETCPInterface: NSObject, GenericSocket { +class NETCPSocket: NSObject, GenericSocket { private static var linkContext = 0 private let impl: NWTCPConnection @@ -55,13 +55,13 @@ class NETCPInterface: NSObject, GenericSocket { 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() { @@ -73,17 +73,17 @@ class NETCPInterface: NSObject, GenericSocket { guard impl.hasBetterPath else { return nil } - return NETCPInterface(impl: NWTCPConnection(upgradeFor: impl)) + return NETCPSocket(impl: NWTCPConnection(upgradeFor: impl)) } func link(withMTU mtu: Int) -> LinkInterface { - return NETCPLinkInterface(impl: impl) + 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 } @@ -147,7 +147,7 @@ class NETCPInterface: NSObject, GenericSocket { } } -class NETCPLinkInterface: LinkInterface { +class NETCPLink: LinkInterface { private let impl: NWTCPConnection private let maxPacketSize: Int @@ -219,7 +219,7 @@ class NETCPLinkInterface: 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 8f37c05..20814df 100644 --- a/TunnelKit/Sources/AppExtension/Transport/NEUDPInterface.swift +++ b/TunnelKit/Sources/AppExtension/Transport/NEUDPInterface.swift @@ -12,7 +12,7 @@ import SwiftyBeaver private let log = SwiftyBeaver.self -class NEUDPInterface: NSObject, GenericSocket { +class NEUDPSocket: NSObject, GenericSocket { private static var linkContext = 0 private let impl: NWUDPSession @@ -55,13 +55,13 @@ class NEUDPInterface: NSObject, GenericSocket { 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() { @@ -72,17 +72,17 @@ class NEUDPInterface: NSObject, GenericSocket { guard impl.hasBetterPath else { return nil } - return NEUDPInterface(impl: NWUDPSession(upgradeFor: impl)) + return NEUDPSocket(impl: NWUDPSession(upgradeFor: impl)) } func link(withMTU mtu: Int) -> LinkInterface { - return NEUDPLinkInterface(impl: impl, mtu: mtu) + 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 } @@ -149,7 +149,7 @@ class NEUDPInterface: NSObject, GenericSocket { } } -class NEUDPLinkInterface: LinkInterface { +class NEUDPLink: LinkInterface { private let impl: NWUDPSession private let maxDatagrams: Int @@ -204,7 +204,7 @@ class NEUDPLinkInterface: LinkInterface { } } -extension NEUDPInterface { +extension NEUDPSocket { override var description: String { guard let hostEndpoint = impl.endpoint as? NWHostEndpoint else { return impl.endpoint.description