feature: Support client connections over UDP

This commit is contained in:
yuanyuanxiang
2025-07-02 03:53:21 +08:00
parent 763b4f6f25
commit 848f4089bb
8 changed files with 134 additions and 57 deletions

View File

@@ -138,7 +138,7 @@ BOOL CMy2015RemoteApp::InitInstance()
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ洢<DAB4><E6B4A2><EFBFBD>õ<EFBFBD>ע<EFBFBD><D7A2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// TODO: Ӧ<>ʵ<EFBFBD><CAB5>޸ĸ<DEB8><C4B8>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD>޸<EFBFBD>Ϊ<EFBFBD><CEAA>˾<EFBFBD><CBBE><EFBFBD><EFBFBD>֯<EFBFBD><D6AF>
SetRegistryKey(_T("Remoter"));
SetRegistryKey(_T("YAMA"));
CMy2015RemoteDlg dlg(nullptr);
m_pMainWnd = &dlg;

View File

@@ -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(); i<n; ++i)
{
CONTEXT_OBJECT* ContextObject = (CONTEXT_OBJECT*)m_CList_Online.GetItemData(i);
if (!ContextObject->bLogin)
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);

View File

@@ -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) //<2F>Է<EFBFBD><D4B7>ر<EFBFBD><D8B1><EFBFBD><EFBFBD>׽<EFBFBD><D7BD><EFBFBD>
{
RemoveStaleContext(ContextObject);
return FALSE;
}
//<2F><><EFBFBD><EFBFBD><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><D4BC><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD>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); //Ͷ<><CDB6><EFBFBD>µĽ<C2B5><C4BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵ<EFBFBD><DDB5><EFBFBD><EFBFBD><EFBFBD>
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);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><CDB5><EFBFBD><EFBFBD><EFBFBD>
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) ) //<2F><><EFBFBD><EFBFBD>Ͷ<EFBFBD><CDB6>ʧ<EFBFBD><CAA7>
@@ -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");
}
}

View File

@@ -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);

View File

@@ -2,6 +2,7 @@
#include "IOCPUDPServer.h"
#include <thread>
#include <iostream>
#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);
// <20>ͷ<EFBFBD>
delete ioCtx;
delete ctx;
AddCount(-1);
PostRecv(); // <20><><EFBFBD><EFBFBD><EFBFBD>
@@ -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

View File

@@ -41,6 +41,6 @@ private:
struct IO_CONTEXT {
OVERLAPPED ol;
CONTEXT_OBJECT* pContext;
CONTEXT_UDP* pContext;
};
};

View File

@@ -8,6 +8,7 @@
#include "Buffer.h"
#define XXH_INLINE_ALL
#include "xxhash.h"
#include <WS2tcpip.h>
#define PACKET_LENGTH 0x2000
@@ -250,9 +251,32 @@ public:
virtual void Disconnect(CONTEXT_OBJECT* ctx) {}
};
typedef class CONTEXT_OBJECT
class context {
public:
// <20><><EFBFBD><EFBFBD><E9BAAF>
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; // <20>Ƿ<EFBFBD> login
std::string PeerName; // <20>Զ<EFBFBD>IP
Server* server; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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<PCONTEXT_OBJECT> 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;
}
};