// 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 注入): // - HandlerT:PTYHandler / ScreenHandler / SystemManager / FileManager // - createHandler 可返回 nullptr 表示初始化失败(如 macOS ScreenHandler 无录屏权限) // - onReady 完成首包发送或额外 setup // // 用法见 linux/main.cpp / macos/main.mm 的 *workingThread 调用点。 #pragma once #include #include #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(IOCPClient*) // 返回 nullptr 表示初始化失败(如权限拒绝),线程会跳过 callback 安装直接 leave。 // OnReadyFn 签名: void(IOCPClient*, HandlerT*) // handler 装上 callback 后立即调用,可在此发送首包或做额外 setup。 template inline void RunSubConnThread(const char* threadName, CreateFn createHandler, OnReadyFn onReady) { try { std::unique_ptr 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 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()); } }