Feature: Implement KCP protocol - based on UDP
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
DestroyCursor(m_CursorHandleArray[i]);
|
||||
}
|
||||
|
||||
int getCurrentCursorIndex()
|
||||
int getCurrentCursorIndex() const
|
||||
{
|
||||
CURSORINFO ci;
|
||||
ci.cbSize = sizeof(CURSORINFO);
|
||||
|
||||
@@ -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>棩
|
||||
|
||||
@@ -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
118
client/IOCPKCPClient.cpp
Normal 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
34
client/IOCPKCPClient.h
Normal 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_;
|
||||
};
|
||||
@@ -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;
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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
1299
common/ikcp.c
Normal file
File diff suppressed because it is too large
Load Diff
416
common/ikcp.h
Normal file
416
common/ikcp.h
Normal 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
|
||||
|
||||
|
||||
@@ -178,7 +178,10 @@ int CMy2015RemoteApp::ExitInstance()
|
||||
CloseHandle(m_Mutex);
|
||||
m_Mutex = NULL;
|
||||
}
|
||||
Delete();
|
||||
__try{
|
||||
Delete();
|
||||
}__except(EXCEPTION_EXECUTE_HANDLER){
|
||||
}
|
||||
|
||||
SAFE_DELETE(m_iniFile);
|
||||
|
||||
|
||||
@@ -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.
@@ -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};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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");
|
||||
|
||||
226
server/2015Remote/IOCPKCPServer.cpp
Normal file
226
server/2015Remote/IOCPKCPServer.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
67
server/2015Remote/IOCPKCPServer.h
Normal file
67
server/2015Remote/IOCPKCPServer.h
Normal 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();
|
||||
};
|
||||
@@ -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";
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
Reference in New Issue
Block a user