Release 3.8.2.13: iOS Packet Tunnel client and Clash URL subscriptions.
ci / test (macos-latest) (push) Waiting to run
ci / test (ubuntu-latest) (push) Waiting to run
ci / test (windows-latest) (push) Waiting to run

Add SwiftUI + Network Extension (LibXray/hev), parse Clash Meta YAML from subscription URLs into vless/trojan/hy2 share links, keep the selected server on connect, and ship Navis-3.8.2.13.ipa with versioned changelog.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
M4
2026-08-01 22:46:32 +03:00
co-authored by Cursor
parent 8b564110d5
commit 7ceb3a5148
44 changed files with 4165 additions and 72 deletions
+42
View File
@@ -0,0 +1,42 @@
import Foundation
import Darwin
import NetworkExtension
enum TunFileDescriptor {
/// Locate the utun socket used by NEPacketTunnelProvider (unsupported but widely used).
static func find() -> Int32? {
if let fd = packetFlowKVO() {
return fd
}
return findUtunByGetsockopt()
}
private static func packetFlowKVO() -> Int32? {
// Caller may set via associated object; left for PacketTunnelProvider to try first.
nil
}
private static func findUtunByGetsockopt() -> Int32? {
var buf = [CChar](repeating: 0, count: Int(IFNAMSIZ))
let prefix = Array("utun".utf8CString.dropLast())
for fd: Int32 in 0...1024 {
var len = socklen_t(buf.count)
// SOL_LOCAL=0 / SYSPROTO_CONTROL path varies; use getsockopt(fd, 2, 2) like WireGuard/others.
if getsockopt(fd, 2, 2, &buf, &len) == 0 {
if buf.starts(with: prefix) {
return fd
}
}
}
return nil
}
}
extension NEPacketTunnelProvider {
func resolveTunnelFileDescriptor() -> Int32? {
if let fd = packetFlow.value(forKeyPath: "socket.fileDescriptor") as? Int32, fd >= 0 {
return fd
}
return TunFileDescriptor.find()
}
}