Release 3.8.2.13: iOS Packet Tunnel client and Clash URL subscriptions.
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:
@@ -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()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user