SimpleTunnel/StatusViewController.swift
/* |
Copyright (C) 2016 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
This file contains the StatusViewController class, which controls a view used to start and stop a VPN connection, and display the status of the VPN connection. |
*/ |
import UIKit |
import NetworkExtension |
import SimpleTunnelServices |
// MARK: Extensions |
/// Make NEVPNStatus convertible to a string |
extension NEVPNStatus: CustomStringConvertible { |
public var description: String { |
switch self { |
case .disconnected: return "Disconnected" |
case .invalid: return "Invalid" |
case .connected: return "Connected" |
case .connecting: return "Connecting" |
case .disconnecting: return "Disconnecting" |
case .reasserting: return "Reconnecting" |
} |
} |
} |
/// A view controller object for a view that displays VPN status information and allows the user to start and stop the VPN. |
class StatusViewController: UITableViewController { |
// MARK: Properties |
/// A switch that toggles the enabled state of the VPN configuration. |
@IBOutlet weak var enabledSwitch: UISwitch! |
/// A switch that starts and stops the VPN. |
@IBOutlet weak var startStopToggle: UISwitch! |
/// A label that contains the current status of the VPN. |
@IBOutlet weak var statusLabel: UILabel! |
/// The target VPN configuration. |
var targetManager = NEVPNManager.shared() |
// MARK: UIViewController |
/// Handle the event where the view is being displayed. |
override func viewWillAppear(_ animated: Bool) { |
super.viewWillAppear(animated) |
// Initialize the UI |
enabledSwitch.isOn = targetManager.isEnabled |
startStopToggle.isOn = (targetManager.connection.status != .disconnected && targetManager.connection.status != .invalid) |
statusLabel.text = targetManager.connection.status.description |
navigationItem.title = targetManager.localizedDescription |
// Register to be notified of changes in the status. |
NotificationCenter.default.addObserver(forName: NSNotification.Name.NEVPNStatusDidChange, object: targetManager.connection, queue: OperationQueue.main, using: { notification in |
self.statusLabel.text = self.targetManager.connection.status.description |
self.startStopToggle.isOn = (self.targetManager.connection.status != .disconnected && self.targetManager.connection.status != .disconnecting && self.targetManager.connection.status != .invalid) |
}) |
// Disable the start/stop toggle if the configuration is not enabled. |
startStopToggle.isEnabled = enabledSwitch.isOn |
// Send a simple IPC message to the provider, handle the response. |
if let session = targetManager.connection as? NETunnelProviderSession, |
let message = "Hello Provider".data(using: String.Encoding.utf8) |
, targetManager.connection.status != .invalid |
{ |
do { |
try session.sendProviderMessage(message) { response in |
if response != nil { |
let responseString = NSString(data: response!, encoding: String.Encoding.utf8.rawValue) |
simpleTunnelLog("Received response from the provider: \(responseString)") |
} else { |
simpleTunnelLog("Got a nil response from the provider") |
} |
} |
} catch { |
simpleTunnelLog("Failed to send a message to the provider") |
} |
} |
} |
/// Handle the event where the view is being hidden. |
override func viewWillDisappear(_ animated: Bool) { |
super.viewWillDisappear(animated) |
// Stop watching for status change notifications. |
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.NEVPNStatusDidChange, object: targetManager.connection) |
} |
/// Handle the user toggling the "enabled" switch. |
@IBAction func enabledToggled(_ sender: AnyObject) { |
targetManager.isEnabled = enabledSwitch.isOn |
targetManager.saveToPreferences { error in |
guard error == nil else { |
self.enabledSwitch.isOn = self.targetManager.isEnabled |
self.startStopToggle.isEnabled = self.enabledSwitch.isOn |
return |
} |
self.targetManager.loadFromPreferences { error in |
self.enabledSwitch.isOn = self.targetManager.isEnabled |
self.startStopToggle.isEnabled = self.enabledSwitch.isOn |
} |
} |
} |
/// Handle the user toggling the "VPN" switch. |
@IBAction func startStopToggled(_ sender: AnyObject) { |
if targetManager.connection.status == .disconnected || targetManager.connection.status == .invalid { |
do { |
try targetManager.connection.startVPNTunnel() |
} |
catch { |
simpleTunnelLog("Failed to start the VPN: \(error)") |
} |
} |
else { |
targetManager.connection.stopVPNTunnel() |
} |
} |
} |
Copyright © 2016 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2016-10-04