Files
markbase/docs/SSH2_SFTP_IMPLEMENTATION_OPTIONS.md
Warren 1300a4e223
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled
MarkBase架构升级:Multi-Volume Virtual Tree + Dual-View Management + Git Remote修正
核心功能:
-  Categories/Series双视图管理(category_view.rs + import_markdown.rs)
-  FUSE Multi-Volume支持(tree_type参数)
-  SSH/SFTP/SCP/rsync协议完整实现(4042行)
-  NFS/SMB Module Phase 1-3完成
-  Archive Module Phase 1-4完成(2916行)
-  Download Center API完整实现
-  S3兼容API实现(560行)

Git配置修正:
-  删除错误origin(gitea.momentry.ddns.net)
-  删除m5max128(指向机器名)
-  设置origin = m5max128gitea.momentry.ddns.net/admin/markbase
-  设置m4minigitea = m4minigitea.momentry.ddns.net/warren/markbase

数据清理:
-  删除38个临时SQLite(保留accusys.sqlite、demo.sqlite)
-  删除.bak、test_*.bin、调试脚本等临时文件
-  删除临时目录(build/、download files/、raid_test/等)
-  更新.gitignore排除临时文件

架构优化:
- 52个文件修改,2434行新增,4739行删除
- Workspace成员整合(16个crate)
- 数据库状态:accusys.sqlite保留(主demo测试)

远程同步:
-  准备推送到m5max128gitea(远程Gitea)
-  准备推送到m4minigitea(本地Gitea)
2026-06-12 12:59:54 +08:00

303 lines
7.4 KiB
Markdown
Raw 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.
# ssh2 SFTP实现方案分析
**分析日期**: 2026-06-10 02:05
**目的**: 确定Phase 2 SFTP Handler实现方式
---
## 一、实现方案对比
### 方案A实现SFTP协议packet ⭐⭐⭐⭐
**原理**直接实现SFTP packet协议
**SFTP协议结构**
```
SFTP Packet格式
- Length4字节packet总长度
- Type1字节操作类型SSH_FXP_INIT=1, SSH_FXP_OPEN=3等
- Request ID4字节请求ID
- Payload变长操作参数
操作类型:
- SSH_FXP_INIT (1):初始化
- SSH_FXP_VERSION (2):版本响应
- SSH_FXP_OPEN (3):打开文件
- SSH_FXP_CLOSE (4):关闭文件
- SSH_FXP_READ (5):读取文件
- SSH_FXP_WRITE (6写入文件
- SSH_FXP_LSTAT (7):获取状态
- SSH_FXP_FSTAT (8获取文件状态
- SSH_FXP_SETSTAT (9设置状态
- SSH_FXP_FSETSTAT (10设置文件状态
- SSH_FXP_OPENDIR (11打开目录
- SSH_FXP_READDIR (12读取目录
- SSH_FXP_REMOVE (13删除文件
- SSH_FXP_MKDIR (14创建目录
- SSH_FXP_RMDIR (15删除目录
- SSH_FXP_REALPATH (16真实路径
- SSH_FXP_STAT (17获取状态
- SSH_FXP_RENAME (18重命名
- SSH_FXP_READLINK (19读取链接
- SSH_FXP_SYMLINK (20创建链接
```
**实现步骤**
1. 定义packet结构
2. 实现packet解析read_packet
3. 实现packet构建write_packet
4. 实现14个操作handler
5. 循环处理客户端请求
**工作量**
- Packet解析约100行
- Packet构建约100行
- 14操作handler约200行
- **总计**约400行
**优势**
- ✅ 完全控制协议细节
- ✅ 可自定义功能
- ✅ 不依赖外部crate
**劣势**
- ⚠️ 工作量较大400行
- ⚠️ 需深入理解SFTP协议
- ⚠️ 测试复杂度高
---
### 方案B使用ssh2 crate内置SFTP ⭐⭐⭐⭐⭐(推荐)
**发现**ssh2 crate可能已内置SFTP支持
**API探索**
```rust
// ssh2 crate SFTP API假设
let sftp = session.sftp()?; // 创建SFTP channel
// SFTP操作
sftp.open(path)?;
sftp.read(file)?;
sftp.write(file, data)?;
sftp.close(file)?;
sftp.readdir(path)?;
sftp.stat(path)?;
sftp.mkdir(path)?;
sftp.remove(path)?;
sftp.rename(old, new)?;
```
**需要验证**
- ssh2 crate是否提供SFTP API
- API是否完整14操作
- 是否需要exec("sftp-server")
**优势**
- ✅ 最小工作量约50行
- ✅ 使用成熟实现
- ✅ 降低风险
**劣势**
- ⚠️ 需验证API是否存在
- ⚠️ 可能功能受限
---
### 方案C使用系统sftp-server程序 ⭐⭐
**原理**调用系统sftp-server binary
**实现**
```rust
channel.exec(true, "/usr/lib/openssh/sftp-server")?;
// 系统sftp-server处理所有SFTP操作
```
**优势**
- ✅ 工作量最小1行
- ✅ 使用OpenSSH成熟实现
- ✅ 功能完整
**劣势**
- ❌ 依赖系统binarymacOS路径/usr/libexec/sftp-server
- ❌ 无法自定义功能
- ❌ FileTree映射不适用
---
## 二、ssh2 crate SFTP API验证
### 查阅ssh2 crate文档
**关键问题**
- ssh2::Session是否有sftp()方法?
- ssh2 crate是否支持SFTP subsystem
**验证方法**
1. 查阅ssh2 crate文档
2. 搜索ssh2-sftp crate
3. 检查ssh2源码
---
### ssh2 crate SFTP API预期
**如果存在,应该类似**
```rust
pub struct Session {
pub fn sftp(&self) -> Result<Sftp>;
}
pub struct Sftp {
pub fn open(&self, path: &Path) -> Result<File>;
pub fn readdir(&self, path: &Path) -> Result<Vec<FileInfo>>;
pub fn stat(&self, path: &Path) -> Result<FileInfo>;
pub fn mkdir(&self, path: &Path) -> Result<()>;
pub fn remove(&self, path: &Path) -> Result<()>;
pub fn rename(&self, old: &Path, new: &Path) -> Result<()>;
}
```
---
## 三、方案选择建议
### 推荐方案方案B ⭐⭐⭐⭐⭐
**理由**
1. 如果ssh2已内置SFTP → 工作量最小50行
2. 如果不存在 → 回退方案A400行
3. 先验证再实施(降低风险)
**实施步骤**
1. 查阅ssh2 crate文档5分钟
2. 如果API存在 → 使用方案B
3. 如果API不存在 → 实施方案A
---
### 验证优先级
**立即验证**
- cargo search ssh2-sftp
- 查阅ssh2 crate文档
- 检查ssh2::Session API
---
## 四、实施方案代码预览
### 方案B代码如果ssh2支持
```rust
// ssh2_server/sftp_handler.rs约50行
use ssh2::{Session, Sftp};
use crate::sftp::filetree::FileTreeMapper;
pub struct Sftp2Handler {
user_id: String,
config: Arc<SftpConfig>,
}
impl Sftp2Handler {
pub fn handle_sftp(&self, session: &Session) -> Result<()> {
let sftp = session.sftp()?;
// 复用FileTree映射
let mapper = FileTreeMapper::new(self.config.clone());
// 处理客户端请求(简化)
loop {
// ⚠️ 需要研究如何读取SFTP请求packet
// ssh2 sftp API可能需要进一步研究
}
Ok(())
}
}
```
---
### 方案A代码手动实现
```rust
// ssh2_server/sftp_handler.rs约400行
use ssh2::Channel;
pub struct Sftp2Handler {
user_id: String,
config: Arc<SftpConfig>,
}
impl Sftp2Handler {
pub fn handle_sftp(&self, channel: &mut Channel) -> Result<()> {
// 1. 发送版本响应
self.send_version(channel)?;
// 2. 循环处理请求
loop {
let packet = self.read_packet(channel)?;
match packet.type {
SSH_FXP_OPEN => self.handle_open(channel, packet)?,
SSH_FXP_READ => self.handle_read(channel, packet)?,
SSH_FXP_WRITE => self.handle_write(channel, packet)?,
SSH_FXP_CLOSE => self.handle_close(channel, packet)?,
SSH_FXP_MKDIR => self.handle_mkdir(channel, packet)?,
SSH_FXP_RMDIR => self.handle_rmdir(channel, packet)?,
SSH_FXP_REMOVE => self.handle_remove(channel, packet)?,
SSH_FXP_RENAME => self.handle_rename(channel, packet)?,
SSH_FXP_OPENDIR => self.handle_opendir(channel, packet)?,
SSH_FXP_READDIR => self.handle_readdir(channel, packet)?,
SSH_FXP_REALPATH => self.handle_realpath(channel, packet)?,
SSH_FXP_STAT => self.handle_stat(channel, packet)?,
SSH_FXP_LSTAT => self.handle_lstat(channel, packet)?,
_ => warn!("Unknown packet type: {}", packet.type),
}
}
}
fn read_packet(&self, channel: &mut Channel) -> Result<SftpPacket> {
// 解析packet length, type, request_id, payload
let mut buf = vec![0u8; 4];
channel.read_exact(&mut buf)?;
let length = u32::from_be_bytes(buf);
let mut packet_buf = vec![0u8; length as usize];
channel.read_exact(&mut packet_buf)?;
// 解析packet
...
}
fn send_version(&self, channel: &mut Channel) -> Result<()> {
// SSH_FXP_VERSION packet
let version_packet = build_version_packet(3); // SFTP version 3
channel.write_all(&version_packet)?;
Ok(())
}
}
```
---
## 五、决策建议
**立即验证ssh2 SFTP API**
- 查阅ssh2 crate文档
- 如果存在 → 方案B推荐
- 如果不存在 → 方案A
**时间评估**
- 方案B50行2小时
- 方案A400行8小时
- 差距6小时
---
**方案选择完成时间**: 2026-06-10 02:10
**版本**: 1.0