// // PacketTunnelProvider.swift // WireGuardNetworkExtension // // Created by Jeroen Leenarts on 19-06-18. // Copyright © 2018 Jason A. Donenfeld . All rights reserved. // import NetworkExtension import os.log enum PacketTunnelProviderError: Error { case tunnelSetupFailed } /// A packet tunnel provider object. class PacketTunnelProvider: NEPacketTunnelProvider { // MARK: Properties /// A reference to the WireGuard wrapper object. let wireGuardWrapper = WireGuardGoWrapper() /// The completion handler to call when the tunnel is fully established. var pendingStartCompletion: ((Error?) -> Void)? /// The completion handler to call when the tunnel is fully disconnected. var pendingStopCompletion: (() -> Void)? // MARK: NEPacketTunnelProvider /// Begin the process of establishing the tunnel. override func startTunnel(options: [String: NSObject]?, completionHandler: @escaping (Error?) -> Void) { os_log("Starting tunnel", log: Log.general, type: .info) //TODO tunnel settings if wireGuardWrapper.turnOn(withInterfaceName: "test", settingsString: "") { // Success completionHandler(nil) } else { completionHandler(PacketTunnelProviderError.tunnelSetupFailed) } } /// Begin the process of stopping the tunnel. override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { os_log("Stopping tunnel", log: Log.general, type: .info) wireGuardWrapper.turnOff() completionHandler() } /// Handle IPC messages from the app. override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)?) { guard let messageString = NSString(data: messageData, encoding: String.Encoding.utf8.rawValue) else { completionHandler?(nil) return } os_log("Got a message from the app: %s", log: Log.general, type: .info, messageString) let responseData = "Hello app".data(using: String.Encoding.utf8) completionHandler?(responseData) } }