mirror of
https://github.com/DefinedNet/mobile_nebula.git
synced 2025-09-05 10:46:04 +00:00
Compare commits
10 commits
d32d9ccd7f
...
043336c627
Author | SHA1 | Date | |
---|---|---|---|
|
043336c627 | ||
|
3ec8868982 | ||
|
281d690ef3 | ||
|
a32d17705c | ||
|
df4c3a51b8 | ||
|
8e9b5fcc4a | ||
|
f3882997be | ||
|
bc67c06ef7 | ||
|
500e49edc3 | ||
|
ae34c59456 |
9 changed files with 49 additions and 30 deletions
|
@ -23,7 +23,7 @@ extension AppMessageError: LocalizedError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PacketTunnelProvider: NEPacketTunnelProvider {
|
class PacketTunnelProvider: NEPacketTunnelProvider, @unchecked Sendable {
|
||||||
private var networkMonitor: NWPathMonitor?
|
private var networkMonitor: NWPathMonitor?
|
||||||
|
|
||||||
private var site: Site?
|
private var site: Site?
|
||||||
|
|
|
@ -6,7 +6,7 @@ import os.log
|
||||||
let log = Logger(subsystem: "net.defined.mobileNebula", category: "Site")
|
let log = Logger(subsystem: "net.defined.mobileNebula", category: "Site")
|
||||||
|
|
||||||
enum SiteError: Error {
|
enum SiteError: Error {
|
||||||
case nonConforming(site: [String: Any]?)
|
case nonConforming(site: String)
|
||||||
case noCertificate
|
case noCertificate
|
||||||
case keyLoad
|
case keyLoad
|
||||||
case keySave
|
case keySave
|
||||||
|
@ -22,7 +22,7 @@ extension SiteError: CustomStringConvertible {
|
||||||
public var description: String {
|
public var description: String {
|
||||||
switch self {
|
switch self {
|
||||||
case .nonConforming(let site):
|
case .nonConforming(let site):
|
||||||
return String("Non-conforming site \(String(describing: site))")
|
return String("Non-conforming site \(site)")
|
||||||
case .noCertificate:
|
case .noCertificate:
|
||||||
return "No certificate found"
|
return "No certificate found"
|
||||||
case .keyLoad:
|
case .keyLoad:
|
||||||
|
@ -150,7 +150,7 @@ let statusString: [NEVPNStatus: String] = [
|
||||||
]
|
]
|
||||||
|
|
||||||
// Represents a site that was pulled out of the system configuration
|
// Represents a site that was pulled out of the system configuration
|
||||||
class Site: Codable {
|
class Site: Codable, @unchecked Sendable {
|
||||||
// Stored in manager
|
// Stored in manager
|
||||||
var name: String
|
var name: String
|
||||||
var id: String
|
var id: String
|
||||||
|
@ -208,7 +208,7 @@ class Site: Codable {
|
||||||
|
|
||||||
let id = dict?["id"] as? String ?? nil
|
let id = dict?["id"] as? String ?? nil
|
||||||
if id == nil {
|
if id == nil {
|
||||||
throw SiteError.nonConforming(site: dict)
|
throw SiteError.nonConforming(site: String(describing: dict))
|
||||||
}
|
}
|
||||||
|
|
||||||
try self.init(path: SiteList.getSiteConfigFile(id: id!, createDir: false))
|
try self.init(path: SiteList.getSiteConfigFile(id: id!, createDir: false))
|
||||||
|
|
|
@ -563,6 +563,7 @@
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
|
SWIFT_STRICT_CONCURRENCY = complete;
|
||||||
SWIFT_UPCOMING_FEATURE_CONCISE_MAGIC_FILE = YES;
|
SWIFT_UPCOMING_FEATURE_CONCISE_MAGIC_FILE = YES;
|
||||||
SWIFT_UPCOMING_FEATURE_DEPRECATE_APPLICATION_MAIN = YES;
|
SWIFT_UPCOMING_FEATURE_DEPRECATE_APPLICATION_MAIN = YES;
|
||||||
SWIFT_UPCOMING_FEATURE_DISABLE_OUTWARD_ACTOR_ISOLATION = YES;
|
SWIFT_UPCOMING_FEATURE_DISABLE_OUTWARD_ACTOR_ISOLATION = YES;
|
||||||
|
@ -574,7 +575,7 @@
|
||||||
SWIFT_UPCOMING_FEATURE_INFER_SENDABLE_FROM_CAPTURES = YES;
|
SWIFT_UPCOMING_FEATURE_INFER_SENDABLE_FROM_CAPTURES = YES;
|
||||||
SWIFT_UPCOMING_FEATURE_ISOLATED_DEFAULT_VALUES = YES;
|
SWIFT_UPCOMING_FEATURE_ISOLATED_DEFAULT_VALUES = YES;
|
||||||
SWIFT_UPCOMING_FEATURE_REGION_BASED_ISOLATION = YES;
|
SWIFT_UPCOMING_FEATURE_REGION_BASED_ISOLATION = YES;
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 6.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
VALIDATE_PRODUCT = YES;
|
VALIDATE_PRODUCT = YES;
|
||||||
};
|
};
|
||||||
|
@ -784,6 +785,7 @@
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
|
SWIFT_STRICT_CONCURRENCY = complete;
|
||||||
SWIFT_UPCOMING_FEATURE_CONCISE_MAGIC_FILE = YES;
|
SWIFT_UPCOMING_FEATURE_CONCISE_MAGIC_FILE = YES;
|
||||||
SWIFT_UPCOMING_FEATURE_DEPRECATE_APPLICATION_MAIN = YES;
|
SWIFT_UPCOMING_FEATURE_DEPRECATE_APPLICATION_MAIN = YES;
|
||||||
SWIFT_UPCOMING_FEATURE_DISABLE_OUTWARD_ACTOR_ISOLATION = YES;
|
SWIFT_UPCOMING_FEATURE_DISABLE_OUTWARD_ACTOR_ISOLATION = YES;
|
||||||
|
@ -795,7 +797,7 @@
|
||||||
SWIFT_UPCOMING_FEATURE_INFER_SENDABLE_FROM_CAPTURES = YES;
|
SWIFT_UPCOMING_FEATURE_INFER_SENDABLE_FROM_CAPTURES = YES;
|
||||||
SWIFT_UPCOMING_FEATURE_ISOLATED_DEFAULT_VALUES = YES;
|
SWIFT_UPCOMING_FEATURE_ISOLATED_DEFAULT_VALUES = YES;
|
||||||
SWIFT_UPCOMING_FEATURE_REGION_BASED_ISOLATION = YES;
|
SWIFT_UPCOMING_FEATURE_REGION_BASED_ISOLATION = YES;
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 6.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
|
@ -849,6 +851,7 @@
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
SWIFT_COMPILATION_MODE = wholemodule;
|
SWIFT_COMPILATION_MODE = wholemodule;
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||||
|
SWIFT_STRICT_CONCURRENCY = complete;
|
||||||
SWIFT_UPCOMING_FEATURE_CONCISE_MAGIC_FILE = YES;
|
SWIFT_UPCOMING_FEATURE_CONCISE_MAGIC_FILE = YES;
|
||||||
SWIFT_UPCOMING_FEATURE_DEPRECATE_APPLICATION_MAIN = YES;
|
SWIFT_UPCOMING_FEATURE_DEPRECATE_APPLICATION_MAIN = YES;
|
||||||
SWIFT_UPCOMING_FEATURE_DISABLE_OUTWARD_ACTOR_ISOLATION = YES;
|
SWIFT_UPCOMING_FEATURE_DISABLE_OUTWARD_ACTOR_ISOLATION = YES;
|
||||||
|
@ -860,7 +863,7 @@
|
||||||
SWIFT_UPCOMING_FEATURE_INFER_SENDABLE_FROM_CAPTURES = YES;
|
SWIFT_UPCOMING_FEATURE_INFER_SENDABLE_FROM_CAPTURES = YES;
|
||||||
SWIFT_UPCOMING_FEATURE_ISOLATED_DEFAULT_VALUES = YES;
|
SWIFT_UPCOMING_FEATURE_ISOLATED_DEFAULT_VALUES = YES;
|
||||||
SWIFT_UPCOMING_FEATURE_REGION_BASED_ISOLATION = YES;
|
SWIFT_UPCOMING_FEATURE_REGION_BASED_ISOLATION = YES;
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 6.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
VALIDATE_PRODUCT = YES;
|
VALIDATE_PRODUCT = YES;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import MobileNebula
|
@preconcurrency import MobileNebula
|
||||||
|
|
||||||
enum APIClientError: Error {
|
enum APIClientError: Error {
|
||||||
case invalidCredentials
|
case invalidCredentials
|
||||||
}
|
}
|
||||||
|
|
||||||
class APIClient {
|
struct APIClient: Sendable {
|
||||||
let apiClient: MobileNebulaAPIClient
|
let apiClient: MobileNebulaAPIClient
|
||||||
let json = JSONDecoder()
|
let json = JSONDecoder()
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import Flutter
|
@preconcurrency import Flutter
|
||||||
import MobileNebula
|
import MobileNebula
|
||||||
import NetworkExtension
|
import NetworkExtension
|
||||||
import SwiftyJSON
|
import SwiftyJSON
|
||||||
|
@ -25,7 +25,8 @@ func MissingArgumentError(message: String, details: Any?) -> FlutterError {
|
||||||
) -> Bool {
|
) -> Bool {
|
||||||
GeneratedPluginRegistrant.register(with: self)
|
GeneratedPluginRegistrant.register(with: self)
|
||||||
|
|
||||||
dnUpdater.updateAllLoop { site in
|
Task {
|
||||||
|
for await site in dnUpdater.siteUpdates {
|
||||||
// Signal the site has changed in case the current site details screen is active
|
// Signal the site has changed in case the current site details screen is active
|
||||||
let container = self.sites?.getContainer(id: site.id)
|
let container = self.sites?.getContainer(id: site.id)
|
||||||
if container != nil {
|
if container != nil {
|
||||||
|
@ -37,6 +38,7 @@ func MissingArgumentError(message: String, details: Any?) -> FlutterError {
|
||||||
// Signal to the main screen to reload
|
// Signal to the main screen to reload
|
||||||
self.ui?.invokeMethod("refreshSites", arguments: nil)
|
self.ui?.invokeMethod("refreshSites", arguments: nil)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
guard let controller = window?.rootViewController as? FlutterViewController else {
|
guard let controller = window?.rootViewController as? FlutterViewController else {
|
||||||
fatalError("rootViewController is not type FlutterViewController")
|
fatalError("rootViewController is not type FlutterViewController")
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import os.log
|
import os.log
|
||||||
|
|
||||||
class DNUpdater {
|
class DNUpdater: @unchecked Sendable {
|
||||||
private let apiClient = APIClient()
|
private let apiClient = APIClient()
|
||||||
private let timer = RepeatingTimer(timeInterval: 15 * 60) // 15 * 60 is 15 minutes
|
private let timer = RepeatingTimer(timeInterval: 15 * 60) // 15 * 60 is 15 minutes
|
||||||
private let log = Logger(subsystem: "net.defined.mobileNebula", category: "DNUpdater")
|
private let log = Logger(subsystem: "net.defined.mobileNebula", category: "DNUpdater")
|
||||||
|
|
||||||
func updateAll(onUpdate: @escaping (Site) -> Void) {
|
func updateAll(onUpdate: @Sendable @escaping (Site) -> Void) {
|
||||||
_ = SiteList { (sites, _) -> Void in
|
_ = SiteList { (sites, _) -> Void in
|
||||||
// NEVPN seems to force us onto the main thread and we are about to make network calls that
|
// NEVPN seems to force us onto the main thread and we are about to make network calls that
|
||||||
// could block for a while. Push ourselves onto another thread to avoid blocking the UI.
|
// could block for a while. Push ourselves onto another thread to avoid blocking the UI.
|
||||||
|
@ -23,21 +23,33 @@ class DNUpdater {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateAllLoop(onUpdate: @escaping (Site) -> Void) {
|
func updateAllLoop(onUpdate: @Sendable @escaping (Site) -> Void) {
|
||||||
timer.eventHandler = {
|
timer.eventHandler = {
|
||||||
self.updateAll(onUpdate: onUpdate)
|
self.updateAll(onUpdate: onUpdate)
|
||||||
}
|
}
|
||||||
timer.resume()
|
timer.resume()
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateSingleLoop(site: Site, onUpdate: @escaping (Site) -> Void) {
|
// Site updates provides an async/await alternative to `.updateAllLoop` that doesn't require a sendable closure.
|
||||||
|
// https://developer.apple.com/documentation/swift/asyncstream
|
||||||
|
var siteUpdates: AsyncStream<Site> {
|
||||||
|
AsyncStream { continuation in
|
||||||
|
self.updateAllLoop(onUpdate: { site in
|
||||||
|
continuation.yield(site)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateSingleLoop(site: Site, onUpdate: @Sendable @escaping (Site) -> Void) {
|
||||||
timer.eventHandler = {
|
timer.eventHandler = {
|
||||||
self.updateSite(site: site, onUpdate: onUpdate)
|
self.updateSite(site: site, onUpdate: onUpdate)
|
||||||
}
|
}
|
||||||
timer.resume()
|
timer.resume()
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateSite(site: Site, onUpdate: @escaping (Site) -> Void) {
|
func updateSite(site: Site, onUpdate: @Sendable @escaping (Site) -> Void) {
|
||||||
do {
|
do {
|
||||||
if !site.managed {
|
if !site.managed {
|
||||||
return
|
return
|
||||||
|
|
|
@ -78,14 +78,14 @@ class Sites {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SiteUpdater: NSObject, FlutterStreamHandler {
|
class SiteUpdater: NSObject, FlutterStreamHandler, @unchecked Sendable {
|
||||||
private var eventSink: FlutterEventSink?
|
private var eventSink: FlutterEventSink?
|
||||||
private var eventChannel: FlutterEventChannel
|
private var eventChannel: FlutterEventChannel
|
||||||
private var site: Site
|
private var site: Site
|
||||||
private var notification: Any?
|
private var notification: Any?
|
||||||
public var startFunc: (() -> Void)?
|
public var startFunc: (() -> Void)?
|
||||||
private var configFd: Int32? = nil
|
private var configFd: Int32?
|
||||||
private var configObserver: (any DispatchSourceFileSystemObject)? = nil
|
private var configObserver: (any DispatchSourceFileSystemObject)?
|
||||||
|
|
||||||
init(messenger: any FlutterBinaryMessenger, site: Site) {
|
init(messenger: any FlutterBinaryMessenger, site: Site) {
|
||||||
do {
|
do {
|
||||||
|
|
|
@ -9,7 +9,7 @@ toolchain go1.22.4
|
||||||
require (
|
require (
|
||||||
github.com/DefinedNet/dnapi v0.0.0-20241212205635-1d1f0084d118
|
github.com/DefinedNet/dnapi v0.0.0-20241212205635-1d1f0084d118
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
github.com/slackhq/nebula v1.9.5
|
github.com/slackhq/nebula v1.9.6
|
||||||
golang.org/x/crypto v0.32.0
|
golang.org/x/crypto v0.32.0
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
)
|
)
|
||||||
|
|
|
@ -133,6 +133,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
|
||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/slackhq/nebula v1.9.5 h1:ZrxcvP/lxwFglaijmiwXLuCSkybZMJnqSYI1S8DtGnY=
|
github.com/slackhq/nebula v1.9.5 h1:ZrxcvP/lxwFglaijmiwXLuCSkybZMJnqSYI1S8DtGnY=
|
||||||
github.com/slackhq/nebula v1.9.5/go.mod h1:1+4q4wd3dDAjO8rKCttSb9JIVbklQhuJiBp5I0lbIsQ=
|
github.com/slackhq/nebula v1.9.5/go.mod h1:1+4q4wd3dDAjO8rKCttSb9JIVbklQhuJiBp5I0lbIsQ=
|
||||||
|
github.com/slackhq/nebula v1.9.6 h1:Fl0LE2dHDeVEK3R+un59Z3V4ZzbZ6q2e/zF4ClaD5yo=
|
||||||
|
github.com/slackhq/nebula v1.9.6/go.mod h1:1+4q4wd3dDAjO8rKCttSb9JIVbklQhuJiBp5I0lbIsQ=
|
||||||
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 h1:TG/diQgUe0pntT/2D9tmUCz4VNwm9MfrtPr0SU2qSX8=
|
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 h1:TG/diQgUe0pntT/2D9tmUCz4VNwm9MfrtPr0SU2qSX8=
|
||||||
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E=
|
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
|
Loading…
Add table
Reference in a new issue