diff --git a/多平台架构设计.md b/多平台架构设计.md index fa3e069..649c50a 100644 --- a/多平台架构设计.md +++ b/多平台架构设计.md @@ -189,7 +189,9 @@ pub enum Path { Direct { addr: SocketAddr }, Relay { endpoint: EndpointId } } --- -## 6. ⚠️ 必须现在拍板:手机主控 vs 不做中继 +## 6. ✅ 已裁决:不做中继(2026-10-28) + +> **裁决结论**:公司不提供中继服务器,中继不做。以下保留原始分析以免后人重蹈讨论。 **手机在蜂窝网络下几乎 100% 处于运营商级 NAT(CGNAT),打洞打不通。** 这不是实现问题,是网络事实——`100.64.0.0/10` 那段地址根本没给你可映射的公网端口。 @@ -197,16 +199,56 @@ pub enum Path { Direct { addr: SocketAddr }, Relay { endpoint: EndpointId } } 后果:**"主控端支持安卓/iOS" + "不做中继" = 手机只能在 WiFi 下用。** 地铁上、外面、用流量,一律连不上。 -三条出路,必须选一条: +三条出路: | 方案 | 代价 | 说明 | |---|---|---| -| **A. 只靠 IPv6** | 部分用户不可用 | 国内三大运营商 v6 覆盖率高,手机 v6 可用性远好于 v4 公网。**推荐先做,能覆盖大多数** | -| **B. 补一个只为移动端服务的中继** | 视频带宽成本 | 可用率 100%,但账单跟着视频流量走 | -| **C. 接受"手机只能 WiFi"** | 产品力受限 | 零成本,但要写进产品说明,别让用户以为坏了 | +| **A. 只靠 IPv6** | 部分用户不可用 | 国内三大运营商 v6 覆盖率高,手机 v6 可用性远好于 v4 公网 | +| B. 补一个只为移动端服务的中继 | 视频带宽成本 | **已排除:公司不提供额外服务器** | +| C. 接受"手机只能 WiFi" | 产品力受限 | 零成本,但要写进产品说明 | -**我的建议:A 先做(架构里 v6 是一等公民),B 的接口留在 `PathProvider` 里不给实现,等真要推移动端再决定。** -不要现在就把路堵死——留接口的成本几乎为零,推倒重来成本极高。 +### 6.1 裁决内容与边界(2026-10-28) + +| 项 | 裁决 | +|---|---| +| 中继 / TURN / relay 服务器 | **不做**。公司不提供额外服务器,且无预算计划 | +| IPv6 | **一等公民**。候选地址排序 v6 优先,`signaling.rs` 已实现 | +| 中继接口预留 | **不预留**。不写 `PathProvider` trait、不写 `Path::Relay` 变体 | +| 连接层边界 | **仍要做**。理由见 §6.2,与中继无关 | + +**为什么不留中继接口**:留接口的收益是「将来补中继不用动会话层」,但既然中继已被排除, +`Path::Relay` 这类变体永远不会被构造,只会产生 `dead_code` 警告,要么 `#[allow]` 要么日后删除。 +**零收益的预留就是纯负担。** + +### 6.2 连接层边界与中继接口是两件事 + +这两件事常被混为一谈,必须分开: + +| | 内容 | 现在做不做 | +|---|---|---| +| **连接层边界** | 把"怎么连"(信令/打洞/直连)与"连上干什么"(收流/解码/渲染)分开 | ✅ **要做** | +| **中继接口** | `enum Path { Direct, Relay }` 这类类型预留 | ❌ **不做** | + +连接层边界本身就有独立价值,与中继无关: + +1. **连接方式确定会变**:局域网 `IP:端口` → 将来设备码 + 打洞,这是已定的路线; +2. **安卓主控要复用**:`viewer-core` 收流解码渲染不应知道对面是怎么连上的; +3. **可测性**:解码逻辑能脱离真连接单独测试。 + +做法是把它抽成一个函数边界(输入目标描述、返回 `quinn::Connection`), +**不是**定义 trait 或枚举。 + +### 6.3 对产品的影响(必须写进对外说明) + +| 网络环境 | 能否连接 | +|---|---| +| 双方任一侧无公网 IPv6,且处于 CGNAT 后 | ❌ **无法连接,无解** | +| 双方都有公网 IPv6 | ✅ 可直连 | +| 局域网 / 双方都有可打洞的公网 IPv4 | ✅ 可直连 | +| 对称 NAT(双方) | ❌ 通常不通 | + +**这不是 bug,是已知边界。** 用户在外网连不上时,UI 必须给出可执行提示 +(`PunchFailReason::user_hint()` 已提供文案),不能停留在"连接中"。 --- @@ -263,7 +305,10 @@ pub enum Path { Direct { addr: SocketAddr }, Relay { endpoint: EndpointId } } ## 10. 开放问题(需要拍板) -1. 中继:确认走 §6 的 A 方案(v6 优先、留接口不实现)? +> §10 第 1 条已于 2026-10-28 裁决,见 §6。 + +1. ~~中继:确认走 §6 的 A 方案(v6 优先、留接口不实现)?~~ + **已裁决:不做中继、不留接口、v6 优先、但保留连接层边界。详见 §6.1 / §6.2。** 2. 移动端:先 Android 还是直接砍 iOS? 3. UI 框架:确认 Tauri v2,还是先原生桌面 + 后面再说移动? 4. 账号体系:现在是"输验证码",要支持设备列表就得有账号/设备 ID 体系——什么时候做? diff --git a/打洞与信令设计.md b/打洞与信令设计.md index 2b698bc..f289a5b 100644 --- a/打洞与信令设计.md +++ b/打洞与信令设计.md @@ -1,7 +1,9 @@ # 打洞与信令设计(无中继方案) -> 状态:协议契约已落在 `common/src/signaling.rs`,待 A 过审后合入 main。 +> 状态:协议契约已落在 `common/src/signaling.rs`,已合入 main(`703eb64`)。 > 决策:**不做中继(无 TURN / coturn)**,服务器只保留信令 + STUN 职能。 +> **裁决确认(2026-10-28)**:公司不提供中继服务器,本决策为最终结论, +> 同时**不预留中继接口**(理由见《多平台架构设计.md》§6.1 / §6.2)。 > 关联:`构建运行手册.md` §7 第 4 项、`Git协作规范.md` 二·B 第 ③ 项。 ## 1. 结论先行:信令不是中继