Network Extension didn’t called Code Answer

Hello Developer, Hope you guys are doing great. Today at Tutorial Guruji Official website, we are sharing the answer of Network Extension didn’t called without wasting too much if your time.

The question is published on by Tutorial Guruji team.

I am trying to connect VPN using OpenVPNAdapter but the PacketTunnelProvider isn’t called from the controller. What am i missing here?

Controller.swift

import NetworkExtension

var providerManager: NETunnelProviderManager!
var provider = PacketTunnelProvider()

override func viewDidLoad() {
    super.viewDidLoad()
    self.loadProviderManager {
        self.configureVPN(response: self.arrResponse[0], serverAddress: self.arrResponse[0].iP, username: "vpn", password: "vpn")
    }
}

func loadProviderManager(completion:@escaping () -> Void) {
    NETunnelProviderManager.loadAllFromPreferences { (managers, error) in
        if error == nil {
            self.providerManager = managers?.first ?? NETunnelProviderManager()
            completion()
        }
    }
}

func configureVPN(response:Response,serverAddress: String, username: String, password: String) {
    
    let data = Data(base64Encoded:response.openVPNConfigDataBase64, options: .ignoreUnknownCharacters)
    print(data!)
    let decodedString = String(data: data!, encoding: .utf8)!
    print(decodedString)
    self.providerManager?.loadFromPreferences { error in
        if error == nil {
            let tunnelProtocol = NETunnelProviderProtocol()
            tunnelProtocol.username = username
            tunnelProtocol.serverAddress = serverAddress
            tunnelProtocol.providerBundleIdentifier = "***.*****.********.***********.********"
            tunnelProtocol.providerConfiguration = ["ovpn": data!, "username": username, "password": password]
            tunnelProtocol.disconnectOnSleep = false
            self.providerManager.protocolConfiguration = tunnelProtocol
            self.providerManager.localizedDescription = "SMVPN"
            self.providerManager.isEnabled = true
            self.providerManager.saveToPreferences(completionHandler: { (error) in
                if error == nil  {
                    self.providerManager.loadFromPreferences(completionHandler: { (error) in
                        if error == nil {
                            self.provider.startTunnel(options: nil) { error in //this  called here not in network extension
                                if error != nil {
                                    print(error!)
                                }else {
                                    
                                }
                            }
                        }else {
                            print(error!.localizedDescription)
                        }
                    })
                }
            })
        }
    }
}

Project Entitlement

enter image description here

PacketTunnelProvider.swift

import NetworkExtension
import OpenVPNAdapter

class PacketTunnelProvider: NEPacketTunnelProvider {
    
    var startHandler: ((Error?) -> Void)?
    var stopHandler: (() -> Void)?
    var vpnReachability = OpenVPNReachability()

    var configuration: OpenVPNConfiguration!
    var properties: OpenVPNConfigurationEvaluation!
    var UDPSession: NWUDPSession!
    var TCPConnection: NWTCPConnection!

    lazy var vpnAdapter: OpenVPNAdapter = {
        let adapter = OpenVPNAdapter()
        adapter.delegate = self
        return adapter
    }()

    override func startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void) {
        // Add code here to start the process of connecting the tunnel.
        guard
            let protocolConfiguration = protocolConfiguration as? NETunnelProviderProtocol,
            let providerConfiguration = protocolConfiguration.providerConfiguration
            else {
                fatalError()
        }
        guard let ovpnFileContent: Data = providerConfiguration["ovpn"] as? Data else { return }
            let configuration = OpenVPNConfiguration()
            configuration.fileContent = ovpnFileContent
            do {
                properties = try vpnAdapter.apply(configuration: configuration)
            } catch {
                completionHandler(error)
                return
            }
        configuration.tunPersist = true

        if !properties.autologin {
            if let username: String = providerConfiguration["username"] as? String, let password: String = providerConfiguration["password"] as? String {
                let credentials = OpenVPNCredentials()
                credentials.username = username
                credentials.password = password
                do {
                    try vpnAdapter.provide(credentials: credentials)
                } catch {
                    completionHandler(error)
                    return
                }
            }
        }

        vpnReachability.startTracking { [weak self] status in
            guard status != .notReachable else { return }
            self?.vpnAdapter.reconnect(afterTimeInterval: 5)
        }

        startHandler = completionHandler
        vpnAdapter.connect(using: self)
    }
    
    override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
        // Add code here to start the process of stopping the tunnel.
        stopHandler = completionHandler
        if vpnReachability.isTracking {
            vpnReachability.stopTracking()
        }
        vpnAdapter.disconnect()
        completionHandler()
    }
    
    override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)?) {
        // Add code here to handle the message.
        if let handler = completionHandler {
            handler(messageData)
        }
    }
    
    override func sleep(completionHandler: @escaping () -> Void) {
        // Add code here to get ready to sleep.
        completionHandler()
    }
    
    override func wake() {
        // Add code here to wake up.
    }
}

extension PacketTunnelProvider: OpenVPNAdapterDelegate {
    func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, configureTunnelWithNetworkSettings networkSettings: NEPacketTunnelNetworkSettings?, completionHandler: @escaping (Error?) -> Void) {
        setTunnelNetworkSettings(networkSettings) { (error) in
            completionHandler(error == nil ? self.packetFlow as? Error : nil)
        }
    }


    func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, configureTunnelWithNetworkSettings networkSettings: NEPacketTunnelNetworkSettings?, completionHandler: @escaping (OpenVPNAdapterPacketFlow?) -> Void) {
        setTunnelNetworkSettings(networkSettings) { (error) in
            completionHandler(error == nil ? self.packetFlow : nil)
        }
    }

    func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, handleEvent event: OpenVPNAdapterEvent, message: String?) {
        switch event {
        case .connected:
            if reasserting {
                reasserting = false
            }
            guard let startHandler = startHandler else { return }
            startHandler(nil)
            self.startHandler = nil
        case .disconnected:
            guard let stopHandler = stopHandler else { return }
            if vpnReachability.isTracking {
                vpnReachability.stopTracking()
            }
            stopHandler()
            self.stopHandler = nil
        case .reconnecting:
            reasserting = true
        default:
            break
        }
    }

    func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, handleError error: Error) {
        guard let fatal = (error as NSError).userInfo[OpenVPNAdapterErrorFatalKey] as? Bool, fatal == true else {
            return
        }
        NSLog("Error: (error.localizedDescription)")
        NSLog("Connection Info: (vpnAdapter.connectionInformation.debugDescription)")
        if vpnReachability.isTracking {
            vpnReachability.stopTracking()
        }

        if let startHandler = startHandler {
            startHandler(error)
            self.startHandler = nil
        } else {
            cancelTunnelWithError(error)
        }
    }

    func openVPNAdapter(_ openVPNAdapter: OpenVPNAdapter, handleLogMessage logMessage: String) {
        NSLog("Log: (logMessage)")
    }

}

extension PacketTunnelProvider: OpenVPNAdapterPacketFlow {
    func readPackets(completionHandler: @escaping ([Data], [NSNumber]) -> Void) {
        packetFlow.readPackets(completionHandler: completionHandler)
    }

    func writePackets(_ packets: [Data], withProtocols protocols: [NSNumber]) -> Bool {
        return packetFlow.writePackets(packets, withProtocols: protocols)
    }

}

extension NEPacketTunnelFlow: OpenVPNAdapterPacketFlow {}

Extension Entitlement

enter image description here

self.provider.startTunnel(options: nil) { error in // This is called here, not in network extension

This method is called from controller but didn’t get called in network extension.

I posted all my code, so if I missed something, then please let me know. Any help is appreciated.

I found this question but I haven’t figured it out yet. PacketTunnelProvider network extension not called Swift 3

Answer

Finally i found my mistake it’s i tried to called network extension but it will never called. so i called NETunnelProviderManager directly and it will work.

self.providerManager.loadFromPreferences(completionHandler: { (error) in
                            if error == nil {
                                do {
                                    try self.providerManager.connection.startVPNTunnel()

                                } catch let error {
                                    print(error.localizedDescription)
                                }
                            }else {
                                print(error!.localizedDescription)
                            }
                        })
We are here to answer your question about Network Extension didn’t called - If you find the proper solution, please don't forgot to share this with your team members.

Related Posts

Tutorial Guruji