feat(file-transfer): add host file offers - #737
Conversation
Walkthrough新增主机到客户端文件传输能力:包含内存 offer 存储、HTTP 响应与路由、配置开关、confighttp/nvhttp 入口接入、构建集成和单元测试;同时更新了控制面板子模块指针。 Changes文件传输功能实现
控制面板子模块升级
Sequence Diagram(s)sequenceDiagram
participant LocalClient
participant confighttp
participant file_transfer_store
participant nvhttp
participant PairedClient
LocalClient->>confighttp: POST /api/v1/file-transfer/offers
confighttp->>confighttp: authenticate() + net::PC 校验
confighttp->>file_transfer_store: create_single_file_offer(path)
file_transfer_store-->>confighttp: create_result_t
confighttp-->>LocalClient: JSON offer response
PairedClient->>nvhttp: GET /api/v1/file-transfer/{64-hex-id}
nvhttp->>file_transfer_store: get(id)
file_transfer_store-->>nvhttp: get_result_t
nvhttp-->>PairedClient: download response / file stream
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/file_transfer_http.cpp`:
- Around line 98-100: The X-Sunshine-File-Name header on line 98 directly uses
the raw name variable without sanitization, creating a potential HTTP response
splitting vulnerability if the filename contains control characters like CR or
LF. The Content-Disposition header below it correctly applies
ascii_fallback_filename() to sanitize the filename, but X-Sunshine-File-Name
does not. Fix this by applying the same ascii_fallback_filename(name) function
to the name parameter when emplacing the X-Sunshine-File-Name header to ensure
consistent sanitization across both headers and prevent response header
injection attacks.
In `@src/file_transfer_http.h`:
- Around line 59-63: When the file open fails in the (!in) condition block, the
error response is reusing out.headers which contains headers intended for
successful downloads (such as Content-Length and Content-Disposition). These
headers do not match the JSON error body being returned, causing client parsing
issues. Replace the out.headers parameter in the resp->write call with an
appropriate empty or minimal headers object that matches the JSON error response
content, ensuring the response contract is consistent between headers and body.
In `@src/file_transfer_store.cpp`:
- Around line 33-37: The make_id() function throws a std::runtime_error when
RAND_bytes fails at lines 35-36, but the call to make_id() around lines 113-116
in create_single_file_offer lacks exception handling. This breaks the consistent
error handling pattern used in the rest of create_single_file_offer where errors
are converted to structured returns with error_code checks (see lines 85-98).
Wrap the make_id() call in a try-catch block and convert the caught exception to
a controlled error return { false, "rng_failed", {} } to maintain consistent
error handling and prevent the exception from propagating to the HTTP handling
layer.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 6f1dfe1f-e33d-41d1-b526-7655b7eb5f5c
📒 Files selected for processing (13)
cmake/compile_definitions/common.cmakesrc/config.cppsrc/config.hsrc/confighttp.cppsrc/file_transfer_http.cppsrc/file_transfer_http.hsrc/file_transfer_store.cppsrc/file_transfer_store.hsrc/nvhttp.cppsrc/nvhttp/file_transfer_api.cppsrc/nvhttp/file_transfer_api.hsrc_assets/common/sunshine-control-paneltests/unit/test_file_transfer.cpp
📜 Review details
🧰 Additional context used
📓 Path-based instructions (3)
src/**/*.{cpp,c,h}
⚙️ CodeRabbit configuration file
src/**/*.{cpp,c,h}: Sunshine 核心 C++ 源码,自托管游戏串流服务器。审查要点:内存安全、 线程安全、RAII 资源管理、安全漏洞。注意预处理宏控制的平台相关代码。
Files:
src/nvhttp/file_transfer_api.cppsrc/nvhttp/file_transfer_api.hsrc/nvhttp.cppsrc/config.hsrc/config.cppsrc/file_transfer_store.hsrc/confighttp.cppsrc/file_transfer_store.cppsrc/file_transfer_http.cppsrc/file_transfer_http.h
cmake/**
⚙️ CodeRabbit configuration file
cmake/**: CMake 构建系统文件。审查跨平台兼容性、现代 CMake 实践。
Files:
cmake/compile_definitions/common.cmake
tests/**
⚙️ CodeRabbit configuration file
tests/**: 测试文件。验证测试覆盖率、边界情况和断言正确性。
Files:
tests/unit/test_file_transfer.cpp
🔇 Additional comments (10)
src_assets/common/sunshine-control-panel (1)
1-1: 子模块更新符合预期,构建系统兼容性已验证。此更改将
sunshine-control-panel子模块从de175aa更新至c371acf,启用了 Windows 文件传输功能。验证确认新提交包含所有必需的构建文件:package.json中的build:renderer脚本、src-tauri/Cargo.toml及完整的目录结构均完整无缺。src/file_transfer_store.h (1)
16-56: LGTM!cmake/compile_definitions/common.cmake (1)
139-144: LGTM!tests/unit/test_file_transfer.cpp (1)
33-102: LGTM!src/config.h (1)
222-222: 该变更片段已核对,当前无需补充评论。src/config.cpp (1)
558-558: 该变更片段已核对,当前无需补充评论。Also applies to: 1457-1457
src/confighttp.cpp (1)
44-44: 该变更片段已核对,当前无需补充评论。Also applies to: 3015-3039
src/nvhttp/file_transfer_api.h (1)
1-15: 该变更片段已核对,当前无需补充评论。src/nvhttp/file_transfer_api.cpp (1)
1-13: 该变更片段已核对,当前无需补充评论。src/nvhttp.cpp (1)
47-47: 该变更片段已核对,当前无需补充评论。Also applies to: 954-957
…-context-menu # Conflicts: # src_assets/common/sunshine-control-panel
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src_assets/common/sunshine-control-panel`:
- Line 1: The submodule pointer is referencing a commit that is not on the
branch configured in .gitmodules, causing the tauri submodule to diverge from
the intended history. Update the submodule reference in the
sunshine-control-panel submodule so it points to a commit that belongs to the
configured tauri branch, or adjust the .gitmodules branch setting if the new tip
is intentional. Use the submodule entry and .gitmodules branch configuration to
keep the checkout consistent for clone and CI flows.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: f0f3885f-7899-4a2e-8481-2869c8a3bd0d
📒 Files selected for processing (4)
src/config.cppsrc/config.hsrc/confighttp.cppsrc_assets/common/sunshine-control-panel
🚧 Files skipped from review as they are similar to previous changes (3)
- src/config.h
- src/confighttp.cpp
- src/config.cpp
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
- GitHub Check: Windows
| @@ -1 +1 @@ | |||
| Subproject commit a0432e073266acb29b50cba2dc3dc76cf64415dc | |||
| Subproject commit 8b8dada639d76c6fa28b578b4a1539d1e9d98641 | |||
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# 验证子模块提交在上游仓库可达
COMMIT="8b8dada639d76c6fa28b578b4a1539d1e9d98641"
REPO="https://github.com/qiin2333/sunshine-control-panel.git"
# 列出所有远端引用,检查该提交是否被任一引用包含
git ls-remote "$REPO" | grep -i "$COMMIT" && echo "提交是某引用的 tip" || echo "非引用 tip(可能仍在历史中,需进一步检查)"
# 通过 GitHub API 确认提交对象存在
gh api "repos/qiin2333/sunshine-control-panel/commits/${COMMIT}" \
--jq '{sha: .sha, date: .commit.committer.date, message: .commit.message}' \
&& echo "提交存在于上游仓库" || echo "提交在上游仓库不存在或不可访问"
# 确认该提交是否包含在 tauri 分支历史中
gh api "repos/qiin2333/sunshine-control-panel/compare/tauri...${COMMIT}" \
--jq '{status: .status, ahead_by: .ahead_by, behind_by: .behind_by}' \
&& echo "已对比 tauri 分支" || echo "无法对比 tauri 分支"Repository: AlkaidLab/foundation-sunshine
Length of output: 578
修正子模块指针:该提交不属于 .gitmodules 指定的 tauri 分支。
验证确认提交 8b8dada639d76c6fa28b578b4a1539d1e9d98641 存在,但它是 codex/file-transfer-context-menu 分支的 tip,且与 .gitmodules 配置的 tauri 分支历史分叉(diverged)。
该提交包含 tauri 的合并记录但未位于 tauri 分支上。这种配置会导致 git clone --recurse-submodules 或 CI 构建时产生状态不一致(无法保证检出 tauri 分支时自动包含此提交)。若目标是特定功能分支,建议同时更新 .gitmodules 中的 branch 配置,或确认构建流程不依赖显式 checkout tauri 的行为。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src_assets/common/sunshine-control-panel` at line 1, The submodule pointer is
referencing a commit that is not on the branch configured in .gitmodules,
causing the tauri submodule to diverge from the intended history. Update the
submodule reference in the sunshine-control-panel submodule so it points to a
commit that belongs to the configured tauri branch, or adjust the .gitmodules
branch setting if the new tip is intentional. Use the submodule entry and
.gitmodules branch configuration to keep the checkout consistent for clone and
CI flows.
改了啥呀
/api/v1/file-transfer/offers创建 offer,/api/v1/file-transfer/<id>下载文件。file_transfer配置开关、CMake 源文件列表和单测覆盖。sunshine-control-panel子模块到 feat(file-transfer): add send-to-client shell entry qiin2333/sunshine-control-panel#44 的分支提交,让 Explorer 右键菜单能发送 offer。master,解决子模块 gitlink 冲突。为啥要改
验证
cargo checkinsrc_assets/common/sunshine-control-panel/src-taurigit diff --checkin Sunshine and control-panelgit diff --check HEAD~1 HEADin sync temp clones for Sunshine, control-panel, and moonlight-qtcmake --build build --target sunshine当前本机失败在 MSYS2cc.exe/c++.exe,第三方 C 文件和既有 C++ 文件均无诊断返回 1;最小int main(){return 0;}也同样失败,判断为本机工具链状态问题,不是新增文件专属错误。