mirror of
https://github.com/yggdrasil-network/yggdrasil-ios.git
synced 2025-04-27 21:55:10 +03:00
Various tweaks
This commit is contained in:
parent
0245b6db5e
commit
9ce78d5007
9 changed files with 471 additions and 18 deletions
252
Yggdrasil Network Cross-Platform/ConfigurationProxy.swift
Normal file
252
Yggdrasil Network Cross-Platform/ConfigurationProxy.swift
Normal file
|
@ -0,0 +1,252 @@
|
||||||
|
//
|
||||||
|
// 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.fix()
|
||||||
|
}
|
||||||
|
|
||||||
|
init(json: Data) throws {
|
||||||
|
super.init()
|
||||||
|
self.json = json
|
||||||
|
try self.convertToDict()
|
||||||
|
self.fix()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func fix() {
|
||||||
|
self.set("Listen", to: [] as [String])
|
||||||
|
self.set("AdminListen", to: "none")
|
||||||
|
self.set("IfName", to: "dummy")
|
||||||
|
|
||||||
|
if self.get("AutoStart") == nil {
|
||||||
|
self.set("AutoStart", to: ["WiFi": false, "Mobile": false] as [String: Bool])
|
||||||
|
}
|
||||||
|
|
||||||
|
let multicastInterfaces = self.get("MulticastInterfaces") as? [[String: Any]] ?? []
|
||||||
|
if multicastInterfaces.count == 0 {
|
||||||
|
self.set("MulticastInterfaces", to: [
|
||||||
|
[
|
||||||
|
"Regex": "en.*",
|
||||||
|
"Beacon": true,
|
||||||
|
"Listen": true,
|
||||||
|
]
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public var multicastBeacons: Bool {
|
||||||
|
get {
|
||||||
|
let multicastInterfaces = self.get("MulticastInterfaces") as? [[String: Any]] ?? []
|
||||||
|
if multicastInterfaces.count == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return multicastInterfaces[0]["Beacon"] as? Bool ?? true
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
var multicastInterfaces = self.get("MulticastInterfaces") as? [[String: Any]] ?? []
|
||||||
|
multicastInterfaces[0]["Beacon"] = newValue
|
||||||
|
self.set("MulticastInterfaces", to: multicastInterfaces)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public var multicastListen: Bool {
|
||||||
|
get {
|
||||||
|
let multicastInterfaces = self.get("MulticastInterfaces") as? [[String: Any]] ?? []
|
||||||
|
if multicastInterfaces.count == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return multicastInterfaces[0]["Listen"] as? Bool ?? true
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
var multicastInterfaces = self.get("MulticastInterfaces") as? [[String: Any]] ?? []
|
||||||
|
multicastInterfaces[0]["Listen"] = newValue
|
||||||
|
self.set("MulticastInterfaces", to: 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("PublicKey") as? String ?? self.get("SigningPublicKey") 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("PublicKey") as? String {
|
||||||
|
return "yggdrasil-\(pubkey).conf.json"
|
||||||
|
}
|
||||||
|
return "yggdrasil.conf.json"
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
158
Yggdrasil Network Cross-Platform/CrossPlatformAppDelegate.swift
Normal file
158
Yggdrasil Network Cross-Platform/CrossPlatformAppDelegate.swift
Normal file
|
@ -0,0 +1,158 @@
|
||||||
|
//
|
||||||
|
// 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 yggdrasilDHT: [[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
|
||||||
|
if let address = address {
|
||||||
|
self.yggdrasilSelfIP = String(data: address, encoding: .utf8)!
|
||||||
|
NotificationCenter.default.post(name: .YggdrasilSelfUpdated, object: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try? session.sendProviderMessage("subnet".data(using: .utf8)!) { (subnet) in
|
||||||
|
if let subnet = subnet {
|
||||||
|
self.yggdrasilSelfSubnet = String(data: subnet, encoding: .utf8)!
|
||||||
|
NotificationCenter.default.post(name: .YggdrasilSelfUpdated, object: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try? session.sendProviderMessage("coords".data(using: .utf8)!) { (coords) in
|
||||||
|
if let coords = coords {
|
||||||
|
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 peers = peers {
|
||||||
|
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("dht".data(using: .utf8)!) { (peers) in
|
||||||
|
if let peers = peers {
|
||||||
|
if let jsonResponse = try? JSONSerialization.jsonObject(with: peers, options: []) as? [[String: Any]] {
|
||||||
|
self.yggdrasilDHT = jsonResponse
|
||||||
|
NotificationCenter.default.post(name: .YggdrasilDHTUpdated, object: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func clearStatus() {
|
||||||
|
self.yggdrasilSelfIP = "N/A"
|
||||||
|
self.yggdrasilSelfSubnet = "N/A"
|
||||||
|
self.yggdrasilSelfCoords = "[]"
|
||||||
|
self.yggdrasilPeers = []
|
||||||
|
self.yggdrasilDHT = []
|
||||||
|
NotificationCenter.default.post(name: .YggdrasilSelfUpdated, object: nil)
|
||||||
|
NotificationCenter.default.post(name: .YggdrasilPeersUpdated, object: nil)
|
||||||
|
NotificationCenter.default.post(name: .YggdrasilDHTUpdated, object: nil)
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,24 +9,28 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||||
|
|
||||||
private var readThread: Thread?
|
private var readThread: Thread?
|
||||||
private var writeThread: Thread?
|
private var writeThread: Thread?
|
||||||
private var writeBuffer = Data(count: 65535)
|
private let readBuffer = NSMutableData(length: 65535)
|
||||||
|
private let writeBuffer = Data(count: 65535)
|
||||||
|
|
||||||
@objc func readPacketsFromTun() {
|
@objc func readPacketsFromTun() {
|
||||||
autoreleasepool {
|
self.packetFlow.readPackets { (packets: [Data], protocols: [NSNumber]) in
|
||||||
self.packetFlow.readPackets { (packets: [Data], protocols: [NSNumber]) in
|
autoreleasepool {
|
||||||
for packet in packets {
|
for packet in packets {
|
||||||
try? self.yggdrasil.sendBuffer(packet, length: packet.count)
|
try? self.yggdrasil.sendBuffer(packet, length: packet.count)
|
||||||
}
|
}
|
||||||
self.readPacketsFromTun()
|
|
||||||
}
|
}
|
||||||
|
self.readPacketsFromTun()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func writePacketsToTun() {
|
@objc func writePacketsToTun() {
|
||||||
|
var n: Int = 0
|
||||||
|
let readData = Data(bytesNoCopy: readBuffer!.mutableBytes, count: 65535, deallocator: .none)
|
||||||
while true {
|
while true {
|
||||||
autoreleasepool {
|
autoreleasepool {
|
||||||
if let data = try? self.yggdrasil.recv() {
|
try? self.yggdrasil.recvBuffer(readBuffer as Data?, ret0_: &n)
|
||||||
self.packetFlow.writePackets([data], withProtocols: [NSNumber](repeating: AF_INET6 as NSNumber, count: 1))
|
if n > 0 {
|
||||||
|
self.packetFlow.writePackets([readData[..<n]], withProtocols: [NSNumber](repeating: AF_INET6 as NSNumber, count: 1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,5 +15,5 @@ extension Notification.Name {
|
||||||
static let YggdrasilSelfUpdated = Notification.Name("YggdrasilSelfUpdated")
|
static let YggdrasilSelfUpdated = Notification.Name("YggdrasilSelfUpdated")
|
||||||
static let YggdrasilPeersUpdated = Notification.Name("YggdrasilPeersUpdated")
|
static let YggdrasilPeersUpdated = Notification.Name("YggdrasilPeersUpdated")
|
||||||
static let YggdrasilSettingsUpdated = Notification.Name("YggdrasilSettingsUpdated")
|
static let YggdrasilSettingsUpdated = Notification.Name("YggdrasilSettingsUpdated")
|
||||||
static let YggdrasilDHTUpdated = Notification.Name("YggdrasilPeersUpdated")
|
static let YggdrasilDHTUpdated = Notification.Name("YggdrasilDHTUpdated")
|
||||||
}
|
}
|
||||||
|
|
20
Yggdrasil Network iOS/Extensions/Data.swift
Normal file
20
Yggdrasil Network iOS/Extensions/Data.swift
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
//
|
||||||
|
// Data.swift
|
||||||
|
// YggdrasilNetworkExtension
|
||||||
|
//
|
||||||
|
// Created by Neil on 15/11/2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension Data {
|
||||||
|
/// This computed value is only needed because of [this](https://github.com/golang/go/issues/33745) issue in the
|
||||||
|
/// golang/go repository. It is a workaround until the problem is solved upstream.
|
||||||
|
///
|
||||||
|
/// The data object is converted into an array of bytes and than returned wrapped in an `NSMutableData` object. In
|
||||||
|
/// thas way Gomobile takes it as it is without copying. The Swift side remains responsible for garbage collection.
|
||||||
|
var mutable: Data {
|
||||||
|
var array = [UInt8](self)
|
||||||
|
return NSMutableData(bytes: &array, length: self.count) as Data
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,17 +38,16 @@
|
||||||
</array>
|
</array>
|
||||||
<key>UISupportedInterfaceOrientations</key>
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
<array>
|
<array>
|
||||||
<string>UIInterfaceOrientationPortrait</string>
|
|
||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||||
</array>
|
</array>
|
||||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||||
<array>
|
<array>
|
||||||
<string>UIInterfaceOrientationPortrait</string>
|
|
||||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
|
||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||||
</array>
|
</array>
|
||||||
<key>UTExportedTypeDeclarations</key>
|
<key>UTExportedTypeDeclarations</key>
|
||||||
<array>
|
<array>
|
||||||
|
|
|
@ -12,6 +12,9 @@
|
||||||
3939196D21E39313009320F3 /* UIDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3939196C21E39313009320F3 /* UIDevice.swift */; };
|
3939196D21E39313009320F3 /* UIDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3939196C21E39313009320F3 /* UIDevice.swift */; };
|
||||||
3939197321E39815009320F3 /* ToggleTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3939197221E39815009320F3 /* ToggleTableViewCell.swift */; };
|
3939197321E39815009320F3 /* ToggleTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3939197221E39815009320F3 /* ToggleTableViewCell.swift */; };
|
||||||
394A1EB321DEA46400D9F553 /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 394A1EB221DEA46400D9F553 /* SettingsViewController.swift */; };
|
394A1EB321DEA46400D9F553 /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 394A1EB221DEA46400D9F553 /* SettingsViewController.swift */; };
|
||||||
|
3952ADB729945AF700B3835D /* ConfigurationProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3952ADB629945AF700B3835D /* ConfigurationProxy.swift */; };
|
||||||
|
3952ADB829945AF700B3835D /* ConfigurationProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3952ADB629945AF700B3835D /* ConfigurationProxy.swift */; };
|
||||||
|
3952ADBA29945AFA00B3835D /* CrossPlatformAppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3952ADB929945AFA00B3835D /* CrossPlatformAppDelegate.swift */; };
|
||||||
39682A392225AD15004FB670 /* CopyableLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39682A382225AD15004FB670 /* CopyableLabel.swift */; };
|
39682A392225AD15004FB670 /* CopyableLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39682A382225AD15004FB670 /* CopyableLabel.swift */; };
|
||||||
3996AF38270328080070947D /* Yggdrasil.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3996AF37270328080070947D /* Yggdrasil.xcframework */; };
|
3996AF38270328080070947D /* Yggdrasil.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3996AF37270328080070947D /* Yggdrasil.xcframework */; };
|
||||||
3996AF39270328080070947D /* Yggdrasil.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3996AF37270328080070947D /* Yggdrasil.xcframework */; };
|
3996AF39270328080070947D /* Yggdrasil.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3996AF37270328080070947D /* Yggdrasil.xcframework */; };
|
||||||
|
@ -24,7 +27,7 @@
|
||||||
E593CE761DF8FC3C00D7265D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E593CE751DF8FC3C00D7265D /* Assets.xcassets */; };
|
E593CE761DF8FC3C00D7265D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E593CE751DF8FC3C00D7265D /* Assets.xcassets */; };
|
||||||
E593CE791DF8FC3C00D7265D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E593CE771DF8FC3C00D7265D /* LaunchScreen.storyboard */; };
|
E593CE791DF8FC3C00D7265D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E593CE771DF8FC3C00D7265D /* LaunchScreen.storyboard */; };
|
||||||
E593CE9C1DF905AF00D7265D /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = E593CE9B1DF905AF00D7265D /* PacketTunnelProvider.swift */; };
|
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, ); }; };
|
E593CEA01DF905AF00D7265D /* YggdrasilNetworkExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = E593CE971DF905AF00D7265D /* YggdrasilNetworkExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
@ -38,15 +41,15 @@
|
||||||
/* End PBXContainerItemProxy section */
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
E593CEA41DF905B000D7265D /* Embed App Extensions */ = {
|
E593CEA41DF905B000D7265D /* Embed Foundation Extensions */ = {
|
||||||
isa = PBXCopyFilesBuildPhase;
|
isa = PBXCopyFilesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
dstPath = "";
|
dstPath = "";
|
||||||
dstSubfolderSpec = 13;
|
dstSubfolderSpec = 13;
|
||||||
files = (
|
files = (
|
||||||
E593CEA01DF905AF00D7265D /* YggdrasilNetworkExtension.appex in Embed App Extensions */,
|
E593CEA01DF905AF00D7265D /* YggdrasilNetworkExtension.appex in Embed Foundation Extensions */,
|
||||||
);
|
);
|
||||||
name = "Embed App Extensions";
|
name = "Embed Foundation Extensions";
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
@ -59,6 +62,8 @@
|
||||||
3939196C21E39313009320F3 /* UIDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIDevice.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>"; };
|
3939197221E39815009320F3 /* ToggleTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToggleTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
394A1EB221DEA46400D9F553 /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = "<group>"; };
|
394A1EB221DEA46400D9F553 /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = "<group>"; };
|
||||||
|
3952ADB629945AF700B3835D /* ConfigurationProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConfigurationProxy.swift; sourceTree = "<group>"; };
|
||||||
|
3952ADB929945AFA00B3835D /* CrossPlatformAppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrossPlatformAppDelegate.swift; sourceTree = "<group>"; };
|
||||||
39682A382225AD15004FB670 /* CopyableLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CopyableLabel.swift; sourceTree = "<group>"; };
|
39682A382225AD15004FB670 /* CopyableLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CopyableLabel.swift; sourceTree = "<group>"; };
|
||||||
3996AF37270328080070947D /* Yggdrasil.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = Yggdrasil.xcframework; sourceTree = "<group>"; };
|
3996AF37270328080070947D /* Yggdrasil.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = Yggdrasil.xcframework; sourceTree = "<group>"; };
|
||||||
39AE88382319C93F0010FFF6 /* NetworkExtension.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NetworkExtension.framework; path = System/Library/Frameworks/NetworkExtension.framework; sourceTree = SDKROOT; };
|
39AE88382319C93F0010FFF6 /* NetworkExtension.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NetworkExtension.framework; path = System/Library/Frameworks/NetworkExtension.framework; sourceTree = SDKROOT; };
|
||||||
|
@ -142,6 +147,16 @@
|
||||||
path = "UI Components";
|
path = "UI Components";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
3952ADB529945AE900B3835D /* Yggdrasil Network Core */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
3952ADB929945AFA00B3835D /* CrossPlatformAppDelegate.swift */,
|
||||||
|
3952ADB629945AF700B3835D /* ConfigurationProxy.swift */,
|
||||||
|
);
|
||||||
|
name = "Yggdrasil Network Core";
|
||||||
|
path = "Yggdrasil Network Cross-Platform";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
399D032221DA775D0016354F /* Frameworks */ = {
|
399D032221DA775D0016354F /* Frameworks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -154,6 +169,7 @@
|
||||||
E593CE621DF8FC3C00D7265D = {
|
E593CE621DF8FC3C00D7265D = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
3952ADB529945AE900B3835D /* Yggdrasil Network Core */,
|
||||||
3913E99E21DB9B41001E0EC7 /* YggdrasilNetwork.entitlements */,
|
3913E99E21DB9B41001E0EC7 /* YggdrasilNetwork.entitlements */,
|
||||||
3913E99C21DB9B1C001E0EC7 /* YggdrasilNetworkExtension.entitlements */,
|
3913E99C21DB9B1C001E0EC7 /* YggdrasilNetworkExtension.entitlements */,
|
||||||
E593CE981DF905AF00D7265D /* Yggdrasil Network Extension */,
|
E593CE981DF905AF00D7265D /* Yggdrasil Network Extension */,
|
||||||
|
@ -205,7 +221,7 @@
|
||||||
E593CE671DF8FC3C00D7265D /* Sources */,
|
E593CE671DF8FC3C00D7265D /* Sources */,
|
||||||
E593CE681DF8FC3C00D7265D /* Frameworks */,
|
E593CE681DF8FC3C00D7265D /* Frameworks */,
|
||||||
E593CE691DF8FC3C00D7265D /* Resources */,
|
E593CE691DF8FC3C00D7265D /* Resources */,
|
||||||
E593CEA41DF905B000D7265D /* Embed App Extensions */,
|
E593CEA41DF905B000D7265D /* Embed Foundation Extensions */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
|
@ -241,7 +257,7 @@
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastSwiftUpdateCheck = 1010;
|
LastSwiftUpdateCheck = 1010;
|
||||||
LastUpgradeCheck = 1250;
|
LastUpgradeCheck = 1420;
|
||||||
ORGANIZATIONNAME = "";
|
ORGANIZATIONNAME = "";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
E593CE6A1DF8FC3C00D7265D = {
|
E593CE6A1DF8FC3C00D7265D = {
|
||||||
|
@ -328,6 +344,8 @@
|
||||||
3939196D21E39313009320F3 /* UIDevice.swift in Sources */,
|
3939196D21E39313009320F3 /* UIDevice.swift in Sources */,
|
||||||
394A1EB321DEA46400D9F553 /* SettingsViewController.swift in Sources */,
|
394A1EB321DEA46400D9F553 /* SettingsViewController.swift in Sources */,
|
||||||
E593CE711DF8FC3C00D7265D /* TableViewController.swift in Sources */,
|
E593CE711DF8FC3C00D7265D /* TableViewController.swift in Sources */,
|
||||||
|
3952ADBA29945AFA00B3835D /* CrossPlatformAppDelegate.swift in Sources */,
|
||||||
|
3952ADB729945AF700B3835D /* ConfigurationProxy.swift in Sources */,
|
||||||
39682A392225AD15004FB670 /* CopyableLabel.swift in Sources */,
|
39682A392225AD15004FB670 /* CopyableLabel.swift in Sources */,
|
||||||
E593CE6F1DF8FC3C00D7265D /* AppDelegate.swift in Sources */,
|
E593CE6F1DF8FC3C00D7265D /* AppDelegate.swift in Sources */,
|
||||||
3913E9C021DD3A51001E0EC7 /* SplitViewController.swift in Sources */,
|
3913E9C021DD3A51001E0EC7 /* SplitViewController.swift in Sources */,
|
||||||
|
@ -341,6 +359,7 @@
|
||||||
files = (
|
files = (
|
||||||
39CC924D221DEDD3004960DC /* NSNotification.swift in Sources */,
|
39CC924D221DEDD3004960DC /* NSNotification.swift in Sources */,
|
||||||
E593CE9C1DF905AF00D7265D /* PacketTunnelProvider.swift in Sources */,
|
E593CE9C1DF905AF00D7265D /* PacketTunnelProvider.swift in Sources */,
|
||||||
|
3952ADB829945AF700B3835D /* ConfigurationProxy.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "1250"
|
LastUpgradeVersion = "1420"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "1250"
|
LastUpgradeVersion = "1420"
|
||||||
wasCreatedForAppExtension = "YES"
|
wasCreatedForAppExtension = "YES"
|
||||||
version = "2.0">
|
version = "2.0">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
|
@ -84,6 +84,7 @@
|
||||||
savedToolIdentifier = ""
|
savedToolIdentifier = ""
|
||||||
useCustomWorkingDirectory = "NO"
|
useCustomWorkingDirectory = "NO"
|
||||||
debugDocumentVersioning = "YES"
|
debugDocumentVersioning = "YES"
|
||||||
|
askForAppToLaunch = "Yes"
|
||||||
launchAutomaticallySubstyle = "2">
|
launchAutomaticallySubstyle = "2">
|
||||||
<BuildableProductRunnable
|
<BuildableProductRunnable
|
||||||
runnableDebuggingMode = "0">
|
runnableDebuggingMode = "0">
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue