Add clash mode selector & always on
This commit is contained in:
@@ -11,6 +11,7 @@ public enum SharedPreferences {
|
||||
@Preference<Bool>("disable_memory_limit", defaultValue: disableMemoryLimitByDefault) public static var disableMemoryLimit
|
||||
|
||||
@Preference<Int>("max_log_lines", defaultValue: 300) public static var maxLogLines
|
||||
@Preference<Bool>("always_on", defaultValue: false) public static var alwaysOn
|
||||
|
||||
#if os(macOS)
|
||||
@Preference<Bool>("show_menu_bar_extra", defaultValue: true) public static var showMenuBarExtra
|
||||
|
||||
@@ -6,6 +6,7 @@ public class CommandClient: ObservableObject {
|
||||
case status
|
||||
case groups
|
||||
case log
|
||||
case clashMode
|
||||
}
|
||||
|
||||
private let connectionType: ConnectionType
|
||||
@@ -17,11 +18,15 @@ public class CommandClient: ObservableObject {
|
||||
@Published public var status: LibboxStatusMessage?
|
||||
@Published public var groups: [LibboxOutboundGroup]?
|
||||
@Published public var logList: [String]
|
||||
@Published public var clashModeList: [String]
|
||||
@Published public var clashMode: String
|
||||
|
||||
public init(_ connectionType: ConnectionType, logMaxLines: Int = 300) {
|
||||
self.connectionType = connectionType
|
||||
self.logMaxLines = logMaxLines
|
||||
logList = []
|
||||
clashModeList = []
|
||||
clashMode = ""
|
||||
isConnected = false
|
||||
}
|
||||
|
||||
@@ -57,6 +62,8 @@ public class CommandClient: ObservableObject {
|
||||
clientOptions.command = LibboxCommandGroup
|
||||
case .log:
|
||||
clientOptions.command = LibboxCommandLog
|
||||
case .clashMode:
|
||||
clientOptions.command = LibboxCommandClashMode
|
||||
}
|
||||
clientOptions.statusInterval = Int64(2 * NSEC_PER_SEC)
|
||||
let client = LibboxNewCommandClient(clientHandler(self), clientOptions)!
|
||||
@@ -68,6 +75,7 @@ public class CommandClient: ObservableObject {
|
||||
try client.connect()
|
||||
commandClient = client
|
||||
return
|
||||
} catch {
|
||||
}
|
||||
try Task.checkCancellation()
|
||||
}
|
||||
@@ -127,5 +135,18 @@ public class CommandClient: ObservableObject {
|
||||
self.commandClient.groups = newGroups
|
||||
}
|
||||
}
|
||||
|
||||
func initializeClashMode(_ modeList: LibboxStringIteratorProtocol?, currentMode: String?) {
|
||||
DispatchQueue.main.sync {
|
||||
self.commandClient.clashModeList = modeList!.toArray()
|
||||
self.commandClient.clashMode = currentMode!
|
||||
}
|
||||
}
|
||||
|
||||
func updateClashMode(_ newMode: String?) {
|
||||
DispatchQueue.main.sync {
|
||||
self.commandClient.clashMode = newMode!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import NetworkExtension
|
||||
public class ExtensionPlatformInterface: NSObject, LibboxPlatformInterfaceProtocol {
|
||||
private let tunnel: NEPacketTunnelProvider
|
||||
private let commandServer: LibboxCommandServer
|
||||
private var networkSettings: NEPacketTunnelNetworkSettings?
|
||||
|
||||
init(_ tunnel: NEPacketTunnelProvider, _ logServer: LibboxCommandServer) {
|
||||
self.tunnel = tunnel
|
||||
@@ -88,6 +89,7 @@ public class ExtensionPlatformInterface: NSObject, LibboxPlatformInterfaceProtoc
|
||||
settings.proxySettings = proxySettings
|
||||
}
|
||||
|
||||
networkSettings = settings
|
||||
try runBlocking { [self] in
|
||||
try await tunnel.setTunnelNetworkSettings(settings)
|
||||
}
|
||||
@@ -153,4 +155,21 @@ public class ExtensionPlatformInterface: NSObject, LibboxPlatformInterfaceProtoc
|
||||
public func underNetworkExtension() -> Bool {
|
||||
true
|
||||
}
|
||||
|
||||
public func clearDNSCache() {
|
||||
guard let networkSettings else {
|
||||
return
|
||||
}
|
||||
tunnel.reasserting = true
|
||||
tunnel.setTunnelNetworkSettings(nil) { _ in
|
||||
}
|
||||
tunnel.setTunnelNetworkSettings(networkSettings) { _ in
|
||||
}
|
||||
tunnel.reasserting = false
|
||||
}
|
||||
|
||||
public func closeTun() throws {
|
||||
tunnel.setTunnelNetworkSettings(nil) { _ in
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,8 +38,26 @@ public class ExtensionProfile: ObservableObject {
|
||||
}
|
||||
}
|
||||
|
||||
private func setOnDemandRules() {
|
||||
let interfaceRule = NEOnDemandRuleConnect()
|
||||
interfaceRule.interfaceTypeMatch = .any
|
||||
let probeRule = NEOnDemandRuleConnect()
|
||||
probeRule.probeURL = URL(string: "http://captive.apple.com")
|
||||
manager.onDemandRules = [interfaceRule, probeRule]
|
||||
}
|
||||
|
||||
public func updateAlwaysOn(_ newState: Bool) async throws {
|
||||
manager.isOnDemandEnabled = newState
|
||||
setOnDemandRules()
|
||||
try await manager.saveToPreferences()
|
||||
}
|
||||
|
||||
public func start() async throws {
|
||||
manager.isEnabled = true
|
||||
if SharedPreferences.alwaysOn {
|
||||
manager.isOnDemandEnabled = true
|
||||
setOnDemandRules()
|
||||
}
|
||||
try await manager.saveToPreferences()
|
||||
#if os(macOS)
|
||||
if Variant.useSystemExtension {
|
||||
@@ -53,6 +71,7 @@ public class ExtensionProfile: ObservableObject {
|
||||
}
|
||||
|
||||
public func stop() {
|
||||
manager.isOnDemandEnabled = false
|
||||
manager.connection.stopVPNTunnel()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user