# INP2P 任务拆分

## 项目概述

自研 P2P 组网系统，两个二进制：`inp2ps`（信令服务器）+ `inp2pc`（客户端）。
UDP 打洞优先，分层中继，超级辅助节点。

项目位置：`/root/.openclaw/workspace/inp2p/`

---

## 一、核心层（我负责）

**目标**：两个二进制能跑起来、能连上、能打洞、能建隧道、能中继。

### M1: 信令连接（预计 400 行）✅ 完成
- [x] 协议定义 `pkg/protocol/` — 消息格式、编解码、类型枚举
- [x] 信令连接 `pkg/signal/` — WSS 封装、handler 注册、同步请求/响应
- [x] 认证 `pkg/auth/` — CRC64 token 生成、TOTP 生成/验证、一次性中继令牌
- [x] 配置 `pkg/config/` — Server/Client 配置结构体、默认值、环境变量
- [x] **inp2ps 信令主循环** `internal/server/server.go`
  - [x] WSS 接受连接 → Login 验证 → 注册节点
  - [x] 心跳管理 → 超时离线清理
  - [x] ReportBasic 处理 **（必须回响应，OpenP2P 踩过的坑）**
  - [x] 节点上线广播
  - [x] 连接协调 `internal/server/coordinator.go`（收到 A 的 ConnectReq → 同时推送给 A 和 B punch 参数）
- [x] **inp2pc 信令主循环** `internal/client/client.go`
  - [x] WSS 连接 → Login → ReportBasic → 心跳
  - [x] 断线重连（5s 退避）
  - [x] 收到 PushConnectReq 后触发打洞
  - [x] 收到 PushNodeOnline 后重试 apps

### M2: NAT 探测（预计 200 行）✅ 完成
- [x] UDP STUN 客户端/服务端 `pkg/nat/`
- [x] TCP STUN 回退
- [x] **集成到 inp2ps main**：启动 4 个 STUN listener（UDP×2 + TCP×2）
- [x] **集成到 inp2pc main**：登录前先探测，结果带入 LoginReq
- [ ] 定期重新探测（每 5 分钟），NATType 变化时通知 server

### M3: 打洞（预计 300 行）✅ 完成
- [x] UDP punch 基础实现 `pkg/punch/`
- [x] TCP punch 基础实现
- [x] 优先级链（direct → UDP → TCP）
- [x] **双端同步打洞协调** `internal/server/coordinator.go`
  - [x] server 收到 A 的 ConnectReq
  - [x] 同时推送 PunchStart 给 A 和 B（带对方的 IP:Port + NAT 类型）
  - [x] 双方同时调 `punch.Connect()`
  - [x] 任一方成功后报告 PunchResult
- [ ] Symmetric NAT 端口预测（可选优化）
- [ ] 打洞结果上报 + 统计

### M4: 隧道 + 多路复用（预计 500 行）✅ 完成
- [x] 隧道框架 `pkg/tunnel/` — 端口转发、统计、生命周期
- [x] **流多路复用协议** `pkg/mux/`
  - [x] 帧格式：`StreamID(4B) + Flags(1B) + Len(2B) + Data`
  - [x] SYN/FIN/DATA/PING/PONG/RST 控制帧
  - [x] Session（多路复用会话）+ Stream（虚拟连接，实现 net.Conn）
  - [x] Ring buffer 接收缓冲
  - [x] 7 个单元测试 + 1 个性能基准测试 全部通过
- [x] TCP 端口转发实现（listener → mux stream → peer demux → dst connect）
  - [x] 端到端测试通过（echo server + tunnel + 验证数据一致性）
  - [x] 5 并发连接测试通过
- [ ] UDP 端口转发实现
- [x] 连接池/复用（同 peer 多 app 共享一条 tunnel）

### M5: 中继（预计 400 行）✅ 完成
- [x] 中继管理器 `pkg/relay/` — 完整实现（~320 行）
- [x] **中继节点选择策略**（server 端 `server.GetRelayNodes()`）
  - [x] 同用户 `--relay` 节点优先
  - [x] 全局 `--super` 节点次优
  - [x] server 自身中继兜底
- [x] **中继握手协议**（长度前缀 JSON）
  - [x] A → relay: TCP 连接 + RelayHandshake{sessionID, role="from", token, node}
  - [x] B → relay: TCP 连接 + RelayHandshake{sessionID, role="to", token, node}
  - [x] relay: TOTP 验证 → 配对等待（30s 超时）→ 双向桥接
  - [x] 结果回传 relayResult{error, detail}
- [x] **中继认证**
  - [x] 同用户：TOTP(token, now)
  - [x] 跨用户超级节点：server 签发 `RelayToken`（HMAC-SHA256 签名，含 TTL）
- [x] **客户端工具函数** `ConnectToRelay()` — 封装完整握手+等待配对
- [x] **测试覆盖**（3/3 通过）
  - [x] TestRelayBridge — A↔B 双向数据验证
  - [x] TestRelayLargeData — 1MB 精确传输
  - [x] TestRelayAuthDenied — 错误 TOTP 被正确拒绝
- [ ] 中继带宽统计 + 负载均衡

### M6: inp2ps / inp2pc main 入口（预计 200 行）✅ 完成
- [x] `cmd/inp2ps/main.go` — flag 解析、启动 STUN + WSS + API + 优雅退出
- [x] `cmd/inp2pc/main.go` — flag 解析、config.json 读写、优雅退出
- [x] 端到端验证：server + 2 client 同时运行，health API 显示 nodes=2

---

## 二、次要层（可由他人完成）

### S1: 配置持久化
- `inp2pc` 的 `config.json` 读写（登录后 server 回的 token/node 写回文件）
- 支持 `-newconfig` 覆盖文件配置
- 热重载（收到 PushEditApp 后更新本地 config）

### S2: SDWAN 虚拟组网
- TUN 虚拟网卡创建
- 虚拟 IP 分配（server 侧管理子网）
- 组网路由表管理
- 中心模式 vs 全互联模式

### S3: 日志系统
- 分级日志（DEBUG/INFO/WARN/ERROR）
- 日志轮转（按大小）
- 日志目录 `log/`

### S4: 系统集成
- Systemd service 文件生成
- 开机自启
- Daemon 模式（`-d` fork 子进程）
- 自动更新（可选）

### S5: 安全加固
- TLS 证书自动生成（自签名）
- 连接限速
- 单 IP 最大连接数限制
- Brute-force 保护

---

## 三、前端 + Web API（可由他人完成）

### F1: REST API（inp2ps 内嵌 Gin）
- `POST /api/v1/login` — JWT 签发
- `GET /api/v1/devices` — 设备列表（名称、IP、NAT 类型、在线状态、版本）
- `GET /api/v1/devices/:node` — 设备详情
- `POST /api/v1/devices/:node/app` — 创建隧道
- `DELETE /api/v1/devices/:node/app/:name` — 删除隧道
- `PUT /api/v1/devices/:node/app/:name` — 编辑隧道（启停）
- `GET /api/v1/dashboard` — 概览统计
- `GET /api/v1/connections` — 活跃连接列表（打洞/中继/RTT）
- `GET /api/v1/relays` — 中继节点状态
- `POST /api/v1/sdwan/edit` — SDWAN 配置
- `GET /api/v1/sdwans` — SDWAN 列表
- `GET /api/v1/health` — 健康检查

### F2: Web 控制台 UI
- 设备列表页（在线/离线、NAT 类型标签、版本）
- 隧道管理（创建/编辑/删除/启停）
- 连接状态页（实时连接方式、RTT、流量）
- 中继节点页（负载、带宽、会话数）
- SDWAN 组网页
- Dashboard 概览
- 用户管理（admin/operator RBAC）

### F3: 客户端安装脚本
- `GET /api/v1/client/bootstrap` — 返回安装参数
- 一键安装脚本（curl | bash）
- 多架构支持（amd64/arm64）

---

## 依赖关系

```
M1 (信令) ← 无依赖，最先完成
M2 (NAT)  ← 依赖 M1
M3 (打洞) ← 依赖 M1 + M2
M4 (隧道) ← 依赖 M3
M5 (中继) ← 依赖 M1 + M4
M6 (main) ← 依赖 M1~M5

S1~S5 ← 依赖 M6 完成后可并行
F1    ← 依赖 M1（设备数据来自 server 内存）
F2    ← 依赖 F1
F3    ← 依赖 M6
```

## 当前状态

```
pkg/
├── protocol/  ✅ 完成（消息格式、NAT 枚举、所有结构体）
├── config/    ✅ 完成（Server/Client 配置、环境变量、校验、STUN 端口）
├── auth/      ✅ 完成（CRC64 token、TOTP、一次性中继令牌）
├── nat/       ✅ 完成（UDP/TCP STUN 客户端 + 服务端，集成验证通过）
├── signal/    ✅ 完成（WSS 封装、handler、同步请求/响应）
├── punch/     ✅ 完成（UDP/TCP punch + direct + 优先级链）
├── mux/       ✅ 完成（流多路复用，7 测试 + 1 benchmark 全部通过）
├── tunnel/    ✅ 完成（基于 mux 的端口转发，端到端测试通过）
└── relay/     ✅ 完成（中继握手、TOTP 认证、双向桥接、3 测试通过）

internal/
├── server/    ✅ 完成（登录、心跳、report、relay 选择、节点管理、打洞协调）
│   ├── server.go       — WSS 主循环、handler 注册
│   └── coordinator.go  — 打洞协调、EditApp/DeleteApp 推送
└── client/    ✅ 完成（连接、登录、打洞、中继回退、app 管理、断线重连）

cmd/
├── inp2ps/    ✅ 完成（flag、STUN、WSS、API、graceful shutdown）
└── inp2pc/    ✅ 完成（flag、config.json、relay、graceful shutdown）

编译状态: ✅ go build ./... 通过
测试状态: ✅ go test ./... 全部通过
  - internal/client: 1 test (8.3s) — 完整 NAT+WSS+Login+Report 链路
  - internal/server: 2 tests (0.8s) — Login + 双客户端 + Relay 发现
  - pkg/mux: 7 tests + 1 bench (0.2s) — 并发/大载荷/FIN/session
  - pkg/tunnel: 3 tests (0.16s) — 端到端转发/5 并发/统计

  - pkg/relay: 3 tests (0.3s) — 双向桥接/1MB 中继/认证拒绝

二进制: bin/inp2ps (6.0MB) + bin/inp2pc (5.6MB) (静态编译, strip)
```

## 接口约定（核心层 ↔ 前端/次要层）

### server.Server 暴露的方法（供 F1 REST API 调用）
```go
srv.GetNode(name string) *NodeInfo          // 查单个设备
srv.GetOnlineNodes() []*NodeInfo            // 在线设备列表
srv.GetRelayNodes(user string) []*NodeInfo  // 中继节点列表
srv.PushConnect(from, to, app)              // 触发打洞
// NodeInfo 字段: Name, PublicIP, NATType, Version, OS, LanIP, 
//   RelayEnabled, SuperRelay, ShareBandwidth, LoginTime, LastHeartbeat, Apps
```

### client.Client 暴露的方法（供 S1 配置持久化调用）
```go
client.Run() error    // 主循环（阻塞）
client.Stop()         // 优雅退出
// 配置通过 config.ClientConfig 传入
```
