Refactor: extract Linux/macOS client shared code into common

This commit is contained in:
yuanyuanxiang
2026-05-10 09:49:07 +02:00
parent 70354e244c
commit d46176f4ef
9 changed files with 443 additions and 424 deletions

70
common/sub_conn_thread.h Normal file
View File

@@ -0,0 +1,70 @@
// sub_conn_thread.h
// Linux/macOS 客户端子连接 worker 线程的统一骨架。
//
// 各 worker 线程Shell / ScreenSpy / FileManager / SystemManager 等)共有的步骤:
// 1. new IOCPClient(g_bExit, exit_while_disconnect=true)
// 2. Enter log
// 3. EnableSubConnAuth(true, g_myClientID)(子连接强制 ConnAuth
// 4. ConnectServer内部会执行 PerformConnAuth失败返 false
// 5. 创建 platform handler
// 6. setManagerCallBack 装回调
// 7. 调 onReady发首包TOKEN_TERMINAL_START / SendBitmapInfo() 等)
// 8. while (running && connected && !g_bExit) Sleep
// 9. 清回调防止 dangling
// 10. Leave log
// 11. catch exceptions
//
// 平台差异(通过 lambda 注入):
// - HandlerTPTYHandler / ScreenHandler / SystemManager / FileManager
// - createHandler 可返回 nullptr 表示初始化失败(如 macOS ScreenHandler 无录屏权限)
// - onReady 完成首包发送或额外 setup
//
// 用法见 linux/main.cpp / macos/main.mm 的 *workingThread 调用点。
#pragma once
#include <memory>
#include <stdexcept>
#include "client/IOCPClient.h"
#include "common/commands.h"
#include "common/logger.h"
extern State g_bExit;
extern uint64_t g_myClientID;
extern CONNECT_ADDRESS g_SETTINGS;
// 子连接 worker 线程通用骨架。
//
// CreateFn 签名: std::unique_ptr<HandlerT>(IOCPClient*)
// 返回 nullptr 表示初始化失败(如权限拒绝),线程会跳过 callback 安装直接 leave。
// OnReadyFn 签名: void(IOCPClient*, HandlerT*)
// handler 装上 callback 后立即调用,可在此发送首包或做额外 setup。
template <class HandlerT, class CreateFn, class OnReadyFn>
inline void RunSubConnThread(const char* threadName, CreateFn createHandler, OnReadyFn onReady)
{
try {
std::unique_ptr<IOCPClient> ClientObject(new IOCPClient(g_bExit, true));
void* clientAddr = ClientObject.get();
Mprintf(">>> Enter %s [%p]\n", threadName, clientAddr);
// 子连接:开启 auth。Linux/macOS IOCPClient 不带 m_conn显式传入 g_myClientID。
ClientObject->EnableSubConnAuth(true, g_myClientID);
if (!g_bExit && ClientObject->ConnectServer(g_SETTINGS.ServerIP(), g_SETTINGS.ServerPort())) {
std::unique_ptr<HandlerT> handler = createHandler(ClientObject.get());
if (handler) {
ClientObject->setManagerCallBack(handler.get(),
IOCPManager::DataProcess,
IOCPManager::ReconnectProcess);
onReady(ClientObject.get(), handler.get());
while (ClientObject->IsRunning() && ClientObject->IsConnected() && S_CLIENT_NORMAL == g_bExit)
Sleep(1000);
// 清除回调,防止重连线程访问已销毁的 handler
ClientObject->setManagerCallBack(nullptr, nullptr, nullptr);
}
}
Mprintf(">>> Leave %s [%p]\n", threadName, clientAddr);
} catch (const std::exception& e) {
Mprintf("*** %s exception: %s ***\n", threadName, e.what());
}
}