Files
markbase/docs/russh_analysis/API_LIMITATIONS.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

30 KiB
Raw Blame History

russh v0.61.2 API限制分析报告

分析日期: 2026-06-09
分析目标: 评估russh库在rsync集成中的技术可行性
分析范围: Channel API、数据流处理、Multiplexing、rsync握手流程


1. Channel API能力分析

1.1 channel.data()方法存在性

结论: channel.data()方法存在,但存在关键限制。

API定义channels/mod.rs:321

/// Send data to a channel.
pub async fn data<R: tokio::io::AsyncRead + Unpin>(&self, data: R) -> Result<(), Error> {
    self.send_data(None, data).await
}

/// Send owned bytes to a channel without copying them into the `AsyncWrite` path.
pub async fn data_bytes(&self, data: impl Into<Bytes>) -> Result<(), Error> {
    self.send_bytes(None, data.into()).await
}

关键发现:

  • data()方法存在,接受AsyncRead类型参数
  • data_bytes()方法存在,接受Bytes类型参数(零拷贝)
  • 支持异步发送(async fn
  • ⚠️ 单向数据发送,无返回值(Result<(), Error>
  • ⚠️ 仅用于服务器向客户端发送数据

1.2 channel.read()双向流支持 ⚠️

结论: channel.read()方法不存在,但有替代方案。

Channel API完整能力矩阵

方法 存在性 功能 适用场景
channel.data() 存在 发送数据 Sender模式
channel.wait() 存在 接收ChannelMsg 接收所有消息类型
channel.make_reader() 存在 创建AsyncRead流 接收Data消息
channel.into_stream() 存在 创建双向Stream 唯一双向方案
channel.read() 不存在 直接读取数据 API缺失

替代方案分析:

方案1channel.wait() - 接收所有消息类型

// channels/mod.rs:655
pub async fn wait(&mut self) -> Option<ChannelMsg> {
    self.read_half.wait().await
}

// ChannelMsg枚举定义channels/mod.rs:21-114
pub enum ChannelMsg {
    Data { data: Bytes },          // ← 数据消息
    ExtendedData { data: Bytes, ext: u32 },  // ← 扩展数据stderr
    Eof,                           // ← EOF信号
    Close,                         // ← 关闭信号
    Open { ... },
    ExitStatus { exit_status: u32 },
    // ... 其他控制消息
}

优点:

  • 可以接收所有消息类型Data、Eof、Close、ExitStatus等
  • 完整的SSH协议消息处理能力

缺点:

  • ⚠️ 需要手动处理ChannelMsg枚举代码复杂度高
  • ⚠️ 需要循环调用wait(),无法直接作为流使用
  • ⚠️ 不支持AsyncRead trait无法直接用于russh-sftp

方案2channel.make_reader() - AsyncRead流

// channels/mod.rs:677
pub fn make_reader(&mut self) -> impl AsyncRead + '_ {
    self.read_half.make_reader()
}

优点:

  • 实现AsyncRead trait可直接用于SFTP等子系统
  • 自动过滤Data消息忽略其他控制消息
  • 支持异步读取

缺点:

  • ⚠️ 仅支持读取,无法同时发送数据
  • ⚠️ 需要借用&mut self无法同时持有channel用于发送
  • ⚠️ 无法实现双向流rsync receiver模式需要

方案3channel.into_stream() - 双向Stream

// channels/mod.rs:661
pub fn into_stream(self) -> ChannelStream<S> {
    ChannelStream::new(
        io::ChannelTx::new(...),  // ← 发送端AsyncWrite
        io::ChannelRx::new(...),  // ← 接收端AsyncRead
    )
}

ChannelStream实现channels/channel_stream.rs

impl<S> AsyncRead for ChannelStream<S> {
    fn poll_read(...) -> Poll<io::Result<()>> {
        Pin::new(&mut self.rx).poll_read(cx, buf)  // ← 使用ChannelRx读取
    }
}

impl<S> AsyncWrite for ChannelStream<S> {
    fn poll_write(...) -> Poll<Result<usize, io::Error>> {
        Pin::new(&mut self.tx).poll_write(cx, buf)  // ← 使用ChannelTx写入
    }
}

优点:

  • 唯一支持双向流的方案
  • 同时实现AsyncRead + AsyncWrite
  • 可以直接用于russh-sftp的run()函数
  • 支持异步读写符合tokio生态

缺点:

  • ⚠️ 消耗Channel所有权selfinto_stream(self)
  • ⚠️ 无法再调用channel.data()等原始方法
  • ⚠️ 需要在创建stream前准备好所有逻辑

1.3 异步读取数据支持

结论: 完全支持异步读取。

异步支持证据:

// ChannelReadHalf.wait() - 异步接收消息
pub async fn wait(&mut self) -> Option<ChannelMsg> {
    self.receiver.recv().await  // ← tokio::sync::mpsc异步接收
}

// ChannelRx.poll_read() - 异步读取流
impl AsyncRead for ChannelRx<R> {
    fn poll_read(...) -> Poll<io::Result<()>> {
        match ready!(self.channel.borrow_mut().receiver.poll_recv(cx)) {
            Some(msg) => (msg, 0),
            None => return Poll::Ready(Ok(())),
        }
        // ... 处理Data消息
    }
}

异步特性:

  • 基于tokio::sync::mpsc的异步channel
  • 支持Future/async/await语法
  • 支持AsyncRead/AsyncWrite trait
  • 完整集成tokio生态

2. 数据流处理能力分析

2.1 Sender模式数据发送能力

结论: Sender模式完全支持但仅适用于单向发送。

Sender模式实现server.rs:177

// MarkBase现有实现rsync sender模式
if rsync_cmd.is_sender_mode() {
    let data = tokio::fs::read(&file_path).await?;
    
    // 发送数据到channel
    channel.data(&send_data[..]).await?;  // ← 单向发送
    
    // 发送退出状态
    channel.exit_status(0).await?;
}

支持能力:

  • 读取本地文件
  • 压缩数据(可选)
  • 通过channel.data()发送数据
  • 发送exit_status退出状态
  • 完整Sender模式支持

技术限制:

  • ⚠️ 无法接收客户端的响应如rsync protocol握手
  • ⚠️ 无法处理复杂的双向交互协议

2.2 Receiver模式数据接收能力 ⚠️

结论: Receiver模式理论上支持,但存在技术障碍。

Receiver模式需求server.rs:190

// MarkBase现有代码中的TODO注释
else {
    log::info!("Rsync receiver mode: receiving file {}", file_path);
    
    // Receiver模式接收文件数据
    // 简化实现等待channel数据需要russh API支持
    // 完整实现需要双向数据流处理
    
    // TODO: 实现channel.read() - russh API限制 ⚠️
    log::warn!("Rsync receiver mode requires bidirectional stream support");
    
    channel.exit_status(1).await?;  // ← 暂时不支持
}

技术障碍分析:

障碍类型 具体问题 解决方案
API缺失 channel.read()不存在 使用into_stream()
所有权冲突 Channel已被消耗 无法再调用channel.data()
消息类型处理 需过滤Data消息 ChannelRx自动过滤
协议复杂性 rsync握手需双向交互 需完整协议实现

可能的实现路径:

路径1使用into_stream()

// 理论实现(未验证)
let stream = channel.into_stream();  // ← 消耗channel所有权

// 接收客户端数据
let mut buf = vec![0u8; 1024];
let n = stream.read(&mut buf).await?;  // ← AsyncRead

// 写入本地文件
tokio::fs::write(&file_path, &buf[..n]).await?;

// 发送响应
stream.write_all(b"ACK").await?;  // ← AsyncWrite

路径2使用wait()循环

// 理论实现(未验证)
loop {
    match channel.wait().await {
        Some(ChannelMsg::Data { data }) => {
            // 接收数据
            tokio::fs::write(&file_path, &data).await?;
        }
        Some(ChannelMsg::Eof) => {
            // EOF信号
            channel.exit_status(0).await?;
            break;
        }
        None => break,  // ← channel关闭
        _ => {}  // ← 忽略其他消息
    }
}

2.3 双向数据流交互可能性 ⚠️

结论: 理论上可行,但需要完整协议实现。

双向流交互需求rsync protocol

rsync Protocol握手流程
┌─────────────────────────────────────────────────────┐
│ Phase 1: Connection Setup                           │
│ - Client sends: "rsync\n"                           │
│ - Server responds: "@RSYNCD: 31\n"                  │
│ - Client sends: "@RSYNCD: 31\n"                     │
└─────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────┐
│ Phase 2: Authentication                             │
│ - Client sends command line                         │
│ - Server validates user/path                        │
│ - Server sends: "@RSYNCD: OK\n"                     │
└─────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────┐
│ Phase 3: File Transfer                               │
│ - Sender: sends file data + checksums               │
│ - Receiver: sends ACK/requests                      │
│ - Multiple round-trips                              │
└─────────────────────────────────────────────────────┘

russh双向流能力评估

双向流需求 russh支持 实现难度
Phase 1: 握手 支持 中等(需解析协议)
Phase 2: 认证 支持 已有bcrypt
Phase 3: Sender 支持 低(单向发送)
Phase 3: Receiver ⚠️ ⚠️ 部分支持 高(双向交互)

关键发现:

  • Phase 1-2可用into_stream()实现
  • Sender模式可用channel.data()实现
  • ⚠️ Receiver模式需要完整协议状态机 ⚠️
  • ⚠️ rsync protocol未标准化需参考OpenSSH实现

3. Multiplexing支持分析

3.1 russh是否支持multiplexing protocol

结论: russh 不支持SSH multiplexing protocol

证据分析client/mod.rs:85

/// It is in charge of multiplexing and keeping track of various channels

关键误解澄清:

  • ⚠️ "multiplexing"在russh源码中指的是多channel管理
  • ⚠️ 不是SSH Control MultiplexingOpenSSH的ControlMaster
  • russh不支持ControlMaster/ControlPath协议

SSH Multiplexing vs russh Channel Multiplexing

特性 SSH Control Multiplexing russh Channel Multiplexing
定义 一个SSH连接承载多个SSH会话 一个SSH连接承载多个channel
协议 OpenSSH专有协议 SSH RFC 4254标准协议
实现 ControlMaster + ControlPath 多个ChannelId并发
用途 连接复用、减少认证开销 并行执行多个命令
russh支持 不支持 支持

russh Channel Multiplexing实现

// Session内部管理多个channels
pub struct Session {
    channels: HashMap<ChannelId, Channel<Msg>>,  // ← 多channel并发
}

// 示例:并发执行多个命令
let channel1 = session.channel_open_session().await?;
let channel2 = session.channel_open_session().await?;  // ← 第二个channel

channel1.exec("ls").await?;
channel2.exec("pwd").await?;  // ← 并发执行

3.2 Message type区分能力

结论: 完全支持Message type区分。

ChannelMsg完整枚举channels/mod.rs:21-114

pub enum ChannelMsg {
    // 数据消息
    Data { data: Bytes },                  // ← STDOUT数据
    ExtendedData { data: Bytes, ext: u32 },  // ← STDERR数据ext=1
    
    // 控制消息
    Open { id, max_packet_size, window_size },
    Eof,                                    // ← EOF信号
    Close,                                  // ← 关闭信号
    
    // 客户端请求client only
    RequestPty { ... },
    RequestShell { want_reply: bool },
    Exec { want_reply: bool, command: Vec<u8> },
    RequestSubsystem { want_reply: bool, name: String },
    Signal { signal: Sig },
    
    // 服务器响应server only
    ExitStatus { exit_status: u32 },        // ← 退出状态
    ExitSignal { signal_name, core_dumped, ... },
    Success,                                // ← 成功响应
    Failure,                                // ← 失败响应
    WindowAdjusted { new_size: u32 },
    XonXoff { client_can_do: bool },
    
    // 其他
    SetEnv { ... },
    WindowChange { ... },
    AgentForward { ... },
    RequestX11 { ... },
    OpenFailure(ChannelOpenFailure),
}

Message type分类

类别 Message类型 处理方式
数据消息 Data, ExtendedData 通过ChannelRx读取
控制消息 Eof, Close, ExitStatus 通过wait()接收
请求消息 Exec, RequestSubsystem 通过Handler trait处理
响应消息 Success, Failure 通过Handler trait返回

3.3 控制消息和数据消息分离

结论: 完全支持分离。

分离机制:

方案1ChannelRx自动过滤

// channels/io/rx.rs:46
impl AsyncRead for ChannelRx<R> {
    fn poll_read(...) -> Poll<io::Result<()>> {
        match (&msg, self.ext) {
            (ChannelMsg::Data { data }, None) => {
                // ← 只处理Data消息自动过滤其他消息
                buf.put_slice(&data[idx..idx + readable]);
                Poll::Ready(Ok(()))
            }
            (ChannelMsg::ExtendedData { data, ext }, Some(target)) if *ext == target => {
                // ← 只处理匹配的ExtendedData
                buf.put_slice(&data[idx..idx + readable]);
                Poll::Ready(Ok(()))
            }
            (ChannelMsg::Eof, _) => {
                // ← EOF信号关闭流
                self.channel.borrow_mut().receiver.close();
                Poll::Ready(Ok(()))
            }
            _ => {
                // ← 忽略其他控制消息ExitStatus、Close等
                cx.waker().wake_by_ref();
                Poll::Pending
            }
        }
    }
}

方案2Channel.wait()手动分离

loop {
    match channel.wait().await {
        Some(ChannelMsg::Data { data }) => {
            // ← 处理数据消息
            process_data(data);
        }
        Some(ChannelMsg::ExitStatus { exit_status }) => {
            // ← 处理控制消息
            log::info!("Exit status: {}", exit_status);
            break;
        }
        Some(ChannelMsg::Close) => {
            // ← 处理控制消息
            log::info!("Channel closed");
            break;
        }
        _ => {}  // ← 忽略其他消息
    }
}

4. rsync集成可行性分析

4.1 完整握手流程实现可能性 ⚠️

结论: 技术上可行,但实现难度高。

rsync Protocol握手流程OpenSSH标准

Phase 1: Connection Setup1-2 round-trips
┌─────────┐                    ┌─────────┐
│ Client  │                    │ Server  │
└─────────┘                    └─────────┘
    │                              │
    │──── "rsync\n" ──────────────>│  (1) Client announces
    │                              │
    │<─── "@RSYNCD: 31\n" ─────────│  (2) Server version
    │                              │
    │──── "@RSYNCD: 31\n" ─────────>│  (3) Client confirms
    │                              │
    
Phase 2: Authentication1 round-trip
    │                              │
    │──── command line ────────────>│  (4) Client sends command
    │   (e.g., "-e.ssh.lso...")    │
    │                              │
    │<─── "@RSYNCD: OK\n" ─────────│  (5) Server validates
    │                              │
    
Phase 3: File TransferMultiple round-trips
    │                              │
    │  Sender模式:                 │
    │──── File data + checksums ───>│  (6) Sender sends data
    │                              │
    │  Receiver模式:               │
    │<─── File data requests ──────│  (7) Receiver requests
    │──── ACK + more data ─────────>│  (8) Sender responds
    │                              │
    │<─── Exit status ─────────────│  (9) Server exits
    │                              │

russh实现分析

Phase 实现难度 关键技术 russh能力
Phase 1 中等 协议解析 + 字符串匹配 into_stream()
Phase 2 命令解析 + 认证验证 已有bcrypt
Phase 3: Sender 单向数据发送 channel.data()
Phase 3: Receiver ⚠️ 双向交互协议 ⚠️ 需完整实现

技术障碍:

障碍1Protocol未标准化

  • ⚠️ rsync protocol未公开RFC文档
  • ⚠️ 需参考OpenSSH源码实现
  • ⚠️ 版本兼容性问题rsync 31.x vs 30.x

障碍2双向交互复杂

  • ⚠️ Receiver需要发送请求、接收数据、发送ACK
  • ⚠️ 需完整状态机实现
  • ⚠️ Window size管理SSH flow control

障碍3Checksum计算

  • ⚠️ rsync使用rolling checksumadler32 + MD4
  • ⚠️ 需实现rsync算法库
  • ⚠️ 性能优化需求

4.2 Task 4-5实施技术障碍 ⚠️⚠️⚠️

结论: 存在3个HIGH级别障碍

障碍矩阵:

障碍级别 障碍描述 影响范围 解决方案
HIGH channel.read() API缺失 Receiver模式无法实现 使用into_stream()
HIGH rsync protocol未标准化 无法实现完整握手 参考OpenSSH源码
HIGH 双向交互协议复杂性 需完整状态机 需专业rsync实现
MEDIUM Channel所有权消耗 无法同时发送接收 Split channel
MEDIUM Window size管理 SSH flow control 自动管理
LOW rsync算法实现 Rolling checksum 使用rsync crate

详细障碍分析:

障碍1channel.read() API缺失

问题:

// 期望API不存在
let data = channel.read(1024).await?;  // ← ❌ API不存在

// 实际替代方案
let stream = channel.into_stream();     // ← 消耗所有权 ⚠️
let n = stream.read(&mut buf).await?;  // ← AsyncRead

影响:

  • ⚠️ 无法在保留channel的同时读取数据
  • ⚠️ 需要提前准备所有逻辑(消耗所有权)
  • ⚠️ 无法动态切换Sender/Receiver模式

解决方案:

  • 使用into_stream()创建双向流
  • 提前解析rsync命令确定模式
  • 使用channel.split()分离读写(需验证)

障碍2rsync protocol未标准化

问题:

  • ⚠️ rsync protocol无公开RFC文档
  • ⚠️ 仅能参考OpenSSH源码sftp-server.c
  • ⚠️ 版本兼容性问题rsync 31.x vs 30.x

证据:

# OpenSSH源码位置
openssh/sftp-server.c:main()  ← rsync protocol实现
openssh/sftp-common.c         ← 辅助函数

影响:

  • ⚠️ 需逆向分析OpenSSH实现
  • ⚠️ 可能遗漏协议细节
  • ⚠️ 版本兼容性测试成本高

解决方案:

  • 参考OpenSSH源码实现开源
  • 使用rsync命令测试验证逆向工程
  • 添加版本协商机制

障碍3双向交互协议复杂性

问题:

// rsync receiver需要复杂的状态机
loop {
    // 1. 接收客户端请求
    let request = stream.read(&mut buf).await?;
    
    // 2. 解析请求类型
    match parse_rsync_request(&request) {
        RsyncRequest::FileData { checksum } => {
            // 3. 计算本地checksum
            let local_checksum = compute_checksum(&file)?;
            
            // 4. 发送差异块
            stream.write_all(&delta_blocks).await?;
        }
        RsyncRequest::Ack => {
            // 5. 发送更多数据
            stream.write_all(&next_chunk).await?;
        }
    }
}

影响:

  • ⚠️ 需完整状态机实现10+ 状态)
  • ⚠️ 错误处理复杂(超时、断连)
  • ⚠️ 性能优化需求rolling checksum

解决方案:

  • 参考rsync crate如果存在
  • 使用简化版rsync协议无delta传输
  • ⚠️ 需专业rsync知识

4.3 可能的替代方案

方案矩阵:

方案 技术栈 实现难度 功能完整性 推荐度
方案1简化rsync russh + 自定义协议 Sender only
方案2调用rsync命令 russh + rsync CLI 完整
方案3使用SFTP russh + russh-sftp 完整
方案4完整rsync实现 russh + rsync protocol 完整
方案5使用librsync russh + C library 完整

方案1简化rsync实现

实现思路:

// 只实现Sender模式单向发送
pub async fn handle_rsync_sender(channel: Channel<Msg>, file_path: &str) -> Result<()> {
    // Phase 1: Connection Setup
    channel.data(b"rsync\n").await?;
    
    // Phase 2: Authentication
    channel.data(b"@RSYNCD: OK\n").await?;
    
    // Phase 3: File TransferSender only
    let file_data = tokio::fs::read(file_path).await?;
    channel.data_bytes(Bytes::from(file_data)).await?;
    
    // Phase 4: Exit
    channel.exit_status(0).await?;
    channel.close().await?;
    
    Ok(())
}

优点:

  • 实现简单(单向发送)
  • 兼容rsync sender模式
  • 性能高(无协议开销)

缺点:

  • ⚠️ 不支持Receiver模式
  • ⚠️ 不支持增量传输delta
  • ⚠️ 不支持rsync高级特性checksum、压缩

方案2调用rsync命令

实现思路:

// 通过SSH exec调用远程rsync命令
pub async fn handle_rsync_command(channel: Channel<Msg>, command: &str) -> Result<()> {
    // 使用SSH exec运行rsync命令
    channel.exec(true, command).await?;
    
    // 读取rsync输出
    loop {
        match channel.wait().await {
            Some(ChannelMsg::Data { data }) => {
                // 处理rsync输出
                process_rsync_output(data);
            }
            Some(ChannelMsg::ExitStatus { exit_status }) => {
                log::info!("rsync exit: {}", exit_status);
                break;
            }
            None => break,
            _ => {}
        }
    }
    
    Ok(())
}

优点:

  • 完整rsync功能调用标准命令
  • 实现简单仅需SSH exec
  • 性能高rsync原生实现

缺点:

  • ⚠️ 需要远程服务器安装rsync
  • ⚠️ 无法完全控制rsync行为
  • ⚠️ 安全性问题exec命令

方案3使用SFTP替代

实现思路:

// 使用SFTP子系统传输文件
pub async fn handle_file_transfer(channel: Channel<Msg>) -> Result<()> {
    // 转换为stream
    let stream = channel.into_stream();
    
    // 运行SFTP subsystem
    russh_sftp::server::run(stream, sftp_handler).await;
    
    // SFTP提供完整文件传输功能
    // - upload/download
    // - directory listing
    // - permission management
    // - checksum verification
}

优点:

  • 最佳方案
  • russh-sftp已实现2.3.0
  • 标准协议RFC draft
  • 完整功能upload/download/list
  • 安全认证bcrypt
  • 性能优化DashMap并发

缺点:

  • ⚠️ 不支持rsync增量传输delta
  • ⚠️ 不兼容rsync客户端
  • ⚠️ 需要客户端支持SFTP

方案4完整rsync协议实现

实现思路:

// 完整rsync protocol状态机
pub struct RsyncProtocol {
    state: RsyncState,
    stream: ChannelStream<Msg>,
}

impl RsyncProtocol {
    pub async fn handshake(&mut self) -> Result<()> {
        // Phase 1: Connection Setup
        self.stream.write_all(b"rsync\n").await?;
        let version = self.read_line().await?;
        
        // Phase 2: Authentication
        self.stream.write_all(b"@RSYNCD: 31\n").await?;
        let command = self.read_command().await?;
        
        // Phase 3: File Transfer完整实现
        match self.parse_command(&command) {
            Sender { path } => self.sender_mode(path).await?,
            Receiver { path } => self.receiver_mode(path).await?,
        }
    }
    
    async fn sender_mode(&mut self, path: &str) -> Result<()> {
        // ... 复杂实现
    }
    
    async fn receiver_mode(&mut self, path: &str) -> Result<()> {
        // ... 复杂实现(双向交互)
    }
}

优点:

  • 完整rsync功能
  • 兼容rsync客户端
  • 支持增量传输

缺点:

  • ⚠️ 实现难度极高
  • ⚠️ 需完整协议知识
  • ⚠️ 需专业rsync算法
  • ⚠️ 开发周期长2-4周

方案5使用librsyncC library

实现思路:

// 调用librsync C library
extern crate librsync;

pub async fn handle_rsync_with_librsync(stream: ChannelStream<Msg>) -> Result<()> {
    // 使用FFI调用librsync
    let delta = librsync::compute_delta(&source, &target)?;
    
    // 发送delta数据
    stream.write_all(&delta).await?;
}

优点:

  • 使用成熟的rsync算法库
  • 性能优化C实现
  • 支持增量传输

缺点:

  • ⚠️ 需要FFI绑定复杂
  • ⚠️ 需要处理C/Rust内存管理
  • ⚠️ librsync维护状况不明
  • ⚠️ 集成成本高

5. 实施建议

5.1 立即可行的方案

推荐方案3 - 使用SFTP替代

实施步骤:

Step 1验证现有SFTP实现

# 测试SFTP功能
cargo run --bin markbase-core -- sftp --user warren --port 2023

# 测试上传/下载
sftp -P 2023 warren@127.0.0.1
> put test.txt
> get test.txt

Step 2扩展SFTP功能

// 添加checksum verification
impl Handler for SftpHandler {
    async fn read(&mut self, id: u32, handle: String, offset: u64, len: u32) -> Result<Data> {
        let data = self.read_file_data(handle, offset, len)?;
        
        // 计算checksum可选
        let checksum = md5::compute(&data);
        log::info!("Checksum: {:?}", checksum);
        
        Ok(Data { id, data })
    }
}

Step 3提供rsync-like接口

// 通过Web API提供rsync-like功能
#[derive(Serialize)]
pub struct RsyncResponse {
    files_transferred: usize,
    total_size: u64,
    checksum: String,
    duration_ms: u64,
}

// REST API
POST /api/v2/rsync/upload
POST /api/v2/rsync/download
GET  /api/v2/rsync/status

5.2 短期可行方案

推荐方案2 - 调用rsync命令

实施步骤:

Step 1实现SSH exec handler

// server.rs
async fn exec_request(&mut self, channel_id: ChannelId, command: &str) -> Result<()> {
    let channel = self.get_channel(channel_id).await;
    
    // 转换为stream
    let stream = channel.into_stream();
    
    // 启动rsync命令
    let mut child = tokio::process::Command::new("rsync")
        .arg("-av")
        .arg("--progress")
        .arg(source)
        .arg(dest)
        .stdout(Stdio::piped())
        .spawn()?;
    
    // 流式传输rsync输出
    let mut stdout = child.stdout.take()?;
    tokio::io::copy(&mut stdout, &mut stream).await?;
    
    // 发送退出状态
    let status = child.wait().await?;
    stream.write_all(&format!("Exit: {}\n", status).as_bytes()).await?;
    
    Ok(())
}

Step 2配置安全限制

# config/sftp.toml
[exec]
allowed_commands = ["rsync", "ls", "pwd"]
max_execution_time = 300  # seconds
require_approval = true

5.3 长期方案

推荐方案1 + 方案4混合

实施策略:

Phase 11-2周实现简化Sender模式

  • 实现单向文件发送
  • 基本握手流程
  • Exit status处理

Phase 22-3周参考OpenSSH实现Receiver

  • ⚠️ 逆向分析OpenSSH sftp-server.c
  • ⚠️ 实现双向交互协议
  • ⚠️ 状态机实现

Phase 31-2周性能优化

  • ⚠️ Rolling checksum实现
  • ⚠️ Delta传输算法
  • ⚠️ 性能测试

6. 结论

6.1 russh API能力总结

能力项 状态 评级
channel.data()存在性 存在
异步发送支持 支持
channel.read()存在性 不存在
双向流支持 ⚠️ 间接支持into_stream
Message type区分 支持
Multiplexing protocol 不支持

6.2 rsync集成可行性总结

集成项 状态 障碍级别
Sender模式 可行 LOW
Receiver模式 ⚠️ 困难 HIGH
完整握手流程 ⚠️ 困难 HIGH
Delta传输 ⚠️ 极困难 HIGH

6.3 最终建议

推荐方案优先级:

  1. 方案3SFTP替代 (立即实施)

    • 原因:已实现、标准协议、完整功能
    • 时间0天现有代码已实现
  2. 方案2调用rsync命令 (短期实施)

    • 原因:实现简单、完整功能
    • 时间1-2天
  3. 方案1简化rsync (中期实施)

    • 原因:兼容性需求、可控实现
    • 时间1-2周
  4. 方案4完整rsync (长期研究)

    • 原因:技术障碍高、开发周期长
    • 时间2-4周

报告完成日期: 2026-06-09
报告版本: 1.0
下次更新: 待实施反馈后更新