Simplified process startup on macOS and Linux
This commit is contained in:
parent
9e03c9680c
commit
b462f3fb6c
40 changed files with 1343 additions and 1157 deletions
|
|
@ -39,10 +39,10 @@ extension Tunnel {
|
|||
var isOn: Binding<Bool> {
|
||||
Binding {
|
||||
switch self.status {
|
||||
case .unknown, .disabled, .disconnecting, .disconnected, .invalid, .permissionRequired, .configurationReadWriteFailed:
|
||||
return false
|
||||
case .connecting, .reasserting, .connected:
|
||||
return true
|
||||
true
|
||||
default:
|
||||
false
|
||||
}
|
||||
} set: { newValue in
|
||||
switch (self.status, newValue) {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
import Combine
|
||||
import BurrowShared
|
||||
import NetworkExtension
|
||||
import SwiftUI
|
||||
|
||||
@Observable class Tunnel {
|
||||
@Observable
|
||||
class Tunnel {
|
||||
private(set) var status: Status = .unknown
|
||||
private var error: NEVPNError?
|
||||
|
||||
private let logger = Logger.logger(for: Tunnel.self)
|
||||
private let bundleIdentifier: String
|
||||
private let configure: (NETunnelProviderManager, NETunnelProviderProtocol) -> Void
|
||||
private var tasks: [Task<Void, Error>] = []
|
||||
|
|
@ -49,33 +51,34 @@ import SwiftUI
|
|||
self.bundleIdentifier = bundleIdentifier
|
||||
self.configure = configure
|
||||
|
||||
listenForUpdates()
|
||||
Task { await update() }
|
||||
}
|
||||
|
||||
private func listenForUpdates() {
|
||||
let center = NotificationCenter.default
|
||||
let statusTask = Task {
|
||||
for try await _ in center.notifications(named: .NEVPNStatusDidChange).map({ _ in () }) {
|
||||
status = currentStatus
|
||||
}
|
||||
}
|
||||
let configurationTask = Task {
|
||||
let configurationChanged = Task {
|
||||
for try await _ in center.notifications(named: .NEVPNConfigurationChange).map({ _ in () }) {
|
||||
await update()
|
||||
}
|
||||
}
|
||||
tasks = [statusTask, configurationTask]
|
||||
let statusChanged = Task {
|
||||
for try await _ in center.notifications(named: .NEVPNStatusDidChange).map({ _ in () }) {
|
||||
await MainActor.run {
|
||||
status = currentStatus
|
||||
}
|
||||
}
|
||||
}
|
||||
tasks = [configurationChanged, statusChanged]
|
||||
|
||||
Task { await update() }
|
||||
}
|
||||
|
||||
private func update() async {
|
||||
do {
|
||||
let updated = try await NETunnelProviderManager.managers
|
||||
await MainActor.run { managers = updated }
|
||||
await MainActor.run {
|
||||
managers = updated
|
||||
}
|
||||
} catch let vpnError as NEVPNError {
|
||||
error = vpnError
|
||||
} catch {
|
||||
print(error)
|
||||
logger.error("Failed to update VPN configurations: \(error)")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -117,9 +120,7 @@ import SwiftUI
|
|||
}
|
||||
|
||||
deinit {
|
||||
for task in tasks {
|
||||
task.cancel()
|
||||
}
|
||||
tasks.forEach { $0.cancel() }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -127,19 +128,19 @@ extension NEVPNConnection {
|
|||
var tunnelStatus: Tunnel.Status {
|
||||
switch status {
|
||||
case .connected:
|
||||
return .connected(connectedDate!)
|
||||
.connected(connectedDate!)
|
||||
case .connecting:
|
||||
return .connecting
|
||||
.connecting
|
||||
case .disconnecting:
|
||||
return .disconnecting
|
||||
.disconnecting
|
||||
case .disconnected:
|
||||
return .disconnected
|
||||
.disconnected
|
||||
case .reasserting:
|
||||
return .reasserting
|
||||
.reasserting
|
||||
case .invalid:
|
||||
return .invalid
|
||||
.invalid
|
||||
@unknown default:
|
||||
return .unknown
|
||||
.unknown
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,14 +8,20 @@
|
|||
|
||||
/* Begin PBXBuildFile section */
|
||||
0B28F1562ABF463A000D44B0 /* DataTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B28F1552ABF463A000D44B0 /* DataTypes.swift */; };
|
||||
0B46E8E02AC918CA00BA2A3C /* BurrowIpc.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B46E8DF2AC918CA00BA2A3C /* BurrowIpc.swift */; };
|
||||
0B46E8E02AC918CA00BA2A3C /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0B46E8DF2AC918CA00BA2A3C /* Client.swift */; };
|
||||
43AA26D82A10004900F14CE6 /* MenuView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43AA26D72A10004900F14CE6 /* MenuView.swift */; };
|
||||
D00117312B2FFFC900D87C25 /* NWConnection+Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00117302B2FFFC900D87C25 /* NWConnection+Async.swift */; };
|
||||
D00117332B3001A400D87C25 /* NewlineProtocolFramer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00117322B3001A400D87C25 /* NewlineProtocolFramer.swift */; };
|
||||
D001173B2B30341C00D87C25 /* Logging.swift in Sources */ = {isa = PBXBuildFile; fileRef = D001173A2B30341C00D87C25 /* Logging.swift */; };
|
||||
D00117442B30372900D87C25 /* libBurrowShared.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D00117382B30341C00D87C25 /* libBurrowShared.a */; };
|
||||
D00117452B30372C00D87C25 /* libBurrowShared.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D00117382B30341C00D87C25 /* libBurrowShared.a */; };
|
||||
D00AA8972A4669BC005C8102 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D00AA8962A4669BC005C8102 /* AppDelegate.swift */; };
|
||||
D020F65829E4A697002790F6 /* PacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = D020F65729E4A697002790F6 /* PacketTunnelProvider.swift */; };
|
||||
D020F65D29E4A697002790F6 /* BurrowNetworkExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = D020F65329E4A697002790F6 /* BurrowNetworkExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
D05B9F7629E39EEC008CB1F9 /* BurrowApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05B9F7529E39EEC008CB1F9 /* BurrowApp.swift */; };
|
||||
D05B9F7829E39EEC008CB1F9 /* TunnelView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05B9F7729E39EEC008CB1F9 /* TunnelView.swift */; };
|
||||
D05B9F7A29E39EED008CB1F9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D05B9F7929E39EED008CB1F9 /* Assets.xcassets */; };
|
||||
D08252762B5C9FC4005DA378 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08252752B5C9FC4005DA378 /* Constants.swift */; };
|
||||
D0BCC5FD2A086D4700AD070D /* NetworkExtension+Async.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BCC5FC2A086D4700AD070D /* NetworkExtension+Async.swift */; };
|
||||
D0BCC5FF2A086E1C00AD070D /* Status.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BCC5FE2A086E1C00AD070D /* Status.swift */; };
|
||||
D0BCC6082A0981FE00AD070D /* Tunnel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B98FC629FDC5B5004E7149 /* Tunnel.swift */; };
|
||||
|
|
@ -24,6 +30,20 @@
|
|||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
D00117462B30373100D87C25 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = D05B9F6A29E39EEC008CB1F9 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D00117372B30341C00D87C25;
|
||||
remoteInfo = Shared;
|
||||
};
|
||||
D00117482B30373500D87C25 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = D05B9F6A29E39EEC008CB1F9 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = D00117372B30341C00D87C25;
|
||||
remoteInfo = Shared;
|
||||
};
|
||||
D020F65B29E4A697002790F6 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = D05B9F6A29E39EEC008CB1F9 /* Project object */;
|
||||
|
|
@ -49,8 +69,14 @@
|
|||
|
||||
/* Begin PBXFileReference section */
|
||||
0B28F1552ABF463A000D44B0 /* DataTypes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataTypes.swift; sourceTree = "<group>"; };
|
||||
0B46E8DF2AC918CA00BA2A3C /* BurrowIpc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BurrowIpc.swift; sourceTree = "<group>"; };
|
||||
0B46E8DF2AC918CA00BA2A3C /* Client.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = "<group>"; };
|
||||
43AA26D72A10004900F14CE6 /* MenuView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuView.swift; sourceTree = "<group>"; };
|
||||
D00117302B2FFFC900D87C25 /* NWConnection+Async.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NWConnection+Async.swift"; sourceTree = "<group>"; };
|
||||
D00117322B3001A400D87C25 /* NewlineProtocolFramer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewlineProtocolFramer.swift; sourceTree = "<group>"; };
|
||||
D00117382B30341C00D87C25 /* libBurrowShared.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libBurrowShared.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D001173A2B30341C00D87C25 /* Logging.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logging.swift; sourceTree = "<group>"; };
|
||||
D00117412B30347800D87C25 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
|
||||
D00117422B30348D00D87C25 /* Shared.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Shared.xcconfig; sourceTree = "<group>"; };
|
||||
D00AA8962A4669BC005C8102 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
D020F63D29E4A1FF002790F6 /* Identity.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Identity.xcconfig; sourceTree = "<group>"; };
|
||||
D020F64029E4A1FF002790F6 /* Compiler.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Compiler.xcconfig; sourceTree = "<group>"; };
|
||||
|
|
@ -70,6 +96,8 @@
|
|||
D05B9F7529E39EEC008CB1F9 /* BurrowApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BurrowApp.swift; sourceTree = "<group>"; };
|
||||
D05B9F7729E39EEC008CB1F9 /* TunnelView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelView.swift; sourceTree = "<group>"; };
|
||||
D05B9F7929E39EED008CB1F9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
D08252742B5C9DEB005DA378 /* Constants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Constants.h; sourceTree = "<group>"; };
|
||||
D08252752B5C9FC4005DA378 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
|
||||
D0B98FBF29FD8072004E7149 /* build-rust.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "build-rust.sh"; sourceTree = "<group>"; };
|
||||
D0B98FC629FDC5B5004E7149 /* Tunnel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tunnel.swift; sourceTree = "<group>"; };
|
||||
D0B98FD829FDDB6F004E7149 /* libburrow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = libburrow.h; sourceTree = "<group>"; };
|
||||
|
|
@ -80,10 +108,18 @@
|
|||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
D00117352B30341C00D87C25 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D020F65029E4A697002790F6 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D00117442B30372900D87C25 /* libBurrowShared.a in Frameworks */,
|
||||
D0BCC6092A09A03E00AD070D /* libburrow.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
|
@ -92,6 +128,7 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D00117452B30372C00D87C25 /* libBurrowShared.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
@ -106,6 +143,33 @@
|
|||
path = Menu;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D00117392B30341C00D87C25 /* Shared */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D001173A2B30341C00D87C25 /* Logging.swift */,
|
||||
D08252752B5C9FC4005DA378 /* Constants.swift */,
|
||||
D00117422B30348D00D87C25 /* Shared.xcconfig */,
|
||||
D001173F2B30347800D87C25 /* Constants */,
|
||||
);
|
||||
path = Shared;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D001173F2B30347800D87C25 /* Constants */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D08252742B5C9DEB005DA378 /* Constants.h */,
|
||||
D00117412B30347800D87C25 /* module.modulemap */,
|
||||
);
|
||||
path = Constants;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D00117432B30372900D87C25 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D020F63C29E4A1FF002790F6 /* Configuration */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
|
@ -122,12 +186,14 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
D020F65729E4A697002790F6 /* PacketTunnelProvider.swift */,
|
||||
0B46E8DF2AC918CA00BA2A3C /* Client.swift */,
|
||||
0B28F1552ABF463A000D44B0 /* DataTypes.swift */,
|
||||
D00117322B3001A400D87C25 /* NewlineProtocolFramer.swift */,
|
||||
D00117302B2FFFC900D87C25 /* NWConnection+Async.swift */,
|
||||
D020F65929E4A697002790F6 /* Info.plist */,
|
||||
D020F66729E4A95D002790F6 /* NetworkExtension-iOS.entitlements */,
|
||||
D020F66629E4A95D002790F6 /* NetworkExtension-macOS.entitlements */,
|
||||
D020F66229E4A6E5002790F6 /* NetworkExtension.xcconfig */,
|
||||
0B28F1552ABF463A000D44B0 /* DataTypes.swift */,
|
||||
0B46E8DF2AC918CA00BA2A3C /* BurrowIpc.swift */,
|
||||
D0B98FD729FDDB57004E7149 /* libburrow */,
|
||||
);
|
||||
path = NetworkExtension;
|
||||
|
|
@ -138,8 +204,10 @@
|
|||
children = (
|
||||
D05B9F7429E39EEC008CB1F9 /* App */,
|
||||
D020F65629E4A697002790F6 /* NetworkExtension */,
|
||||
D00117392B30341C00D87C25 /* Shared */,
|
||||
D020F63C29E4A1FF002790F6 /* Configuration */,
|
||||
D05B9F7329E39EEC008CB1F9 /* Products */,
|
||||
D00117432B30372900D87C25 /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
|
|
@ -148,6 +216,7 @@
|
|||
children = (
|
||||
D05B9F7229E39EEC008CB1F9 /* Burrow.app */,
|
||||
D020F65329E4A697002790F6 /* BurrowNetworkExtension.appex */,
|
||||
D00117382B30341C00D87C25 /* libBurrowShared.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -184,6 +253,23 @@
|
|||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
D00117372B30341C00D87C25 /* Shared */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D001173C2B30341C00D87C25 /* Build configuration list for PBXNativeTarget "Shared" */;
|
||||
buildPhases = (
|
||||
D00117342B30341C00D87C25 /* Sources */,
|
||||
D00117352B30341C00D87C25 /* Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
D082527D2B5DEB80005DA378 /* PBXTargetDependency */,
|
||||
);
|
||||
name = Shared;
|
||||
productName = Shared;
|
||||
productReference = D00117382B30341C00D87C25 /* libBurrowShared.a */;
|
||||
productType = "com.apple.product-type.library.static";
|
||||
};
|
||||
D020F65229E4A697002790F6 /* NetworkExtension */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D020F65E29E4A697002790F6 /* Build configuration list for PBXNativeTarget "NetworkExtension" */;
|
||||
|
|
@ -196,7 +282,8 @@
|
|||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
D08252712B5C3E2E005DA378 /* PBXTargetDependency */,
|
||||
D08252792B5DEB78005DA378 /* PBXTargetDependency */,
|
||||
D00117492B30373500D87C25 /* PBXTargetDependency */,
|
||||
);
|
||||
name = NetworkExtension;
|
||||
productName = BurrowNetworkExtension;
|
||||
|
|
@ -215,7 +302,8 @@
|
|||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
D08252732B5C3E33005DA378 /* PBXTargetDependency */,
|
||||
D082527B2B5DEB7D005DA378 /* PBXTargetDependency */,
|
||||
D00117472B30373100D87C25 /* PBXTargetDependency */,
|
||||
D020F65C29E4A697002790F6 /* PBXTargetDependency */,
|
||||
);
|
||||
name = App;
|
||||
|
|
@ -230,9 +318,12 @@
|
|||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = 1;
|
||||
LastSwiftUpdateCheck = 1430;
|
||||
LastUpgradeCheck = 1510;
|
||||
LastSwiftUpdateCheck = 1510;
|
||||
LastUpgradeCheck = 1430;
|
||||
TargetAttributes = {
|
||||
D00117372B30341C00D87C25 = {
|
||||
CreatedOnToolsVersion = 15.1;
|
||||
};
|
||||
D020F65229E4A697002790F6 = {
|
||||
CreatedOnToolsVersion = 14.3;
|
||||
};
|
||||
|
|
@ -251,7 +342,7 @@
|
|||
);
|
||||
mainGroup = D05B9F6929E39EEC008CB1F9;
|
||||
packageReferences = (
|
||||
D082526F2B5C3E23005DA378 /* XCRemoteSwiftPackageReference "SwiftLint" */,
|
||||
D08252772B5DEB6E005DA378 /* XCRemoteSwiftPackageReference "SwiftLint" */,
|
||||
);
|
||||
productRefGroup = D05B9F7329E39EEC008CB1F9 /* Products */;
|
||||
projectDirPath = "";
|
||||
|
|
@ -259,6 +350,7 @@
|
|||
targets = (
|
||||
D05B9F7129E39EEC008CB1F9 /* App */,
|
||||
D020F65229E4A697002790F6 /* NetworkExtension */,
|
||||
D00117372B30341C00D87C25 /* Shared */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
|
@ -306,12 +398,23 @@
|
|||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
D00117342B30341C00D87C25 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D001173B2B30341C00D87C25 /* Logging.swift in Sources */,
|
||||
D08252762B5C9FC4005DA378 /* Constants.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D020F64F29E4A697002790F6 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D00117332B3001A400D87C25 /* NewlineProtocolFramer.swift in Sources */,
|
||||
0B28F1562ABF463A000D44B0 /* DataTypes.swift in Sources */,
|
||||
0B46E8E02AC918CA00BA2A3C /* BurrowIpc.swift in Sources */,
|
||||
D00117312B2FFFC900D87C25 /* NWConnection+Async.swift in Sources */,
|
||||
0B46E8E02AC918CA00BA2A3C /* Client.swift in Sources */,
|
||||
D020F65829E4A697002790F6 /* PacketTunnelProvider.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
|
@ -333,22 +436,50 @@
|
|||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
D00117472B30373100D87C25 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D00117372B30341C00D87C25 /* Shared */;
|
||||
targetProxy = D00117462B30373100D87C25 /* PBXContainerItemProxy */;
|
||||
};
|
||||
D00117492B30373500D87C25 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D00117372B30341C00D87C25 /* Shared */;
|
||||
targetProxy = D00117482B30373500D87C25 /* PBXContainerItemProxy */;
|
||||
};
|
||||
D020F65C29E4A697002790F6 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = D020F65229E4A697002790F6 /* NetworkExtension */;
|
||||
targetProxy = D020F65B29E4A697002790F6 /* PBXContainerItemProxy */;
|
||||
};
|
||||
D08252712B5C3E2E005DA378 /* PBXTargetDependency */ = {
|
||||
D08252792B5DEB78005DA378 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
productRef = D08252702B5C3E2E005DA378 /* SwiftLintPlugin */;
|
||||
productRef = D08252782B5DEB78005DA378 /* SwiftLintPlugin */;
|
||||
};
|
||||
D08252732B5C3E33005DA378 /* PBXTargetDependency */ = {
|
||||
D082527B2B5DEB7D005DA378 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
productRef = D08252722B5C3E33005DA378 /* SwiftLintPlugin */;
|
||||
productRef = D082527A2B5DEB7D005DA378 /* SwiftLintPlugin */;
|
||||
};
|
||||
D082527D2B5DEB80005DA378 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
productRef = D082527C2B5DEB80005DA378 /* SwiftLintPlugin */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
D001173D2B30341C00D87C25 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D00117422B30348D00D87C25 /* Shared.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
D001173E2B30341C00D87C25 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D00117422B30348D00D87C25 /* Shared.xcconfig */;
|
||||
buildSettings = {
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
D020F65F29E4A697002790F6 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D020F66229E4A6E5002790F6 /* NetworkExtension.xcconfig */;
|
||||
|
|
@ -394,6 +525,15 @@
|
|||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
D001173C2B30341C00D87C25 /* Build configuration list for PBXNativeTarget "Shared" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
D001173D2B30341C00D87C25 /* Debug */,
|
||||
D001173E2B30341C00D87C25 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
D020F65E29E4A697002790F6 /* Build configuration list for PBXNativeTarget "NetworkExtension" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
|
@ -424,7 +564,7 @@
|
|||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCRemoteSwiftPackageReference section */
|
||||
D082526F2B5C3E23005DA378 /* XCRemoteSwiftPackageReference "SwiftLint" */ = {
|
||||
D08252772B5DEB6E005DA378 /* XCRemoteSwiftPackageReference "SwiftLint" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/realm/SwiftLint.git";
|
||||
requirement = {
|
||||
|
|
@ -435,14 +575,19 @@
|
|||
/* End XCRemoteSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
D08252702B5C3E2E005DA378 /* SwiftLintPlugin */ = {
|
||||
D08252782B5DEB78005DA378 /* SwiftLintPlugin */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = D082526F2B5C3E23005DA378 /* XCRemoteSwiftPackageReference "SwiftLint" */;
|
||||
package = D08252772B5DEB6E005DA378 /* XCRemoteSwiftPackageReference "SwiftLint" */;
|
||||
productName = "plugin:SwiftLintPlugin";
|
||||
};
|
||||
D08252722B5C3E33005DA378 /* SwiftLintPlugin */ = {
|
||||
D082527A2B5DEB7D005DA378 /* SwiftLintPlugin */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = D082526F2B5C3E23005DA378 /* XCRemoteSwiftPackageReference "SwiftLint" */;
|
||||
package = D08252772B5DEB6E005DA378 /* XCRemoteSwiftPackageReference "SwiftLint" */;
|
||||
productName = "plugin:SwiftLintPlugin";
|
||||
};
|
||||
D082527C2B5DEB80005DA378 /* SwiftLintPlugin */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = D08252772B5DEB6E005DA378 /* XCRemoteSwiftPackageReference "SwiftLint" */;
|
||||
productName = "plugin:SwiftLintPlugin";
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
SKIP_INSTALL = NO
|
||||
MERGED_BINARY_TYPE = manual
|
||||
|
||||
LD_RUNPATH_SEARCH_PATHS[sdk=iphone*] = $(inherited) @executable_path/Frameworks
|
||||
LD_RUNPATH_SEARCH_PATHS[sdk=macosx*] = $(inherited) @executable_path/../Frameworks
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ CODE_SIGN_IDENTITY = Apple Development
|
|||
|
||||
INFOPLIST_FILE = Configuration/Info.plist
|
||||
GENERATE_INFOPLIST_FILE = YES
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = Copyright © 2023 Hack Club
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = Copyright © 2023-2024 Hack Club
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Burrow
|
||||
|
||||
ENABLE_BITCODE = NO
|
||||
|
|
|
|||
|
|
@ -1,2 +1,4 @@
|
|||
MERGED_BINARY_TYPE = manual
|
||||
|
||||
LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @executable_path/../../Frameworks
|
||||
LD_RUNPATH_SEARCH_PATHS[sdk=macos*] = $(inherited) @executable_path/../Frameworks @executable_path/../../../../Frameworks
|
||||
|
|
|
|||
|
|
@ -1,133 +0,0 @@
|
|||
import Foundation
|
||||
import Network
|
||||
import os
|
||||
|
||||
final class LineProtocol: NWProtocolFramerImplementation {
|
||||
static let definition = NWProtocolFramer.Definition(implementation: LineProtocol.self)
|
||||
static let label = "Lines"
|
||||
init(framer: NWProtocolFramer.Instance) { }
|
||||
func start(framer: NWProtocolFramer.Instance) -> NWProtocolFramer.StartResult { .ready }
|
||||
func stop(framer: NWProtocolFramer.Instance) -> Bool { true }
|
||||
func wakeup(framer: NWProtocolFramer.Instance) { }
|
||||
func cleanup(framer: NWProtocolFramer.Instance) { }
|
||||
func lines(from buffer: UnsafeMutableRawBufferPointer?) -> (lines: [Data], size: Int)? {
|
||||
guard let buffer = buffer else { return nil }
|
||||
let lines = buffer
|
||||
.split(separator: 10)
|
||||
guard !lines.isEmpty else { return nil }
|
||||
let size = lines
|
||||
.lazy
|
||||
.map(\.count)
|
||||
.reduce(0, +) + lines.count
|
||||
let strings = lines
|
||||
.lazy
|
||||
.map { Data($0) }
|
||||
return (lines: Array(strings), size: size)
|
||||
}
|
||||
func handleInput(framer: NWProtocolFramer.Instance) -> Int {
|
||||
var result: [Data] = []
|
||||
_ = framer.parseInput(minimumIncompleteLength: 1, maximumLength: 16_000) { buffer, _ in
|
||||
guard let (lines, size) = lines(from: buffer) else {
|
||||
return 0
|
||||
}
|
||||
result = lines
|
||||
return size
|
||||
}
|
||||
for line in result {
|
||||
framer.deliverInput(data: line, message: .init(instance: framer), isComplete: true)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
func handleOutput(
|
||||
framer: NWProtocolFramer.Instance,
|
||||
message: NWProtocolFramer.Message,
|
||||
messageLength: Int,
|
||||
isComplete: Bool
|
||||
) {
|
||||
do {
|
||||
try framer.writeOutputNoCopy(length: messageLength)
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension NWConnection {
|
||||
func receiveMessage() async throws -> (Data?, NWConnection.ContentContext?, Bool) {
|
||||
try await withUnsafeThrowingContinuation { continuation in
|
||||
receiveMessage { completeContent, contentContext, isComplete, error in
|
||||
if let error = error {
|
||||
continuation.resume(throwing: error)
|
||||
}
|
||||
continuation.resume(returning: (completeContent, contentContext, isComplete))
|
||||
}
|
||||
}
|
||||
}
|
||||
func send_raw(_ request: Data) async throws -> Data {
|
||||
try await withCheckedThrowingContinuation { continuation in
|
||||
let comp: NWConnection.SendCompletion = .contentProcessed {error in
|
||||
if let error = error {
|
||||
continuation.resume(with: .failure(error))
|
||||
} else {
|
||||
continuation.resume(with: .success(request))
|
||||
}
|
||||
}
|
||||
self.send(content: request, completion: comp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final class BurrowIpc {
|
||||
let connection: NWConnection
|
||||
private var generator = SystemRandomNumberGenerator()
|
||||
private var logger: Logger
|
||||
init(logger: Logger) {
|
||||
let params = NWParameters.tcp
|
||||
params.defaultProtocolStack
|
||||
.applicationProtocols
|
||||
.insert(NWProtocolFramer.Options(definition: LineProtocol.definition), at: 0)
|
||||
let connection = NWConnection(to: .unix(path: "burrow.sock"), using: params)
|
||||
connection.start(queue: .global())
|
||||
self.connection = connection
|
||||
self.logger = logger
|
||||
}
|
||||
func send<T: Request, U: Decodable>(_ request: T) async throws -> U {
|
||||
do {
|
||||
let id: UInt = generator.next(upperBound: UInt.max)
|
||||
var copy = request
|
||||
copy.id = id
|
||||
var data = try JSONEncoder().encode(request)
|
||||
data.append(contentsOf: [10])
|
||||
_ = try await self.connection.send_raw(data)
|
||||
return try JSONDecoder().decode(Response<U>.self, from: data).result
|
||||
} catch {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
func receive_raw() async throws -> Data {
|
||||
let (completeContent, _, _) = try await connection.receiveMessage()
|
||||
self.logger.info("Received raw message response")
|
||||
guard let data = completeContent else {
|
||||
throw BurrowError.resultIsNone
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func request<U: Decodable>(_ request: any Request, type: U.Type) async throws -> U {
|
||||
do {
|
||||
var data: Data = try JSONEncoder().encode(request)
|
||||
data.append(contentsOf: [10])
|
||||
_ = try await self.connection.send_raw(data)
|
||||
self.logger.debug("message sent")
|
||||
let receivedData = try await receive_raw()
|
||||
self.logger.info("Received result: \(String(decoding: receivedData, as: UTF8.self))")
|
||||
return try self.parse_response(receivedData)
|
||||
} catch {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
func parse_response<U: Decodable>(_ response: Data) throws -> U {
|
||||
try JSONDecoder().decode(U.self, from: response)
|
||||
}
|
||||
}
|
||||
60
Apple/NetworkExtension/Client.swift
Normal file
60
Apple/NetworkExtension/Client.swift
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
import BurrowShared
|
||||
import Foundation
|
||||
import Network
|
||||
|
||||
final class Client {
|
||||
let connection: NWConnection
|
||||
|
||||
private let logger: Logger = Logger.logger(for: Client.self)
|
||||
private var generator = SystemRandomNumberGenerator()
|
||||
|
||||
convenience init() throws {
|
||||
self.init(url: try Constants.socketURL)
|
||||
}
|
||||
|
||||
init(url: URL) {
|
||||
let endpoint: NWEndpoint
|
||||
if url.isFileURL {
|
||||
endpoint = .unix(path: url.path(percentEncoded: false))
|
||||
} else {
|
||||
endpoint = .url(url)
|
||||
}
|
||||
|
||||
let parameters = NWParameters.tcp
|
||||
parameters.defaultProtocolStack
|
||||
.applicationProtocols
|
||||
.insert(NWProtocolFramer.Options(definition: NewlineProtocolFramer.definition), at: 0)
|
||||
connection = NWConnection(to: endpoint, using: parameters)
|
||||
connection.start(queue: .global())
|
||||
}
|
||||
|
||||
func request<U: Decodable>(_ request: any Request, type: U.Type = U.self) async throws -> U {
|
||||
do {
|
||||
var copy = request
|
||||
copy.id = generator.next(upperBound: UInt.max)
|
||||
let content = try JSONEncoder().encode(copy)
|
||||
logger.debug("> \(String(decoding: content, as: UTF8.self))")
|
||||
|
||||
try await self.connection.send(content: content)
|
||||
let (response, _, _) = try await connection.receiveMessage()
|
||||
|
||||
logger.debug("< \(String(decoding: response, as: UTF8.self))")
|
||||
return try JSONDecoder().decode(U.self, from: response)
|
||||
} catch {
|
||||
logger.error("\(error, privacy: .public)")
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
connection.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
extension Constants {
|
||||
static var socketURL: URL {
|
||||
get throws {
|
||||
try groupContainerURL.appending(component: "burrow.sock", directoryHint: .notDirectory)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8,10 +8,11 @@ enum BurrowError: Error {
|
|||
case resultIsNone
|
||||
}
|
||||
|
||||
protocol Request: Codable where CommandT: Codable {
|
||||
associatedtype CommandT
|
||||
protocol Request: Codable where Command: Codable {
|
||||
associatedtype Command
|
||||
|
||||
var id: UInt { get set }
|
||||
var command: CommandT { get set }
|
||||
var command: Command { get set }
|
||||
}
|
||||
|
||||
struct BurrowSingleCommand: Request {
|
||||
|
|
@ -38,13 +39,6 @@ struct BurrowStartRequest: Codable {
|
|||
let Start: StartOptions
|
||||
}
|
||||
|
||||
func start_req_fd(id: UInt) -> BurrowRequest<BurrowStartRequest> {
|
||||
let command = BurrowStartRequest(Start: BurrowStartRequest.StartOptions(
|
||||
tun: BurrowStartRequest.TunOptions(name: nil, no_pi: false, tun_excl: false, tun_retrieve: true, address: nil)
|
||||
))
|
||||
return BurrowRequest(id: id, command: command)
|
||||
}
|
||||
|
||||
struct Response<T>: Decodable where T: Decodable {
|
||||
var id: UInt
|
||||
var result: T
|
||||
|
|
|
|||
32
Apple/NetworkExtension/NWConnection+Async.swift
Normal file
32
Apple/NetworkExtension/NWConnection+Async.swift
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
import Foundation
|
||||
import Network
|
||||
|
||||
extension NWConnection {
|
||||
// swiftlint:disable:next large_tuple
|
||||
func receiveMessage() async throws -> (Data, NWConnection.ContentContext?, Bool) {
|
||||
try await withUnsafeThrowingContinuation { continuation in
|
||||
receiveMessage { completeContent, contentContext, isComplete, error in
|
||||
if let error {
|
||||
continuation.resume(throwing: error)
|
||||
} else {
|
||||
guard let completeContent = completeContent else {
|
||||
fatalError("Both error and completeContent were nil")
|
||||
}
|
||||
continuation.resume(returning: (completeContent, contentContext, isComplete))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func send(content: Data) async throws {
|
||||
try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<Void, Error>) in
|
||||
send(content: content, completion: .contentProcessed { error in
|
||||
if let error {
|
||||
continuation.resume(throwing: error)
|
||||
} else {
|
||||
continuation.resume(returning: ())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,17 +2,19 @@
|
|||
<!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.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.server</key>
|
||||
<true/>
|
||||
<key>com.apple.developer.networking.networkextension</key>
|
||||
<array>
|
||||
<string>packet-tunnel-provider</string>
|
||||
</array>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>$(APP_GROUP_IDENTIFIER)</string>
|
||||
</array>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.server</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,6 @@ PRODUCT_BUNDLE_IDENTIFIER = $(NETWORK_EXTENSION_BUNDLE_IDENTIFIER)
|
|||
INFOPLIST_FILE = NetworkExtension/Info.plist
|
||||
|
||||
CODE_SIGN_ENTITLEMENTS = NetworkExtension/NetworkExtension-iOS.entitlements
|
||||
CODE_SIGN_ENTITLEMENTS[sdk=macos*] = NetworkExtension/NetworkExtension-macOS.entitlements
|
||||
CODE_SIGN_ENTITLEMENTS[sdk=macosx*] = NetworkExtension/NetworkExtension-macOS.entitlements
|
||||
|
||||
SWIFT_INCLUDE_PATHS = $(inherited) $(PROJECT_DIR)/NetworkExtension
|
||||
|
|
|
|||
54
Apple/NetworkExtension/NewlineProtocolFramer.swift
Normal file
54
Apple/NetworkExtension/NewlineProtocolFramer.swift
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
import Foundation
|
||||
import Network
|
||||
|
||||
final class NewlineProtocolFramer: NWProtocolFramerImplementation {
|
||||
private static let delimeter: UInt8 = 10 // `\n`
|
||||
|
||||
static let definition = NWProtocolFramer.Definition(implementation: NewlineProtocolFramer.self)
|
||||
static let label = "Lines"
|
||||
|
||||
init(framer: NWProtocolFramer.Instance) { }
|
||||
|
||||
func start(framer: NWProtocolFramer.Instance) -> NWProtocolFramer.StartResult { .ready }
|
||||
func stop(framer: NWProtocolFramer.Instance) -> Bool { true }
|
||||
|
||||
func wakeup(framer: NWProtocolFramer.Instance) { }
|
||||
func cleanup(framer: NWProtocolFramer.Instance) { }
|
||||
|
||||
func handleInput(framer: NWProtocolFramer.Instance) -> Int {
|
||||
while true {
|
||||
var result: [Data] = []
|
||||
let parsed = framer.parseInput(minimumIncompleteLength: 1, maximumLength: 16_000) { buffer, _ in
|
||||
guard let buffer else { return 0 }
|
||||
var lines = buffer
|
||||
.split(separator: Self.delimeter, omittingEmptySubsequences: false)
|
||||
.map { Data($0) }
|
||||
guard lines.count > 1 else { return 0 }
|
||||
_ = lines.popLast()
|
||||
|
||||
result = lines
|
||||
return lines.reduce(lines.count) { $0 + $1.count }
|
||||
}
|
||||
|
||||
guard parsed && !result.isEmpty else { break }
|
||||
|
||||
for line in result {
|
||||
framer.deliverInput(data: line, message: .init(instance: framer), isComplete: true)
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func handleOutput(
|
||||
framer: NWProtocolFramer.Instance,
|
||||
message: NWProtocolFramer.Message,
|
||||
messageLength: Int,
|
||||
isComplete: Bool
|
||||
) {
|
||||
do {
|
||||
try framer.writeOutputNoCopy(length: messageLength)
|
||||
framer.writeOutput(data: [Self.delimeter])
|
||||
} catch {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,51 +1,49 @@
|
|||
import BurrowShared
|
||||
import libburrow
|
||||
import NetworkExtension
|
||||
import os
|
||||
|
||||
class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
let logger = Logger(subsystem: "com.hackclub.burrow", category: "frontend")
|
||||
var client: BurrowIpc?
|
||||
var osInitialized = false
|
||||
private let logger = Logger.logger(for: PacketTunnelProvider.self)
|
||||
|
||||
override func startTunnel(options: [String: NSObject]? = nil) async throws {
|
||||
logger.log("Starting tunnel")
|
||||
if !osInitialized {
|
||||
libburrow.initialize_oslog()
|
||||
osInitialized = true
|
||||
}
|
||||
libburrow.start_srv()
|
||||
client = BurrowIpc(logger: logger)
|
||||
logger.info("Started server")
|
||||
do {
|
||||
let command = BurrowSingleCommand(id: 0, command: "ServerConfig")
|
||||
guard let data = try await client?.request(command, type: Response<BurrowResult<ServerConfigData>>.self)
|
||||
else {
|
||||
throw BurrowError.cantParseResult
|
||||
}
|
||||
libburrow.spawnInProcess(socketPath: try Constants.socketURL.path)
|
||||
|
||||
let client = try Client()
|
||||
|
||||
let command = BurrowRequest(id: 0, command: "ServerConfig")
|
||||
let data = try await client.request(command, type: Response<BurrowResult<ServerConfigData>>.self)
|
||||
|
||||
let encoded = try JSONEncoder().encode(data.result)
|
||||
self.logger.log("Received final data: \(String(decoding: encoded, as: UTF8.self))")
|
||||
guard let serverconfig = data.result.Ok else {
|
||||
throw BurrowError.resultIsError
|
||||
}
|
||||
guard let tunNs = self.generateTunSettings(from: serverconfig) else {
|
||||
guard let tunNs = generateTunSettings(from: serverconfig) else {
|
||||
throw BurrowError.addrDoesntExist
|
||||
}
|
||||
try await self.setTunnelNetworkSettings(tunNs)
|
||||
self.logger.info("Set remote tunnel address to \(tunNs.tunnelRemoteAddress)")
|
||||
|
||||
// let tunFd = self.packetFlow.value(forKeyPath: "socket.fileDescriptor") as! Int;
|
||||
// self.logger.info("Found File Descriptor: \(tunFd)")
|
||||
let startCommand = start_req_fd(id: 1)
|
||||
guard let data = try await client?.request(startCommand, type: Response<BurrowResult<String>>.self)
|
||||
else {
|
||||
throw BurrowError.cantParseResult
|
||||
}
|
||||
let encodedStartRes = try JSONEncoder().encode(data.result)
|
||||
self.logger.log("Received start server response: \(String(decoding: encodedStartRes, as: UTF8.self))")
|
||||
let startRequest = BurrowRequest(
|
||||
id: .random(in: (.min)..<(.max)),
|
||||
command: BurrowStartRequest(
|
||||
Start: BurrowStartRequest.StartOptions(
|
||||
tun: BurrowStartRequest.TunOptions(
|
||||
name: nil, no_pi: false, tun_excl: false, tun_retrieve: true, address: nil
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
let response = try await client.request(startRequest, type: Response<BurrowResult<String>>.self)
|
||||
self.logger.log("Received start server response: \(String(describing: response.result))")
|
||||
} catch {
|
||||
self.logger.error("An error occurred: \(error)")
|
||||
self.logger.error("Failed to start tunnel: \(error)")
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
private func generateTunSettings(from: ServerConfigData) -> NETunnelNetworkSettings? {
|
||||
let cfig = from.ServerConfig
|
||||
guard let addr = cfig.address else {
|
||||
|
|
@ -57,13 +55,4 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
|||
logger.log("Initialized ipv4 settings: \(nst.ipv4Settings)")
|
||||
return nst
|
||||
}
|
||||
override func stopTunnel(with reason: NEProviderStopReason) async {
|
||||
}
|
||||
override func handleAppMessage(_ messageData: Data) async -> Data? {
|
||||
messageData
|
||||
}
|
||||
override func sleep() async {
|
||||
}
|
||||
override func wake() {
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
void start_srv();
|
||||
void initialize_oslog();
|
||||
__attribute__((__swift_name__("spawnInProcess(socketPath:)")))
|
||||
extern void spawn_in_process(const char * __nullable path);
|
||||
|
|
|
|||
22
Apple/Shared/Constants.swift
Normal file
22
Apple/Shared/Constants.swift
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
@_implementationOnly import Constants
|
||||
|
||||
public enum Constants {
|
||||
enum Error: Swift.Error {
|
||||
case invalidAppGroupIdentifier
|
||||
}
|
||||
|
||||
public static let bundleIdentifier = AppBundleIdentifier
|
||||
public static let appGroupIdentifier = AppGroupIdentifier
|
||||
|
||||
public static var groupContainerURL: URL {
|
||||
get throws { try _groupContainerURL.get() }
|
||||
}
|
||||
|
||||
private static let _groupContainerURL: Result<URL, Error> = {
|
||||
guard let groupContainerURL = FileManager.default
|
||||
.containerURL(forSecurityApplicationGroupIdentifier: appGroupIdentifier) else {
|
||||
return .failure(.invalidAppGroupIdentifier)
|
||||
}
|
||||
return .success(groupContainerURL)
|
||||
}()
|
||||
}
|
||||
11
Apple/Shared/Constants/Constants.h
Normal file
11
Apple/Shared/Constants/Constants.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
#define MACRO_STRING_(m) #m
|
||||
#define MACRO_STRING(m) @MACRO_STRING_(m)
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
static NSString * const AppBundleIdentifier = MACRO_STRING(APP_BUNDLE_IDENTIFIER);
|
||||
static NSString * const AppGroupIdentifier = MACRO_STRING(APP_GROUP_IDENTIFIER);
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
4
Apple/Shared/Constants/module.modulemap
Normal file
4
Apple/Shared/Constants/module.modulemap
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
module Constants {
|
||||
header "Constants.h"
|
||||
export *
|
||||
}
|
||||
19
Apple/Shared/Logging.swift
Normal file
19
Apple/Shared/Logging.swift
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import os
|
||||
@_exported import OSLog
|
||||
|
||||
extension Logger {
|
||||
private static let loggers: OSAllocatedUnfairLock<[String: Logger]> = OSAllocatedUnfairLock(initialState: [:])
|
||||
|
||||
public static let subsystem = Constants.bundleIdentifier
|
||||
|
||||
public static func logger(for type: Any.Type) -> Logger {
|
||||
let category = String(describing: type)
|
||||
let logger = loggers.withLock { loggers in
|
||||
if let logger = loggers[category] { return logger }
|
||||
let logger = Logger(subsystem: subsystem, category: category)
|
||||
loggers[category] = logger
|
||||
return logger
|
||||
}
|
||||
return logger
|
||||
}
|
||||
}
|
||||
5
Apple/Shared/Shared.xcconfig
Normal file
5
Apple/Shared/Shared.xcconfig
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
PRODUCT_NAME = BurrowShared
|
||||
MERGEABLE_LIBRARY = YES
|
||||
|
||||
SWIFT_INCLUDE_PATHS = $(PROJECT_DIR)/Shared/Constants
|
||||
GCC_PREPROCESSOR_DEFINITIONS = APP_BUNDLE_IDENTIFIER=$(APP_BUNDLE_IDENTIFIER) APP_GROUP_IDENTIFIER=$(APP_GROUP_IDENTIFIER)
|
||||
Loading…
Add table
Add a link
Reference in a new issue