Skip to content

fix(remote-connect): prevent rustls CryptoProvider panic on reconnect#1101

Open
ococl wants to merge 1 commit into
GCWing:mainfrom
ococl:main
Open

fix(remote-connect): prevent rustls CryptoProvider panic on reconnect#1101
ococl wants to merge 1 commit into
GCWing:mainfrom
ococl:main

Conversation

@ococl
Copy link
Copy Markdown
Contributor

@ococl ococl commented Jun 8, 2026

fix(remote-connect): prevent rustls CryptoProvider panic on reconnect

  • Install ring CryptoProvider early at desktop startup to avoid duplicate install_default() races between reqwest and tokio-tungstenite
  • Wrap Windows TLS connector construction in catch_unwind for defense-in-depth
  • Enable explicit rustls features [ring, std, tls12] in Cargo.toml
  • Adapt relay-server routes to axum 0.8 path param syntax ({room_id}, {*rest})
  • Add mobile-web dev scripts to package.json
  • Add .codebuddy to .gitignore

Summary

修复远程控制(remote-connect)在连接/重连时进程崩溃的问题。

rustls 0.23default-features = false 的配置下,进程内多个组件(reqwest、tokio-tungstenite)可能在各自初始化时尝试调用 install_default() 安装 CryptoProvider。第二次调用会触发 panic,在远程控制重连(reconnect)场景中导致 tokio task unwind,最终引发桌面程序崩溃。

本次修复通过在 desktop 启动早期统一安装 CryptoProvider,并在 TLS connector 构建处增加 catch_unwind 兜底,彻底消除该崩溃路径。

Type and Areas

Type:

bug fix

Areas:

Rust core, desktop/Tauri, server/relay

Motivation / Impact

问题:当用户在使用远程控制功能时,如果网络出现波动触发自动重连,桌面端有一定概率直接崩溃退出。

根因rustls 0.23+default-features = false 模式下不提供默认的 CryptoProviderreqwesttokio-tungstenite 都会在首次 TLS 操作时尝试调用 rustls::crypto::ring::default_provider().install_default()。该函数在 provider 已安装时会 panic(而非返回错误),因此在重连路径上极易触发第二次安装,导致整个 tokio task unwind,进而拖垮进程。

解决方案

  1. 提前统一安装:在 bitfun-desktop 启动早期调用 ensure_rustls_crypto_provider(),确保进程生命周期内只安装一次。
  2. 防御性兜底:在 Windows 平台的 dial() 函数中,使用 std::panic::catch_unwind 包裹 build_windows_rustls_connector(),即使出现意料之外的 panic,也能将其转换为 Result::Err,避免扩散到 tokio runtime。
  3. 显式声明依赖:在 workspace Cargo.toml 中为 rustls 显式启用 ringstdtls12 特性,避免隐式依赖缺失。

额外变更

  • relay-server 的路由参数语法从 :room_id 更新为 {room_id}(axum 0.8 兼容性修复)。
  • package.json 新增若干 mobile-web 开发脚本(开发体验改进)。
  • .gitignore 新增 .codebuddy

Verification

  • cargo check --workspace ✅ 通过
  • cargo check -p bitfun-desktop ✅ 通过

Reviewer Notes

未采纳的AI审计建议

在代码审计阶段,AI提出了以下两项改进建议。经评估,本次 PR 暂不采纳,原因如下:

1. 统一非 Windows 平台逻辑

建议:让 ensure_rustls_crypto_provider 在非 Windows 平台也执行 install_default(),确保"启动时统一安装"的意图在所有平台生效。

未采纳原因:当前非 Windows 分支在 dial() 内部已手动调用 install_default(),且 tokio-tungstenite 在非 Windows 平台内置了自动处理逻辑。由于不清楚上游作者(rustls / tokio-tungstenite)在跨平台场景下的完整设计意图,为避免引入不必要的兼容性风险,暂时保持现有实现不变。

2. 增强 catch_unwind 错误信息

建议:当前 map_err(|_| anyhow!(...)) 丢弃了 panic payload。如果 panic 确实发生,payload 对诊断很有帮助。可以改为:

.map_err(|payload| {
    let msg = payload.downcast_ref::<&str>().copied()
        .or_else(|| payload.downcast_ref::<String>().map(|s| s.as_str()))
        .unwrap_or("unknown panic");
    anyhow!("dial {ws_url}: TLS connector construction panicked: {msg}")
})

未采纳原因catch_unwind 在此处主要作为 defense-in-depth(纵深防御)手段。若桌面启动时的 ensure_rustls_crypto_provider() 已成功执行,则 build_windows_rustls_connector 内部理论上不应再因 install_default() 而 panic。保留简洁的错误转换即可满足当前需求,暂不需要增加额外的 downcast 逻辑。

其他说明

  • BitFun-Installer/src-tauri/gen/schemas/* 为 Tauri 构建自动生成文件,随 desktop 侧的改动同步更新。

Checklist

  • This PR is focused and does not include secrets, temporary prompts, generated scratch files, or unrelated artifacts.
  • Relevant verification is recorded above, or skipped checks are explained.
  • User-facing strings, docs, and locales are updated where applicable.

    本次为底层崩溃修复,无用户可见文案变更,未更新 locale。

- Install ring CryptoProvider early at desktop startup to avoid duplicate install_default() races between reqwest and tokio-tungstenite

- Wrap Windows TLS connector construction in catch_unwind for defense-in-depth

- Enable explicit rustls features [ring, std, tls12] in Cargo.toml

- Adapt relay-server routes to axum 0.8 path param syntax ({room_id}, {*rest})

- Add mobile-web dev scripts to package.json

- Add .codebuddy to .gitignore
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant