docs: 修正还原计划,确认 net 模块已实现数据包解析
This commit is contained in:
1 parent
faf109a6a3
commit
a46bba2435
2 files changed
+195
-77
No files matched your search
@@ -236,113 +236,118 @@
|
||||
|
||||
---
|
||||
|
||||
## 5. 官方 Socket 链路反编译
|
||||
## 5. 官方 Socket 链路
|
||||
|
||||
### 5.1 先纠正一个事实
|
||||
### 5.1 先纠正:数据包解析已经实现
|
||||
|
||||
官方客户端**没有 Socket.IO**。在 `3DTank/src` 与 `main.6469b966.js` 中搜索 `socket.io` / `engine.io` / `io.connect` 均为 0 命中。
|
||||
不是“从零反编译”。KT 工程已经有一套完整的官方包解析:
|
||||
|
||||
官方用的是**原生 WebSocket + 自定义二进制协议**:
|
||||
- `TankiOffline/net/src/jsMain/kotlin/Net/Generated/`:
|
||||
- `DownlinkRegistry`:**681** 个 methodId → codec
|
||||
- `UplinkRegistry`:**361** 个 methodId → codec
|
||||
- `ModelRegistry`:**363** 个 modelId → codec
|
||||
- 14 个 codec 模块:85183 / 47243 / 85196 / 31908 / 16100 / 10283 / 25377 / 54199 / 37504 / 88693 / 89803 / 85667 / 67222 / 99527
|
||||
- 另有 24635 / 1510 / 29554 / 45686 / 61860 / 71105 / 85745 / 87072
|
||||
- `Net/Protocol/`:
|
||||
- `Entry`:Hash Request / Hash Response / EnterSpace / OpenSpace
|
||||
- `SpaceFrame`:帧体 → 记录
|
||||
- `StreamDecoder`:明文/探测/解密三阶段、XOR key
|
||||
- `Containers`:Lt / Pt / Zt / Alias
|
||||
- `TankStateCodec`
|
||||
- `Net/Wire/ModelCodec`
|
||||
- `App/Session/`:
|
||||
- `SpaceSession`:Feed → DecodedRecord
|
||||
- `SessionRouter`:DecodedRecord → DownlinkActions → Redux Store
|
||||
- `UplinkEncoder`:动作 → 上行帧
|
||||
- `SessionCheck` / `StateCheck` / `AutoTest`:自检与真实中继测试
|
||||
- `App/State/`:
|
||||
- 89/89 reducer 切片
|
||||
- `DownlinkActions` / `DownlinkModelActions`
|
||||
- `RootState` / `RootWiring`
|
||||
|
||||
- `3DTank/src/module_61860.js:992`:`new WebSocket(this.t7u_1)`
|
||||
- `this.t7u_1 = t + "://" + n + ":" + i + "/"`(protocol / host / port)
|
||||
- `binaryType = "arraybuffer"`
|
||||
- 连接后走 `Ee(t)` 协议对象、`p7u_1` / `q7u_1` 编解码、`r7u_1` 命令分发
|
||||
所以“官方所有的数据包解析”这件事,KT 工程已经做了大部分,不需要重新读 14 个 codec 模块。
|
||||
|
||||
所以计划是反编译**官方 WebSocket 链路**;如果另有 Socket.IO 入口(例如网页活动页),需要单独给出 URL,我再补一条支线。
|
||||
### 5.2 真正缺的是“链路前半段”
|
||||
|
||||
### 5.2 链路分层
|
||||
现在的 `LobbyClient` 是:
|
||||
|
||||
```text
|
||||
启动
|
||||
└─ 配置 / 区域
|
||||
├─ config.xml(c{server}.3dtank.com/config.xml)
|
||||
├─ status.js(3dtank.com/s/status.js)
|
||||
└─ balancer(balancer.*.tankionline.com/balancer)
|
||||
└─ BalancerStatus / BalancerNode / BalancerNodeEndpoint
|
||||
└─ 选节点 host:port
|
||||
└─ WebSocket(protocol://host:port/)
|
||||
├─ 登录 / 鉴权
|
||||
├─ Hash Request / Hash Response
|
||||
├─ Open Space / EnterSpace
|
||||
├─ LoadDependencies
|
||||
└─ Space 二进制帧
|
||||
├─ 解帧 / 解密
|
||||
├─ 命令 id + 字段
|
||||
└─ SessionRouter → RootState
|
||||
登录表单 → LobbyClient.Login → Connect(中继 URL) → Hash Request → ...
|
||||
```
|
||||
|
||||
### 5.3 反编译步骤
|
||||
它缺的是官方链路的前半段:
|
||||
|
||||
#### S1 配置 / Balancer
|
||||
1. **config / status / balancer**:官方节点发现
|
||||
2. **auth**:账号密码 → token/cookie
|
||||
3. **官方 WebSocket 建连**:protocol/host/port、header、子协议
|
||||
4. **覆盖率**:真实官方会话下 `SessionRouter.Unmapped` / `Failed` 是否归零
|
||||
5. **golden 帧校验**:现有 codec 是否 byte-for-byte 对得上
|
||||
|
||||
1. 读 `module_13431`:区域、`config.xml`、`status.js`、balancer URL 规则。
|
||||
2. 读 `module_61860` 的 `BalancerStatus` / `BalancerNode` / `BalancerNodeEndpoint` 字段。
|
||||
3. 抓一次官方启动请求:config、status、balancer。
|
||||
4. 产出 `docs/BalancerProtocol.md`:URL 规则、字段、选节点算法。
|
||||
### 5.3 链路分层(已有 / 待补)
|
||||
|
||||
#### S2 登录 / 鉴权
|
||||
| 层 | 状态 | 位置 |
|
||||
|---|---|---|
|
||||
| config / status / balancer | 待补 | `module_13431` / `module_61860` |
|
||||
| auth / 登录 | 待补 | `module_82347` Entrance / `module_61860` |
|
||||
| WebSocket 建连 | 待补 | `module_61860:992` `Ie` |
|
||||
| Hash / OpenSpace / EnterSpace | 已有 | `Net/Protocol/Entry.kt` |
|
||||
| 帧解码 / XOR | 已有 | `Net/Protocol/StreamDecoder.kt` |
|
||||
| 记录解码 | 已有 | `Net/Protocol/SpaceFrame.kt` + `Registry.kt` |
|
||||
| 容器 Lt/Pt/Zt/Alias | 已有 | `Net/Protocol/Containers.kt` |
|
||||
| 记录 → 动作 | 已有 | `App/Session/SessionRouter.kt` |
|
||||
| 动作 → 上行 | 已有 | `App/Session/UplinkEncoder.kt` |
|
||||
| 状态 | 已有 | `App/State/` |
|
||||
|
||||
1. 读 `module_82347` 的 `EntranceComponentStyle` + `xxn` / `Tzn` / `gKt` / `sWt`。
|
||||
2. 找登录请求:HTTP/WS、方法、路径、body、header、cookie、token。
|
||||
3. 抓包:登录成功/失败、验证码、记住我、社交登录。
|
||||
4. 产出 `docs/AuthProtocol.md`:请求/响应、错误码、token 生命周期。
|
||||
### 5.4 待补工作
|
||||
|
||||
#### S3 WebSocket 建连
|
||||
#### S1 config / balancer
|
||||
|
||||
1. 读 `module_61860` `Ie`:URL、子协议、header、binaryType。
|
||||
2. 读 `Ee(t)`:protocol 对象、版本、握手字段。
|
||||
3. 读 `p7u_1` / `q7u_1`:帧格式、长度、压缩、加密。
|
||||
4. 产出 `docs/SocketProtocol.md`:建连、帧格式、心跳、重连。
|
||||
1. 读 `module_13431` 的 URL 规则、区域、config.xml、status.js、balancer。
|
||||
2. 读 `module_61860` 的 `BalancerStatus` / `BalancerNode` / `BalancerNodeEndpoint`。
|
||||
3. 抓官方启动请求。
|
||||
4. 在 Kotlin 实现 `BalancerClient`,输出 `docs/BalancerProtocol.md`。
|
||||
|
||||
#### S4 Lobby 握手
|
||||
#### S2 auth
|
||||
|
||||
1. `Hash Request` / `Hash Response`:字段、digest、加密标志。
|
||||
2. `Open Space`:spaceId、节点、token。
|
||||
3. `EnterSpace`:digest、spaceId。
|
||||
4. `LoadDependencies`:zt 载荷、依赖列表。
|
||||
5. 与现有 `LobbyClient` 逐字段对照,删掉中继特化代码。
|
||||
1. 读 `module_82347` Entrance 的登录请求。
|
||||
2. 抓登录成功/失败、token/cookie。
|
||||
3. 在 `LobbyClient.Login` 里替换 `Connect(中继)` 为官方 auth + 官方 WS。
|
||||
4. 输出 `docs/AuthProtocol.md`。
|
||||
|
||||
#### S5 Space 协议
|
||||
#### S3 官方 WebSocket
|
||||
|
||||
1. 读 14 个 codec 模块:85183 / 47243 / 85196 / 31908 / 16100 / 10283 / 25377 / 54199 / 37504 / 88693 / 89803 / 85667 / 67222 / 99527。
|
||||
2. 命令 id + 字段序号 + 默认值逐项入表。
|
||||
3. 用 `wss_server.js` 抓 golden 帧,做 encode/decode 对比。
|
||||
4. 产出 `docs/SpaceProtocol.md` + `names/codec_fields.json`。
|
||||
1. 读 `module_61860` `Ie`:URL、header、子协议、binaryType。
|
||||
2. 用官方 URL 替换 `LobbyClient.Connect`。
|
||||
3. 保留现有 `Entry` / `SpaceSession` / `SessionRouter`。
|
||||
4. 输出 `docs/SocketProtocol.md`。
|
||||
|
||||
#### S6 状态映射
|
||||
#### S4 覆盖率审计
|
||||
|
||||
1. 读 `module_10032`(Redux 核心)、`module_18334`(DI)、`module_61860`(对象模型)。
|
||||
2. 命令 → 记录 → RootState 槽位逐项对照。
|
||||
3. 产出 `docs/StateMap.md` 更新。
|
||||
1. 用官方会话跑 `SessionRouter`,收集 `UnmappedIds` / `FailedIds`。
|
||||
2. 对照 `Registry.kt` / `DownlinkActions`,逐项补齐。
|
||||
3. 目标:`Unmapped = 0`、`Failed = 0`(或只剩明确不需要的 UI-only 记录)。
|
||||
4. 输出 `docs/NetCoverage.md`。
|
||||
|
||||
### 5.4 工具链
|
||||
#### S5 golden 帧
|
||||
|
||||
| 工具 | 用途 |
|
||||
|---|---|
|
||||
| `3DTank/tools/serve.js` | 本地静态 + 反向代理 + config 改写 |
|
||||
| `3DTank/tools/wss_server.js` | 中继 + 抓包 + 实时解密 |
|
||||
| `3DTank/tools/analyze_packets.js` | 抓包分析 |
|
||||
| `3DTank/tools/prefetch_assets.js` | 资源预拉 |
|
||||
| `3DTank/tools/headless_probe.js` | 页面探针 / CSS / 截图 |
|
||||
| `3DTank/tools/server/` | 协议服务端骨架(codec/dispatch/session/space/world) |
|
||||
| Chrome DevTools Protocol | 网络抓包、HAR、WS frames |
|
||||
| mitmproxy / Fiddler | TLS 抓包(如需要) |
|
||||
1. 用 `wss_server.js` / CDP 抓官方帧。
|
||||
2. 对每个 methodId 做 encode/decode 对比。
|
||||
3. 差异写入 `docs/NetCoverage.md`。
|
||||
|
||||
### 5.5 验收
|
||||
|
||||
1. 不经过 `9091` 中继,直接连官方节点。
|
||||
1. 不经过 `9091` 中继,直连官方节点。
|
||||
2. 登录成功,拿到 Lobby 状态。
|
||||
3. 进入 Space,收到 `LoadDependencies` 并完成依赖加载。
|
||||
4. 抓包 golden 帧回放,编解码 byte-for-byte 一致。
|
||||
5. 同一账号下,客户端 RootState 与官方客户端一致(至少用户、货币、车库、任务、聊天)。
|
||||
4. `SessionRouter.Unmapped = 0`、`Failed = 0`。
|
||||
5. golden 帧 byte-for-byte 一致。
|
||||
|
||||
### 5.6 风险
|
||||
|
||||
- TLS/证书、区域限制、登录验证码。
|
||||
- 官方协议版本更新(codec 字段漂移)。
|
||||
- token/加密密钥的获取方式。
|
||||
- 反作弊/风控(只做本地复现,不绕过官方限制)。
|
||||
- TLS/证书、区域限制、验证码。
|
||||
- token/加密密钥获取。
|
||||
- 官方协议版本更新导致 codec 漂移。
|
||||
- 反作弊/风控(只做本地复现,不绕过限制)。
|
||||
|
||||
---
|
||||
|
||||
@@ -381,10 +386,14 @@
|
||||
- 补 `EntranceComponentStyle` 的社交登录、找回密码、错误 tooltip。
|
||||
- 补 `gKt` 输入组件的 `visualState` / `error` / 图标。
|
||||
- 补 `sWt` 共享按钮的完整样式。
|
||||
2. 同时开 **S1/S2 链路取证**:
|
||||
2. 同时做 **Net 覆盖率审计**(不是重写 codec):
|
||||
- 用现有 `net` 模块 + `SessionRouter` 跑真实/中继会话。
|
||||
- 收集 `UnmappedIds` / `FailedIds`,逐项补齐 `Registry.kt` / `DownlinkActions`。
|
||||
- 产出 `NetCoverage.md`。
|
||||
3. 同时开 **S1/S2 链路取证**:
|
||||
- 用 CDP 抓官方 config/status/balancer/login。
|
||||
- 产出 `BalancerProtocol.md` / `AuthProtocol.md`。
|
||||
3. 把 `UiTranslationStatus.md` 改成“只有 100% 才写已完成”,其余全部列“进行中”。
|
||||
4. 把 `UiTranslationStatus.md` 改成“只有 100% 才写已完成”,其余全部列“进行中”。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
# Net Coverage
|
||||
|
||||
> 目的:证明 KT 工程已经实现官方数据包解析,并明确“还缺什么”。
|
||||
> 结论:**解析层基本完成**;缺的是官方链路前半段(config/balancer/auth/WS)和真实会话覆盖率审计。
|
||||
|
||||
## 1. 已实现
|
||||
|
||||
### 1.1 生成物(`TankiOffline/net/src/jsMain/kotlin/Net/Generated/`)
|
||||
|
||||
| 文件 | 内容 | 数量 |
|
||||
|---|---|---|
|
||||
| `Registry.kt` → `DownlinkRegistry.ByMethodId` | methodId → downlink codec | **681** |
|
||||
| `Registry.kt` → `UplinkRegistry.ByMethodId` | methodId → uplink codec | **361** |
|
||||
| `Registry.kt` → `ModelRegistry.ByModelId` | modelId → model codec | **363** |
|
||||
| `Metadata.kt` | 模型名 / method 名 / 字段元数据 | — |
|
||||
|
||||
生成的 codec 模块:
|
||||
|
||||
```text
|
||||
Downlink: 10283 1510 25377 29554 31908 37504 47243 54199 85183 85196 85667 88693 89803
|
||||
Models: 01510 10283 16100 24635 25377 31908 37504 45686 47243 54199 61860 67222
|
||||
71105 85183 85196 85667 85745 87072 88693 89803 99527
|
||||
Uplink: 10283 25377 37504 47243 54199 85183 85196 85667 89803
|
||||
```
|
||||
|
||||
覆盖原版 14 个 codec 模块:85183 / 47243 / 85196 / 31908 / 16100 / 10283 / 25377 / 54199 / 37504 / 88693 / 89803 / 85667 / 67222 / 99527。
|
||||
|
||||
### 1.2 协议层(`Net/Protocol/`)
|
||||
|
||||
| 文件 | 作用 |
|
||||
|---|---|
|
||||
| `Entry.kt` | Hash Request / Hash Response / EnterSpace / OpenSpace / BuildObjectDataRequest |
|
||||
| `SpaceFrame.kt` | 帧体 → 记录;处理 nullmap / alias |
|
||||
| `StreamDecoder.kt` | 明文 / 探测 / 解密三阶段;XOR key |
|
||||
| `Containers.kt` | Lt / Pt / Zt / Alias 容器 |
|
||||
| `TankStateCodec.kt` | 坦克状态 |
|
||||
| `Wire/ModelCodec.kt` | 模型编解码接口 |
|
||||
|
||||
### 1.3 会话层(`App/Session/`)
|
||||
|
||||
| 文件 | 作用 |
|
||||
|---|---|
|
||||
| `SpaceSession.kt` | WebSocket 字节 → `DecodedRecord` |
|
||||
| `SessionRouter.kt` | `DecodedRecord` → `DownlinkActions` / `DownlinkModelActions` → Redux |
|
||||
| `UplinkEncoder.kt` | 动作 → 上行帧 |
|
||||
| `SessionCheck.kt` | 会话自检 |
|
||||
| `StateCheck.kt` | Redux 状态自检 |
|
||||
| `AutoTest.kt` | 真实中继一次性测试 |
|
||||
|
||||
### 1.4 状态层(`App/State/`)
|
||||
|
||||
- 89/89 reducer 切片(见 `KtRebuild_Plan.md`)。
|
||||
- `RootState.kt` / `RootWiring.kt`。
|
||||
- `DownlinkActions.kt` / `DownlinkModelActions.kt`。
|
||||
- `ActionCatalog.kt` / `ActionSamples.kt`。
|
||||
|
||||
## 2. 还没实现
|
||||
|
||||
### 2.1 链路前半段
|
||||
|
||||
| 层 | 状态 | 依据 |
|
||||
|---|---|---|
|
||||
| config.xml / status.js | 未实现 | `module_13431` |
|
||||
| balancer | 未实现 | `module_13431` / `module_61860` |
|
||||
| auth(账号密码 → token/cookie) | 未实现 | `module_82347` Entrance / `module_61860` |
|
||||
| 官方 WebSocket 建连 | 未实现 | `module_61860:992` `Ie` |
|
||||
| 直连官方节点 | 未实现 | 当前 `LobbyClient` 走 `9091` 中继 |
|
||||
|
||||
### 2.2 覆盖率审计
|
||||
|
||||
`SessionRouter` 已有计数器:
|
||||
|
||||
```kotlin
|
||||
var Unmapped: Int
|
||||
var Failed: Int
|
||||
val UnmappedIds: MutableMap<Long, Int>
|
||||
val UnmappedModels: MutableMap<String, Int>
|
||||
val FailedIds: MutableMap<Long, Int>
|
||||
val FailedReasons: MutableMap<String, Int>
|
||||
```
|
||||
|
||||
目标:
|
||||
|
||||
- `Unmapped = 0`
|
||||
- `Failed = 0`
|
||||
- `UnmappedModels` 为空
|
||||
|
||||
需要跑一次真实官方会话,收集并补齐。
|
||||
|
||||
### 2.3 golden 帧
|
||||
|
||||
现有 codec 是否 byte-for-byte 对得上,需要:
|
||||
|
||||
1. 用 `wss_server.js` / CDP 抓官方帧。
|
||||
2. 对每个 methodId 做 encode/decode 对比。
|
||||
3. 差异写入本文件。
|
||||
|
||||
## 3. 结论
|
||||
|
||||
- **数据包解析:已实现**(681 downlink / 361 uplink / 363 model / 14 codec 模块 / Entry / SpaceFrame / StreamDecoder / Containers / SessionRouter / 89 reducer)。
|
||||
- **官方链路:未实现**(config / balancer / auth / 官方 WS)。
|
||||
- **覆盖率:未审计**(`Unmapped` / `Failed` 未归零验证)。
|
||||
- **golden 帧:未校验**。
|
||||
|
||||
下一步不是重写 codec,而是:
|
||||
|
||||
1. 补 config / balancer / auth / 官方 WS。
|
||||
2. 跑真实会话,驱动 `Unmapped` / `Failed` 归零。
|
||||
3. golden 帧 byte diff。
|
||||
Reference in new issue
Block a user