Sanitised

This commit is contained in:
Neil Alexander 2020-07-19 14:20:15 +01:00
commit 52ca049b50
39 changed files with 3283 additions and 0 deletions

69
.gitignore vendored Normal file
View file

@ -0,0 +1,69 @@
# macOS
.DS_Store
*.framework/
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## Build generated
build/
DerivedData/
## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
## Other
*.moved-aside
*.xcuserstate
## Obj-C/Swift specific
*.hmap
*.ipa
*.dSYM.zip
*.dSYM
## Playgrounds
timeline.xctimeline
playground.xcworkspace
# Swift Package Manager
#
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
# Packages/
.build/
# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
Pods/
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Build
# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output

View file

@ -0,0 +1,220 @@
//
// ConfigurationProxy.swift
// YggdrasilNetwork
//
// Created by Neil Alexander on 07/01/2019.
//
#if canImport(UIKit)
import UIKit
#elseif canImport(AppKit)
import AppKit
#endif
import Yggdrasil
import NetworkExtension
#if os(iOS)
class PlatformItemSource: NSObject, UIActivityItemSource {
func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
return "yggdrasil.conf"
}
func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
return nil
}
}
#elseif os(OSX)
class PlatformItemSource: NSObject {}
#endif
class ConfigurationProxy: PlatformItemSource {
private var json: Data? = nil
private var dict: [String: Any]? = nil
override init() {
super.init()
self.json = MobileGenerateConfigJSON()
do {
try self.convertToDict()
} catch {
NSLog("ConfigurationProxy: Error deserialising JSON (\(error))")
}
#if os(iOS)
self.set("name", inSection: "NodeInfo", to: UIDevice.current.name)
#elseif os(OSX)
self.set("name", inSection: "NodeInfo", to: Host.current().localizedName ?? "")
#endif
self.set("MulticastInterfaces", to: ["en*"] as [String])
self.set("AllowFromDirect", inSection: "SessionFirewall", to: true)
self.set("AllowFromRemote", inSection: "SessionFirewall", to: false)
self.set("AlwaysAllowOutbound", inSection: "SessionFirewall", to: true)
self.set("Enable", inSection: "SessionFirewall", to: true)
}
init(json: Data) throws {
super.init()
self.json = json
try self.convertToDict()
}
private func fix() {
self.set("Listen", to: [] as [String])
self.set("AdminListen", to: "none")
self.set("IfName", to: "dummy")
self.set("Enable", inSection: "SessionFirewall", to: true)
self.set("MaxTotalQueueSize", inSection: "SwitchOptions", to: 1048576)
if self.get("AutoStart") == nil {
self.set("AutoStart", to: ["WiFi": false, "Mobile": false] as [String: Bool])
}
let interfaces = self.get("MulticastInterfaces") as? [String] ?? []
if interfaces.contains(where: { $0 == "lo0" }) {
self.add("lo0", in: "MulticastInterfaces")
}
}
func get(_ key: String) -> Any? {
if let dict = self.dict {
if dict.keys.contains(key) {
return dict[key]
}
}
return nil
}
func get(_ key: String, inSection section: String) -> Any? {
if let dict = self.get(section) as? [String: Any] {
if dict.keys.contains(key) {
return dict[key]
}
}
return nil
}
func add(_ value: Any, in key: String) {
if self.dict != nil {
if self.dict![key] as? [Any] != nil {
var temp = self.dict![key] as? [Any] ?? []
temp.append(value)
self.dict!.updateValue(temp, forKey: key)
}
}
}
func remove(_ value: String, from key: String) {
if self.dict != nil {
if self.dict![key] as? [String] != nil {
var temp = self.dict![key] as? [String] ?? []
if let index = temp.firstIndex(of: value) {
temp.remove(at: index)
}
self.dict!.updateValue(temp, forKey: key)
}
}
}
func remove(index: Int, from key: String) {
if self.dict != nil {
if self.dict![key] as? [Any] != nil {
var temp = self.dict![key] as? [Any] ?? []
temp.remove(at: index)
self.dict!.updateValue(temp, forKey: key)
}
}
}
func set(_ key: String, to value: Any) {
if self.dict != nil {
self.dict![key] = value
}
}
func set(_ key: String, inSection section: String, to value: Any?) {
if self.dict != nil {
if self.dict!.keys.contains(section), let value = value {
var temp = self.dict![section] as? [String: Any] ?? [:]
temp.updateValue(value, forKey: key)
self.dict!.updateValue(temp, forKey: section)
}
}
}
func data() -> Data? {
do {
try self.convertToJson()
return self.json
} catch {
return nil
}
}
func save(to manager: inout NETunnelProviderManager) throws {
self.fix()
if let data = self.data() {
let providerProtocol = NETunnelProviderProtocol()
#if os(iOS)
providerProtocol.providerBundleIdentifier = "eu.neilalexander.yggdrasil.extension"
#elseif os(OSX)
providerProtocol.providerBundleIdentifier = "eu.neilalexander.yggdrasilmac.extension"
#endif
providerProtocol.providerConfiguration = [ "json": data ]
providerProtocol.serverAddress = "yggdrasil"
providerProtocol.username = self.get("EncryptionPublicKey") as? String ?? "(unknown public key)"
let disconnectrule = NEOnDemandRuleDisconnect()
var rules: [NEOnDemandRule] = [disconnectrule]
if self.get("WiFi", inSection: "AutoStart") as? Bool ?? false {
let wifirule = NEOnDemandRuleConnect()
wifirule.interfaceTypeMatch = .wiFi
rules.insert(wifirule, at: 0)
}
#if canImport(UIKit)
if self.get("Mobile", inSection: "AutoStart") as? Bool ?? false {
let mobilerule = NEOnDemandRuleConnect()
mobilerule.interfaceTypeMatch = .cellular
rules.insert(mobilerule, at: 0)
}
#endif
manager.onDemandRules = rules
manager.isOnDemandEnabled = rules.count > 1
providerProtocol.disconnectOnSleep = rules.count > 1
manager.protocolConfiguration = providerProtocol
manager.saveToPreferences(completionHandler: { (error:Error?) in
if let error = error {
print(error)
} else {
print("Save successfully")
NotificationCenter.default.post(name: NSNotification.Name.YggdrasilSettingsUpdated, object: self)
}
})
}
}
private func convertToDict() throws {
self.dict = try JSONSerialization.jsonObject(with: self.json!, options: []) as? [String: Any]
}
private func convertToJson() throws {
self.json = try JSONSerialization.data(withJSONObject: self.dict as Any, options: .prettyPrinted)
}
#if canImport(UIKit)
override func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
return "yggdrasil.conf"
}
override func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
return self.data()
}
func activityViewController(_ activityViewController: UIActivityViewController, subjectForActivityType activityType: UIActivity.ActivityType?) -> String {
if let pubkey = self.get("EncryptionPublicKey") as? String, pubkey.count > 56 {
return "yggdrasil-\(pubkey.dropFirst(56)).conf.json"
}
return "yggdrasil.conf.json"
}
#endif
}

View file

@ -0,0 +1,151 @@
//
// AppDelegateExtension.swift
// Yggdrasil Network
//
// Created by Neil Alexander on 11/01/2019.
//
import Foundation
import NetworkExtension
import Yggdrasil
import UIKit
class CrossPlatformAppDelegate: PlatformAppDelegate {
var vpnManager: NETunnelProviderManager = NETunnelProviderManager()
#if os(iOS)
let yggdrasilComponent = "eu.neilalexander.yggdrasil.extension"
#elseif os(OSX)
let yggdrasilComponent = "eu.neilalexander.yggdrasilmac.extension"
#endif
var yggdrasilConfig: ConfigurationProxy? = nil
var yggdrasilAdminTimer: DispatchSourceTimer?
var yggdrasilSelfIP: String = "N/A"
var yggdrasilSelfSubnet: String = "N/A"
var yggdrasilSelfCoords: String = "[]"
var yggdrasilPeers: [[String: Any]] = [[:]]
var yggdrasilSwitchPeers: [[String: Any]] = [[:]]
var yggdrasilNodeInfo: [String: Any] = [:]
func applicationDidBecomeActive(_ application: UIApplication) {
if self.yggdrasilAdminTimer == nil {
self.yggdrasilAdminTimer = DispatchSource.makeTimerSource(flags: .strict, queue: DispatchQueue(label: "Admin Queue"))
self.yggdrasilAdminTimer!.schedule(deadline: DispatchTime.now(), repeating: DispatchTimeInterval.seconds(2), leeway: DispatchTimeInterval.seconds(1))
self.yggdrasilAdminTimer!.setEventHandler {
self.makeIPCRequests()
}
}
if self.yggdrasilAdminTimer != nil {
self.yggdrasilAdminTimer!.resume()
}
NotificationCenter.default.addObserver(forName: .NEVPNStatusDidChange, object: nil, queue: nil, using: { notification in
if let conn = notification.object as? NEVPNConnection {
self.updateStatus(conn: conn)
}
})
self.updateStatus(conn: self.vpnManager.connection)
}
func updateStatus(conn: NEVPNConnection) {
if conn.status == .connected {
self.makeIPCRequests()
} else if conn.status == .disconnecting || conn.status == .disconnected {
self.clearStatus()
}
}
func applicationWillResignActive(_ application: UIApplication) {
if self.yggdrasilAdminTimer != nil {
self.yggdrasilAdminTimer!.suspend()
}
}
func vpnTunnelProviderManagerInit() {
NETunnelProviderManager.loadAllFromPreferences { (savedManagers: [NETunnelProviderManager]?, error: Error?) in
if let error = error {
print(error)
}
if let savedManagers = savedManagers {
for manager in savedManagers {
if (manager.protocolConfiguration as? NETunnelProviderProtocol)?.providerBundleIdentifier == self.yggdrasilComponent {
print("Found saved VPN Manager")
self.vpnManager = manager
}
}
}
self.vpnManager.loadFromPreferences(completionHandler: { (error: Error?) in
if let error = error {
print(error)
}
if let vpnConfig = self.vpnManager.protocolConfiguration as? NETunnelProviderProtocol,
let confJson = vpnConfig.providerConfiguration!["json"] as? Data {
print("Found existing protocol configuration")
self.yggdrasilConfig = try? ConfigurationProxy(json: confJson)
} else {
print("Generating new protocol configuration")
self.yggdrasilConfig = ConfigurationProxy()
}
self.vpnManager.localizedDescription = "Yggdrasil"
self.vpnManager.isEnabled = true
if let config = self.yggdrasilConfig {
try? config.save(to: &self.vpnManager)
}
})
}
}
func makeIPCRequests() {
if self.vpnManager.connection.status != .connected {
return
}
if let session = self.vpnManager.connection as? NETunnelProviderSession {
try? session.sendProviderMessage("address".data(using: .utf8)!) { (address) in
self.yggdrasilSelfIP = String(data: address!, encoding: .utf8)!
NotificationCenter.default.post(name: .YggdrasilSelfUpdated, object: nil)
}
try? session.sendProviderMessage("subnet".data(using: .utf8)!) { (subnet) in
self.yggdrasilSelfSubnet = String(data: subnet!, encoding: .utf8)!
NotificationCenter.default.post(name: .YggdrasilSelfUpdated, object: nil)
}
try? session.sendProviderMessage("coords".data(using: .utf8)!) { (coords) in
self.yggdrasilSelfCoords = String(data: coords!, encoding: .utf8)!
NotificationCenter.default.post(name: .YggdrasilSelfUpdated, object: nil)
}
try? session.sendProviderMessage("peers".data(using: .utf8)!) { (peers) in
if let jsonResponse = try? JSONSerialization.jsonObject(with: peers!, options: []) as? [[String: Any]] {
self.yggdrasilPeers = jsonResponse
NotificationCenter.default.post(name: .YggdrasilPeersUpdated, object: nil)
}
}
try? session.sendProviderMessage("switchpeers".data(using: .utf8)!) { (switchpeers) in
if let jsonResponse = try? JSONSerialization.jsonObject(with: switchpeers!, options: []) as? [[String: Any]] {
self.yggdrasilSwitchPeers = jsonResponse
NotificationCenter.default.post(name: .YggdrasilSwitchPeersUpdated, object: nil)
}
}
}
}
func clearStatus() {
self.yggdrasilSelfIP = "N/A"
self.yggdrasilSelfSubnet = "N/A"
self.yggdrasilSelfCoords = "[]"
self.yggdrasilPeers = []
self.yggdrasilSwitchPeers = []
NotificationCenter.default.post(name: .YggdrasilSelfUpdated, object: nil)
NotificationCenter.default.post(name: .YggdrasilPeersUpdated, object: nil)
NotificationCenter.default.post(name: .YggdrasilSwitchPeersUpdated, object: nil)
}
}

View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>Yggdrasil Network Extension</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>0.1</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.networkextension.packet-tunnel</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).PacketTunnelProvider</string>
</dict>
</dict>
</plist>

View file

@ -0,0 +1,136 @@
import NetworkExtension
import Foundation
import Yggdrasil
class PacketTunnelProvider: NEPacketTunnelProvider {
var yggdrasil: MobileYggdrasil = MobileYggdrasil()
var conduit: DummyConduitEndpoint? = nil
var yggdrasilConfig: ConfigurationProxy?
@objc func readPacketsFromTun() {
if let conduit = self.conduit {
autoreleasepool {
self.packetFlow.readPackets { (packets: [Data], protocols: [NSNumber]) in
for packet in packets {
conduit.send(packet)
}
self.readPacketsFromTun()
}
}
}
}
@objc func writePacketsToTun() {
while let conduit = self.conduit {
autoreleasepool {
if let data = conduit.recv() {
self.packetFlow.writePackets([data], withProtocols: [NSNumber](repeating: AF_INET6 as NSNumber, count: 1))
}
}
}
}
func startYggdrasil() -> Error? {
var err: Error? = nil
self.setTunnelNetworkSettings(nil) { (error: Error?) -> Void in
NSLog("Starting Yggdrasil")
if let error = error {
NSLog("Failed to clear Yggdrasil tunnel network settings: " + error.localizedDescription)
err = error
}
if self.yggdrasilConfig == nil {
NSLog("No configuration proxy!")
return
}
if let config = self.yggdrasilConfig {
NSLog("Configuration loaded")
do {
self.conduit = try self.yggdrasil.startJSON(config.data())
} catch {
NSLog("Starting Yggdrasil process produced an error: " + error.localizedDescription)
return
}
let address = self.yggdrasil.getAddressString()
let subnet = self.yggdrasil.getSubnetString()
NSLog("Yggdrasil IPv6 address: " + address)
NSLog("Yggdrasil IPv6 subnet: " + subnet)
let tunnelNetworkSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: address)
tunnelNetworkSettings.ipv6Settings = NEIPv6Settings(addresses: [address], networkPrefixLengths: [7])
tunnelNetworkSettings.ipv6Settings?.includedRoutes = [NEIPv6Route(destinationAddress: "0200::", networkPrefixLength: 7)]
NSLog("Setting tunnel network settings...")
self.setTunnelNetworkSettings(tunnelNetworkSettings) { (error: Error?) -> Void in
NSLog("setTunnelNetworkSettings completed successfully")
if let error = error {
NSLog("Failed to set Yggdrasil tunnel network settings: " + error.localizedDescription)
err = error
} else {
NSLog("Yggdrasil tunnel settings set successfully")
let readthread: Thread = Thread(target: self, selector: #selector(self.readPacketsFromTun), object: nil)
readthread.name = "TUN Packet Reader"
readthread.qualityOfService = .utility
let writethread: Thread = Thread(target: self, selector: #selector(self.writePacketsToTun), object: nil)
writethread.name = "TUN Packet Writer"
writethread.qualityOfService = .utility
readthread.start()
writethread.start()
}
}
}
}
return err
}
override func startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void) {
if let conf = (self.protocolConfiguration as! NETunnelProviderProtocol).providerConfiguration {
if let json = conf["json"] as? Data {
do {
self.yggdrasilConfig = try ConfigurationProxy(json: json)
} catch {
NSLog("Error in Yggdrasil startTunnel: Configuration is invalid")
return
}
if let error = self.startYggdrasil() {
NSLog("Error in Yggdrasil startTunnel: " + error.localizedDescription)
} else {
NSLog("Yggdrasil completion handler called")
completionHandler(nil)
}
}
}
}
override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
try? self.yggdrasil.stop()
super.stopTunnel(with: reason, completionHandler: completionHandler)
}
override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)? = nil) {
let request = String(data: messageData, encoding: .utf8)
switch request {
case "address":
completionHandler?(self.yggdrasil.getAddressString().data(using: .utf8))
case "subnet":
completionHandler?(self.yggdrasil.getSubnetString().data(using: .utf8))
case "coords":
completionHandler?(self.yggdrasil.getCoordsString().data(using: .utf8))
case "peers":
completionHandler?(self.yggdrasil.getPeersJSON().data(using: .utf8))
case "switchpeers":
completionHandler?(self.yggdrasil.getSwitchPeersJSON().data(using: .utf8))
default:
completionHandler?(nil)
}
}
}

View file

@ -0,0 +1,5 @@
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "GCDAsyncSocket.h"

View file

@ -0,0 +1,16 @@
//
// AppDelegate+AppDelegateExtension.h
// Yggdrasil Network
//
// Created by Neil Alexander on 11/01/2019.
//
NS_ASSUME_NONNULL_BEGIN
@interface AppDelegate ()
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,21 @@
import UIKit
#if os(iOS)
class PlatformAppDelegate: UIResponder, UIApplicationDelegate {}
#elseif os(OSX)
class PlatformAppDelegate: NSObject, NSApplicationDelegate {}
#endif
@UIApplicationMain
class AppDelegate: CrossPlatformAppDelegate {
var window: UIWindow?
let configDir = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true)[0]
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch
self.vpnTunnelProviderManagerInit()
return true
}
}

View file

@ -0,0 +1,19 @@
//
// NSNotification.swift
// YggdrasilNetwork
//
// Created by Neil Alexander on 20/02/2019.
//
#if canImport(UIKit)
import UIKit
#elseif canImport(AppKit)
import AppKit
#endif
extension Notification.Name {
static let YggdrasilSelfUpdated = Notification.Name("YggdrasilSelfUpdated")
static let YggdrasilPeersUpdated = Notification.Name("YggdrasilPeersUpdated")
static let YggdrasilSwitchPeersUpdated = Notification.Name("YggdrasilSwitchPeersUpdated")
static let YggdrasilSettingsUpdated = Notification.Name("YggdrasilSettingsUpdated")
}

View file

@ -0,0 +1,104 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "20x20",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "drawing copy-1.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "drawing copy.png",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "20x20",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "drawing copy-2.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "drawing copy-3.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "drawing copy-5.png",
"scale" : "2x"
},
{
"size" : "1024x1024",
"idiom" : "ios-marketing",
"filename" : "drawing copy-4.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4 KiB

View file

@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View file

@ -0,0 +1,23 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "img1.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "img2.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "img3.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View file

@ -0,0 +1,28 @@
import Foundation
import UIKit
extension UIDevice {
/// A Boolean value indicating whether the device has cellular data capabilities (true) or not (false).
var hasCellularCapabilites: Bool {
var addrs: UnsafeMutablePointer<ifaddrs>?
var cursor: UnsafeMutablePointer<ifaddrs>?
defer { freeifaddrs(addrs) }
guard getifaddrs(&addrs) == 0 else { return false }
cursor = addrs
while cursor != nil {
guard
let utf8String = cursor?.pointee.ifa_name,
let name = NSString(utf8String: utf8String),
name == "pdp_ip0"
else {
cursor = cursor?.pointee.ifa_next
continue
}
return true
}
return false
}
}

View file

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>Yggdrasil</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.1</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>UIFileSharingEnabled</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.text</string>
</array>
<key>UTTypeDescription</key>
<string>Yggdrasil Configuration File</string>
<key>UTTypeIconFiles</key>
<array/>
<key>UTTypeIdentifier</key>
<string>eu.neilalexander.yggdrasil.configuration</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>yggconf</string>
</array>
</dict>
</dict>
</array>
</dict>
</plist>

View file

@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="YggdrasilNetwork" translatesAutoresizingMaskIntoConstraints="NO" id="3Lc-gG-kep">
<rect key="frame" x="28" y="229.5" width="319" height="128"/>
<constraints>
<constraint firstAttribute="width" secondItem="3Lc-gG-kep" secondAttribute="height" multiplier="159:64" id="NYe-AY-mCL"/>
<constraint firstAttribute="width" relation="lessThanOrEqual" constant="400" id="lIj-gT-vW9"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Experimental" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0Nr-Vm-h9W">
<rect key="frame" x="137.5" y="626" width="100" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="3Lc-gG-kep" secondAttribute="trailing" constant="28" id="J9j-Ek-mVq"/>
<constraint firstItem="3Lc-gG-kep" firstAttribute="centerY" secondItem="6Tk-OE-BBY" secondAttribute="centerY" constant="-50" id="MLF-C3-5Is"/>
<constraint firstItem="3Lc-gG-kep" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="6Tk-OE-BBY" secondAttribute="leading" constant="28" id="VpK-lC-s00"/>
<constraint firstItem="6Tk-OE-BBY" firstAttribute="bottom" secondItem="0Nr-Vm-h9W" secondAttribute="bottom" constant="20" id="WcT-Cw-bXi"/>
<constraint firstItem="0Nr-Vm-h9W" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="ZHc-EA-sHG"/>
<constraint firstItem="3Lc-gG-kep" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="xej-Yh-XPz"/>
</constraints>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="52" y="374.66266866566718"/>
</scene>
</scenes>
<resources>
<image name="YggdrasilNetwork" width="785.45452880859375" height="256.90908813476562"/>
</resources>
</document>

View file

@ -0,0 +1,704 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="sjP-mj-LKX">
<device id="retina4_0" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15510"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Peers-->
<scene sceneID="YjI-Ak-tYt">
<objects>
<tableViewController title="Peers" id="Aro-kj-1Us" customClass="PeersViewController" customModule="YggdrasilNetwork" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="jrG-5P-x67">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="configuredPeerPrototype" textLabel="s5X-wa-HWH" style="IBUITableViewCellStyleDefault" id="8Oo-lj-bGn">
<rect key="frame" x="0.0" y="55.5" width="320" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="8Oo-lj-bGn" id="l78-DB-hkK">
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="(discovered)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="s5X-wa-HWH">
<rect key="frame" x="16" y="0.0" width="288" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="discoveredPeerPrototype" textLabel="DBc-bQ-Fql" detailTextLabel="6Zr-Ab-5mg" style="IBUITableViewCellStyleSubtitle" id="GeY-vZ-Kfa">
<rect key="frame" x="0.0" y="99" width="320" height="55.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="GeY-vZ-Kfa" id="CVl-gJ-x3R">
<rect key="frame" x="0.0" y="0.0" width="320" height="55.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="(static)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="DBc-bQ-Fql">
<rect key="frame" x="16" y="10" width="54.5" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="200:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="6Zr-Ab-5mg">
<rect key="frame" x="16" y="31.5" width="26" height="14.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="menuPrototype" textLabel="hGp-hS-MXO" style="IBUITableViewCellStyleDefault" id="X8B-Ij-Uxu">
<rect key="frame" x="0.0" y="154.5" width="320" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="X8B-Ij-Uxu" id="VFl-pZ-ioq">
<rect key="frame" x="0.0" y="0.0" width="293" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Menu item" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="hGp-hS-MXO">
<rect key="frame" x="16" y="0.0" width="269" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="togglePrototype" id="7yi-ur-bht" customClass="ToggleTableViewCell" customModule="YggdrasilNetwork" customModuleProvider="target">
<rect key="frame" x="0.0" y="198" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="7yi-ur-bht" id="xEb-l3-99b">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Toggle item" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ij2-ls-8ZT">
<rect key="frame" x="16" y="12.5" width="231" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="MYo-S3-kzH">
<rect key="frame" x="255" y="7" width="51" height="31.5"/>
</switch>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="MYo-S3-kzH" secondAttribute="bottom" constant="5.5" id="GE4-ve-zue"/>
<constraint firstItem="MYo-S3-kzH" firstAttribute="leading" secondItem="ij2-ls-8ZT" secondAttribute="trailing" constant="8" id="HY3-fl-iyt"/>
<constraint firstItem="ij2-ls-8ZT" firstAttribute="leading" secondItem="xEb-l3-99b" secondAttribute="leadingMargin" id="K5Q-In-8A5"/>
<constraint firstAttribute="trailing" secondItem="MYo-S3-kzH" secondAttribute="trailing" constant="16" id="OfU-Jc-Jh0"/>
<constraint firstItem="ij2-ls-8ZT" firstAttribute="centerY" secondItem="MYo-S3-kzH" secondAttribute="centerY" id="g5U-4E-XRi"/>
<constraint firstItem="MYo-S3-kzH" firstAttribute="top" secondItem="xEb-l3-99b" secondAttribute="top" constant="7" id="wvd-yp-ouw"/>
</constraints>
</tableViewCellContentView>
<connections>
<outlet property="label" destination="ij2-ls-8ZT" id="4kY-1u-gbw"/>
<outlet property="toggle" destination="MYo-S3-kzH" id="WDg-LO-UM4"/>
</connections>
</tableViewCell>
</prototypes>
<sections/>
<connections>
<outlet property="dataSource" destination="Aro-kj-1Us" id="LKO-i9-QW7"/>
<outlet property="delegate" destination="Aro-kj-1Us" id="Gth-NL-fBx"/>
</connections>
</tableView>
<toolbarItems>
<barButtonItem systemItem="add" id="MOW-Lh-hSQ">
<connections>
<action selector="addNewPeerButtonPressed:" destination="Aro-kj-1Us" id="CS3-Z6-tRA"/>
</connections>
</barButtonItem>
</toolbarItems>
<navigationItem key="navigationItem" title="Peers" id="4pr-Fq-FKY"/>
<simulatedToolbarMetrics key="simulatedBottomBarMetrics"/>
<connections>
<outlet property="addButtonItem" destination="MOW-Lh-hSQ" id="2UM-tD-SnA"/>
<outlet property="peerTable" destination="jrG-5P-x67" id="RPw-J3-r1C"/>
</connections>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="nJT-Ej-FI5" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1761" y="1212"/>
</scene>
<!--Peers-->
<scene sceneID="psN-bH-gYF">
<objects>
<navigationController title="Peers" id="LPj-bu-hdp" sceneMemberID="viewController">
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="ifJ-0T-bJ4">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<connections>
<segue destination="Aro-kj-1Us" kind="relationship" relationship="rootViewController" id="rED-QI-0E9"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="gCh-Is-VRG" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1761" y="426"/>
</scene>
<!--Settings-->
<scene sceneID="VfF-sj-c5P">
<objects>
<tableViewController title="Settings" id="FeQ-BB-bF5" customClass="SettingsViewController" customModule="YggdrasilNetwork" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="Cd3-Fg-6d3">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
<sections>
<tableViewSection headerTitle="Node Info" footerTitle="Information entered here is public and may be shown on network maps." id="su8-4b-N3L">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" id="nxn-IW-t8I">
<rect key="frame" x="0.0" y="55.5" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="nxn-IW-t8I" id="a0m-Mn-9fE">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField opaque="NO" contentMode="scaleToFill" horizontalCompressionResistancePriority="250" contentHorizontalAlignment="trailing" contentVerticalAlignment="center" placeholder="None" textAlignment="right" adjustsFontForContentSizeCategory="YES" minimumFontSize="9" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="iRg-tv-diq">
<rect key="frame" x="134" y="1" width="171" height="43"/>
<constraints>
<constraint firstAttribute="height" constant="43" id="cRe-aZ-mWa"/>
</constraints>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<textInputTraits key="textInputTraits" autocapitalizationType="words" keyboardType="alphabet" enablesReturnKeyAutomatically="YES" textContentType="nickname"/>
<connections>
<action selector="deviceNameEdited:" destination="FeQ-BB-bF5" eventType="editingDidEnd" id="lfQ-f7-dSt"/>
</connections>
</textField>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Device Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" preferredMaxLayoutWidth="102" translatesAutoresizingMaskIntoConstraints="NO" id="ieL-P9-WNc">
<rect key="frame" x="16" y="0.0" width="102" height="44"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="2cx-q4-by8"/>
<constraint firstAttribute="width" constant="102" id="MVL-qb-gJw"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="iRg-tv-diq" secondAttribute="trailing" constant="15" id="5Ww-uH-INm"/>
<constraint firstItem="ieL-P9-WNc" firstAttribute="top" secondItem="a0m-Mn-9fE" secondAttribute="top" id="Hoe-Le-Zln"/>
<constraint firstItem="iRg-tv-diq" firstAttribute="leading" secondItem="ieL-P9-WNc" secondAttribute="trailing" constant="16" id="JXX-kn-TTD"/>
<constraint firstAttribute="bottom" secondItem="ieL-P9-WNc" secondAttribute="bottom" id="MOQ-cH-sUE"/>
<constraint firstItem="iRg-tv-diq" firstAttribute="top" secondItem="a0m-Mn-9fE" secondAttribute="top" constant="1" id="O3n-WK-oyd"/>
<constraint firstAttribute="bottom" secondItem="iRg-tv-diq" secondAttribute="bottom" id="heq-bT-FXa"/>
<constraint firstItem="ieL-P9-WNc" firstAttribute="leading" secondItem="a0m-Mn-9fE" secondAttribute="leading" constant="16" id="hy7-uL-DHk"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection headerTitle="Automatically Start On" footerTitle="Yggdrasil will be automatically started when connected to the above networks." id="bjf-vx-Swh">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="checkmark" indentationWidth="10" textLabel="NYE-Pu-5Gk" style="IBUITableViewCellStyleDefault" id="pwi-5Y-UxD">
<rect key="frame" x="0.0" y="191" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="pwi-5Y-UxD" id="631-3X-gfX">
<rect key="frame" x="0.0" y="0.0" width="280" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Wi-Fi" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="NYE-Pu-5Gk">
<rect key="frame" x="16" y="0.0" width="256" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<color key="tintColor" red="0.20340806249999999" green="0.47218620779999998" blue="0.96475774049999996" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="checkmark" indentationWidth="10" textLabel="ZdY-uX-KE6" style="IBUITableViewCellStyleDefault" id="iwW-oY-kqV">
<rect key="frame" x="0.0" y="235" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="iwW-oY-kqV" id="Pe0-bO-Sd1">
<rect key="frame" x="0.0" y="0.0" width="280" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Mobile Network" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="ZdY-uX-KE6">
<rect key="frame" x="16" y="0.0" width="256" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<color key="tintColor" red="0.20340806249999999" green="0.47218620779999998" blue="0.96475774049999996" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection headerTitle="Allow traffic from" id="s6m-tK-gtR">
<string key="footerTitle">The above options allow you to control whether your device is reachable from other devices on the network. "All outgoing traffic" allows connections only to devices that you initiate first. This does not affect peerings.</string>
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="checkmark" indentationWidth="10" textLabel="X1a-uW-3xE" style="IBUITableViewCellStyleDefault" id="SLl-8Z-hnZ">
<rect key="frame" x="0.0" y="370.5" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="SLl-8Z-hnZ" id="erI-m7-1Qf">
<rect key="frame" x="0.0" y="0.0" width="280" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Peered devices" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="X1a-uW-3xE">
<rect key="frame" x="16" y="0.0" width="256" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<color key="tintColor" red="0.20340806249999999" green="0.47218620779999998" blue="0.96475774049999996" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="checkmark" indentationWidth="10" textLabel="aBz-rP-L1T" style="IBUITableViewCellStyleDefault" id="D0S-Qw-28s">
<rect key="frame" x="0.0" y="414.5" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="D0S-Qw-28s" id="PQQ-JM-w0f">
<rect key="frame" x="0.0" y="0.0" width="280" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Other devices" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="aBz-rP-L1T">
<rect key="frame" x="16" y="0.0" width="256" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<color key="tintColor" red="0.20340806249999999" green="0.47218620779999998" blue="0.96475774049999996" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="checkmark" indentationWidth="10" textLabel="1NE-eU-QbN" style="IBUITableViewCellStyleDefault" id="LgH-VV-ofl">
<rect key="frame" x="0.0" y="458.5" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="LgH-VV-ofl" id="TYk-M2-yjB">
<rect key="frame" x="0.0" y="0.0" width="280" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="All outgoing traffic" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="1NE-eU-QbN">
<rect key="frame" x="16" y="0.0" width="256" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<color key="tintColor" red="0.20340806249999999" green="0.47218620779999998" blue="0.96475774049999996" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection headerTitle="Public Keys" footerTitle="Your public keys form your identity on the network. They are safe to be shared." id="Bqi-0N-6vQ">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" textLabel="HTU-3c-4CN" detailTextLabel="P02-mF-z69" style="IBUITableViewCellStyleValue1" id="Osh-HO-1v1">
<rect key="frame" x="0.0" y="642" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Osh-HO-1v1" id="GnT-sE-p01">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Encryption" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="HTU-3c-4CN">
<rect key="frame" x="16" y="12" width="82.5" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Unknown" textAlignment="right" lineBreakMode="headTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="P02-mF-z69" customClass="CopyableLabel" customModule="YggdrasilNetwork" customModuleProvider="target">
<rect key="frame" x="232" y="12" width="72" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" textLabel="SeD-oT-h3h" detailTextLabel="ISL-Pq-1z4" style="IBUITableViewCellStyleValue1" id="80f-wf-ING">
<rect key="frame" x="0.0" y="686" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="80f-wf-ING" id="fed-pT-rbF">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Signing" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="SeD-oT-h3h">
<rect key="frame" x="16" y="12" width="57.5" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Unknown" textAlignment="right" lineBreakMode="headTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="ISL-Pq-1z4" customClass="CopyableLabel" customModule="YggdrasilNetwork" customModuleProvider="target">
<rect key="frame" x="232" y="12" width="72" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection headerTitle="Backup" id="mD0-CO-qvR">
<string key="footerTitle">Configuration will be exported to the Files app. Your configuration contains your private keys which are extremely sensitive. You must not share it with others.</string>
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="0zV-IH-vF4" style="IBUITableViewCellStyleDefault" id="IgR-eA-aHt">
<rect key="frame" x="0.0" y="821.5" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="IgR-eA-aHt" id="wsZ-KR-yUu">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Import configuration" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="0zV-IH-vF4">
<rect key="frame" x="16" y="0.0" width="288" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<color key="tintColor" red="0.20340806249999999" green="0.47218620779999998" blue="0.96475774049999996" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.20340806249999999" green="0.47218620779999998" blue="0.96475774049999996" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="n0W-r2-Cp7" style="IBUITableViewCellStyleDefault" id="Fgj-Ug-A8R">
<rect key="frame" x="0.0" y="865.5" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Fgj-Ug-A8R" id="l0v-9n-Tzb">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Export configuration" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="n0W-r2-Cp7">
<rect key="frame" x="15" y="0.0" width="297" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<color key="tintColor" red="0.20340806249999999" green="0.47218620779999998" blue="0.96475774049999996" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.20340806249999999" green="0.47218620779999998" blue="0.96475774049999996" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection headerTitle="Reset" footerTitle="Resetting will overwrite with newly generated configuration. Your public keys and IP address on the network will change." id="QPd-T4-5id">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="Jc5-vz-oTA" style="IBUITableViewCellStyleDefault" id="Cgi-Yk-esa">
<rect key="frame" x="0.0" y="1033" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Cgi-Yk-esa" id="qMT-ha-vJK">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Reset configuration" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Jc5-vz-oTA">
<rect key="frame" x="15" y="0.0" width="297" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<color key="tintColor" red="0.20340806249999999" green="0.47218620779999998" blue="0.96475774049999996" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.81077963080000004" green="0.26273393630000003" blue="0.2154698987" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
</sections>
<connections>
<outlet property="dataSource" destination="FeQ-BB-bF5" id="UKi-St-qym"/>
<outlet property="delegate" destination="FeQ-BB-bF5" id="Pbu-nP-u0N"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="Settings" id="13i-0q-HI5"/>
<connections>
<outlet property="autoStartMobileCell" destination="iwW-oY-kqV" id="kDV-jT-IBR"/>
<outlet property="autoStartWiFiCell" destination="pwi-5Y-UxD" id="UJo-BZ-aXf"/>
<outlet property="deviceNameField" destination="iRg-tv-diq" id="ffH-UY-BAT"/>
<outlet property="encryptionPublicKeyLabel" destination="P02-mF-z69" id="Yee-Zz-cFd"/>
<outlet property="sessionFirewallOtherCell" destination="D0S-Qw-28s" id="Wtm-yf-r4z"/>
<outlet property="sessionFirewallOutboundCell" destination="LgH-VV-ofl" id="1hr-Qy-6ip"/>
<outlet property="sessionFirewallPeeredCell" destination="SLl-8Z-hnZ" id="rR6-pc-7Jc"/>
<outlet property="signingPublicKeyLabel" destination="ISL-Pq-1z4" id="SVQ-aX-N3C"/>
</connections>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="eco-Zl-sgd" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="2571" y="1212"/>
</scene>
<!--Settings-->
<scene sceneID="ot0-wd-NE5">
<objects>
<navigationController title="Settings" id="g4p-RE-Qtl" sceneMemberID="viewController">
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="p6Z-I0-Zza">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<connections>
<segue destination="FeQ-BB-bF5" kind="relationship" relationship="rootViewController" id="pga-rT-3Jc"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="tUJ-Lk-YoU" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="2571" y="426"/>
</scene>
<!--Yggdrasil-->
<scene sceneID="zY7-dE-7Ay">
<objects>
<tableViewController title="Yggdrasil" id="s1Q-pC-XBn" customClass="TableViewController" customModule="YggdrasilNetwork" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="vHG-eF-QEu">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
<sections>
<tableViewSection footerTitle="You must restart Yggdrasil to make configuration changes effective." id="Jwl-JP-RuU">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" id="49H-YI-ie3">
<rect key="frame" x="0.0" y="18" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="49H-YI-ie3" id="ZPC-T2-kah">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Enable Yggdrasil" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="alk-ml-y9V">
<rect key="frame" x="16" y="12" width="127" height="20"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="trailing" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="qre-Dz-rWw">
<rect key="frame" x="255" y="7" width="51" height="31"/>
<connections>
<action selector="toggleVPNStatus:forEvent:" destination="s1Q-pC-XBn" eventType="valueChanged" id="Mvh-gf-qg0"/>
</connections>
</switch>
</subviews>
<constraints>
<constraint firstItem="qre-Dz-rWw" firstAttribute="top" secondItem="ZPC-T2-kah" secondAttribute="top" constant="7" id="6Yd-ne-dsL"/>
<constraint firstItem="alk-ml-y9V" firstAttribute="top" secondItem="ZPC-T2-kah" secondAttribute="top" constant="12" id="Du8-1c-XP8"/>
<constraint firstAttribute="trailing" secondItem="qre-Dz-rWw" secondAttribute="trailing" constant="16" id="SUT-kR-Vtj"/>
<constraint firstAttribute="bottom" secondItem="alk-ml-y9V" secondAttribute="bottom" constant="12" id="Sz7-IF-DrB"/>
<constraint firstItem="alk-ml-y9V" firstAttribute="leading" secondItem="ZPC-T2-kah" secondAttribute="leading" constant="16" id="kGE-t0-Aph"/>
</constraints>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" textLabel="dZv-7O-fZv" style="IBUITableViewCellStyleDefault" id="m9f-Bi-XeH">
<rect key="frame" x="0.0" y="62" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="m9f-Bi-XeH" id="utU-J9-9M8">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="No active connections" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="dZv-7O-fZv">
<rect key="frame" x="16" y="0.0" width="288" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="17"/>
<color key="textColor" name="systemRedColor" catalog="System" colorSpace="catalog"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection headerTitle="Statistics" id="nJf-RJ-qUC">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="0.0" textLabel="MUj-Ni-chU" detailTextLabel="ceY-dc-u9v" style="IBUITableViewCellStyleValue1" id="Ela-vk-pnR">
<rect key="frame" x="0.0" y="190" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Ela-vk-pnR" id="fnr-ZG-yiF">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="IP" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="MUj-Ni-chU">
<rect key="frame" x="16" y="12" width="15" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="N/A" textAlignment="right" lineBreakMode="headTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" adjustsFontForContentSizeCategory="YES" id="ceY-dc-u9v" customClass="CopyableLabel" customModule="YggdrasilNetwork" customModuleProvider="target">
<rect key="frame" x="275.5" y="12" width="28.5" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="blue" indentationWidth="10" textLabel="Q8j-k7-HTk" detailTextLabel="MLH-EY-4VQ" style="IBUITableViewCellStyleValue1" id="1BH-o1-n90">
<rect key="frame" x="0.0" y="234" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="1BH-o1-n90" id="aLD-3W-BlB">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Subnet" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Q8j-k7-HTk">
<rect key="frame" x="16" y="12" width="55" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="N/A" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" id="MLH-EY-4VQ" customClass="CopyableLabel" customModule="YggdrasilNetwork" customModuleProvider="target">
<rect key="frame" x="275.5" y="12" width="28.5" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<color key="textColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" textLabel="9jY-kM-E6n" detailTextLabel="JYJ-ov-02q" style="IBUITableViewCellStyleValue1" id="g00-iP-grJ">
<rect key="frame" x="0.0" y="278" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="g00-iP-grJ" id="C21-9O-H5d">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Coordinates" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="9jY-kM-E6n">
<rect key="frame" x="16" y="12" width="93" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="[]" textAlignment="right" lineBreakMode="headTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" adjustsFontForContentSizeCategory="YES" id="JYJ-ov-02q" customClass="CopyableLabel" customModule="YggdrasilNetwork" customModuleProvider="target">
<rect key="frame" x="291.5" y="12" width="12.5" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection headerTitle="Configuration" id="gRf-Ts-qeJ">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="blue" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="rT6-UD-Cn5" detailTextLabel="vc0-Rq-wtq" style="IBUITableViewCellStyleValue1" id="qRF-c3-JyG">
<rect key="frame" x="0.0" y="378" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="qRF-c3-JyG" id="gcO-mr-jgp">
<rect key="frame" x="0.0" y="0.0" width="293" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Peers" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="rT6-UD-Cn5">
<rect key="frame" x="16" y="12" width="43.5" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="No peers" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" id="vc0-Rq-wtq">
<rect key="frame" x="215.5" y="12" width="69.5" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<color key="textColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
<connections>
<segue destination="LPj-bu-hdp" kind="showDetail" id="tx6-4f-Vm0"/>
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="blue" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="CPw-Tm-fZl" style="IBUITableViewCellStyleDefault" id="Ugm-vO-zYq">
<rect key="frame" x="0.0" y="422" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Ugm-vO-zYq" id="Jkh-no-wta">
<rect key="frame" x="0.0" y="0.0" width="293" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Settings" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="CPw-Tm-fZl">
<rect key="frame" x="16" y="0.0" width="269" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
<connections>
<segue destination="g4p-RE-Qtl" kind="showDetail" id="hEo-ra-aPX"/>
</connections>
</tableViewCell>
</cells>
</tableViewSection>
</sections>
<connections>
<outlet property="dataSource" destination="s1Q-pC-XBn" id="ASk-mj-jQP"/>
<outlet property="delegate" destination="s1Q-pC-XBn" id="3yd-vi-tqY"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="Yggdrasil" leftItemsSupplementBackButton="YES" largeTitleDisplayMode="always" id="zEJ-Ur-D8L">
<barButtonItem key="backBarButtonItem" title="Status" id="kru-5r-NnH"/>
<barButtonItem key="rightBarButtonItem" systemItem="refresh" id="SK1-2o-4fg">
<connections>
<action selector="onRefreshButton:" destination="s1Q-pC-XBn" id="Tqe-lm-dDv"/>
</connections>
</barButtonItem>
</navigationItem>
<connections>
<outlet property="connectedStatusLabel" destination="dZv-7O-fZv" id="DfM-cR-8VQ"/>
<outlet property="statsSelfCoords" destination="JYJ-ov-02q" id="lcM-hA-tsY"/>
<outlet property="statsSelfCoordsCell" destination="g00-iP-grJ" id="Ho9-VC-QSe"/>
<outlet property="statsSelfIP" destination="ceY-dc-u9v" id="Zob-e3-cVr"/>
<outlet property="statsSelfIPCell" destination="Ela-vk-pnR" id="01S-pD-zJc"/>
<outlet property="statsSelfPeers" destination="vc0-Rq-wtq" id="usQ-EN-040"/>
<outlet property="statsSelfSubnet" destination="MLH-EY-4VQ" id="33U-qS-FUE"/>
<outlet property="statsSelfSubnetCell" destination="1BH-o1-n90" id="Njb-oQ-W5C"/>
<outlet property="toggleConnect" destination="qre-Dz-rWw" id="Oox-v4-K0x"/>
<outlet property="toggleLabel" destination="alk-ml-y9V" id="o4p-Xn-ofm"/>
<outlet property="toggleTableView" destination="vHG-eF-QEu" id="iNr-0v-RoB"/>
</connections>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Nbt-Cc-GRV" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="2571" y="-338"/>
</scene>
<!--Yggdrasil-->
<scene sceneID="NHm-je-2CC">
<objects>
<navigationController title="Yggdrasil" id="Dz7-et-ljx" sceneMemberID="viewController">
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="uxo-U2-UUS">
<rect key="frame" x="0.0" y="0.0" width="320" height="91"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<toolbar key="toolbar" opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="6hK-6f-rI2">
<autoresizingMask key="autoresizingMask"/>
</toolbar>
<connections>
<segue destination="s1Q-pC-XBn" kind="relationship" relationship="rootViewController" id="foA-iq-EPh"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="nYt-zg-2Gb" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1762" y="-337"/>
</scene>
<!--Split View Controller-->
<scene sceneID="9co-Q0-BvB">
<objects>
<splitViewController modalPresentationStyle="pageSheet" id="sjP-mj-LKX" customClass="SplitViewController" customModule="YggdrasilNetwork" customModuleProvider="target" sceneMemberID="viewController">
<connections>
<segue destination="Dz7-et-ljx" kind="relationship" relationship="masterViewController" id="QfQ-La-EfI"/>
</connections>
</splitViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Fe3-ey-WRA" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="811" y="-5"/>
</scene>
</scenes>
</document>

View file

@ -0,0 +1,52 @@
//
// CopyableLabel.swift
// YggdrasilNetwork
//
// Created by Neil Alexander on 26/02/2019.
//
import UIKit
class CopyableLabel: UILabel {
override public var canBecomeFirstResponder: Bool {
get {
return true
}
}
override init(frame: CGRect) {
super.init(frame: frame)
self.isUserInteractionEnabled = true
self.addGestureRecognizer(UILongPressGestureRecognizer(
target: self,
action: #selector(showMenu(sender:))
))
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.isUserInteractionEnabled = true
self.addGestureRecognizer(UILongPressGestureRecognizer(
target: self,
action: #selector(showMenu(sender:))
))
}
override func copy(_ sender: Any?) {
UIPasteboard.general.string = text
UIMenuController.shared.setMenuVisible(false, animated: true)
}
@objc func showMenu(sender: Any?) {
self.becomeFirstResponder()
let menu = UIMenuController.shared
if !menu.isMenuVisible {
menu.setTargetRect(bounds, in: self)
menu.setMenuVisible(true, animated: true)
}
}
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
return (action == #selector(copy(_:)))
}
}

View file

@ -0,0 +1,26 @@
//
// ToggleTableViewCell.swift
// YggdrasilNetwork
//
// Created by Neil Alexander on 07/01/2019.
//
import UIKit
class ToggleTableViewCell: UITableViewCell {
@IBOutlet weak var label: UILabel!
@IBOutlet weak var toggle: UISwitch!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}

View file

@ -0,0 +1,312 @@
//
// PeersViewController.swift
// YggdrasilNetwork
//
// Created by Neil Alexander on 07/01/2019.
//
import UIKit
import NetworkExtension
import CoreTelephony
class PeersViewController: UITableViewController {
var app = UIApplication.shared.delegate as! AppDelegate
var config: [String: Any]? = nil
@IBOutlet var peerTable: UITableView!
@IBOutlet weak var addButtonItem: UIBarButtonItem!
override func viewDidLoad() {
super.viewDidLoad()
if let proto = self.app.vpnManager.protocolConfiguration as? NETunnelProviderProtocol {
config = proto.providerConfiguration ?? nil
}
self.navigationItem.rightBarButtonItems = [
self.editButtonItem,
self.addButtonItem
]
}
override func viewWillAppear(_ animated: Bool) {
NotificationCenter.default.addObserver(self, selector: #selector(self.onYggdrasilPeersUpdated), name: NSNotification.Name.YggdrasilPeersUpdated, object: nil)
}
override func viewWillDisappear(_ animated: Bool) {
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.YggdrasilPeersUpdated, object: nil)
}
@objc func onYggdrasilPeersUpdated(notification: NSNotification) {
peerTable.reloadData()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 3
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0: return app.yggdrasilSwitchPeers.count
case 1:
if let config = self.app.yggdrasilConfig {
if let peers = config.get("Peers") as? [String] {
return peers.count
}
}
return 0
case 2:
if UIDevice.current.hasCellularCapabilites {
return 3
}
return 2
default: return 0
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch indexPath.section {
case 0:
let cell = tableView.dequeueReusableCell(withIdentifier: "discoveredPeerPrototype", for: indexPath)
let peers = app.yggdrasilSwitchPeers.sorted { (a, b) -> Bool in
return (a["Port"] as! Int) < (b["Port"] as! Int)
}
if indexPath.row < peers.count {
let value = peers[indexPath.row]
let proto = value["Protocol"] as? String ?? "tcp"
let sent = value["BytesSent"] as? Double ?? 0
let recvd = value["BytesRecvd"] as? Double ?? 0
let rx = self.format(bytes: sent)
let tx = self.format(bytes: recvd)
cell.textLabel?.text = "\(value["Endpoint"] ?? "unknown")"
cell.detailTextLabel?.text = "\(proto.uppercased()) peer on port \(value["Port"] ?? "unknown"), sent \(tx), received \(rx)"
}
return cell
case 1:
let cell = tableView.dequeueReusableCell(withIdentifier: "configuredPeerPrototype", for: indexPath)
if let config = self.app.yggdrasilConfig {
if let peers = config.get("Peers") as? [String] {
cell.textLabel?.text = peers[indexPath.last!]
} else {
cell.textLabel?.text = "(unknown)"
}
}
return cell
case 2:
switch indexPath.last {
case 0:
let cell = tableView.dequeueReusableCell(withIdentifier: "togglePrototype", for: indexPath) as! ToggleTableViewCell
cell.isUserInteractionEnabled = true
cell.label?.text = "Search for multicast peers"
cell.label?.isEnabled = true
cell.toggle?.addTarget(self, action: #selector(toggledMulticast), for: .valueChanged)
cell.toggle?.isEnabled = true
if let config = self.app.yggdrasilConfig {
let interfaces = config.get("MulticastInterfaces") as? [String] ?? []
cell.toggle?.isOn = interfaces.contains("en*")
}
return cell
case 1:
let cell = tableView.dequeueReusableCell(withIdentifier: "togglePrototype", for: indexPath) as! ToggleTableViewCell
cell.isUserInteractionEnabled = false
cell.label?.text = "Search for nearby iOS peers"
cell.label?.isEnabled = false
cell.toggle?.addTarget(self, action: #selector(toggledAWDL), for: .valueChanged)
cell.toggle?.setOn(false, animated: false)
cell.toggle?.isEnabled = false
/*if let config = self.app.yggdrasilConfig {
let interfaces = config.get("MulticastInterfaces") as? [String] ?? []
cell.toggle?.isOn = interfaces.contains("awdl0")
}*/
return cell
case 2:
let cell = tableView.dequeueReusableCell(withIdentifier: "menuPrototype", for: indexPath)
cell.isUserInteractionEnabled = true
cell.textLabel?.text = "Device settings"
cell.textLabel?.isEnabled = true
return cell
default:
let cell = tableView.dequeueReusableCell(withIdentifier: "menuPrototype", for: indexPath)
cell.isUserInteractionEnabled = false
cell.textLabel?.text = "Unknown"
cell.textLabel?.isEnabled = true
return cell
}
default:
let cell = tableView.dequeueReusableCell(withIdentifier: "configuredPeerPrototype", for: indexPath)
cell.textLabel?.text = "(unknown)"
return cell
}
}
func format(bytes: Double) -> String {
guard bytes > 0 else {
return "0 bytes"
}
// Adapted from http://stackoverflow.com/a/18650828
let suffixes = ["bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
let k: Double = 1000
let i = floor(log(bytes) / log(k))
// Format number with thousands separator and everything below 1 GB with no decimal places.
let numberFormatter = NumberFormatter()
numberFormatter.maximumFractionDigits = i < 3 ? 0 : 1
numberFormatter.numberStyle = .decimal
let numberString = numberFormatter.string(from: NSNumber(value: bytes / pow(k, i))) ?? "Unknown"
let suffix = suffixes[Int(i)]
return "\(numberString) \(suffix)"
}
@objc func toggledMulticast(_ sender: UISwitch) {
if let config = self.app.yggdrasilConfig {
var interfaces = config.get("MulticastInterfaces") as! [String]
if sender.isOn {
interfaces.append("en*")
} else {
interfaces.removeAll(where: { $0 == "en*" })
}
config.set("MulticastInterfaces", to: interfaces as [String])
try? config.save(to: &app.vpnManager)
}
}
@objc func toggledAWDL(_ sender: UISwitch) {
if let config = self.app.yggdrasilConfig {
var interfaces = config.get("MulticastInterfaces") as! [String]
if sender.isOn {
interfaces.append("awdl0")
} else {
interfaces.removeAll(where: { $0 == "awdl0" })
}
config.set("MulticastInterfaces", to: interfaces as [String])
try? config.save(to: &app.vpnManager)
}
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
switch section {
case 0:
if self.app.yggdrasilPeers.count > 0 {
return "Connected Peers"
}
return "No peers currently connected"
case 1:
if let config = self.app.yggdrasilConfig {
if let peers = config.get("Peers") as? [String] {
if peers.count > 0 {
return "Configured Peers"
}
}
}
return "No peers currently configured"
case 2:
return "Peer Connectivity"
default: return "(Unknown)"
}
}
override func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
switch section {
case 1:
return "Yggdrasil will automatically attempt to connect to configured peers when started."
case 2:
var str = "Multicast peers will be discovered on the same Wi-Fi network or via USB."
if UIDevice.current.hasCellularCapabilites {
str += " Data charges may apply when using mobile data. You can prevent mobile data usage in the device settings."
}
return str
default: return nil
}
}
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return indexPath.first == 1
}
override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
switch indexPath.first {
case 0:
return [UITableViewRowAction(style: UITableViewRowAction.Style.default, title: "Disconnect", handler: { (action, index) in
})]
case 1:
return [UITableViewRowAction(style: UITableViewRowAction.Style.normal, title: "Remove", handler: { (action, index) in
print(action, index)
if let config = self.app.yggdrasilConfig {
config.remove(index: index.last!, from: "Peers")
do {
try config.save(to: &self.app.vpnManager)
tableView.reloadSections(IndexSet(integer: 1), with: UITableView.RowAnimation.automatic)
} catch {
let alert = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.parent?.present(alert, animated: true, completion: nil)
print("Error removing: \(error)")
}
}
})]
default:
return []
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
switch indexPath.first {
case 2:
if let last = indexPath.last, last == 2 {
UIApplication.shared.open(NSURL(string:UIApplication.openSettingsURLString)! as URL, options: [:]) { (result) in
NSLog("Result " + result.description)
}
}
default:
break
}
tableView.deselectRow(at: indexPath, animated: true)
}
@IBAction func addNewPeerButtonPressed(_ sender: UIBarButtonItem) {
let alert = UIAlertController(title: "Add Configured Peer", message: """
Enter the full URI of the peer to add. Yggdrasil will automatically connect to this peer when started.
""", preferredStyle: UIAlertController.Style.alert)
let action = UIAlertAction(title: "Add", style: .default) { (alertAction) in
let textField = alert.textFields![0] as UITextField
if let text = textField.text?.trimmingCharacters(in: .whitespacesAndNewlines) {
if let config = self.app.yggdrasilConfig {
if let peers = config.get("Peers") as? [String], !peers.contains(text) {
config.add(text, in: "Peers")
do {
try config.save(to: &self.app.vpnManager)
if let index = config.get("Peers") as? [String] {
self.peerTable.insertRows(at: [IndexPath(indexes: [1, index.count-1])], with: .automatic)
self.peerTable.reloadSections(IndexSet(integer: 1), with: UITableView.RowAnimation.automatic)
}
} catch {
let alert = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.parent?.present(alert, animated: true, completion: nil)
print("Add error: \(error)")
}
} else {
let alert = UIAlertController(title: "Error", message: "Peer already exists", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.parent?.present(alert, animated: true, completion: nil)
}
}
}
}
let cancel = UIAlertAction(title: "Cancel", style: .cancel)
alert.addTextField { (textField) in
textField.placeholder = "tcp://hostname:port"
}
alert.addAction(action)
alert.addAction(cancel)
self.present(alert, animated: true, completion: nil)
}
}

View file

@ -0,0 +1,159 @@
//
// SettingsTableViewController.swift
// YggdrasilNetwork
//
// Created by Neil Alexander on 03/01/2019.
//
import UIKit
import NetworkExtension
class SettingsViewController: UITableViewController, UIDocumentBrowserViewControllerDelegate {
var app = UIApplication.shared.delegate as! AppDelegate
@IBOutlet weak var deviceNameField: UITextField!
@IBOutlet weak var encryptionPublicKeyLabel: UILabel!
@IBOutlet weak var signingPublicKeyLabel: UILabel!
@IBOutlet weak var autoStartWiFiCell: UITableViewCell!
@IBOutlet weak var autoStartMobileCell: UITableViewCell!
@IBOutlet weak var sessionFirewallPeeredCell: UITableViewCell!
@IBOutlet weak var sessionFirewallOtherCell: UITableViewCell!
@IBOutlet weak var sessionFirewallOutboundCell: UITableViewCell!
override func viewDidLoad() {
super.viewDidLoad()
if let config = self.app.yggdrasilConfig {
deviceNameField.text = config.get("name", inSection: "NodeInfo") as? String ?? ""
encryptionPublicKeyLabel.text = config.get("EncryptionPublicKey") as? String ?? "Unknown"
signingPublicKeyLabel.text = config.get("SigningPublicKey") as? String ?? "Unknown"
sessionFirewallPeeredCell.accessoryType = config.get("AllowFromDirect", inSection: "SessionFirewall") as? Bool ?? true ? .checkmark : .none
sessionFirewallOtherCell.accessoryType = config.get("AllowFromRemote", inSection: "SessionFirewall") as? Bool ?? true ? .checkmark : .none
sessionFirewallOutboundCell.accessoryType = config.get("AlwaysAllowOutbound", inSection: "SessionFirewall") as? Bool ?? true ? .checkmark : .none
autoStartWiFiCell.accessoryType = config.get("WiFi", inSection: "AutoStart") as? Bool ?? false ? .checkmark : .none
autoStartMobileCell.accessoryType = config.get("Mobile", inSection: "AutoStart") as? Bool ?? false ? .checkmark : .none
}
}
@IBAction func deviceNameEdited(_ sender: UITextField) {
if let config = self.app.yggdrasilConfig {
config.set("name", inSection: "NodeInfo", to: sender.text)
try? config.save(to: &app.vpnManager)
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
switch indexPath.first {
case 1:
let settings = [
"WiFi",
"Mobile"
]
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = cell.accessoryType == .checkmark ? .none : .checkmark
if let config = self.app.yggdrasilConfig {
config.set(settings[indexPath.last!], inSection: "AutoStart", to: cell.accessoryType == .checkmark)
try? config.save(to: &app.vpnManager)
}
}
case 2:
let settings = [
"AllowFromDirect",
"AllowFromRemote",
"AlwaysAllowOutbound"
]
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = cell.accessoryType == .checkmark ? .none : .checkmark
if let config = self.app.yggdrasilConfig {
config.set(settings[indexPath.last!], inSection: "SessionFirewall", to: cell.accessoryType == .checkmark)
try? config.save(to: &app.vpnManager)
}
}
case 4:
switch indexPath.last {
case 0: // import
if #available(iOS 11.0, *) {
let open = UIDocumentBrowserViewController(forOpeningFilesWithContentTypes: ["eu.neilalexander.yggdrasil.configuration"])
open.delegate = self
open.allowsDocumentCreation = false
open.allowsPickingMultipleItems = false
open.additionalTrailingNavigationBarButtonItems = [ UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelDocumentBrowser)) ]
self.present(open, animated: true, completion: nil)
} else {
let alert = UIAlertController(title: "Import Configuration", message: "Not supported on this version of iOS!", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
case 1: // export
if let config = self.app.yggdrasilConfig, let data = config.data() {
var fileURL: URL?
var fileDir: URL?
do {
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd"
let date = dateFormatter.string(from: Date())
fileDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
fileURL = fileDir?.appendingPathComponent("Yggdrasil Backup \(date).yggconf")
try? data.write(to: fileURL!)
} catch {
break
}
if let dir = fileDir {
let sharedurl = dir.absoluteString.replacingOccurrences(of: "file://", with: "shareddocuments://")
let furl: URL = URL(string: sharedurl)!
UIApplication.shared.open(furl, options: [:], completionHandler: nil)
}
}
default:
break
}
case 5:
let alert = UIAlertController(title: "Warning", message: "This operation will reset your configuration and generate new keys. This is not reversible unless your configuration has been exported. Changes will not take effect until the next time Yggdrasil is restarted.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Reset", style: .destructive, handler: { action in
self.app.yggdrasilConfig = ConfigurationProxy()
if let config = self.app.yggdrasilConfig {
try? config.save(to: &self.app.vpnManager)
self.viewDidLoad()
}}))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
default:
break
}
tableView.deselectRow(at: indexPath, animated: true)
}
@objc func cancelDocumentBrowser() {
self.dismiss(animated: true, completion: nil)
}
@available(iOS 11.0, *)
func documentBrowser(_ controller: UIDocumentBrowserViewController, didPickDocumentsAt documentURLs: [URL]) {
do {
if let url = documentURLs.first {
let data = try Data(contentsOf: url)
let conf = try ConfigurationProxy(json: data)
try conf.save(to: &self.app.vpnManager)
self.app.yggdrasilConfig = conf
controller.dismiss(animated: true, completion: nil)
let alert = UIAlertController(title: "Import Configuration", message: "Configuration file has been imported.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
} catch {
controller.dismiss(animated: true, completion: nil)
let alert = UIAlertController(title: "Import Failed", message: "Unable to import this configuration file.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
self.viewDidLoad()
}
}

View file

@ -0,0 +1,18 @@
//
// SplitViewController.swift
// YggdrasilNetwork
//
// Created by Neil Alexander on 02/01/2019.
//
import UIKit
class SplitViewController: UISplitViewController, UISplitViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
self.preferredDisplayMode = .allVisible
}
}

View file

@ -0,0 +1,133 @@
import UIKit
import NetworkExtension
import Yggdrasil
class TableViewController: UITableViewController {
var app = UIApplication.shared.delegate as! AppDelegate
@IBOutlet var connectedStatusLabel: UILabel!
@IBOutlet var toggleTableView: UITableView!
@IBOutlet var toggleLabel: UILabel!
@IBOutlet var toggleConnect: UISwitch!
@IBOutlet weak var statsSelfIPCell: UITableViewCell!
@IBOutlet weak var statsSelfSubnetCell: UITableViewCell!
@IBOutlet weak var statsSelfCoordsCell: UITableViewCell!
@IBOutlet var statsSelfIP: UILabel!
@IBOutlet var statsSelfSubnet: UILabel!
@IBOutlet var statsSelfCoords: UILabel!
@IBOutlet var statsSelfPeers: UILabel!
override func viewDidLoad() {
NotificationCenter.default.addObserver(self, selector: #selector(self.onYggdrasilSelfUpdated), name: NSNotification.Name.YggdrasilSelfUpdated, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.onYggdrasilPeersUpdated), name: NSNotification.Name.YggdrasilPeersUpdated, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.onYggdrasilSwitchPeersUpdated), name: NSNotification.Name.YggdrasilSwitchPeersUpdated, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.onYggdrasilSettingsUpdated), name: NSNotification.Name.YggdrasilSettingsUpdated, object: nil)
}
@IBAction func onRefreshButton(_ sender: UIButton) {
sender.isEnabled = false
app.makeIPCRequests()
sender.isEnabled = true
}
override func viewWillAppear(_ animated: Bool) {
//NotificationCenter.default.addObserver(self, selector: #selector(TableViewController.VPNStatusDidChange(_:)), name: NSNotification.Name.NEVPNStatusDidChange, object: nil)
if let row = self.tableView.indexPathForSelectedRow {
self.tableView.deselectRow(at: row, animated: true)
}
}
override func viewWillDisappear(_ animated: Bool) {
//NotificationCenter.default.removeObserver(self, name: NSNotification.Name.NEVPNStatusDidChange, object: nil)
}
override func viewDidAppear(_ animated: Bool) {
self.onYggdrasilSelfUpdated(notification: NSNotification.init(name: NSNotification.Name.YggdrasilSettingsUpdated, object: nil))
}
override func viewWillLayoutSubviews() {
self.onYggdrasilSelfUpdated(notification: NSNotification.init(name: NSNotification.Name.YggdrasilSettingsUpdated, object: nil))
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let row = self.tableView.indexPathForSelectedRow {
self.tableView.deselectRow(at: row, animated: true)
}
}
@objc func onYggdrasilSettingsUpdated(notification: NSNotification) {
toggleLabel.isEnabled = !app.vpnManager.isOnDemandEnabled
toggleConnect.isEnabled = !app.vpnManager.isOnDemandEnabled
if let footer = toggleTableView.footerView(forSection: 0) {
if let label = footer.textLabel {
label.text = app.vpnManager.isOnDemandEnabled ? "Yggdrasil will automatically stop and start based on settings." : "You must restart Yggdrasil to make configuration changes effective."
}
}
}
func updateConnectedStatus() {
if self.app.vpnManager.connection.status == .connected {
if app.yggdrasilSwitchPeers.count > 0 {
connectedStatusLabel.text = "Connected"
connectedStatusLabel.textColor = UIColor(red: 0.37, green: 0.79, blue: 0.35, alpha: 1.0)
} else {
connectedStatusLabel.text = "No active connections"
connectedStatusLabel.textColor = UIColor.red
}
} else {
connectedStatusLabel.text = "Not enabled"
connectedStatusLabel.textColor = UIColor.systemGray
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
@objc func onYggdrasilSelfUpdated(notification: NSNotification) {
statsSelfIP.text = app.yggdrasilSelfIP
statsSelfSubnet.text = app.yggdrasilSelfSubnet
statsSelfCoords.text = app.yggdrasilSelfCoords
statsSelfIPCell.layoutSubviews()
statsSelfSubnetCell.layoutSubviews()
statsSelfCoordsCell.layoutSubviews()
let status = self.app.vpnManager.connection.status
toggleConnect.isOn = status == .connecting || status == .connected
self.updateConnectedStatus()
}
@objc func onYggdrasilSwitchPeersUpdated(notification: NSNotification) {
self.updateConnectedStatus()
}
@objc func onYggdrasilPeersUpdated(notification: NSNotification) {
let peercount = app.yggdrasilSwitchPeers.count
if peercount <= 0 {
statsSelfPeers.text = "No peers"
} else if peercount == 1 {
statsSelfPeers.text = "\(peercount) peer"
} else {
statsSelfPeers.text = "\(peercount) peers"
}
}
@IBAction func toggleVPNStatus(_ sender: UISwitch, forEvent event: UIEvent) {
if sender.isOn {
do {
try self.app.vpnManager.connection.startVPNTunnel()
} catch {
print(error)
}
} else {
self.app.vpnManager.connection.stopVPNTunnel()
}
}
}

View file

@ -0,0 +1,670 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 51;
objects = {
/* Begin PBXBuildFile section */
3913E9C021DD3A51001E0EC7 /* SplitViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3913E9BF21DD3A51001E0EC7 /* SplitViewController.swift */; };
3939196B21E35A7C009320F3 /* PeersViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3939196A21E35A7C009320F3 /* PeersViewController.swift */; };
3939196D21E39313009320F3 /* UIDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3939196C21E39313009320F3 /* UIDevice.swift */; };
3939197321E39815009320F3 /* ToggleTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3939197221E39815009320F3 /* ToggleTableViewCell.swift */; };
3939197521E3AADB009320F3 /* ConfigurationProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3939197421E3AADB009320F3 /* ConfigurationProxy.swift */; };
3940354623F4C0C100E81A29 /* Yggdrasil.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3944B66321DAAEA500AF102D /* Yggdrasil.framework */; };
394A1EB321DEA46400D9F553 /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 394A1EB221DEA46400D9F553 /* SettingsViewController.swift */; };
39682A392225AD15004FB670 /* CopyableLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39682A382225AD15004FB670 /* CopyableLabel.swift */; };
397346D521E8E422009B17F6 /* CrossPlatformAppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 397346D421E8E422009B17F6 /* CrossPlatformAppDelegate.swift */; };
39AE88392319C93F0010FFF6 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 39AE88382319C93F0010FFF6 /* NetworkExtension.framework */; };
39AE883A2319CA750010FFF6 /* ConfigurationProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3939197421E3AADB009320F3 /* ConfigurationProxy.swift */; };
39CC924C221DEDCE004960DC /* NSNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39CC924B221DEDCE004960DC /* NSNotification.swift */; };
39CC924D221DEDD3004960DC /* NSNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39CC924B221DEDCE004960DC /* NSNotification.swift */; };
E593CE6F1DF8FC3C00D7265D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E593CE6E1DF8FC3C00D7265D /* AppDelegate.swift */; };
E593CE711DF8FC3C00D7265D /* TableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E593CE701DF8FC3C00D7265D /* TableViewController.swift */; };
E593CE741DF8FC3C00D7265D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E593CE721DF8FC3C00D7265D /* Main.storyboard */; };
E593CE761DF8FC3C00D7265D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E593CE751DF8FC3C00D7265D /* Assets.xcassets */; };
E593CE791DF8FC3C00D7265D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E593CE771DF8FC3C00D7265D /* LaunchScreen.storyboard */; };
E593CE9C1DF905AF00D7265D /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = E593CE9B1DF905AF00D7265D /* PacketTunnelProvider.swift */; };
E593CEA01DF905AF00D7265D /* YggdrasilNetworkExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = E593CE971DF905AF00D7265D /* YggdrasilNetworkExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
E593CE9E1DF905AF00D7265D /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = E593CE631DF8FC3C00D7265D /* Project object */;
proxyType = 1;
remoteGlobalIDString = E593CE961DF905AF00D7265D;
remoteInfo = NEPacketTunnelVPNDemoTunnel;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
E593CEA41DF905B000D7265D /* Embed App Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 13;
files = (
E593CEA01DF905AF00D7265D /* YggdrasilNetworkExtension.appex in Embed App Extensions */,
);
name = "Embed App Extensions";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
3913E99C21DB9B1C001E0EC7 /* YggdrasilNetworkExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = YggdrasilNetworkExtension.entitlements; sourceTree = "<group>"; };
3913E99E21DB9B41001E0EC7 /* YggdrasilNetwork.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = YggdrasilNetwork.entitlements; sourceTree = "<group>"; };
3913E9BF21DD3A51001E0EC7 /* SplitViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplitViewController.swift; sourceTree = "<group>"; };
3939196A21E35A7C009320F3 /* PeersViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PeersViewController.swift; sourceTree = "<group>"; };
3939196C21E39313009320F3 /* UIDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIDevice.swift; sourceTree = "<group>"; };
3939197221E39815009320F3 /* ToggleTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToggleTableViewCell.swift; sourceTree = "<group>"; };
3939197421E3AADB009320F3 /* ConfigurationProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurationProxy.swift; sourceTree = "<group>"; };
3944B66321DAAEA500AF102D /* Yggdrasil.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Yggdrasil.framework; sourceTree = "<group>"; };
394A1EB221DEA46400D9F553 /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = "<group>"; };
39682A382225AD15004FB670 /* CopyableLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CopyableLabel.swift; sourceTree = "<group>"; };
397346D021E8BB5F009B17F6 /* NetworkExtension.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NetworkExtension.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/NetworkExtension.framework; sourceTree = DEVELOPER_DIR; };
397346D421E8E422009B17F6 /* CrossPlatformAppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrossPlatformAppDelegate.swift; sourceTree = "<group>"; };
39AE88382319C93F0010FFF6 /* NetworkExtension.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NetworkExtension.framework; path = System/Library/Frameworks/NetworkExtension.framework; sourceTree = SDKROOT; };
39CC924B221DEDCE004960DC /* NSNotification.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSNotification.swift; sourceTree = "<group>"; };
E593CE6B1DF8FC3C00D7265D /* YggdrasilNetwork.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = YggdrasilNetwork.app; sourceTree = BUILT_PRODUCTS_DIR; };
E593CE6E1DF8FC3C00D7265D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
E593CE701DF8FC3C00D7265D /* TableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableViewController.swift; sourceTree = "<group>"; };
E593CE731DF8FC3C00D7265D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
E593CE751DF8FC3C00D7265D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
E593CE781DF8FC3C00D7265D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
E593CE7A1DF8FC3C00D7265D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
E593CE971DF905AF00D7265D /* YggdrasilNetworkExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = YggdrasilNetworkExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
E593CE9B1DF905AF00D7265D /* PacketTunnelProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PacketTunnelProvider.swift; sourceTree = "<group>"; };
E593CE9D1DF905AF00D7265D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
E593CE681DF8FC3C00D7265D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
39AE88392319C93F0010FFF6 /* NetworkExtension.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
E593CE941DF905AF00D7265D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
3940354623F4C0C100E81A29 /* Yggdrasil.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
39042D3121E4BDA20088A534 /* Storyboards */ = {
isa = PBXGroup;
children = (
E593CE721DF8FC3C00D7265D /* Main.storyboard */,
E593CE771DF8FC3C00D7265D /* LaunchScreen.storyboard */,
);
path = Storyboards;
sourceTree = "<group>";
};
3939196E21E3979C009320F3 /* View Controllers */ = {
isa = PBXGroup;
children = (
E593CE701DF8FC3C00D7265D /* TableViewController.swift */,
3939196A21E35A7C009320F3 /* PeersViewController.swift */,
394A1EB221DEA46400D9F553 /* SettingsViewController.swift */,
3913E9BF21DD3A51001E0EC7 /* SplitViewController.swift */,
);
path = "View Controllers";
sourceTree = "<group>";
};
3939196F21E397A9009320F3 /* Extensions */ = {
isa = PBXGroup;
children = (
3939196C21E39313009320F3 /* UIDevice.swift */,
);
path = Extensions;
sourceTree = "<group>";
};
3939197021E397BC009320F3 /* Application */ = {
isa = PBXGroup;
children = (
E593CE6E1DF8FC3C00D7265D /* AppDelegate.swift */,
39CC924B221DEDCE004960DC /* NSNotification.swift */,
);
path = Application;
sourceTree = "<group>";
};
3939197121E397D1009320F3 /* UI Components */ = {
isa = PBXGroup;
children = (
3939197221E39815009320F3 /* ToggleTableViewCell.swift */,
39682A382225AD15004FB670 /* CopyableLabel.swift */,
);
path = "UI Components";
sourceTree = "<group>";
};
399D032221DA775D0016354F /* Frameworks */ = {
isa = PBXGroup;
children = (
39AE88382319C93F0010FFF6 /* NetworkExtension.framework */,
397346D021E8BB5F009B17F6 /* NetworkExtension.framework */,
3944B66321DAAEA500AF102D /* Yggdrasil.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
39AE88372319C8840010FFF6 /* Yggdrasil Network Cross-Platform */ = {
isa = PBXGroup;
children = (
397346D421E8E422009B17F6 /* CrossPlatformAppDelegate.swift */,
3939197421E3AADB009320F3 /* ConfigurationProxy.swift */,
);
path = "Yggdrasil Network Cross-Platform";
sourceTree = "<group>";
};
E593CE621DF8FC3C00D7265D = {
isa = PBXGroup;
children = (
3913E99E21DB9B41001E0EC7 /* YggdrasilNetwork.entitlements */,
3913E99C21DB9B1C001E0EC7 /* YggdrasilNetworkExtension.entitlements */,
E593CE981DF905AF00D7265D /* Yggdrasil Network Extension */,
39AE88372319C8840010FFF6 /* Yggdrasil Network Cross-Platform */,
E593CE6D1DF8FC3C00D7265D /* Yggdrasil Network iOS */,
E593CE6C1DF8FC3C00D7265D /* Products */,
399D032221DA775D0016354F /* Frameworks */,
);
sourceTree = "<group>";
};
E593CE6C1DF8FC3C00D7265D /* Products */ = {
isa = PBXGroup;
children = (
E593CE6B1DF8FC3C00D7265D /* YggdrasilNetwork.app */,
E593CE971DF905AF00D7265D /* YggdrasilNetworkExtension.appex */,
);
name = Products;
sourceTree = "<group>";
};
E593CE6D1DF8FC3C00D7265D /* Yggdrasil Network iOS */ = {
isa = PBXGroup;
children = (
39042D3121E4BDA20088A534 /* Storyboards */,
3939197021E397BC009320F3 /* Application */,
3939196F21E397A9009320F3 /* Extensions */,
3939196E21E3979C009320F3 /* View Controllers */,
3939197121E397D1009320F3 /* UI Components */,
E593CE751DF8FC3C00D7265D /* Assets.xcassets */,
E593CE7A1DF8FC3C00D7265D /* Info.plist */,
);
path = "Yggdrasil Network iOS";
sourceTree = "<group>";
};
E593CE981DF905AF00D7265D /* Yggdrasil Network Extension */ = {
isa = PBXGroup;
children = (
E593CE9B1DF905AF00D7265D /* PacketTunnelProvider.swift */,
E593CE9D1DF905AF00D7265D /* Info.plist */,
);
path = "Yggdrasil Network Extension";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
E593CE6A1DF8FC3C00D7265D /* YggdrasilNetwork */ = {
isa = PBXNativeTarget;
buildConfigurationList = E593CE7D1DF8FC3C00D7265D /* Build configuration list for PBXNativeTarget "YggdrasilNetwork" */;
buildPhases = (
E593CE671DF8FC3C00D7265D /* Sources */,
E593CE681DF8FC3C00D7265D /* Frameworks */,
E593CE691DF8FC3C00D7265D /* Resources */,
E593CEA41DF905B000D7265D /* Embed App Extensions */,
);
buildRules = (
);
dependencies = (
E593CE9F1DF905AF00D7265D /* PBXTargetDependency */,
);
name = YggdrasilNetwork;
productName = NEPacketTunnelVPNDemo;
productReference = E593CE6B1DF8FC3C00D7265D /* YggdrasilNetwork.app */;
productType = "com.apple.product-type.application";
};
E593CE961DF905AF00D7265D /* YggdrasilNetworkExtension */ = {
isa = PBXNativeTarget;
buildConfigurationList = E593CEA31DF905AF00D7265D /* Build configuration list for PBXNativeTarget "YggdrasilNetworkExtension" */;
buildPhases = (
E593CE931DF905AF00D7265D /* Sources */,
E593CE941DF905AF00D7265D /* Frameworks */,
E593CE951DF905AF00D7265D /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = YggdrasilNetworkExtension;
productName = NEPacketTunnelVPNDemoTunnel;
productReference = E593CE971DF905AF00D7265D /* YggdrasilNetworkExtension.appex */;
productType = "com.apple.product-type.app-extension";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
E593CE631DF8FC3C00D7265D /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1010;
LastUpgradeCheck = 1030;
ORGANIZATIONNAME = "";
TargetAttributes = {
E593CE6A1DF8FC3C00D7265D = {
CreatedOnToolsVersion = 8.1;
DevelopmentTeam = R9AV23TXF2;
LastSwiftMigration = 1030;
ProvisioningStyle = Automatic;
SystemCapabilities = {
com.apple.ApplicationGroups.iOS = {
enabled = 1;
};
com.apple.NetworkExtensions.iOS = {
enabled = 1;
};
com.apple.VPNLite = {
enabled = 1;
};
com.apple.iCloud = {
enabled = 0;
};
};
};
E593CE961DF905AF00D7265D = {
CreatedOnToolsVersion = 8.1;
DevelopmentTeam = R9AV23TXF2;
LastSwiftMigration = 1030;
ProvisioningStyle = Automatic;
SystemCapabilities = {
com.apple.ApplicationGroups.iOS = {
enabled = 1;
};
com.apple.NetworkExtensions.iOS = {
enabled = 1;
};
com.apple.VPNLite = {
enabled = 1;
};
};
};
};
};
buildConfigurationList = E593CE661DF8FC3C00D7265D /* Build configuration list for PBXProject "Yggdrasil Network" */;
compatibilityVersion = "Xcode 10.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = E593CE621DF8FC3C00D7265D;
productRefGroup = E593CE6C1DF8FC3C00D7265D /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
E593CE6A1DF8FC3C00D7265D /* YggdrasilNetwork */,
E593CE961DF905AF00D7265D /* YggdrasilNetworkExtension */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
E593CE691DF8FC3C00D7265D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
E593CE791DF8FC3C00D7265D /* LaunchScreen.storyboard in Resources */,
E593CE761DF8FC3C00D7265D /* Assets.xcassets in Resources */,
E593CE741DF8FC3C00D7265D /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
E593CE951DF905AF00D7265D /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
E593CE671DF8FC3C00D7265D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3939196B21E35A7C009320F3 /* PeersViewController.swift in Sources */,
3939197321E39815009320F3 /* ToggleTableViewCell.swift in Sources */,
3939196D21E39313009320F3 /* UIDevice.swift in Sources */,
394A1EB321DEA46400D9F553 /* SettingsViewController.swift in Sources */,
E593CE711DF8FC3C00D7265D /* TableViewController.swift in Sources */,
39682A392225AD15004FB670 /* CopyableLabel.swift in Sources */,
3939197521E3AADB009320F3 /* ConfigurationProxy.swift in Sources */,
E593CE6F1DF8FC3C00D7265D /* AppDelegate.swift in Sources */,
397346D521E8E422009B17F6 /* CrossPlatformAppDelegate.swift in Sources */,
3913E9C021DD3A51001E0EC7 /* SplitViewController.swift in Sources */,
39CC924C221DEDCE004960DC /* NSNotification.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
E593CE931DF905AF00D7265D /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
39CC924D221DEDD3004960DC /* NSNotification.swift in Sources */,
E593CE9C1DF905AF00D7265D /* PacketTunnelProvider.swift in Sources */,
39AE883A2319CA750010FFF6 /* ConfigurationProxy.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
E593CE9F1DF905AF00D7265D /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = E593CE961DF905AF00D7265D /* YggdrasilNetworkExtension */;
targetProxy = E593CE9E1DF905AF00D7265D /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
E593CE721DF8FC3C00D7265D /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
E593CE731DF8FC3C00D7265D /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
E593CE771DF8FC3C00D7265D /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
E593CE781DF8FC3C00D7265D /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
E593CE7B1DF8FC3C00D7265D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 10.1;
MACOSX_DEPLOYMENT_TARGET = 10.12;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
TARGETED_DEVICE_FAMILY = "1,2";
VALID_ARCHS = "arm64 arm64e armv7 armv7s i386 x86_64";
};
name = Debug;
};
E593CE7C1DF8FC3C00D7265D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 10.1;
MACOSX_DEPLOYMENT_TARGET = 10.12;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx";
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
VALID_ARCHS = "arm64 arm64e armv7 armv7s i386 x86_64";
};
name = Release;
};
E593CE7E1DF8FC3C00D7265D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = YggdrasilNetwork.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 20;
DEVELOPMENT_TEAM = R9AV23TXF2;
ENABLE_BITCODE = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
);
INFOPLIST_FILE = "$(SRCROOT)/Yggdrasil Network iOS/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = eu.neilalexander.yggdrasil;
PRODUCT_NAME = "$(TARGET_NAME)";
STRIP_INSTALLED_PRODUCT = NO;
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
E593CE7F1DF8FC3C00D7265D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = YggdrasilNetwork.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 20;
DEVELOPMENT_TEAM = R9AV23TXF2;
ENABLE_BITCODE = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
);
INFOPLIST_FILE = "$(SRCROOT)/Yggdrasil Network iOS/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = eu.neilalexander.yggdrasil;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
E593CEA11DF905AF00D7265D /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = YggdrasilNetworkExtension.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 20;
DEVELOPMENT_TEAM = R9AV23TXF2;
ENABLE_BITCODE = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
);
INFOPLIST_FILE = "$(SRCROOT)/Yggdrasil Network Extension/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = eu.neilalexander.yggdrasil.extension;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
STRIP_INSTALLED_PRODUCT = NO;
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_VERSION = 5.0;
};
name = Debug;
};
E593CEA21DF905AF00D7265D /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = YggdrasilNetworkExtension.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 20;
DEVELOPMENT_TEAM = R9AV23TXF2;
ENABLE_BITCODE = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)",
);
INFOPLIST_FILE = "$(SRCROOT)/Yggdrasil Network Extension/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = eu.neilalexander.yggdrasil.extension;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "8ce353d5-fd5f-4d5e-b664-8ad294091125";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_VERSION = 5.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
E593CE661DF8FC3C00D7265D /* Build configuration list for PBXProject "Yggdrasil Network" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E593CE7B1DF8FC3C00D7265D /* Debug */,
E593CE7C1DF8FC3C00D7265D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
E593CE7D1DF8FC3C00D7265D /* Build configuration list for PBXNativeTarget "YggdrasilNetwork" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E593CE7E1DF8FC3C00D7265D /* Debug */,
E593CE7F1DF8FC3C00D7265D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
E593CEA31DF905AF00D7265D /* Build configuration list for PBXNativeTarget "YggdrasilNetworkExtension" */ = {
isa = XCConfigurationList;
buildConfigurations = (
E593CEA11DF905AF00D7265D /* Debug */,
E593CEA21DF905AF00D7265D /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = E593CE631DF8FC3C00D7265D /* Project object */;
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:/Users/neilalexander/Desktop/Projects/yggdrasil-mobile/NEPacketTunnelVPNDemo/Yggdrasil Network.xcodeproj">
</FileRef>
</Workspace>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict/>
</plist>

View file

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1110"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E593CE6A1DF8FC3C00D7265D"
BuildableName = "YggdrasilNetwork.app"
BlueprintName = "YggdrasilNetwork"
ReferencedContainer = "container:Yggdrasil Network.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E593CE6A1DF8FC3C00D7265D"
BuildableName = "YggdrasilNetwork.app"
BlueprintName = "YggdrasilNetwork"
ReferencedContainer = "container:Yggdrasil Network.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E593CE6A1DF8FC3C00D7265D"
BuildableName = "YggdrasilNetwork.app"
BlueprintName = "YggdrasilNetwork"
ReferencedContainer = "container:Yggdrasil Network.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E593CE6A1DF8FC3C00D7265D"
BuildableName = "YggdrasilNetwork.app"
BlueprintName = "YggdrasilNetwork"
ReferencedContainer = "container:Yggdrasil Network.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View file

@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1110"
wasCreatedForAppExtension = "YES"
version = "2.0">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E593CE961DF905AF00D7265D"
BuildableName = "YggdrasilNetworkExtension.appex"
BlueprintName = "YggdrasilNetworkExtension"
ReferencedContainer = "container:Yggdrasil Network.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E593CE6A1DF8FC3C00D7265D"
BuildableName = "YggdrasilNetwork.app"
BlueprintName = "YggdrasilNetwork"
ReferencedContainer = "container:Yggdrasil Network.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E593CE961DF905AF00D7265D"
BuildableName = "YggdrasilNetworkExtension.appex"
BlueprintName = "YggdrasilNetworkExtension"
ReferencedContainer = "container:Yggdrasil Network.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
launchStyle = "0"
askForAppToLaunch = "Yes"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
stopOnEveryMainThreadCheckerIssue = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"
launchAutomaticallySubstyle = "2">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E593CE6A1DF8FC3C00D7265D"
BuildableName = "YggdrasilNetwork.app"
BlueprintName = "YggdrasilNetwork"
ReferencedContainer = "container:Yggdrasil Network.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES"
launchAutomaticallySubstyle = "2">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "E593CE6A1DF8FC3C00D7265D"
BuildableName = "YggdrasilNetwork.app"
BlueprintName = "YggdrasilNetwork"
ReferencedContainer = "container:Yggdrasil Network.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>packet-tunnel-provider</string>
</array>
<key>com.apple.developer.networking.vpn.api</key>
<array>
<string>allow-vpn</string>
</array>
<key>com.apple.security.application-groups</key>
<array>
<string>group.eu.neilalexander.yggdrasil</string>
</array>
</dict>
</plist>

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.networking.networkextension</key>
<array>
<string>packet-tunnel-provider</string>
</array>
<key>com.apple.developer.networking.vpn.api</key>
<array>
<string>allow-vpn</string>
</array>
<key>com.apple.security.application-groups</key>
<array>
<string>group.eu.neilalexander.yggdrasil</string>
</array>
</dict>
</plist>