NewLife/Stardust

README.md
# StarAgent Native C++ StarAgent 的 C++17 原生实现,与 `spec/protocol.md`、Go/Rust 实现保持协议对齐。支持登录/注销、心跳、令牌续期、`NewServer` 迁移、指数退避重连、HTTP 命令回复、WebSocket 通知、指标采集、内置命令、事件补报与服务安装。 ## 状态 - Windows(MSVC 19.51 / Visual Studio 2026,x64):实际编译、CTest 与一致性测试通过。 - 一致性测试:`conformance --agent staragent.exe --scenario all` → **6 passed / 0 failed**(basic、http-fallback、dedup、expired、reconnect、events)。 - 单元测试:`ctest -C Release` → **2/2**(`staragent_tests` 50/50 checks、`staragent --version`)。 - 真实服务端:在真实 Kestrel StarServer 上完成登录、自动注册、Code/Secret 持久化与在线状态验证(`NativeAgentIntegrationTests`,`ProductCode=StarAgent-Cpp`)。 - Linux/macOS:源码路径完整(`platform_linux.cpp`、`platform_macos.cpp`、`service_posix.cpp`),本机未完成交叉编译验证,建议在对应平台或 CI 上执行 `cmake --build` + `ctest`。 ## 目录 ```text cpp/ ├── CMakeLists.txt ├── README.md ├── src/ │ ├── main.cpp CLI:run/once/version/install/uninstall/start/stop/status │ ├── agent.{hpp,cpp} 登录、心跳、迁移、通知、命令调度、事件补报 │ ├── config.{hpp,cpp} staragent.json、STARAGENT_* 环境变量、原子持久化 │ ├── protocol.{hpp,cpp} PascalCase JSON 模型、时间格式、响应解包 │ ├── http_client.{hpp,cpp} /node/* HTTP 客户端(cpp-httplib) │ ├── ws_client.{hpp,cpp} /node/notify WebSocket(IXWebSocket) │ ├── executor.{hpp,cpp} 命令去重/过期/延迟/并发/超时/白名单 │ ├── metrics.{hpp,cpp} CPU/内存/磁盘/网络/进程/负载指标 │ ├── events.{hpp,cpp} 有界事件队列与落盘 │ ├── logging.{hpp,cpp} 按天轮转日志(保留 7 天) │ ├── platform.hpp 平台抽象 │ ├── platform_windows.cpp PDH / GlobalMemoryStatusEx / GetAdaptersAddresses / SMBIOS │ ├── platform_linux.cpp /proc /sys /statvfs / getifaddrs │ ├── platform_macos.cpp sysctl / host_statistics / vm_stat / getifaddrs │ ├── service_windows.cpp Windows Service(SCM) │ ├── service_posix.cpp systemd / OpenWrt procd / launchd │ └── output_buffer.hpp 64KB 头尾保留缓冲 ├── tests/tests.cpp 协议、配置、事件队列、命令执行器单元测试 └── third_party/ ├── httplib.h cpp-httplib v0.61.0(MIT) ├── json.hpp nlohmann/json v3.12.0(MIT) └── licenses/ 两份依赖许可证原文 ``` ## 构建 ### 依赖 - CMake ≥ 3.20,C++17 编译器(MSVC 2022/2026、GCC 11+、AppleClang 13+)。 - 首次 configure 需要网络:`FetchContent` 从 GitHub 拉取 **IXWebSocket v12.1.0**(BSD-3-Clause)。 - 可选:OpenSSL 开发包(启用 HTTPS/WSS,见下文)。 - 已内置单头文件依赖:cpp-httplib、nlohmann/json,无需额外下载。 ### Windows(已验证) ```powershell # Visual Studio 生成器 & 'C:\vs2026\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe' ` -S StarAgent.Native\cpp -B StarAgent.Native\cpp\build ` -G 'Visual Studio 18 2026' -A x64 & 'C:\vs2026\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe' ` --build StarAgent.Native\cpp\build --config Release --parallel # 测试 & 'C:\vs2026\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\ctest.exe' ` --test-dir StarAgent.Native\cpp\build -C Release --output-on-failure ``` 也可以使用 Ninja(需先 `call vcvars64.bat`): ```bat call C:\vs2026\VC\Auxiliary\Build\vcvars64.bat cmake -S StarAgent.Native\cpp -B StarAgent.Native\cpp\build -G Ninja cmake --build StarAgent.Native\cpp\build ``` 产物:`StarAgent.Native/cpp/build/Release/staragent.exe`。 ### Linux / OpenWrt / macOS ```bash cmake -S StarAgent.Native/cpp -B StarAgent.Native/cpp/build -DCMAKE_BUILD_TYPE=Release cmake --build StarAgent.Native/cpp/build --parallel ctest --test-dir StarAgent.Native/cpp/build --output-on-failure ``` OpenWrt 交叉编译时传入目标工具链文件(`-DCMAKE_TOOLCHAIN_FILE=...`);`service_posix.cpp` 会在目标系统检测 `/etc/rc.common` + `/sbin/procd` 并安装 procd 脚本。 ### 离线 / 不启用 WebSocket ```bash # 已有 IXWebSocket 源码时避免联网 cmake -S ... -DFETCHCONTENT_SOURCE_DIR_IXWEBSOCKET=/path/to/IXWebSocket # 完全不启用 WS:命令改由心跳响应 Commands 下发(HTTP 降级) cmake -S ... -DSTARAGENT_WITH_WS=OFF ``` ## 依赖与许可证 | 依赖 | 版本 | 许可证 | 引入方式 | |------|------|--------|----------| | [cpp-httplib](https://github.com/yhirose/cpp-httplib) | v0.61.0 | MIT | `third_party/httplib.h`,许可证 `third_party/licenses/cpp-httplib.LICENSE` | | [nlohmann/json](https://github.com/nlohmann/json) | v3.12.0 | MIT | `third_party/json.hpp`,许可证 `third_party/licenses/nlohmann-json.LICENSE` | | [IXWebSocket](https://github.com/machinezone/IXWebSocket) | v12.1.0 | BSD-3-Clause | CMake `FetchContent`,源码与许可证位于构建目录 `_deps/ixwebsocket-src` | | OpenSSL(可选) | 系统版本 | Apache-2.0 | 系统包管理器 / 工具链提供 | ## HTTPS / WSS 与 OpenSSL CMake 使用 `find_package(OpenSSL QUIET)`: - **找到 OpenSSL**:自动设置 `STARAGENT_WITH_TLS=ON`,同时为 cpp-httplib 定义 `CPPHTTPLIB_OPENSSL_SUPPORT`,并为 IXWebSocket 设置 `USE_TLS/USE_OPEN_SSL`,支持 `https://` 与 `wss://`。 - **未找到 OpenSSL**:保持 `STARAGENT_WITH_TLS=OFF`,configure 输出明确警告;此构建**仅支持 `http://` / `ws://`**。 - 生产环境必须使用 HTTPS/WSS。请安装 OpenSSL 开发包(如 `libssl-dev`、`openssl-devel`、vcpkg `openssl`)后重新 configure;也可显式指定 `-DSTARAGENT_WITH_TLS=ON`(缺少 OpenSSL 时会直接报错)或 `-DSTARAGENT_WITH_TLS=OFF`。 - `TlsVerify=false` 仅用于测试;默认 `true`,会校验证书。 本机(Windows)未安装 OpenSSL,因此已验证的构建为 **http/ws**;一致性测试的假服务器也使用 http。 ## 配置 默认读取 `staragent.json`(可用 `--config` 或 `STARAGENT_CONFIG` / `STARAGENT_CONFIG_FILE` 覆盖): ```json { "Server": "https://star.example.com:6600", "ProductCode": "StarAgent-Cpp", "Code": "", "Secret": "", "Project": "", "Channel": "Release", "DataDir": "/var/lib/staragent", "LogLevel": "info", "MetricsInterval": 60, "AllowExec": false, "AllowedCommands": [], "CommandTimeout": 30, "TlsVerify": true } ``` 关键校验: - `Server` 必填,scheme 仅 `http`/`https`。 - `MetricsInterval` 5–3600 秒;`CommandTimeout` 1–300 秒。 - `Code`/`Secret` 由登录响应写入,原子落盘并限制为 `0600`(Windows 上为 CRT 只读位 + 数据目录所有者隔离,见“已知限制”)。 ### 环境变量 `STARAGENT_` 前缀覆盖配置;同时兼容下划线别名(例如一致性 runner 注入的变量): | 配置 | 变量 | |------|------| | Server | `STARAGENT_SERVER`、`STARAGENT_SERVER_URL` | | ProductCode | `STARAGENT_PRODUCTCODE`、`STARAGENT_PRODUCT_CODE` | | DataDir | `STARAGENT_DATADIR`、`STARAGENT_DATA_DIR` | | LogLevel | `STARAGENT_LOGLEVEL`、`STARAGENT_LOG_LEVEL` | | MetricsInterval | `STARAGENT_METRICSINTERVAL`、`STARAGENT_METRICS_INTERVAL` | | AllowExec | `STARAGENT_ALLOWEXEC`、`STARAGENT_ALLOW_EXEC` | | AllowedCommands | `STARAGENT_ALLOWEDCOMMANDS`、`STARAGENT_ALLOWED_COMMANDS` | | CommandTimeout | `STARAGENT_COMMANDTIMEOUT`、`STARAGENT_COMMAND_TIMEOUT` | | TlsVerify | `STARAGENT_TLSVERIFY`、`STARAGENT_TLS_VERIFY` | | Code / Secret / Project / Channel | `STARAGENT_CODE` / `STARAGENT_SECRET` / `STARAGENT_PROJECT` / `STARAGENT_CHANNEL` | ### CLI ```text staragent run [--config path] [--server url] [--data dir] [--log-level level] [--allow-exec] [--console] staragent once [--config path] [--console] staragent version staragent install [--config path] [--server url] [--data dir] [--user user] [--log-level level] [--dir dir] staragent uninstall | start | stop | status ``` `run` 为长连接模式;`once` 登录、心跳并处理本次心跳中的命令后退出,适合自检/定时任务。 ## 持久化与日志 - `DataDir/events.json`:有界事件队列(1000 条),失败重试期间保留,重启后恢复。 - `DataDir/logs/staragent-YYYY-MM-DD.log`:按天轮转,保留 7 天;`--console` 同时写 stderr。 - 日志不会输出 `Secret`/`Token`;HTTP 错误体会脱敏后再记录。 ## 命令与安全默认 | 命令 | 平台 | 说明 | |------|------|------| | `bash` | Linux/macOS | 字符串参数或 `{"cmd":"...","timeout":30000}`(毫秒) | | `cmd` | Windows | 同上,通过 `cmd.exe /d /s /c` 执行 | | `node/synctime` | 全平台 | 可选时间字符串;无参数使用服务端时间 | | `node/setchannel` | 全平台 | 修改并持久化更新通道 | | `node/restart` | 全平台 | 1 秒后重启自身进程 | | `node/reboot` / `deploy/*` / `framework/install` | — | 首版回复“不支持命令” | 安全与限制: - `AllowExec=false` 时 `bash`/`cmd` 一律回复 `Status=3` / `命令执行未启用`。 - 开启后仍受 `AllowedCommands` 白名单(精确匹配或 `前缀*`)约束;参数上限 8KB。 - 输出合并 stdout/stderr,超 64KB 保留头尾并插入截断标记。 - 默认超时 30 秒,可由参数覆盖,硬上限 300 秒;超时终止**整个进程树**(Windows Job Object / POSIX 进程组)。 - 最多 4 个命令并发;shell 命令串行执行。 - 命令按 `Id` 去重 1 小时;`Expire` 过期回复 `Status=3`;`StartTime` 未来时先回复 `Status=1` 再延迟执行。 - 所有回复(过期、延迟、取消、成功、失败)都携带原始 `Id`。 ## 安装为系统服务 ### Windows(管理员) ```powershell staragent.exe install --config C:\ProgramData\StarAgent\staragent.json --server https://star.example.com:6600 staragent.exe start staragent.exe status staragent.exe stop staragent.exe uninstall ``` 服务名 `StarAgentNative`;服务命令行包含 `run --config <path> --service`。安装/卸载/启动/停止需要管理员权限。 ### Linux(systemd,root) ```bash sudo staragent install --config /etc/staragent/staragent.json --server https://star.example.com:6600 sudo systemctl enable --now staragent # install 已自动 enable staragent status ``` 写入 `/etc/systemd/system/staragent.service`,`Restart=always`,可选 `--user` 指定运行用户。 ### OpenWrt(procd,root) 检测到 `/etc/rc.common` 与 `/sbin/procd` 时写入 `/etc/init.d/staragent`(`USE_PROCD=1`,含 respawn),并执行 `enable`。 ### macOS(launchd) root 写入 `/Library/LaunchDaemons/com.newlifex.staragent.plist`;普通用户写入 `~/Library/LaunchAgents/`。`install` 会 `launchctl load -w`,`uninstall` 会 unload 并删除 plist。 ## 能力边界与已知限制 - **不自升级**:收到 `/node/upgrade` 非空版本时只记录日志并上报 `Upgrade` 事件,需人工更新;`cap:upgrade=false`。 - **deploy / framework / reboot 未实现**:按协议回复“不支持命令”。 - **WebSocket 可选**:`-DSTARAGENT_WITH_WS=OFF` 时仍可通过心跳 `Commands` 执行命令;但 `--scenario reconnect/dedup` 等 WS 场景不可用。 - **TLS 依赖 OpenSSL**:未检测到 OpenSSL 的构建只能 `http/ws`;生产必须安装 OpenSSL 并重新构建。 - **Windows 权限**:`0600` 通过 CRT `_chmod` 与数据目录隔离近似实现,无法像 POSIX 一样精确设置 ACL;建议将 `DataDir` 放在受控目录。 - **node/restart 与 SCM**:重启会以原命令行拉起新进程;若父进程由 SCM 启动,子进程的 `--service` 在非 SCM 环境下会回退为控制台模式。生产建议同时配置 Windows 服务恢复策略,或改用服务管理器重启。 - **Linux/macOS 验证**:实现已提供,但当前 Windows 环境未完成对应平台的编译/运行验证;建议在 CI 增加 Ubuntu 与 macOS 构建任务。 - **指标降级**:任何单项采集失败只把该字段填 0,不跳过心跳;`Temperature`、`Battery`、`Tcp*` 等未采集字段为 0。 - **无 Android/iOS 实现**;移动端见仓库其他原生目录。 - **状态文件**:`Code`/`Secret` 写入 `staragent.json`;`events.json` 与日志位于 `DataDir`,不会被提交到仓库。 ## 一致性测试 ```powershell cd StarAgent.Native\conformance go build -o conformance.exe ./cmd/conformance .\conformance.exe --agent ..\cpp\build\Release\staragent.exe --scenario all ``` 本次结果: ```text [PASS] basic (2.6s) [PASS] http-fallback (1.7s) [PASS] dedup (2.1s) [PASS] expired (600ms) [PASS] reconnect (2.9s) [PASS] events (3.6s) 6 passed, 0 failed in 13.3s ```