// PacketTunnelProvider.swift — Packet Tunnel Extension 骨架 // // Target: PacketTunnel (NEPacketTunnelProvider extension) // Bundle: com.pangolin.pangolinVpn.PacketTunnel // // 生命周期占位日志;实际 TUN 隧道建立与 libbox 接线由 11F 完成。 // // 与主 App 通信: // 主 App → extension: NETunnelProviderSession.sendProviderMessage(_:responseHandler:) // extension → 主 App: 通过 NEProvider.cancelTunnelWithError 或 NETunnelProviderSession 回调 // // TODO(11F): 在 startTunnel 中初始化 sing-box/libbox TUN 模式内核。 import NetworkExtension import os.log class PacketTunnelProvider: NEPacketTunnelProvider { private let log = OSLog( subsystem: "com.pangolin.pangolinVpn.PacketTunnel", category: "VPN" ) // ── NEPacketTunnelProvider 生命周期 ────────────────────────── override func startTunnel( options: [String: NSObject]?, completionHandler: @escaping (Error?) -> Void ) { os_log( "PacketTunnelProvider: startTunnel — options keys: %{public}@", log: log, type: .info, (options?.keys.joined(separator: ", ") ?? "(none)") ) // TODO(11F): 解析 options["config"] → 写入临时配置文件 // → 调用 libbox/sing-box TUN 启动 API // → 配置 packetFlow / setTunnelNetworkSettings completionHandler(nil) } override func stopTunnel( with reason: NEProviderStopReason, completionHandler: @escaping () -> Void ) { os_log( "PacketTunnelProvider: stopTunnel — reason=%d", log: log, type: .info, reason.rawValue ) // TODO(11F): 停止 sing-box 内核 → 关闭 TUN fd completionHandler() } override func handleAppMessage( _ messageData: Data, completionHandler: ((Data?) -> Void)? ) { os_log( "PacketTunnelProvider: handleAppMessage — %d bytes", log: log, type: .debug, messageData.count ) // TODO(11F): 解码 messageData(JSON 或 protobuf)→ 路由到内核命令 // 如 selectOutbound / getStats 等 completionHandler?(nil) } override func sleep(completionHandler: @escaping () -> Void) { os_log("PacketTunnelProvider: sleep", log: log, type: .debug) // TODO(11F): 挂起内核流量处理 completionHandler() } override func wake() { os_log("PacketTunnelProvider: wake", log: log, type: .debug) // TODO(11F): 恢复内核流量处理 } }