From 84912f4dea0520b6eb72f31f61eae7a6fa0be778 Mon Sep 17 00:00:00 2001 From: wangjia <809946525@qq.com> Date: Mon, 22 Jun 2026 19:06:20 +0800 Subject: [PATCH] =?UTF-8?q?docs(client/ios):=20iOS+iPad=20=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E8=AE=BE=E8=AE=A1=E6=96=B9=E6=A1=88(TestFlight=20?= =?UTF-8?q?=E9=87=8C=E7=A8=8B=E7=A2=91)+=20=E6=96=B0=E5=BB=BA=20docs=20?= =?UTF-8?q?=E7=B4=A2=E5=BC=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 五条工作线:libbox iOS 框架 / Provider 对齐 macOS 修复 / App Group IPC / iPad 布局横屏适配 / TestFlight 分发;头号风险 NE ~50MB 内存红线设双闸。 Co-Authored-By: Claude Opus 4.8 --- docs/index.html | 105 ++++++++++++++++ docs/ios-ipad-support-design.html | 193 ++++++++++++++++++++++++++++++ 2 files changed, 298 insertions(+) create mode 100644 docs/index.html create mode 100644 docs/ios-ipad-support-design.html diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..46dabcf --- /dev/null +++ b/docs/index.html @@ -0,0 +1,105 @@ + + + + + +Pangolin 文档索引 + + + +
+ +

Pangolin 文档索引

+

单一入口:本项目所有设计 / 计划 / 调研 / 排障文档汇总。新增文档须登记于此。

+ +
+

家族规范:设计/调研类新文档一律 HTML(深色主题、自包含);README / plan / CLAUDE.md / 代码内文档仍按既有形式。历史 .md 保留原状、逐步迁移。

+
+ +

设计方案

+
+
    +
  • + iOS + iPad 支持设计方案HTML +

    iOS 隧道从 PoC 桩推到真机连通 + TestFlight;五条工作线 + NE 50MB 内存闸门;iPad 布局适配(分支 feature/pangolin-ios

    +
  • +
  • + 技术方案MD +

    总体技术选型与架构

    +
  • +
  • + VPN 核心嵌入(方案B)MD +

    嵌入 libbox + 系统 VPN API 替换 sudo sing-box 的完整设计

    +
  • +
+
+ +

实现计划

+
+ +
+ +

知识库 / 调研

+
+ +
+ +

排障 Runbook

+
+ +
+ +
+ + diff --git a/docs/ios-ipad-support-design.html b/docs/ios-ipad-support-design.html new file mode 100644 index 0000000..a96b967 --- /dev/null +++ b/docs/ios-ipad-support-design.html @@ -0,0 +1,193 @@ + + + + + +iOS + iPad 支持设计方案 — Pangolin + + + +
+ +

iOS + iPad 支持设计方案

+

Pangolin Flutter 客户端 · 目标里程碑 TestFlight 公测 · 分支 feature/pangolin-ios · 2026-06-22

+ +
+

一句话:iOS 不是从零起步,而是停在一个 “M3 PoC” 半成品上 —— Xcode 工程、Swift 源码、entitlements、iPad 布局骨架都在,唯一硬阻塞是 Libbox.xcframework 只编了 macOS 切片。本方案把 iOS 隧道从「能编译的桩」推到「真机能连通、扛得住 NE 内存红线、可上 TestFlight」,iPad 跟着 iPhone 一起好(同一个 iOS target,非单独版本)。

+
+ +

1. 目标与范围

+ + + + + + +
维度本轮做本轮不做
连通性iPhone / iPad 真机真正连上网、出网走自有节点
分发App Store Connect 配置 + 描述文件 + TestFlight 外部测试完整 App Store 上架审核合规(隐私清单细节、审核问答)
iPad布局适配 + 横屏(宽屏主从/侧边栏,6 屏不拉伸)Split View / Stage Manager 动态重排、外接键盘/指针/拖拽
平台iOS 12+,设备族 iPhone + iPad(已是 "1,2"tvOS / visionOS
+

前置条件已具备:付费 Apple Developer 账号(TeamID BYL4KQHMTN),可上 App Store Connect。

+ +

2. 现状盘点(代码已有什么)

+ + + + + + + + + +
状态说明
Xcode 工程接线已有Runner + PacketTunnel 两 target 已接好;设备族 iPhone+iPad;部署目标 iOS 12
iOS Swift 源码PoC 桩PacketTunnelProvider.swift(20KB) / VpnManager.swift / MemoryMonitor.swift 在,但 Provider 未真正接通 libbox
entitlements已有正确的 iOS 格式:NE packet-tunnel-provider + App Group group.com.pangolin.pangolinVpn
Bundle ID已定主 App com.pangolin.pangolinVpn,扩展 com.pangolin.pangolinVpn.PacketTunnel
Libbox.xcframework缺 iOS 切片当前只有 macos-arm64_x86_64,缺 ios-arm64 + ios-arm64-simulator
DEVELOPMENT_TEAM未设iOS 工程未填 team(macOS 已填 BYL4KQHMTN
iPad 布局骨架shell/tablet_shell.dart + core/responsive/form_factor.dart 起步;design/ui_kits/tablet 有原型
+ +

iOS Provider 与 macOS 的差距(grep 实测)

+ + + + + + + +
关键修复点macOSiOS
后台队列启 libbox(防三方死锁)半(有 DispatchQueue.global,未接启动序列)
非空 LibboxOverrideOptions()(防 SIGSEGV)
阻塞式 startDefaultInterfaceMonitor
startOrReloadService 真正拉起 sing-box
DNS 劫持首条规则服务端渲染下发服务端渲染下发(同源,无需客户端改)
+ +

3. 架构决策:iOS Provider 实现策略

+
+

方案 A —— 移植成独立 iOS 版,两端各自维护 已选

+

仓库本就分 macos/PacketTunnelios/PacketTunnel。两端是真分叉:System Extension vs App Extension、App Group 前缀 BYL4KQHMTN. vs group.、iOS 独有 ~50MB 内存红线。接受可控重复,在 iOS Provider 文件头放一份「与 macOS 的 parity 对照」注释防漂移。

+

取舍:成本最低、最贴合现有结构。

+
+
+

方案 B(未选)—— 抽公共 Swift core 两端共享

+

把 interface monitor / libbox 启动序列 / 配置 IPC 抽成共享文件,平台只留差异 shim。无漂移,但要给 ios + macos 两个独立 Flutter 工程都接好跨 target 共享文件,Xcode 这块很折腾。抽象收益压不过两套工程的接线成本。

+
+ +

4. 五条工作线

+ +
+

① libbox iOS 框架(解阻塞)

+
    +
  • bash scripts/build-libbox.sh apple(不带 platform)→ 产出含 ios-arm64(真机) + ios-arm64-simulator 切片的 Libbox.xcframework,放 client/ios/Frameworks/
  • +
  • Xcode 接线照 macOS 铁律:只 Link 不 Embed(静态库);PacketTunnelOTHER_LDFLAGS="" 切断 CocoaPods 继承;otool -L 验扩展二进制零 @rpath 外部依赖。
  • +
  • iOS 真机签名走嵌入式 provisioning(比 macOS Developer ID 站外分发简单,无需 sysext 公证/staple)。
  • +
+
+ +
+

② iOS Provider 对齐 macOS 修复

+
    +
  • 移植四件套:后台队列启 libbox、非空 LibboxOverrideOptions()阻塞式 startDefaultInterfaceMonitor(阻塞到首个 path 更新再返回)、startOrReloadService 真正拉起 sing-box。
  • +
  • 配置由服务端 BuildClientConfig 渲染原样下发,客户端不拼;DNS 劫持首条规则随配置下发。
  • +
  • iOS 专属:接 MemoryMonitor(已写好)在真机跑满配置打点,验 NE 进程峰值 < 设备 jetsam 上限。
  • +
+
+ +
+

③ App Group / IPC

+
    +
  • entitlements 已是正确的 iOS group.com.pangolin.pangolinVpn,无需改格式。
  • +
  • ios/Runner.xcodeprojDEVELOPMENT_TEAM = BYL4KQHMTN(主 App + 扩展两 target)。
  • +
  • VpnManager.swift(主 App)↔ Provider 经 App Group UserDefaults 通 status/stats(含崩溃恢复读取)。
  • +
+
+ +
+

④ iPad UI 适配(布局 + 横屏)

+
    +
  • shell/tablet_shell.dart + core/responsive/form_factor.dart 做成完整宽屏主从/侧边栏。
  • +
  • 6 个 screen(connect / nodes / stats / settings / account / contact)在 iPad 竖/横屏不拉伸不空旷,对照 design/ui_kits/tablet 原型还原。
  • +
  • Info.plist 开 iPad 全向 orientation;遵守设计 token 单源(颜色走 token,不硬编码)。
  • +
+
+ +
+

⑤ 分发到 TestFlight

+
    +
  • 需用户在开发者后台手点(我给逐步清单):注册 App ID com.pangolin.pangolinVpn + extension ID + 勾 NE capability(packet-tunnel-provider) + 建 App Group。
  • +
  • 出口合规 ITSAppUsesNonExemptEncryption、Archive、上传、TestFlight 外部测试 beta 审核(比正式审核轻)。
  • +
+
+ +

5. 头号风险:iOS NE 内存红线

+
+

iOS Network Extension 进程 ~50MB 内存硬顶(旧设备 ~15MB)× sing-box + 远程 rule-set
+配置层 clientconfig.go 的国内分流走远程拉 geoip-cn.srs / geosite-cn.srs,启动期下载进内存,在 NE 进程里是 jetsam 杀进程的主因。

+

两道闸:

+
    +
  1. 先测:用 MemoryMonitor 在真机跑满配置,拿到峰值 resident 再决定。
  2. +
  3. 不够就瘦身:落 #5 TODO 的本地 .srs 预取(避免启动期下载进内存),必要时 iOS 走精简 rule-set。
  4. +
+

⚠️ TestFlight 推送以「内存实测通过」为前置闸门 —— 内存不过关不推。

+
+ +

其他风险

+ + + + + +
风险缓解
iOS Provider 移植引入新死锁/崩溃严格照 macos-sysext 排障 runbook 的铁律;真机 device console 验证
受限网络封高位端口REALITY 数据口优先走节点 443(与 iPhone/macOS 同策略)
iPad 布局漂移设计稿对照 design/ui_kits/tablet 原型;遵守 token 单源
+ +

6. 验收标准(Definition of Done)

+
    +
  1. scripts/build-libbox.sh apple 产出含 iOS 切片的 xcframework,otool -L 验扩展零外部 @rpath 依赖。
  2. +
  3. iPhone 真机:开关 VPN → sing-box 真正起来 → 能打开境外站点(DNS 不失败)。
  4. +
  5. iPad 真机:同上连通;竖/横屏布局对照原型无拉伸/空旷。
  6. +
  7. MemoryMonitor 真机峰值 < 设备 jetsam 上限(10 分钟稳定运行不被杀)。
  8. +
  9. 成功 Archive 并上传 TestFlight,外部测试者可安装并连通。
  10. +
+ +

7. 不做(YAGNI)

+ + +
+

下一步:进 writing-plans 出逐步实施计划。本文档登记于 docs/index.html

+ +
+ +