开发说明
这份文档说明如何在本仓库里构建、测试并在本地把 exchange 跑起来。部署步骤、协议字段表和各平台安装细节仍以专题文档为准,文末有链接。
工具链
工作区使用 Rust 2021,要求 Rust 1.88 或更新版本。版本写在仓库根 Cargo.toml 的 rust-version 字段里。
工作区与二进制
Rust 工作区包含九个成员:八个位于 crates/,扩展 SDK 位于 sdk/extend/rust。协议类型只定义在 crates/proto,exchange、agent、cli 都依赖这一个 crate,不要在某一端再抄一套消息结构。
| crate | 路径 | 产物 |
|---|---|---|
proto |
crates/proto |
库。控制消息、二进制帧和共享数据结构只在这里 |
exchange |
crates/exchange |
二进制 exchange(包名与二进制名相同) |
agent |
crates/agent |
二进制 remote-agent |
cli |
crates/cli |
二进制 remote-cli |
updater |
crates/updater |
库,供 remote-agent 与 remote-cli 做自更新 |
telemetry |
crates/telemetry |
库,三端共用的异常与日志上报 |
tls-client |
crates/tls-client |
库,共用的 rustls 客户端 TLS 策略与可选代理连接 |
worker-proto |
crates/worker-proto |
库,Workers Exchange 的协议验证与凭据哈希 |
remote-extend-sdk |
sdk/extend/rust |
库,扩展 provider 的帧格式与契约 |
exchange 的源文件入口是 crates/exchange/src/main.rs,没有单独的 [[bin]] 表,所以 cargo build -p exchange 得到的就是 exchange。agent 与 cli 在各自的 Cargo.toml 里把二进制名写成 remote-agent 和 remote-cli。
连接表按职责拆开:
crates/exchange/src/hub.rs管在线设备、重连顶替和 epochcrates/exchange/src/hub/session_table.rs管运维侧编号与设备侧编号的翻译crates/exchange/src/hub/outbound.rs管单条连接的有界发送队列
构建
在仓库根目录执行。
发布档(opt-level = 2、thin LTO,保留 unwind)会编出服务端、命令行和 agent:
cargo build --release
二进制在:
target/release/exchangetarget/release/remote-clitarget/release/remote-agent
release 保留 unwind 是因为 exchange 是常驻多连接进程。单个连接任务 panic 时,unwind 让 tokio 能停掉这一条任务,而不是把同进程里其它设备的会话一起带走。
设备端还要一个体积优先的 profile(opt-level = "z"、LTO、panic = "abort"、strip、codegen-units = 1):
cargo build -p agent --no-default-features --profile release-small
产物是 target/release-small/remote-agent。agent 崩溃后由 procd、systemd 或计划任务拉起,所以这里可以用 panic = "abort" 换体积。
数据库不参与编译。crates/exchange/src/db.rs 使用 sqlx 的运行时查询,不用 query! 宏,因此没有数据库也能 cargo build。
测试
cargo test --workspace
Windows 上不会运行依赖 Unix /bin/sh(或 OpenWrt 上的 /bin/ash)和 PTY 的测试。crates/agent/src/pty.rs 的测试模块由 #[cfg(all(test, unix))] 包住,非 Unix 平台不编译这部分。PTY 实现会依次尝试 /bin/ash 和 /bin/sh。exec.rs 里的进程组与 Unix 信号路径同样只在 Unix 编译;Windows 上的命令测试走 PowerShell,不调用 /bin/sh。改了 exec.rs 或 pty.rs 的 Unix 路径时,需要在 Linux 上再跑一遍 cargo test --workspace,只看 Windows 的结果不够。
单 crate 可以缩小范围,例如 cargo test -p proto 或 cargo test -p exchange -- hub::。
本地启动 exchange
先准备 PostgreSQL,再把连接串放进 DATABASE_URL。这个变量对应 exchange 的 --database-url(见 crates/exchange/src/config.rs)。进程启动时 db::connect 会执行编译期嵌入的迁移:
sqlx::migrate!("../../migrations")
迁移文件在仓库根的 migrations/,启动时自动跑完,不需要 sqlx-cli。
审计操作还需要审计加密密钥,下面的示例生成本地测试密钥。请安全保存,并在后续启动时复用原密钥;不要每次重新生成,否则已有审计详情将无法解密。
export DATABASE_URL='postgres://luci:luci@127.0.0.1:5432/luci'
export AUDIT_ENCRYPTION_KEY="$(python -c 'import base64, secrets; print(base64.b64encode(secrets.token_bytes(32)).decode())')"
cargo run -p exchange -- --listen 127.0.0.1:8080
PowerShell 下先设置环境变量再启动:
$env:DATABASE_URL = "postgres://luci:luci@127.0.0.1:5432/luci"
$env:AUDIT_ENCRYPTION_KEY = python -c "import base64, secrets; print(base64.b64encode(secrets.token_bytes(32)).decode())"
cargo run -p exchange -- --listen 127.0.0.1:8080
已经编过发布二进制时,把上面的 cargo run -p exchange -- 换成 ./target/release/exchange 即可。监听地址的默认值是 0.0.0.0:8080,本地调试建议显式绑到 127.0.0.1。
库里还没有任何启用中的运维账号时,启动过程会自举一个管理员,并把令牌打在这一次的启动日志里。明文只出现这一次。完整的部署、反向代理和账号说明在仓库的 docs/deployment.md。该页包含服务器地址,不在本站公开。
提交前检查
在仓库根目录运行以下检查。修改 Rust 时,先用单 crate 测试缩小反馈范围,再完成工作区检查;格式检查发现与本次修改无关的旧问题时,只格式化改动文件,避免顺带重排其它代码。Android、浏览器扩展和移动控制端还需各自的构建与测试,Rust 测试不能代替它们。
cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace
维护文档
行为变化时先核对实现,再更新 docs/ 中的仓库指南。网站专题同时维护 website/docs/<topic>.md 参考源和 website/docs/content/<locale>/<topic>.md 九种语言正文;命令、字段、代码示例和标题层级必须一致。生成页面和搜索索引由脚本产出,不能只手改 HTML。以下命令从仓库根目录执行,需要 Python 3.11+、markdown-it-py 和 Node.js:
python -m pip install markdown-it-py
python scripts/build-docs.py
python scripts/build-docs.py --check
python scripts/test-docs.py
python scripts/test-docs-markdown.py
node scripts/test-docs-locale.js
python scripts/test-build-docs.py
python scripts/test-site-seo.py
生成检查还会逐字节比较所有生成文件,缺失或过期时失败,且不写文件;CI 在重新生成前执行此检查。
检查会验证翻译完整性、代码示例、标题结构、页面链接、锚点和语言路由。将生成页面与源文件一起提交。构建文档只更新本地文件;网站部署和下载包发布是独立操作。