Initial commit
This commit is contained in:
+272
@@ -0,0 +1,272 @@
|
||||
# MeshRay-Core 架构规范
|
||||
|
||||
> Core 是通用的数据传输引擎,通过 ProtocolPlugin 接口适配不同协议。当前默认内置 WG 插件。
|
||||
|
||||
---
|
||||
|
||||
## 一、目录结构
|
||||
|
||||
```
|
||||
core/
|
||||
├── core.go # 进程入口
|
||||
├── engine.go # 引擎实例
|
||||
├── metrics.go # 监控指标
|
||||
│
|
||||
├── connect/ # 建连层
|
||||
│ ├── strategy.go # 策略调度
|
||||
│ ├── stun.go # STUN 协议
|
||||
│ ├── direct.go # Layer 1
|
||||
│ ├── fake_tcp.go # Layer 2
|
||||
│ ├── real_tcp.go # Layer 3
|
||||
│ ├── turn.go # Layer 4/6/7
|
||||
│ ├── turn_quic.go # Layer 5
|
||||
│ ├── ice.go # Layer 8
|
||||
│ └── ws.go # Layer 9
|
||||
│
|
||||
├── transport/ # 传输层
|
||||
│ ├── conn_manager.go # 连接索引
|
||||
│ ├── relay.go # 转发循环
|
||||
│ └── plugin.go # Plugin 接口
|
||||
│
|
||||
└── plugins/ # 协议插件
|
||||
└── wg/
|
||||
└── wgparse.go # WG 插件实现
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、各文件职责
|
||||
|
||||
### 2.1 根目录(4 个文件)
|
||||
|
||||
| 文件 | 职责 | 持有什么 | 不做什么 |
|
||||
|------|------|---------|----------|
|
||||
| `core.go` | 进程入口,管理多个 Engine | `map[engineID]*Engine` | 不做建连、不转发数据 |
|
||||
| `engine.go` | 一个组网的引擎实例 | strategy、conn_manager、relay、plugin | 不直接调用 connect,由 relay 调用 |
|
||||
| `metrics.go` | 监控指标采集 | 原子计数器(连接数、字节数、切换次数) | 不做业务逻辑 |
|
||||
|
||||
**关键关系**:
|
||||
- `core.go` 持有多个 `engine.go`
|
||||
- `internal/ctr/ctr.go` 直接调用 `core.go` 和 `engine.go` (进程内函数调用)
|
||||
- `engine.go` 持有 connect/、transport/、plugins/ 的实例
|
||||
|
||||
### 2.2 connect/(9 个文件)— 建连层
|
||||
|
||||
**职责**:通过各种网络方式建立连接,最终返回 `net.Conn`。
|
||||
|
||||
**对外暴露的唯一入口**:`strategy.go` 的 `Connect()` 方法。其他 connect 文件只被 `strategy.go` 调用。
|
||||
|
||||
| 文件 | 对应层级 | 职责 | 返回什么 |
|
||||
|------|---------|------|---------|
|
||||
| `strategy.go` | 全部 | 按优先级尝试各层,不通自动切换,定期探测恢复 | `net.Conn` + 当前层级名 |
|
||||
| `stun.go` | 被 direct/ice 调用 | STUN 协议:发送 Binding Request,获取本机公网地址 | `*net.UDPAddr`(地址,不是连接) |
|
||||
| `direct.go` | Layer 1 | 调用 stun 获取候选地址,然后 UDP 打洞 | `net.Conn` |
|
||||
| `fake_tcp.go` | Layer 2 | UDP 包外层封装 TCP 头部,欺骗防火墙 | `net.Conn` |
|
||||
| `real_tcp.go` | Layer 3 | 真正的 TCP 直连打洞 | `net.Conn` |
|
||||
| `turn.go` | Layer 4/6/7 | TURN 协议协商(Allocate/Permission/ChannelBind),参数区分 UDP/TCP/TLS | `net.Conn` |
|
||||
| `turn_quic.go` | Layer 5 | TURN-QUIC 私有扩展(RFC 9000) | `net.Conn` |
|
||||
| `ice.go` | Layer 8 | ICE 协商 + WebRTC DataChannel,内部调用 stun 收集候选 | `net.Conn` |
|
||||
| `ws.go` | Layer 9 | WS/WSS 握手 + 帧收发 + 身份标识 | `net.Conn` |
|
||||
|
||||
**9 层完整编号**:
|
||||
|
||||
| 层级 | 链路名称 | 文件 | 传输方式 | 穿透力 |
|
||||
|------|---------|------|---------|--------|
|
||||
| 1 | Direct-UDP | direct.go | P2P 直连 | 弱(性能最好) |
|
||||
| 2 | Direct-FakeTCP | fake_tcp.go | P2P 直连 | 弱 |
|
||||
| 3 | Direct-RealTCP | real_tcp.go | P2P 直连 | 中 |
|
||||
| 4 | TURN-UDP | turn.go | 中继 | 中 |
|
||||
| 5 | TURN-QUIC | turn_quic.go | 中继 | 中 |
|
||||
| 6 | TURN-TCP | turn.go | 中继 | 强 |
|
||||
| 7 | TURN-TLS | turn.go | 中继 | 强 |
|
||||
| 8 | WebRTC | ice.go | ICE/TURN | 强 |
|
||||
| 9 | WS/WSS | ws.go | 隧道 | 最强(兜底) |
|
||||
|
||||
**strategy.go 的自动切换逻辑**:
|
||||
- 单包超时 500ms → 切到下一层
|
||||
- 10s 滑动窗口丢包率 > 10% → 切到下一层
|
||||
- 当前在第 N 层时,每 30s 探测 Layer 1 → 连续 2 次成功直接切回 Layer 1(不逐层回退)
|
||||
|
||||
**stun.go 的特殊地位**:唯一被多处调用的 connect 文件(direct.go 和 ice.go 都需要它),所以独立存在。
|
||||
|
||||
### 2.3 transport/(3 个文件)— 传输层
|
||||
|
||||
**职责**:用 `net.Conn` 转发数据。不感知具体协议,通过 ProtocolPlugin 接口适配。
|
||||
|
||||
| 文件 | 职责 | 不做什么 |
|
||||
|------|------|---------|
|
||||
| `conn_manager.go` | 连接索引:`peer_key → net.Conn` 的映射 | 不做建连、不转发数据 |
|
||||
| `relay.go` | Read/Write 循环:从本地端口收包 → 查路由 → 通过 conn 发送;从 conn 收包 → 发到本地端口 | 不做建连 |
|
||||
| `plugin.go` | 定义 ProtocolPlugin 接口 | 不实现任何协议 |
|
||||
|
||||
**relay.go 的工作流程**:
|
||||
|
||||
```
|
||||
本地端口收到 WG 密文包
|
||||
→ 调用 plugin.IsControlPacket() 判断包类型
|
||||
→ true:控制包,按已建链路透传
|
||||
→ 调用 plugin.IsDataPacket() 判断
|
||||
→ true:调用 plugin.ExtractRouteID() 提取路由标识
|
||||
→ 查路由标识映射表 → 发往对应本地端口
|
||||
→ 都不是:丢弃
|
||||
```
|
||||
|
||||
**关键**:relay.go 不知道 WireGuard,不知道 receiver index,只知道 route_id。
|
||||
|
||||
### 2.4 plugins/wg/(1 个文件)— 协议插件
|
||||
|
||||
**职责**:实现 ProtocolPlugin 接口,处理 WG 协议特有的包解析。
|
||||
|
||||
| 文件 | 职责 | 不做什么 |
|
||||
|------|------|---------|
|
||||
| `wgparse.go` | 实现 `IsDataPacket`/`ExtractRouteID`/`IsControlPacket` | 不做建连、不转发数据 |
|
||||
|
||||
**WG 插件的具体实现**:
|
||||
|
||||
| 方法 | 逻辑 |
|
||||
|------|------|
|
||||
| `IsControlPacket(packet)` | `packet[0]` ∈ {1, 2, 3} → true |
|
||||
| `IsDataPacket(packet)` | `packet[0]` == 4 → true |
|
||||
| `ExtractRouteID(packet)` | 读取 `packet[4:8]`,网络字节序解析为 uint32(即 WG receiver index) |
|
||||
|
||||
### 2.5 plugins/wg/(1 个文件)
|
||||
|
||||
| 文件 | 职责 |
|
||||
|------|------|
|
||||
| `wgparse.go` | WireGuard 数据包解析和封装 |
|
||||
|
||||
---
|
||||
|
||||
## 三、分层架构图
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ internal/ctr/ctr.go │
|
||||
│ 直接调用 Core (进程内函数调用) │
|
||||
└────────────────────────┬────────────────────────────────┘
|
||||
│ 函数调用
|
||||
┌────────────────────────▼────────────────────────────────┐
|
||||
│ core.go │
|
||||
│ 管理多个 Engine 实例 │
|
||||
└───┬─────────────────────────────────────────────────────┘
|
||||
│ 每个组网一个 Engine
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ engine.go │
|
||||
│ 持有:strategy + conn_manager + relay + plugin │
|
||||
│ 协调 connect/ 和 transport/ 工作 │
|
||||
└───┬─────────────────────────────────────────────────────┘
|
||||
│
|
||||
├──────────────────────────────────────────┐
|
||||
▼ ▼
|
||||
┌───────────────────────┐ ┌───────────────────────┐
|
||||
│ connect/ │ │ transport/ │
|
||||
│ 建连层 │ │ 传输层 │
|
||||
│ │ │ │
|
||||
│ strategy.go │ 返回 │ relay.go │
|
||||
│ ├─ direct.go (L1) │ net.Conn├─ plugin.go │
|
||||
│ ├─ fake_tcp.go (L2) │────────►│ │ ProtocolPlugin │
|
||||
│ ├─ real_tcp.go (L3) │ │ │ │
|
||||
│ ├─ turn.go (L4/6/7) │ │ 插件调用 │
|
||||
│ ├─ turn_quic.go(L5) │ │ ▼ │
|
||||
│ ├─ ice.go (L8) │ │ plugins/wg/ │
|
||||
│ └─ ws.go (L9) │ │ └─ wgparse.go │
|
||||
│ │ │ │
|
||||
│ stun.go (被 direct/ice 调用) │ conn_manager.go │
|
||||
└───────────────────────┘ └───────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、调用关系
|
||||
|
||||
### 4.1 Engine 创建时
|
||||
|
||||
```
|
||||
engine.go
|
||||
→ 创建 WGPlugin(plugins/wg/wgparse.go)
|
||||
→ 创建 Relay,传入 plugin(transport/relay.go)
|
||||
→ 创建 Strategy(connect/strategy.go)
|
||||
→ 创建 ConnManager(transport/conn_manager.go)
|
||||
```
|
||||
|
||||
### 4.2 Bind 流程
|
||||
|
||||
```
|
||||
ctr 直接调用:Bind()
|
||||
→ engine.go 接收函数调用
|
||||
→ engine.go 调用 strategy.Connect()
|
||||
→ strategy 按优先级尝试各层
|
||||
→ Layer 1: direct.go 调用 stun.go 获取候选,尝试 UDP 打洞
|
||||
→ 不通?→ Layer 4: turn.go 调用 TURN 协商
|
||||
→ 不通?→ Layer 9: ws.go 调用 WS 握手
|
||||
→ 返回 net.Conn + 当前层级名
|
||||
→ engine.go 把 net.Conn 注册到 conn_manager
|
||||
→ engine.go 启动 relay 的 Read/Write 循环
|
||||
```
|
||||
|
||||
### 4.3 数据转发流程
|
||||
|
||||
```
|
||||
WG 发出密文包 → 本地端口
|
||||
→ relay.go 收到
|
||||
→ 调用 plugin.IsControlPacket()
|
||||
→ true:按已建链路透传(conn_manager 查 conn)
|
||||
→ 调用 plugin.IsDataPacket()
|
||||
→ true:调用 plugin.ExtractRouteID() 获取 route_id
|
||||
→ 查路由标识映射表 → 找到本地端口 → 发送
|
||||
→ 都不是:丢弃
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、通用层与插件层的边界
|
||||
|
||||
| 层 | 知道什么 | 不知道什么 |
|
||||
|---|---------|-----------|
|
||||
| **connect/** | 网络协议(STUN/TURN/WS/WebRTC) | WireGuard、route_id |
|
||||
| **transport/** | net.Conn、route_id、ProtocolPlugin 接口 | WireGuard、receiver index |
|
||||
| **plugins/wg/** | WG 包格式、receiver index | 网络连接、net.Conn |
|
||||
| **engine.go** | 协调 connect/ 和 transport/ | WG 包格式细节 |
|
||||
|
||||
**如果将来要支持其他协议**:
|
||||
- 新建 `plugins/xxx/xxxparse.go`
|
||||
- 实现 `ProtocolPlugin` 接口的三个方法
|
||||
- `engine.go` 里换成 `xxx.NewPlugin()`
|
||||
- connect/、transport/、core.go 的代码完全不用改
|
||||
|
||||
---
|
||||
|
||||
## 六、Core 接口(直接被 ctr 调用)
|
||||
|
||||
| 方法 | 调用方 | 说明 |
|
||||
|------|--------|------|
|
||||
| `CreateEngine` | ctr | 创建一个 Engine 实例(直接函数调用) |
|
||||
| `Bind` | ctr | 为每个 Peer 开启本地端口,开始建链 |
|
||||
| `Unbind` | ctr | 停止指定 Peer 的端口监听 |
|
||||
| `Start` | ctr | 启动转发主循环 |
|
||||
| `Stop` | ctr | 停止 Engine |
|
||||
| `GetStatus` | ctr | 查询 Engine 状态 |
|
||||
| `NotifyPeerInfo` | ctr | 下发对端候选地址和 route_id |
|
||||
|
||||
**实现位置**:
|
||||
- 所有方法都在 `engine.go` 中实现
|
||||
- `core.go` 提供 Engine 实例管理
|
||||
- ctr通过`coreInst.CreateEngine(...)`直接调用
|
||||
|
||||
---
|
||||
|
||||
## 七、文件清单汇总
|
||||
|
||||
| 目录 | 文件数 | 文件 |
|
||||
|------|--------|------|
|
||||
| 根目录 | 3 | core.go, engine.go, metrics.go |
|
||||
| connect/ | 9 | strategy.go, stun.go, direct.go, fake_tcp.go, real_tcp.go, turn.go, turn_quic.go, ice.go, ws.go |
|
||||
| transport/ | 3 | conn_manager.go, relay.go, plugin.go |
|
||||
| plugins/wg/ | 1 | wgparse.go |
|
||||
| **总计** | **16** | |
|
||||
|
||||
**已删除的文件**:
|
||||
- ~~grpc_service.go~~ - 不再需要(改为直接函数调用)
|
||||
- ~~pool/connpool.go~~ - 不再需要(无连接池)
|
||||
- ~~proto/core.proto~~ - 不再需要 gRPC
|
||||
Reference in New Issue
Block a user