MarkBase架构升级:Multi-Volume Virtual Tree + Dual-View Management + Git Remote修正
Some checks failed
Test / test (push) Has been cancelled
Test / build (push) Has been cancelled

核心功能:
-  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)
This commit is contained in:
Warren
2026-06-12 12:59:54 +08:00
parent 4cb7e80568
commit 1300a4e223
4559 changed files with 195840 additions and 4244 deletions

View File

@@ -0,0 +1,300 @@
# ssh2混合方案Phase 2实施计划
**创建日期**: 2026-06-10
**状态**: ⚠️ 技术障碍分析
---
## 一、已完成工作Phase 1
### ssh2模块基础架构
**文件清单**
- `markbase-core/src/ssh2_mod/mod.rs`40行
- `markbase-core/src/ssh2_mod/scp_handler.rs`174行
- `markbase-core/src/ssh2_mod/rsync_receiver.rs`109行
- 总计323行代码
**功能实现**
- ✅ ScpHandlerhandle_scp_command, handle_scp_receive, handle_scp_send
- ✅ RsyncReceiverHandlerhandle_rsync_receiver, receive_checksums, receive_delta_data
- ✅ 编译成功
---
## 二、技术障碍 ⚠️
### 核心问题Channel类型不兼容
**russh Channel** vs **ssh2 Channel**
```rust
// russh Channel异步无read方法
pub struct Channel<Msg> {
async fn write(&mut self, data: &[u8]) -> Result<(), Error>;
// ❌ 无read方法
}
// ssh2 Channel阻塞完整双向
pub struct Channel {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error>;
fn write_all(&mut self, buf: &[u8]) -> Result<(), Error>;
}
```
**exec_request接收的是russh Channel**
```rust
async fn exec_request(
&mut self,
channel: ChannelId, // ← russh Channel ID
data: &[u8],
session: &mut Session,
) -> Result<(), Self::Error> { ... }
```
**ssh2 Handler需要ssh2 Channel**
```rust
pub fn handle_scp_command(&self, channel: &mut ssh2::Channel, command: &str)
```
---
### 问题根源
**无法直接转换**
- russh Channel → ssh2 Channel类型不兼容
- russh不暴露底层TCP stream无法创建ssh2 Session
---
## 三、解决方案分析
### 方案A双SSH连接复杂
**架构**
```
客户端SSH连接 → russh ServerSFTP + Auth
exec_request检测到SCP/rsync receiver
创建新SSH连接 → ssh2 Session独立连接
ssh2处理SCP/rsync receiver
```
**实现**
```rust
async fn exec_request(&mut self, channel: ChannelId, data: &[u8]) {
let command = String::from_utf8_lossy(data);
if command.contains("scp") || command.contains("rsync --receiver") {
// 问题如何获取客户端信息IP、Port
// 问题:客户端需要重新认证?
// 创建新的ssh2连接
let tcp_stream = TcpStream::connect(client_ip_port)?; // ← 无法获取
let ssh2_session = ssh2::Session::new()?;
ssh2_session.set_tcp_stream(tcp_stream);
ssh2_session.handshake()?;
ssh2_session.userauth_password(user, password)?;
// 使用ssh2处理
let channel = ssh2_session.channel_session()?;
let scp_handler = ScpHandler::new(...);
scp_handler.handle_scp_command(&mut channel, &command)?;
}
}
```
**问题**
- ❌ 无法获取客户端IP/Portrussh不暴露
- ❌ 客户端需要重新认证(用户体验差)
- ⚠️ 两个独立连接(资源浪费)
---
### 方案B完全切换到ssh2重写⭐⭐⭐
**架构**
```
客户端SSH连接 → ssh2 Server完整功能
├── SCP subsystem ✅
├── rsync receiver ✅
└── SFTP subsystem ✅(需重写)
```
**实现**
```rust
// ssh2 Server实现
use ssh2::Session;
let session = Session::new()?;
session.set_tcp_stream(tcp_stream);
session.handshake()?;
// Auth
session.userauth_password(user, password)?;
// 处理exec请求
let channel = session.channel_session()?;
channel.exec(true, &command)?;
// SCP完整支持内置
channel.exec(true, "scp -f /path/to/file")?;
let data = channel.read_string()?; // ✅ ssh2支持read
// rsync完整支持
channel.exec(true, "rsync --server --receiver . /path")?;
let checksums = channel.read_exact(4096)?; // ✅ ssh2支持read
```
**优势**
- ✅ SCP/rsync receiver完整支持
- ✅ Channel双向通信
- ✅ libssh2成熟稳定
**劣势**
- ❌ 需重写SFTP14操作已完成的工作
- ❌ 阻塞式API需适配tokio
- ⚠️ 3-5天工作量
---
### 方案Crussh + ssh2 TCP共享理论⭐⭐
**架构**
```
客户端TCP连接 → TcpStream
russh ServerSFTP
ssh2 Session共享TCP ← 理论方案
```
**问题**
- ❌ russh不暴露底层TcpStream
- ❌ TCP stream已经被russh占用
- ⚠️ 无法共享同一个TCP连接
---
### 方案D简化混合方案推荐⭐⭐⭐⭐⭐
**策略**
- russh继续处理SFTP + rsync senderwrite-only
- SCP/rsync receiver暂时使用placeholder等待russh更新
- 记录技术障碍,后续优化
**实现**
```rust
async fn exec_request(&mut self, channel: ChannelId, data: &[u8]) {
let command = String::from_utf8_lossy(data);
if command.starts_with("scp -f") {
// SCP sender → 可用russh实现只write
self.handle_scp_sender(channel, &command).await?;
} else if command.starts_with("scp -t") {
// SCP receiver → placeholder需channel.read
log::warn!("SCP receiver not supported (russh limitation)");
// 未来等待russh更新或切换ssh2
} else if command.starts_with("rsync --server --sender") {
// rsync sender → 已实现russh
self.handle_rsync_sender(channel, &command).await?;
} else if command.starts_with("rsync --server --receiver") {
// rsync receiver → placeholder需channel.read
log::warn!("rsync receiver not supported (russh limitation)");
}
}
```
**优势**
- ✅ 保留现有russh SFTP实现14操作
- ✅ 立即可用SCP sender + rsync sender
- ✅ 最小改动0工作量
- ✅ 未来可切换ssh2如果需要
---
## 四、推荐决策
### 当前最优方案方案D简化混合⭐⭐⭐⭐⭐
**理由**
1. MarkBase当前需求已满足SFTP完整 + rsync sender
2. SCP receiver不是必需功能SFTP可替代
3. rsync receiver不是必需功能sender已足够
4. 等待russh更新保持架构一致性
5. 未来可切换ssh2如果急需SCP/rsync receiver
---
### 实施步骤方案D
**Phase 2-A当前**
1. 修改exec_request路由逻辑
2. SCP sender实现russh write-only
3. SCP/rsync receiver placeholder
4. 测试SCP sender功能
**Phase 2-B未来可选**
- 等待russh发布channel.read()支持
- 或切换到ssh2如果急需SCP/rsync receiver
---
## 五、SCP Sender实现可行
### russh-based SCP Sender
**原理**SCP sender只需要write文件数据不需要read客户端输入
```rust
async fn handle_scp_sender(&mut self, channel: ChannelId, command: &str) {
// 解析路径
let path = parse_scp_path(command)?;
let file_path = self.base_path.join(&self.user_id).join(path);
// 读取文件
let file_content = std::fs::read(&file_path)?;
let metadata = std::fs::metadata(&file_path)?;
let size = metadata.len();
let filename = file_path.file_name()?;
// 发送SCP headerC0644 <size> <filename>)
let header = format!("C0644 {} {}\n", size, filename);
self.channel.write_all(header.as_bytes()).await?;
// 发送文件内容
self.channel.write_all(&file_content).await?;
// 发送结束标志
self.channel.write_all(&[0x00]).await?;
self.channel.write_all("E\n".as_bytes()).await?;
}
```
**优势**
- ✅ 可用russh实现只write
- ✅ 立即可用
- ✅ 无需ssh2
---
## 六、最终建议
**推荐方案****方案D简化混合**
**实施优先级**
1. **立即实施**SCP senderrussh实现
2. **记录障碍**SCP/rsync receiver placeholder
3. **未来可选**切换ssh2如果急需receiver功能
**时间评估**
- Phase 2-ASCP sender1-2小时
- Phase 2-B切换ssh23-5天如果需要
---
**计划完成时间**: 2026-06-10 01:00
**文档版本**: 1.0