Files
SimpleRemoter/docs/FILE_TRANSFER_V2.md
2026-04-19 22:55:21 +02:00

234 lines
9.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# V2 文件/文本传输功能清单
## 一、文件传输
| 方向 | 触发方式 | 断点续传 | 进度显示 | 备注 |
|------|----------|:--------:|:--------:|------|
| 服务端 → 客户端 | 文件管理器拖放/Ctrl+V | ✅ | ✅ | 支持大文件(>4GB) |
| 客户端 → 服务端 | 文件管理器下载 | ✅ | ✅ | 支持大文件(>4GB) |
| 客户端A → 客户端B (C2C) | 远程桌面 Ctrl+C/Ctrl+V | ✅ | ✅ | 自动捕获目标目录 |
## 二、文本传输
| 方向 | 触发方式 | 说明 |
|------|----------|------|
| 服务端 → 客户端 | 远程桌面剪贴板同步 | `COMMAND_SCREEN_SET_CLIPBOARD` |
| 客户端 → 服务端 | 远程桌面剪贴板同步 | `COMMAND_SCREEN_GET_CLIPBOARD` |
| 客户端A → 客户端B (C2C) | 远程桌面 Ctrl+C/Ctrl+V | 自动粘贴 |
## 三、C2C 传输流程
```
┌─────────────┐ Ctrl+V ┌─────────────┐ CLIPBOARD_V2 ┌─────────────┐
│ 远程桌面B │ ───────────────>│ 服务端 │ ──────────────────>│ 远程桌面A │
│ (目标) │ │ │ │ (源) │
└─────────────┘ └─────────────┘ └─────────────┘
▲ │ │
│ │ C2C_PREPARE │
│<──────────────────────────────┘ │
│ │
│ ┌─────────────┐ │
│ SEND_FILE_V2/C2C_TEXT │ 服务端 │ SEND_FILE_V2/C2C_TEXT │
│<────────────────────────│ (转发) │<──────────────────────────┘
│ └─────────────┘
```
## 四、协议命令
| 命令 | 值 | 用途 |
|------|:--:|------|
| `COMMAND_SEND_FILE_V2` | 85 | V2文件数据包 |
| `COMMAND_FILE_RESUME` | 86 | 断点续传响应 |
| `COMMAND_CLIPBOARD_V2` | 87 | C2C剪贴板请求 |
| `COMMAND_FILE_QUERY_RESUME` | 88 | 断点续传查询 |
| `COMMAND_C2C_PREPARE` | 89 | C2C准备接收通知 |
| `COMMAND_C2C_TEXT` | 90 | C2C文本传输 |
| `COMMAND_FILE_COMPLETE_V2` | 91 | V2文件完成校验包 |
| `COMMAND_C2C_PREPARE_RESP` | 92 | C2C准备响应返回目标目录 |
## 五、核心特性
- **断点续传**: 基于 transferID + 文件特征匹配,支持传输中断后恢复
- **大文件支持**: 使用 uint64_t 存储文件大小和偏移突破4GB限制
- **自动目标目录**: C2C传输自动捕获目标客户端当前焦点窗口的目录
- **自动粘贴**: C2C文本传输完成后自动模拟 Ctrl+V 完成粘贴
- **版本协商**: 能力位 `CLIENT_CAP_V2` + 版本日期双重检测
- **文件完整性校验**: 传输完成后发送 SHA-256 校验包,接收端自动验证
- **服务端开关**: 参数菜单可控制是否启用 V2默认关闭
- **自动清理**: 状态文件超过 7 天自动删除
## 5.1 文件完整性校验
每个文件传输完成后,发送端计算并发送 `COMMAND_FILE_COMPLETE_V2` 校验包:
```cpp
struct FileCompletePacketV2 {
uint8_t cmd; // = 91
uint64_t transferID;
uint64_t srcClientID;
uint64_t dstClientID;
uint32_t fileIndex;
uint64_t fileSize;
uint8_t sha256[32]; // SHA-256 哈希
}; // 69 bytes
```
**工作流程**:
1. 发送端在发送文件数据同时计算 SHA-256
2. 文件最后一个块发送完成后,发送 `FILE_COMPLETE_V2` 校验包
3. 接收端在接收数据时同步计算 SHA-256流式计算无需重读文件
4. 收到校验包后对比哈希值,输出校验结果
**支持的传输方向**:
| 方向 | 校验位置 |
|------|----------|
| 客户端 → 服务端 | 服务端校验 |
| 服务端 → 客户端 | 客户端校验 |
| 客户端A → 客户端B (C2C) | 服务端转发客户端B校验 |
**校验失败处理**:
- 校验失败时自动删除损坏文件
- 日志输出期望和实际的 SHA-256 哈希值
**断点续传与校验**:
- 断点续传时无法使用流式 SHA-256缺少历史数据
- 自动切换为从文件重新计算完整 SHA-256
## 六、相关文件
| 文件 | 说明 |
|------|------|
| `common/commands.h` | 协议命令定义 |
| `common/file_upload.h/cpp` | V2传输核心实现 |
| `client/KernelManager.cpp` | 客户端主连接处理 |
| `client/ScreenManager.cpp` | 客户端远程桌面会话处理 |
| `server/2015Remote/2015RemoteDlg.cpp` | 服务端主逻辑 |
| `server/2015Remote/ScreenSpyDlg.cpp` | 服务端远程桌面会话处理 |
| `server/2015Remote/CDlgFileSend.cpp` | 文件传输进度对话框 |
## 七、使用说明
### C2C 文件传输
1. 打开两个远程桌面窗口源A和目标B
2. 在源A上选中文件按 Ctrl+C
3. 按 X 切换到目标B
4. 按 Ctrl+V文件自动传输到B当前目录
### C2C 文本传输
1. 在源A上复制文本Ctrl+C
2. 按 X 切换到目标B
3. 在目标B的应用中按 Ctrl+V文本自动粘贴
### 断点续传
- 传输中断后,重新执行相同操作
- 系统自动检测已传输部分,从断点继续
- 状态文件保存在 `%TEMP%\FileTransfer\`
- 状态文件超过 7 天自动删除
### 状态文件说明
| 后缀 | 用途 | 说明 |
|------|------|------|
| `.resume` | 断点续传状态 | 记录 transferID、文件列表、已接收字节数 |
| `.recv` | C2C 接收方目录 | 记录目标客户端当前焦点窗口目录 |
| `.send` | C2C 发送方目录 | 记录源客户端剪贴板文件路径 |
所有状态文件统一存放在 `%TEMP%\FileTransfer\` 目录,文件名格式为 `{transferID}.{后缀}`
---
## 八、代码审查报告
### 8.1 审查范围
| 文件 | 改动行数 | 审查结果 |
|------|:--------:|:--------:|
| `common/commands.h` | +16 | ✅ |
| `common/file_upload.h` | +288 | ✅ |
| `SimplePlugins/file_upload.cpp` | 核心实现 | ✅ |
| `client/KernelManager.cpp` | +294 | ✅ |
| `client/ScreenManager.cpp` | +360 | ✅ |
| `server/2015Remote/2015RemoteDlg.cpp` | +698 | ✅ |
| `server/2015Remote/CDlgFileSend.cpp` | +116 | ✅ |
| `server/2015Remote/context.h` | +34 | ✅ |
### 8.2 代码质量评估
#### 优点
1. **协议设计清晰** - 结构体使用 `#pragma pack(push, 1)` 确保跨平台对齐,注释详尽
2. **版本兼容性** - V1/V2 协议共存,旧客户端仍可使用
3. **能力协商机制完善** - `CLIENT_CAP_V2` 能力位 + 版本日期双重检测
4. **断点续传设计** - `transferID + fileIndex` 组合键唯一标识,状态持久化
5. **线程安全** - 使用 `std::mutex` 保护共享状态(`g_fileStatesV2Mtx` 等)
6. **智能指针** - `std::unique_ptr` 管理内存RAII 处理文件句柄
7. **SHA-256 校验** - 使用 Windows bcrypt API流式计算
#### 待改进项
| 优先级 | 问题 | 位置 | 建议 |
|:------:|------|------|------|
| 🟠 中 | 路径穿越未验证 | `file_upload.cpp:712` | `GetRelativePath` 添加 `..` 检查 |
| 🟠 中 | 变量命名误导 | `file_upload.cpp:2463` | `utf8Name` 实际是 ANSI应改名 |
| 🟡 低 | 重复代码 | `KernelManager.cpp` / `ScreenManager.cpp` | C2C_TEXT 处理逻辑可提取公共函数 |
### 8.3 安全审查
| 检查项 | 状态 | 说明 |
|--------|:----:|------|
| 缓冲区溢出 | ✅ | 有长度校验 `if (len < sizeof(...) + nameLength + dataLength)` |
| 认证校验 | ✅ | 使用 hash + hmac 验证 |
| 路径穿越 | ⚠️ | `GetRelativePath` 未检查 `..` 序列(实际风险低) |
| 客户端ID伪造 | ✅ | 通过 `FindHost` 验证客户端存在 |
| 文件句柄泄漏 | ✅ | RAII 析构函数处理 |
| 整数溢出 | ✅ | 使用 `uint64_t` 支持大文件 |
**路径穿越风险分析**:
- `GetRelativePath` 未过滤 `..` 序列
- 实际风险较低C2C 由服务端键盘钩子触发,非任意用户输入
- 建议后续版本加固
### 8.4 边界条件测试建议
| 场景 | 测试点 |
|------|--------|
| 大文件 | >4GB 文件传输和断点续传 |
| 网络抖动 | 传输中断后恢复 |
| 并发传输 | 多个 C2C 同时进行 |
| 客户端重启 | `.resume` 文件恢复 + SHA-256 重算 |
| 目录结构 | 深层嵌套目录创建 |
| 空文件 | 0 字节文件传输和校验 |
---
## 九、提交评估
### 9.1 总体评估:✅ 可发布
| 指标 | 状态 | 说明 |
|------|:----:|------|
| 功能完整性 | ✅ | C2C/断点续传/SHA-256 校验均已实现 |
| 编译通过 | ✅ | 无编译错误 |
| 向后兼容 | ✅ | V1 协议仍可用,能力协商正确 |
| 崩溃风险 | ✅ | 无明显崩溃点 |
| 数据安全 | ✅ | HMAC 认证、长度校验完善 |
### 9.2 问题分类
| 严重程度 | 数量 | 是否阻塞提交 |
|:--------:|:----:|:------------:|
| 🔴 致命 | 0 | - |
| 🟠 中等 | 2 | 否 |
| 🟡 低危 | 1 | 否 |
### 9.3 后续改进建议
1. **路径安全加固** - 在 `GetRelativePath` 添加 `..` 过滤
2. **重复代码重构** - 提取 C2C_TEXT 处理为公共函数
3. **变量命名修正** - `utf8Name``ansiName`
4. **日志级别控制** - 添加 verbose 模式开关
---
*审查日期: 2026-02-27*