Feature: Add MCP remote_open/remote_close remote control sessions
Add M1 of MCP remote control (docs/Mcp_RemoteControl_Design.md): the
remote_open / remote_close tools plus the ScreenCtrlSession state machine.
remote_open establishes a hidden screen sub-connection by reusing
WebService::StartRemoteDesktop (COMMAND_SCREEN_SPY -> CScreenSpyDlg ->
RegisterScreenContext), polls for the sub-connection plus its physical
resolution (TOKEN_BITMAPINFO -> NotifyResolutionChange -> GetScreenSize),
then records the session (single device, single session, reverse-mapped
subCtx for OfflineProc cleanup) and returns {session_id, screen_w,
screen_h}. remote_close validates session_id and tears down the
sub-connection idempotently. A McpRemoteControl settings checkbox (default
off, requires McpReadonly=0) gates the tools; every open/close is audited
via WM_SHOWERRORMSG.
Gating: multi-monitor hosts are rejected with -32008 (phase 1 supports only
single monitor, where Observe=main screen and Act=virtual desktop coincide);
the monitor count comes from the client heartbeat RES_RESOLUTION ("N:W*H").
Known limitations (deferred to the injection milestones): mutual exclusion
with human remote-desktop viewing is one-directional in M1 (a human who
joins during an MCP session can tear it down on disconnect), and subCtx is
not yet dereferenced so no liveness re-check is needed until
remote_mouse/remote_keyboard.
Co-Authored-By: deepseek-v4-pro
This commit is contained in:
@@ -157,6 +157,34 @@ public:
|
||||
// idle 回收:关闭 lastActiveAt 超时且非 busy 的持久会话。返回回收数量。
|
||||
int SweepIdleTerminals(time_t idleTimeoutSec);
|
||||
|
||||
// ===== P5:MCP 远程控制(remote_open / remote_close / remote_mouse / remote_keyboard)=====
|
||||
// 屏幕子连接由 WebService::StartRemoteDesktop 建立的隐藏 CScreenSpyDlg 持有(复用 Web
|
||||
// 路径,见 docs/Mcp_RemoteControl_Design.md §6.3);会话仅记录逻辑状态 + 子连接指针。
|
||||
// 注入走该子连接(COMMAND_SCREEN_CONTROL),与终端一样单设备单会话。
|
||||
void SetRemoteControlEnabled(bool enabled) { m_remoteControlEnabled = enabled; }
|
||||
bool IsRemoteControlEnabled() const { return m_remoteControlEnabled; }
|
||||
|
||||
// 该 host 的屏幕子连接是否被 MCP 远程控制会话持有(OfflineProc 反查用)。
|
||||
bool IsScreenCtrlContext(context* subCtx);
|
||||
|
||||
// 登记控制会话(单设备单会话;sessionId 由调用方生成)。false = 该设备已有会话。
|
||||
bool BeginScreenCtrlOpen(uint64_t device_id, const std::string& sessionId);
|
||||
|
||||
// 子连接就绪(HasActiveSession && 分辨率到达)后调用:填 subCtx/分辨率并置 started。
|
||||
// false = 会话已被并发关闭(调用方应放弃本次 open)。
|
||||
bool MarkScreenCtrlReady(uint64_t device_id, const std::string& sessionId,
|
||||
context* subCtx, int screenW, int screenH);
|
||||
|
||||
// 关闭控制会话(校验 sessionId;擦路由 + 会话)。屏幕子连接的关闭由调用方锁外执行
|
||||
// (CloseWebRemoteDesktopByClientID)。返回 0=已关;1=不存在(幂等);2=sessionId 不匹配。
|
||||
int CloseScreenCtrlSession(uint64_t device_id, const std::string& sessionId);
|
||||
|
||||
// idle 回收:关闭 lastActiveAt 超时的控制会话,并锁外关闭其隐藏对话框。返回回收数量。
|
||||
int SweepIdleScreenCtrl(time_t idleTimeoutSec);
|
||||
|
||||
// 屏幕子连接断开(OfflineProc 调用):擦除该子连接对应的会话 + 路由(幂等)。
|
||||
void OnScreenControlClosed(context* subCtx);
|
||||
|
||||
// 安全配置(启动时由 CMy2015RemoteDlg 读 THIS_CFG 后设置)。
|
||||
void SetReadonly(bool readonly) { m_readonly = readonly; }
|
||||
void SetCmdWhitelist(const std::string& whitelist) { m_cmdWhitelist = whitelist; }
|
||||
@@ -220,9 +248,23 @@ private:
|
||||
std::map<uint64_t, TermSession> m_TermSessions; // device_id → 会话
|
||||
std::map<context*, uint64_t> m_TermContextToDevice; // subCtx → device_id(顶部路由)
|
||||
|
||||
// ===== P5:远程控制会话(受 m_ScreenCtrlMutex 保护;单设备单会话)=====
|
||||
struct ScreenCtrlSession {
|
||||
std::string sessionId; // 会话 token(每次 open 独立随机)
|
||||
context* subCtx = nullptr; // 屏幕子连接上下文(就绪后填;用于注入)
|
||||
bool started = false; // false=子连接建立中;true=已就绪
|
||||
time_t lastActiveAt = 0; // idle 回收用(秒)
|
||||
int screenW = 0; // 物理捕获分辨率(来自 TOKEN_BITMAPINFO)
|
||||
int screenH = 0;
|
||||
};
|
||||
std::mutex m_ScreenCtrlMutex;
|
||||
std::map<uint64_t, ScreenCtrlSession> m_ScreenCtrlSessions; // device_id → 会话
|
||||
std::map<context*, uint64_t> m_ScreenCtrlContextToDevice; // subCtx → device_id(OfflineProc 反查)
|
||||
|
||||
bool m_readonly = true;
|
||||
std::string m_cmdWhitelist;
|
||||
bool m_terminalEnabled = false; // 持久终端开关(默认关;要求 m_readonly=false)
|
||||
bool m_terminalEnabled = false; // 持久终端开关(默认关;要求 m_readonly=false)
|
||||
bool m_remoteControlEnabled = false; // 远程控制开关(默认关;要求 m_readonly=false)
|
||||
};
|
||||
|
||||
// 全局访问器(仿 WebService(),见 WebService.h 末尾)
|
||||
|
||||
Reference in New Issue
Block a user