Skip to content

Commit

Permalink
Merge pull request #350 from amirsaam/main
Browse files Browse the repository at this point in the history
ios log handler base functionality
  • Loading branch information
hiddify-com authored Jan 20, 2024
2 parents 96cf192 + 27411da commit 61db308
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 43 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ release: # Create a new tag for release.
ios-temp-prepare:
flutter upgrade
flutter clean
flutter pub upgrade
# flutter pub upgrade
make prepare platform=ios
# make get-geo-assets
# make get
Expand Down
3 changes: 1 addition & 2 deletions ios/Local Packages/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ let package = Package(
name: "Libcore",
platforms: [
// Minimum platform version
.iOS(.v13),
.tvOS(.v13)
.iOS(.v13)
],
products: [
.library(
Expand Down
3 changes: 3 additions & 0 deletions ios/Runner/Handlers/LogsEventHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ public class LogsEventHandler: NSObject, FlutterPlugin, FlutterStreamHandler {
}

public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
if VPNManager.shared.logCallback {
events(VPNManager.shared.logList)
}
return nil
}

Expand Down
117 changes: 77 additions & 40 deletions ios/Runner/VPN/VPNManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class VPNManager: ObservableObject {
@Published private(set) var upload: Int64 = 0
@Published private(set) var download: Int64 = 0
@Published private(set) var elapsedTime: TimeInterval = 0
@Published private(set) var logList: [String] = []
@Published private(set) var logCallback = false

private var _connectTime: Date?
private var connectTime: Date? {
Expand Down Expand Up @@ -83,30 +85,42 @@ class VPNManager: ObservableObject {
func setup() async throws {
// guard !loaded else { return }
loaded = true
try await loadVPNPreference()
do {
try await loadVPNPreference()
} catch {
onServiceWriteLog(message: error.localizedDescription)
}
}

private func loadVPNPreference() async throws {
let managers = try await NETunnelProviderManager.loadAllFromPreferences()
if let manager = managers.first {
self.manager = manager
return
do {
let managers = try await NETunnelProviderManager.loadAllFromPreferences()
if let manager = managers.first {
self.manager = manager
return
}
let newManager = NETunnelProviderManager()
let `protocol` = NETunnelProviderProtocol()
`protocol`.providerBundleIdentifier = "app.hiddify.com.SingBoxPacketTunnel"
`protocol`.serverAddress = "localhost"
newManager.protocolConfiguration = `protocol`
newManager.localizedDescription = "Hiddify"
try await newManager.saveToPreferences()
try await newManager.loadFromPreferences()
self.manager = newManager
} catch {
onServiceWriteLog(message: error.localizedDescription)
}
let newManager = NETunnelProviderManager()
let `protocol` = NETunnelProviderProtocol()
`protocol`.providerBundleIdentifier = "app.hiddify.com.SingBoxPacketTunnel"
`protocol`.serverAddress = "localhost"
newManager.protocolConfiguration = `protocol`
newManager.localizedDescription = "Hiddify"
try await newManager.saveToPreferences()
try await newManager.loadFromPreferences()
self.manager = newManager
}

private func enableVPNManager() async throws {
manager.isEnabled = true
try await manager.saveToPreferences()
try await manager.loadFromPreferences()
do {
try await manager.saveToPreferences()
try await manager.loadFromPreferences()
} catch {
onServiceWriteLog(message: error.localizedDescription)
}
}

@MainActor private func set(upload: Int64, download: Int64) {
Expand All @@ -121,7 +135,7 @@ class VPNManager: ObservableObject {
return false
}
for key: String in keys.allKeys as! [String] {
if (key == "tap" || key == "tun" || key == "ppp" || key == "ipsec" || key == "ipsec0" || key == "utun1" || key == "utun2") {
if key == "tap" || key == "tun" || key == "ppp" || key == "ipsec" || key == "ipsec0" {
return true
} else if key.starts(with: "utun") {
return true
Expand All @@ -138,11 +152,15 @@ class VPNManager: ObservableObject {
$state.filter { $0 == .disconnected || $0 == .invalid }.first().sink { [weak self] _ in
Task { [weak self] () in
self?.manager = .shared()
let managers = try? await NETunnelProviderManager.loadAllFromPreferences()
for manager in managers ?? [] {
try? await manager.removeFromPreferences()
do {
let managers = try await NETunnelProviderManager.loadAllFromPreferences()
for manager in managers ?? [] {
try await manager.removeFromPreferences()
}
try await self?.loadVPNPreference()
} catch {
onServiceWriteLog(message: error.localizedDescription)
}
try? await self?.loadVPNPreference()
}
}.store(in: &cancelBag)

Expand All @@ -155,31 +173,39 @@ class VPNManager: ObservableObject {
}
guard state == .connected else { return }
guard let connection = manager.connection as? NETunnelProviderSession else { return }
try? connection.sendProviderMessage("stats".data(using: .utf8)!) { [weak self] response in
guard
let response,
let response = String(data: response, encoding: .utf8)
else { return }
let responseComponents = response.components(separatedBy: ",")
guard
responseComponents.count == 2,
let upload = Int64(responseComponents[0]),
let download = Int64(responseComponents[1])
else { return }
Task { [upload, download, weak self] () in
await self?.set(upload: upload, download: download)
do {
try connection.sendProviderMessage("stats".data(using: .utf8)!) { [weak self] response in
guard
let response,
let response = String(data: response, encoding: .utf8)
else { return }
let responseComponents = response.components(separatedBy: ",")
guard
responseComponents.count == 2,
let upload = Int64(responseComponents[0]),
let download = Int64(responseComponents[1])
else { return }
Task { [upload, download, weak self] () in
await self?.set(upload: upload, download: download)
}
}
} catch {
onServiceWriteLog(message: error.localizedDescription)
}
}

func connect(with config: String, disableMemoryLimit: Bool = false) async throws {
await set(upload: 0, download: 0)
guard state == .disconnected else { return }
try await enableVPNManager()
try manager.connection.startVPNTunnel(options: [
"Config": config as NSString,
"DisableMemoryLimit": (disableMemoryLimit ? "YES" : "NO") as NSString,
])
do {
try await enableVPNManager()
try manager.connection.startVPNTunnel(options: [
"Config": config as NSString,
"DisableMemoryLimit": (disableMemoryLimit ? "YES" : "NO") as NSString,
])
} catch {
onServiceWriteLog(message: error.localizedDescription)
}
connectTime = .now
}

Expand All @@ -188,5 +214,16 @@ class VPNManager: ObservableObject {
manager.connection.stopVPNTunnel()
}

}
func onServiceWriteLog(message: String) {
logCallback = true
if logList.count > 300 {
logList.removeFirst()
}
logList.append(message)
}

func onServiceResetLogs() {
logCallback = false
logList.removeAll()
}
}

0 comments on commit 61db308

Please sign in to comment.