Files
One-KVM/docs/modules/msd.md
mofeng-git a8a3b6c66b feat: 添加 RustDesk 协议支持和项目文档
- 新增 RustDesk 模块,支持与 RustDesk 客户端连接
  - 实现会合服务器协议和 P2P 连接
  - 支持 NaCl 加密和密钥交换
  - 添加视频帧和 HID 事件适配器
- 添加 Protobuf 协议定义 (message.proto, rendezvous.proto)
- 新增完整项目文档
  - 各功能模块文档 (video, hid, msd, otg, webrtc 等)
  - hwcodec 和 RustDesk 协议技术报告
  - 系统架构和技术栈文档
- 更新 Web 前端 RustDesk 配置界面和 API
2025-12-31 18:59:52 +08:00

16 KiB

MSD 模块文档

1. 模块概述

MSD (Mass Storage Device) 模块提供虚拟存储设备功能,允许将 ISO/IMG 镜像作为 USB 存储设备挂载到目标计算机。

1.1 主要功能

  • ISO/IMG 镜像挂载
  • 镜像下载管理
  • Ventoy 多 ISO 启动盘
  • 热插拔支持
  • 下载进度追踪

1.2 文件结构

src/msd/
├── mod.rs              # 模块导出
├── controller.rs       # MsdController (20KB)
├── image.rs            # 镜像管理 (21KB)
├── ventoy_drive.rs     # Ventoy 驱动 (24KB)
├── monitor.rs          # 健康监视 (9KB)
└── types.rs            # 类型定义 (6KB)

2. 架构设计

2.1 整体架构

┌─────────────────────────────────────────────────────────────────────────────┐
│                          MSD Architecture                                    │
└─────────────────────────────────────────────────────────────────────────────┘

                    Web API
                       │
                       ▼
              ┌─────────────────┐
              │  MsdController  │
              │ (controller.rs) │
              └────────┬────────┘
                       │
         ┌─────────────┼─────────────┐
         │             │             │
         ▼             ▼             ▼
┌─────────────┐ ┌───────────┐ ┌───────────┐
│   Image     │ │  Ventoy   │ │    OTG    │
│  Manager    │ │   Drive   │ │  Service  │
│ (image.rs)  │ │(ventoy.rs)│ │           │
└──────┬──────┘ └─────┬─────┘ └─────┬─────┘
       │              │             │
       ▼              ▼             ▼
┌─────────────┐ ┌───────────┐ ┌───────────┐
│  /data/     │ │  exFAT    │ │  MSD      │
│  images/    │ │  Drive    │ │ Function  │
└─────────────┘ └───────────┘ └───────────┘
                                    │
                                    ▼
                            ┌───────────────┐
                            │  Target PC    │
                            │  (USB Drive)  │
                            └───────────────┘

2.2 MSD 模式

┌─────────────────────────────────────────────────────────────────────────────┐
│                            MSD Modes                                         │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│  Image Mode                                                                  │
│  ┌───────────┐                                                              │
│  │ ISO/IMG   │ ──► MSD LUN ──► Target PC sees single drive                 │
│  │ File      │                                                              │
│  └───────────┘                                                              │
│  特点:                                                                       │
│  - 单个镜像文件                                                              │
│  - 直接挂载                                                                  │
│  - 适合系统安装                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│  Ventoy Mode                                                                 │
│  ┌───────────┐                                                              │
│  │  ISO 1    │                                                              │
│  ├───────────┤      ┌───────────┐                                          │
│  │  ISO 2    │ ──►  │  Ventoy   │ ──► Target PC sees bootable drive       │
│  ├───────────┤      │  Drive    │     with ISO selection menu              │
│  │  ISO 3    │      └───────────┘                                          │
│  └───────────┘                                                              │
│  特点:                                                                       │
│  - 多个 ISO 文件                                                             │
│  - exFAT 文件系统                                                            │
│  - 启动菜单选择                                                              │
└─────────────────────────────────────────────────────────────────────────────┘

3. 核心组件

3.1 MsdController (controller.rs)

MSD 控制器主类。

pub struct MsdController {
    /// 当前状态
    state: Arc<RwLock<MsdState>>,

    /// 镜像管理器
    image_manager: Arc<ImageManager>,

    /// Ventoy 驱动器
    ventoy_drive: Arc<RwLock<Option<VentoyDrive>>>,

    /// OTG 服务
    otg_service: Arc<OtgService>,

    /// MSD 函数句柄
    msd_function: Arc<RwLock<Option<MsdFunction>>>,

    /// 事件总线
    events: Arc<EventBus>,

    /// 数据目录
    data_dir: PathBuf,
}

impl MsdController {
    /// 创建控制器
    pub async fn new(
        otg_service: Arc<OtgService>,
        data_dir: PathBuf,
        events: Arc<EventBus>,
    ) -> Result<Arc<Self>>;

    /// 获取状态
    pub fn state(&self) -> MsdState;

    /// 连接 MSD
    pub async fn connect(&self) -> Result<()>;

    /// 断开 MSD
    pub async fn disconnect(&self) -> Result<()>;

    /// 切换到镜像模式
    pub async fn set_image(&self, image_id: &str) -> Result<()>;

    /// 切换到 Ventoy 模式
    pub async fn set_ventoy(&self) -> Result<()>;

    /// 清除当前挂载
    pub async fn clear(&self) -> Result<()>;

    /// 列出镜像
    pub fn list_images(&self) -> Vec<ImageInfo>;

    /// 上传镜像
    pub async fn upload_image(&self, name: &str, data: Bytes) -> Result<ImageInfo>;

    /// 从 URL 下载镜像
    pub async fn download_image(&self, url: &str) -> Result<String>;

    /// 删除镜像
    pub async fn delete_image(&self, image_id: &str) -> Result<()>;

    /// 获取下载进度
    pub fn get_download_progress(&self, download_id: &str) -> Option<DownloadProgress>;
}

pub struct MsdState {
    /// 是否可用
    pub available: bool,

    /// 当前模式
    pub mode: MsdMode,

    /// 是否已连接
    pub connected: bool,

    /// 当前镜像信息
    pub current_image: Option<ImageInfo>,

    /// 驱动器信息
    pub drive_info: Option<DriveInfo>,

    /// 错误信息
    pub error: Option<String>,
}

pub enum MsdMode {
    /// 未激活
    None,

    /// 单镜像模式
    Image,

    /// Ventoy 模式
    Drive,
}

3.2 ImageManager (image.rs)

镜像文件管理器。

pub struct ImageManager {
    /// 镜像目录
    images_dir: PathBuf,

    /// 镜像列表缓存
    images: RwLock<HashMap<String, ImageInfo>>,

    /// 下载任务
    downloads: RwLock<HashMap<String, DownloadTask>>,

    /// HTTP 客户端
    http_client: reqwest::Client,
}

impl ImageManager {
    /// 创建管理器
    pub fn new(images_dir: PathBuf) -> Result<Self>;

    /// 扫描镜像目录
    pub fn scan_images(&self) -> Result<Vec<ImageInfo>>;

    /// 获取镜像信息
    pub fn get_image(&self, id: &str) -> Option<ImageInfo>;

    /// 添加镜像
    pub async fn add_image(&self, name: &str, data: Bytes) -> Result<ImageInfo>;

    /// 删除镜像
    pub fn delete_image(&self, id: &str) -> Result<()>;

    /// 开始下载
    pub async fn start_download(&self, url: &str) -> Result<String>;

    /// 取消下载
    pub fn cancel_download(&self, download_id: &str) -> Result<()>;

    /// 获取下载进度
    pub fn get_download_progress(&self, download_id: &str) -> Option<DownloadProgress>;

    /// 验证镜像文件
    fn validate_image(path: &Path) -> Result<ImageFormat>;
}

pub struct ImageInfo {
    /// 唯一 ID
    pub id: String,

    /// 文件名
    pub name: String,

    /// 文件大小
    pub size: u64,

    /// 格式
    pub format: ImageFormat,

    /// 创建时间
    pub created_at: DateTime<Utc>,

    /// 下载状态
    pub download_status: Option<DownloadStatus>,
}

pub enum ImageFormat {
    /// ISO 光盘镜像
    Iso,

    /// 原始磁盘镜像
    Img,

    /// 未知格式
    Unknown,
}

pub struct DownloadProgress {
    /// 已下载字节
    pub downloaded: u64,

    /// 总字节数
    pub total: u64,

    /// 下载速度 (bytes/sec)
    pub speed: u64,

    /// 预计剩余时间
    pub eta_secs: u64,

    /// 状态
    pub status: DownloadStatus,
}

pub enum DownloadStatus {
    Pending,
    Downloading,
    Completed,
    Failed(String),
    Cancelled,
}

3.3 VentoyDrive (ventoy_drive.rs)

Ventoy 可启动驱动器管理。

pub struct VentoyDrive {
    /// 驱动器路径
    drive_path: PathBuf,

    /// 镜像路径
    images: Vec<PathBuf>,

    /// 容量
    capacity: u64,

    /// 已用空间
    used: u64,
}

impl VentoyDrive {
    /// 创建 Ventoy 驱动器
    pub fn create(drive_path: PathBuf, capacity: u64) -> Result<Self>;

    /// 添加 ISO
    pub fn add_iso(&mut self, iso_path: &Path) -> Result<()>;

    /// 移除 ISO
    pub fn remove_iso(&mut self, name: &str) -> Result<()>;

    /// 列出 ISO
    pub fn list_isos(&self) -> Vec<String>;

    /// 获取驱动器信息
    pub fn info(&self) -> DriveInfo;

    /// 获取驱动器路径
    pub fn path(&self) -> &Path;
}

pub struct DriveInfo {
    /// 容量
    pub capacity: u64,

    /// 已用空间
    pub used: u64,

    /// 可用空间
    pub available: u64,

    /// ISO 列表
    pub isos: Vec<String>,
}

4. 类型定义

4.1 MSD 配置

#[derive(Serialize, Deserialize)]
#[typeshare]
pub struct MsdConfig {
    /// 是否启用 MSD
    pub enabled: bool,

    /// 镜像目录
    pub images_dir: Option<String>,

    /// 默认模式
    pub default_mode: MsdMode,

    /// Ventoy 容量 (MB)
    pub ventoy_capacity_mb: u32,
}

impl Default for MsdConfig {
    fn default() -> Self {
        Self {
            enabled: true,
            images_dir: None,
            default_mode: MsdMode::None,
            ventoy_capacity_mb: 4096,  // 4GB
        }
    }
}

5. API 端点

端点 方法 描述
/api/msd/status GET 获取 MSD 状态
/api/msd/connect POST 连接 MSD
/api/msd/disconnect POST 断开 MSD
/api/msd/images GET 列出镜像
/api/msd/images POST 上传镜像
/api/msd/images/:id DELETE 删除镜像
/api/msd/images/download POST 从 URL 下载
/api/msd/images/download/:id GET 获取下载进度
/api/msd/images/download/:id DELETE 取消下载
/api/msd/set-image POST 设置当前镜像
/api/msd/set-ventoy POST 设置 Ventoy 模式
/api/msd/clear POST 清除挂载

响应格式

// GET /api/msd/status
{
    "available": true,
    "mode": "image",
    "connected": true,
    "current_image": {
        "id": "abc123",
        "name": "ubuntu-22.04.iso",
        "size": 4700000000,
        "format": "iso"
    },
    "drive_info": null,
    "error": null
}

// GET /api/msd/images
{
    "images": [
        {
            "id": "abc123",
            "name": "ubuntu-22.04.iso",
            "size": 4700000000,
            "format": "iso",
            "created_at": "2024-01-15T10:30:00Z"
        }
    ]
}

// POST /api/msd/images/download
// Request: { "url": "https://example.com/image.iso" }
// Response: { "download_id": "xyz789" }

// GET /api/msd/images/download/xyz789
{
    "downloaded": 1234567890,
    "total": 4700000000,
    "speed": 12345678,
    "eta_secs": 280,
    "status": "downloading"
}

6. 事件

pub enum SystemEvent {
    MsdStateChanged {
        mode: MsdMode,
        connected: bool,
        image: Option<String>,
        error: Option<String>,
    },

    MsdDownloadProgress {
        download_id: String,
        progress: DownloadProgress,
    },

    MsdDownloadComplete {
        download_id: String,
        image_id: String,
        success: bool,
        error: Option<String>,
    },
}

7. 错误处理

#[derive(Debug, thiserror::Error)]
pub enum MsdError {
    #[error("MSD not available")]
    NotAvailable,

    #[error("Already connected")]
    AlreadyConnected,

    #[error("Not connected")]
    NotConnected,

    #[error("Image not found: {0}")]
    ImageNotFound(String),

    #[error("Invalid image format: {0}")]
    InvalidFormat(String),

    #[error("Download failed: {0}")]
    DownloadFailed(String),

    #[error("Storage full")]
    StorageFull,

    #[error("OTG error: {0}")]
    OtgError(String),

    #[error("IO error: {0}")]
    IoError(#[from] std::io::Error),
}

8. 使用示例

8.1 挂载 ISO 镜像

let msd = MsdController::new(otg_service, data_dir, events).await?;

// 列出镜像
let images = msd.list_images();
println!("Available images: {:?}", images);

// 设置镜像
msd.set_image("abc123").await?;

// 连接到目标 PC
msd.connect().await?;

// 目标 PC 现在可以看到 USB 驱动器...

// 断开连接
msd.disconnect().await?;

8.2 从 URL 下载

// 开始下载
let download_id = msd.download_image("https://example.com/ubuntu.iso").await?;

// 监控进度
loop {
    if let Some(progress) = msd.get_download_progress(&download_id) {
        println!("Progress: {}%", progress.downloaded * 100 / progress.total);

        if matches!(progress.status, DownloadStatus::Completed) {
            break;
        }
    }
    tokio::time::sleep(Duration::from_secs(1)).await;
}

8.3 使用 Ventoy 模式

// 切换到 Ventoy 模式
msd.set_ventoy().await?;

// 获取驱动器信息
let state = msd.state();
if let Some(drive_info) = state.drive_info {
    println!("Capacity: {} MB", drive_info.capacity / 1024 / 1024);
    println!("ISOs: {:?}", drive_info.isos);
}

// 连接
msd.connect().await?;

9. 常见问题

Q: 镜像无法挂载?

  1. 检查镜像文件完整性
  2. 确认文件格式正确
  3. 检查存储空间

Q: 目标 PC 不识别?

  1. 检查 USB 连接
  2. 尝试重新连接
  3. 查看目标 PC 的设备管理器

Q: 下载速度慢?

  1. 检查网络连接
  2. 使用更近的镜像源
  3. 检查磁盘 I/O

Q: Ventoy 启动失败?

  1. 检查目标 PC BIOS 设置
  2. 尝试不同的启动模式
  3. 确认 ISO 文件支持 Ventoy