From da024fb3fbdb08ac22cfdbb20d4d1dd6c40e8614 Mon Sep 17 00:00:00 2001 From: yuanyuanxiang <962914132@qq.com> Date: Sun, 31 May 2026 17:34:30 +0200 Subject: [PATCH] Release v1.3.5 --- ReadMe.md | 29 +++++++++++++++ ReadMe_EN.md | 29 +++++++++++++++ ReadMe_TW.md | 29 +++++++++++++++ client/Script.rc | 4 +-- client/TestRun.rc | Bin 4578 -> 4578 bytes server/2015Remote/2015Remote.rc | Bin 156620 -> 156620 bytes server/2015Remote/UIBranding.h | 2 +- server/go/cmd/winres/icon.png | Bin 0 -> 7765 bytes server/go/cmd/winres/winres.json | 60 +++++++++++++++++++++++++++++++ 9 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 server/go/cmd/winres/icon.png create mode 100644 server/go/cmd/winres/winres.json diff --git a/ReadMe.md b/ReadMe.md index 067e0f0..835c33d 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -357,6 +357,35 @@ nohup ./server_linux_amd64 --port 6543 --http-port 9001 > yama.log 2>&1 & ## 更新日志 +### v1.3.5 (2026.5.31) + +**硬件编码扩展(H.264 / AV1)& 多客户许可证生产化 & FRP 子级自动化** + +**新功能:** +- **客户端硬件编码**:新增 FFmpeg 路径的 `CFFmpegH264Encoder` / `CFFmpegAV1Encoder`,可调用 NVENC / Quick Sync / AMF 等 GPU 编码器;`EncoderFactory` 运行时自动优选 +- **静屏跳编码**:捕获层比对前后帧,完全相同时跳过编码与传输——硬件编码器在静屏不再被强行喂入相同帧 +- **菜单驱动的压缩 / 解压**:自定义文件 + 文件夹选择器(`ZstaPickerDlg`),可从远程主机直接选混合目录树打包或解压到目标路径 +- **下级主控自动起 frp client**:上级签发 V2 授权时一并下发 frp 配置,子级主控启动即接通中继链路,无需人工配 `frpc.toml` +- **合规可裁剪构建**:`DISABLE_X264` / `DISABLE_FFMPEG` 编译开关,可在不动源码的前提下产出完全不带 x264 / FFmpeg 的二进制,配套 `LICENSE-THIRD-PARTY.txt` + +**改进:** +- **多客户许可证服务端硬化**:`licenses.ini` hot-path 互斥锁 + 30s 节流,写频从 0.6 → 0.07 次/秒(外推 100 在线:~160 → ~3.3 次/秒);闭环了"预设续期配额消失"的 read-modify-write 竞态 +- **`licenses.ini` IP 列表 4KB 截断修复**:分段写入避免溢出尾部被永久丢弃 +- **导入 SN 按 `BindType` 严格校验**:避免离线版 / 在线版 / 试用版 SN 串库 +- **客户端 SCLoader 大瘦身**:移除一万行硬编码 stub(`SCLoader.cpp`),改用主控运行时下发 DLL 注入 +- **客户端 logger 优雅退出**:进程退出刷出队列里的日志并记录退出信号 +- **IOCPClient 早期数据包防护**:`setManagerCallBack` 之前抵达的包不再触发空回调崩溃 +- **多显示器光标位置修正 & MJPEG 录制翻转修复**:trace cursor 跨屏坐标系修正;MJPEG 上下颠倒回放修正 + 编码失败 0 字节 AVI 残留清理 +- **FRP `privilegeKey` 改用 UTC 时间戳**:跨时区主控 / 中继 / 客户端不再因本地时区让 frp auth 失效 +- **Linux 客户端 `install.sh` / `uninstall.sh`**:补齐一键部署 / 卸载脚本 +- **Go 服务端构建管线**:`build.ps1` / `build.cmd` 把 Go 主控纳入主构建 +- **Release / Download 链接全量迁移到 Gitea**:v1.3.4+ 不再发到 GitHub + +**Bug 修复:** +- Web 文件管理触屏双击不稳:触摸阈值放宽防误判拖拽 + 两次 `click` 模拟物理双击;修复跨平台文件夹重命名 / 点击无响应 +- 向 sub-master 发送 AUTH 时密码生成路径错误,下级始终认证失败 +- 试用 SN 误进入 V2 / V1 授权下发分支 + ### v1.3.4 (2026.5.20) **Go 主控 & 全平台主控闭环 & Linux/macOS 客户端剪贴板** diff --git a/ReadMe_EN.md b/ReadMe_EN.md index d62ff64..ab8a328 100644 --- a/ReadMe_EN.md +++ b/ReadMe_EN.md @@ -357,6 +357,35 @@ Valid : 2026-02-01 to 2028-02-01 ## Changelog +### v1.3.5 (2026.5.31) + +**Hardware encoding expansion (H.264 / AV1) & multi-tenant license hardening & FRP sub-master automation** + +**New features:** +- **Client hardware encoding**: new `CFFmpegH264Encoder` / `CFFmpegAV1Encoder` on the FFmpeg path, driving NVENC / Quick Sync / AMF GPU encoders; `EncoderFactory` picks the best available encoder at runtime +- **Skip-encode on identical frames**: capture layer compares consecutive frames and skips both encode and transmit when the picture is static — hardware encoders no longer get fed duplicate frames during idle desktops +- **Menu-driven compress / extract**: custom file + folder picker (`ZstaPickerDlg`) lets you select a mixed directory tree on the remote host to zip up, or extract an archive to a target path +- **Auto-launch frp client for sub-masters**: when upstream issues a V2 license, frp config is shipped alongside it; the sub-master connects to the relay automatically with no manual `frpc.toml` +- **Compliance-tailorable build**: `DISABLE_X264` / `DISABLE_FFMPEG` build flags produce binaries with zero x264 / FFmpeg dependency without touching source; paired with `LICENSE-THIRD-PARTY.txt` + +**Improvements:** +- **Multi-tenant license server hardening**: `licenses.ini` hot path now has a recursive mutex + 30s throttle; write rate dropped from 0.6 → 0.07/sec (extrapolated to 100 online targets: ~160 → ~3.3 writes/sec). Closes the read-modify-write race that caused "preset renewal quota silently disappears" +- **`licenses.ini` IP list 4KB truncation fix**: segmented writes prevent the tail of large IP histories from being silently dropped by `WritePrivateProfileString`'s 4KB single-value cap +- **`BindType` enforced on SN import**: offline / online / trial SNs can no longer be cross-imported into the wrong bucket +- **Client SCLoader slim-down**: removed `SCLoader.cpp` (10K lines of hard-coded stub); the client now uses the DLL delivered by the master at runtime +- **Client logger graceful shutdown**: drains queued log lines on exit and records the exit signal — after a restart you still have the last 1-2 seconds of context +- **IOCPClient early-packet guard**: packets that arrive before `setManagerCallBack` no longer trigger a null-callback crash (startup race) +- **Multi-monitor trace-cursor position fix & MJPEG playback flip fix**: trace cursor coordinates corrected for cross-monitor capture; MJPEG upside-down playback fixed and 0-byte AVI residue removed on encoder-open failure +- **FRP `privilegeKey` switched to UTC**: master / relay / client across different time zones no longer reject each other's frp auth because of local-time skew +- **Linux client `install.sh` / `uninstall.sh`**: one-shot install / uninstall scripts, on par with macOS +- **Go server build pipeline**: `build.ps1` / `build.cmd` now build the Go master as part of the main build +- **Release / Download links migrated to Gitea**: v1.3.4+ is no longer published to GitHub + +**Bug fixes:** +- Web file manager touch double-click unreliability: move threshold widened to avoid spurious drag detection, plus two sequential `click` events (20ms apart) instead of the non-standard `dblclick` — fixes folder rename / unresponsive clicks on Windows, Linux, and macOS +- AUTH packet to sub-master used the wrong password generation path, causing sub-masters to fail authentication every time +- Trial SN was being routed through the V2 / V1 license-issue branch + ### v1.3.4 (2026.5.20) **Go master & full-platform master loop & Linux/macOS clipboard** diff --git a/ReadMe_TW.md b/ReadMe_TW.md index c5d46f8..635a090 100644 --- a/ReadMe_TW.md +++ b/ReadMe_TW.md @@ -357,6 +357,35 @@ nohup ./server_linux_amd64 --port 6543 --http-port 9001 > yama.log 2>&1 & ## 更新日誌 +### v1.3.5 (2026.5.31) + +**硬體編碼擴充(H.264 / AV1)& 多客戶授權生產化 & FRP 子級自動化** + +**新功能:** +- **用戶端硬體編碼**:新增 FFmpeg 路徑的 `CFFmpegH264Encoder` / `CFFmpegAV1Encoder`,可呼叫 NVENC / Quick Sync / AMF 等 GPU 編碼器;`EncoderFactory` 執行時自動優選 +- **靜畫跳編碼**:擷取層比對前後影格,完全相同時跳過編碼與傳輸——硬體編碼器在靜畫時不再被強行餵入相同影格 +- **選單驅動的壓縮 / 解壓**:自訂檔案 + 資料夾選擇器(`ZstaPickerDlg`),可從遠端主機直接選混合目錄樹打包或解壓到目標路徑 +- **下級主控自動啟動 frp client**:上級簽發 V2 授權時一併下發 frp 設定,子級主控啟動即接通中繼鏈路,無需人工設定 `frpc.toml` +- **合規可裁剪建置**:`DISABLE_X264` / `DISABLE_FFMPEG` 編譯開關,可在不動原始碼的前提下產出完全不含 x264 / FFmpeg 的二進位,搭配 `LICENSE-THIRD-PARTY.txt` + +**改進:** +- **多客戶授權伺服端硬化**:`licenses.ini` hot-path 互斥鎖 + 30s 節流,寫入頻率從 0.6 → 0.07 次/秒(外推 100 在線:~160 → ~3.3 次/秒);閉環「預設續期配額消失」的 read-modify-write 競態 +- **`licenses.ini` IP 清單 4KB 截斷修復**:分段寫入避免溢出尾部被永久丟棄 +- **匯入 SN 按 `BindType` 嚴格校驗**:避免離線版 / 連線版 / 試用版 SN 串庫 +- **用戶端 SCLoader 大瘦身**:移除一萬行硬編碼 stub(`SCLoader.cpp`),改用主控執行時下發 DLL 注入 +- **用戶端 logger 優雅退出**:程序結束時刷出佇列裡的日誌並記錄退出訊號 +- **IOCPClient 早期封包防護**:`setManagerCallBack` 之前抵達的封包不再觸發空回呼崩潰 +- **多顯示器游標位置修正 & MJPEG 錄製翻轉修復**:trace cursor 跨螢幕座標系修正;MJPEG 上下顛倒回放修正 + 編碼失敗 0 位元組 AVI 殘留清理 +- **FRP `privilegeKey` 改用 UTC 時間戳**:跨時區主控 / 中繼 / 用戶端不再因本地時區讓 frp auth 失效 +- **Linux 用戶端 `install.sh` / `uninstall.sh`**:補齊一鍵部署 / 解除安裝指令稿 +- **Go 伺服端建置管線**:`build.ps1` / `build.cmd` 把 Go 主控納入主建置流程 +- **Release / Download 連結全面遷移到 Gitea**:v1.3.4+ 不再發行到 GitHub + +**Bug 修復:** +- Web 檔案管理觸控雙擊不穩:觸控閾值放寬避免誤判拖曳 + 兩次 `click` 模擬實體雙擊;修復跨平台資料夾重新命名 / 點擊無回應 +- 向 sub-master 發送 AUTH 時密碼產生路徑錯誤,下級始終認證失敗 +- 試用 SN 誤進入 V2 / V1 授權下發分支 + ### v1.3.4 (2026.5.20) **Go 主控 & 全平台主控閉環 & Linux/macOS 用戶端剪貼簿** diff --git a/client/Script.rc b/client/Script.rc index a17c76d..f77bbd7 100644 --- a/client/Script.rc +++ b/client/Script.rc @@ -88,7 +88,7 @@ IDR_WAVE WAVE "Res\\msg.wav" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,3,4 + FILEVERSION 1,0,3,5 PRODUCTVERSION 1,0,0,1 FILEFLAGSMASK 0x3fL #ifdef _DEBUG @@ -106,7 +106,7 @@ BEGIN BEGIN VALUE "CompanyName", "FUCK THE UNIVERSE" VALUE "FileDescription", "A GHOST" - VALUE "FileVersion", "1.0.3.4" + VALUE "FileVersion", "1.0.3.5" VALUE "InternalName", "ServerDll.dll" VALUE "LegalCopyright", "Copyright (C) 2019-2026" VALUE "OriginalFilename", "ServerDll.dll" diff --git a/client/TestRun.rc b/client/TestRun.rc index 8e9f86b9dcf29d3d6669e63e28f6bef782ec6e01..3068810f2bf3709bb840f62090fc63fec0172a61 100644 GIT binary patch delta 25 hcmaE){78929|xo9=6()+W=7M=iaffT-*A6p1ps&T2+IHf delta 25 hcmaE){78929|xn!=6()+W=50AiaffT-*A6p1ps&22+05d diff --git a/server/2015Remote/2015Remote.rc b/server/2015Remote/2015Remote.rc index d0513862f01b25f5b0fde87f188650f9ec064d24..cc034459e2b6fd8bcec8ca2aa4a6c6c11363765d 100644 GIT binary patch delta 45 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