forked from metin-server/m2dev-client-src
Networking Overhaul: Modern packets, buffers, handshake, dispatch & security hardening
See Readme
This commit is contained in:
@@ -374,61 +374,14 @@ D3DXVECTOR3 CPlaneCollisionInstance::OnGetCollisionMovementAdjust(const CDynamic
|
||||
const auto vv = (s.v3Position - m_attribute.v3Position);
|
||||
float t= - D3DXVec3Dot(&m_attribute.v3Normal, &vv)/d;
|
||||
|
||||
//D3DXVECTOR3 onplane = s.v3Position+t*advance;
|
||||
|
||||
if (D3DXVec3Dot(&m_attribute.v3Normal, &advance)>=0)
|
||||
{
|
||||
//return m_attribute.v3Normal*((-s.fRadius+D3DXVec3Dot(&m_attribute.v3Normal, &(s.v3Position-m_attribute.v3Position)))*gc_fReduceMove);
|
||||
return t*advance -s.fRadius*m_attribute.v3Normal;
|
||||
}
|
||||
else
|
||||
{
|
||||
//return m_attribute.v3Normal*((s.fRadius+D3DXVec3Dot(&m_attribute.v3Normal, &(s.v3Position-m_attribute.v3Position)))*gc_fReduceMove);
|
||||
return t*advance +s.fRadius*m_attribute.v3Normal;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*if (D3DXVec3Dot(&m_attribute.v3Normal, &advance)>=0)
|
||||
{
|
||||
Tracef("%f %f\n",s.fRadius,-(D3DXVec3Dot(&m_attribute.v3Normal, &(s.v3Position-m_attribute.v3Position))));
|
||||
return m_attribute.v3Normal*((-s.fRadius+D3DXVec3Dot(&m_attribute.v3Normal, &(s.v3Position-m_attribute.v3Position)))*gc_fReduceMove);
|
||||
}
|
||||
else
|
||||
{
|
||||
Tracef("%f %f\n",(s.fRadius),(D3DXVec3Dot(&m_attribute.v3Normal, &(s.v3Position-m_attribute.v3Position))));
|
||||
return m_attribute.v3Normal*((s.fRadius+D3DXVec3Dot(&m_attribute.v3Normal, &(s.v3Position-m_attribute.v3Position)))*gc_fReduceMove);
|
||||
}*/
|
||||
|
||||
|
||||
/*
|
||||
D3DXVECTOR3 advance = s.v3Position-s.v3LastPosition;
|
||||
D3DXVECTOR3 slide(-advance.y,advance.x,advance.z);
|
||||
slide = m_attribute.v3Normal;
|
||||
|
||||
D3DXVECTOR3 radius_adjust = advance;
|
||||
D3DXVec3Normalize(&radius_adjust,&radius_adjust);
|
||||
radius_adjust*=s.fRadius;
|
||||
|
||||
float d = D3DXVec3Dot(&m_attribute.v3Normal, &slide);
|
||||
if (d>=-0.0001 && d<=0.0001)
|
||||
return D3DXVECTOR3(0.0f,0.0f,0.0f);
|
||||
|
||||
float t= - D3DXVec3Dot(&m_attribute.v3Normal, &(s.v3Position+radius_adjust-m_attribute.v3Position))
|
||||
/ d;*/
|
||||
|
||||
//D3DXVECTOR3 nextposition;
|
||||
//nextposition = s.v3Position + t*slide;
|
||||
//Tracef("$T %f",t);
|
||||
//if (D3DXVec3Dot(&m_attribute.v3Normal, &advance)>=0)
|
||||
// return (t*slide - m_attribute.v3Normal * s.fRadius)/**gc_fReduceMove*/;
|
||||
//else
|
||||
// return (t*slide + m_attribute.v3Normal * s.fRadius)/*gc_fReduceMove*/;
|
||||
//if (D3DXVec3Dot(&m_attribute.v3Normal, &advance)>=0)
|
||||
// return (t*slide + m_attribute.v3Normal * D3DXVec3Dot(&m_attribute.v3Normal,&(s.v3LastPosition-m_attribute.v3Position))/** s.fRadius*/)*gc_fReduceMove;
|
||||
//else
|
||||
// return (t*slide + m_attribute.v3Normal * D3DXVec3Dot(&m_attribute.v3Normal,&(s.v3LastPosition-m_attribute.v3Position))/*s.fRadius*/)*gc_fReduceMove;
|
||||
//
|
||||
}
|
||||
|
||||
void CPlaneCollisionInstance::Render(D3DFILLMODE /*d3dFillMode*/)
|
||||
@@ -462,12 +415,6 @@ bool CCylinderCollisionInstance::CollideCylinderVSDynamicSphere(const TCylinderD
|
||||
if (s.v3Position.z - s.fRadius > c_rattribute.v3Position.z + c_rattribute.fHeight)
|
||||
return false;
|
||||
|
||||
/*D3DXVECTOR2 v2curDistance(s.v3Position.x - c_rattribute.v3Position.x, s.v3Position.y - c_rattribute.v3Position.y);
|
||||
float fDistance = D3DXVec2Length(&v2curDistance);
|
||||
if (fDistance <= s.fRadius + c_rattribute.fRadius)
|
||||
return true;
|
||||
*/
|
||||
|
||||
D3DXVECTOR3 oa, ob;
|
||||
IntersectLineSegments(c_rattribute.v3Position, D3DXVECTOR3(c_rattribute.v3Position.x,c_rattribute.v3Position.y,c_rattribute.v3Position.z+c_rattribute.fHeight), s.v3LastPosition, s.v3Position, oa, ob);
|
||||
const auto vv = (oa - ob);
|
||||
@@ -671,32 +618,6 @@ bool CAABBCollisionInstance::OnCollisionDynamicSphere(const CDynamicSphereInstan
|
||||
D3DXVECTOR3 CAABBCollisionInstance::OnGetCollisionMovementAdjust(const CDynamicSphereInstance & s) const
|
||||
{
|
||||
|
||||
//Tracef("OnGetCollisionMovementAdjust v3Min.x = %f, v3Max.x = %f\n", m_attribute.v3Min.x, m_attribute.v3Max.x);
|
||||
/*
|
||||
float fARadius = D3DXVec3Length(&(m_attribute.v3Min - m_attribute.v3Max));
|
||||
if (D3DXVec3LengthSq(&(s.v3Position-(m_attribute.v3Max + m_attribute.v3Min)))>=(s.fRadius+fARadius)*(fARadius+s.fRadius))
|
||||
return D3DXVECTOR3(0.0f,0.0f,0.0f);
|
||||
D3DXVECTOR3 c;
|
||||
D3DXVec3Cross(&c, &(s.v3Position-s.v3LastPosition), &D3DXVECTOR3(0.0f,0.0f,1.0f) );
|
||||
|
||||
float sum = - D3DXVec3Dot(&c,&(s.v3Position-(m_attribute.v3Max + m_attribute.v3Min)));
|
||||
float mul = (s.fRadius+fARadius)*(s.fRadius+fARadius)-D3DXVec3LengthSq(&(s.v3Position-(m_attribute.v3Max + m_attribute.v3Min)));
|
||||
|
||||
if (sum*sum-4*mul<=0)
|
||||
return D3DXVECTOR3(0.0f,0.0f,0.0f);
|
||||
float sq = sqrt(sum*sum-4*mul);
|
||||
float t1=-sum-sq, t2=-sum+sq;
|
||||
t1*=0.5f;
|
||||
t2*=0.5f;
|
||||
|
||||
if (fabs(t1)<=fabs(t2))
|
||||
{
|
||||
return (gc_fReduceMove*t1)*c;
|
||||
}
|
||||
else
|
||||
return (gc_fReduceMove*t2)*c;
|
||||
*/
|
||||
|
||||
D3DXVECTOR3 v3Temp;
|
||||
if(s.v3Position.x + s.fRadius <= m_attribute.v3Min.x) { v3Temp.x = m_attribute.v3Min.x; }
|
||||
else if(s.v3Position.x - s.fRadius >= m_attribute.v3Max.x) { v3Temp.x = m_attribute.v3Max.x; }
|
||||
|
||||
73
src/EterLib/ControlPackets.h
Normal file
73
src/EterLib/ControlPackets.h
Normal file
@@ -0,0 +1,73 @@
|
||||
#pragma once
|
||||
|
||||
// Control-plane packet structs used by all CNetworkStream subclasses.
|
||||
// Extracted from UserInterface/Packet.h so the base class (EterLib)
|
||||
// can handle key exchange, ping/pong, and phase transitions without
|
||||
// depending on UserInterface.
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
// Control-plane header constants (subset of CG::/GC:: namespaces).
|
||||
// The full CG/GC namespaces live in Packet.h which includes this file,
|
||||
// so all existing code sees these via Packet.h as before.
|
||||
namespace CG
|
||||
{
|
||||
constexpr uint16_t PONG = 0x0006;
|
||||
constexpr uint16_t KEY_RESPONSE = 0x000A;
|
||||
}
|
||||
namespace GC
|
||||
{
|
||||
constexpr uint16_t PING = 0x0007;
|
||||
constexpr uint16_t PHASE = 0x0008;
|
||||
constexpr uint16_t KEY_CHALLENGE = 0x000B;
|
||||
constexpr uint16_t KEY_COMPLETE = 0x000C;
|
||||
}
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct TPacketGCPhase
|
||||
{
|
||||
uint16_t header;
|
||||
uint16_t length;
|
||||
uint8_t phase;
|
||||
};
|
||||
|
||||
struct TPacketGCPing
|
||||
{
|
||||
uint16_t header;
|
||||
uint16_t length;
|
||||
uint32_t server_time;
|
||||
};
|
||||
|
||||
struct TPacketCGPong
|
||||
{
|
||||
uint16_t header;
|
||||
uint16_t length;
|
||||
};
|
||||
|
||||
struct TPacketGCKeyChallenge
|
||||
{
|
||||
uint16_t header;
|
||||
uint16_t length;
|
||||
uint8_t server_pk[32];
|
||||
uint8_t challenge[32];
|
||||
uint32_t server_time;
|
||||
};
|
||||
|
||||
struct TPacketCGKeyResponse
|
||||
{
|
||||
uint16_t header;
|
||||
uint16_t length;
|
||||
uint8_t client_pk[32];
|
||||
uint8_t challenge_response[32];
|
||||
};
|
||||
|
||||
struct TPacketGCKeyComplete
|
||||
{
|
||||
uint16_t header;
|
||||
uint16_t length;
|
||||
uint8_t encrypted_token[32 + 16];
|
||||
uint8_t nonce[24];
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
@@ -240,48 +240,3 @@ void CDecal::Render()
|
||||
sizeof(TPDTVertex));
|
||||
}
|
||||
|
||||
/*
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CDecalManager
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
CDecalManager aDecalManager;
|
||||
|
||||
CDecalManager::CDecalManager()
|
||||
{
|
||||
m_DecalPtrVector.clear();
|
||||
}
|
||||
|
||||
CDecalManager::~CDecalManager()
|
||||
{
|
||||
m_DecalPtrVector.clear();
|
||||
}
|
||||
|
||||
void CDecalManager::Add(CDecal * pDecal)
|
||||
{
|
||||
m_DecalPtrVector.push_back(pDecal);
|
||||
}
|
||||
|
||||
void CDecalManager::Remove(CDecal * pDecal)
|
||||
{
|
||||
std::vector<CDecal *>::iterator aIterator;
|
||||
for (aIterator = m_DecalPtrVector.begin(); aIterator != m_DecalPtrVector.end();)
|
||||
{
|
||||
if (*aIterator == pDecal)
|
||||
aIterator = m_DecalPtrVector.erase(aIterator);
|
||||
else
|
||||
++aIterator;
|
||||
}
|
||||
}
|
||||
|
||||
void CDecalManager::Update()
|
||||
{
|
||||
for (DWORD dwi = 0; dwi < m_DecalPtrVector.size(); ++dwi)
|
||||
m_DecalPtrVector[dwi]->Update();
|
||||
}
|
||||
|
||||
void CDecalManager::Render()
|
||||
{
|
||||
for (DWORD dwi = 0; dwi < m_DecalPtrVector.size(); ++dwi)
|
||||
m_DecalPtrVector[dwi]->Render();
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
#include "StdAfx.h"
|
||||
#include "NetDatagram.h"
|
||||
|
||||
CNetworkDatagram::CNetworkDatagram()
|
||||
{
|
||||
__Initialize();
|
||||
}
|
||||
|
||||
CNetworkDatagram::~CNetworkDatagram()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void CNetworkDatagram::Destroy()
|
||||
{
|
||||
if (INVALID_SOCKET==m_sock)
|
||||
return;
|
||||
|
||||
closesocket(m_sock);
|
||||
|
||||
__Initialize();
|
||||
}
|
||||
|
||||
bool CNetworkDatagram::Create(UINT uPort)
|
||||
{
|
||||
assert(INVALID_SOCKET==m_sock);
|
||||
m_sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
DWORD arg = 1;
|
||||
ioctlsocket(m_sock, FIONBIO, &arg); // Non-blocking mode
|
||||
|
||||
SOCKADDR_IN sockAddrIn;
|
||||
memset(&sockAddrIn, 0, sizeof(SOCKADDR_IN));
|
||||
sockAddrIn.sin_family = AF_INET;
|
||||
sockAddrIn.sin_addr.s_addr = INADDR_ANY;
|
||||
sockAddrIn.sin_port = htons(uPort);
|
||||
|
||||
if (SOCKET_ERROR == bind(m_sock, (PSOCKADDR)&sockAddrIn, sizeof(SOCKADDR_IN)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4127)
|
||||
void CNetworkDatagram::Update()
|
||||
{
|
||||
if (m_sock == INVALID_SOCKET)
|
||||
return;
|
||||
|
||||
FD_ZERO(&m_fdsRecv);
|
||||
FD_ZERO(&m_fdsSend);
|
||||
|
||||
FD_SET(m_sock, &m_fdsRecv);
|
||||
FD_SET(m_sock, &m_fdsSend);
|
||||
|
||||
TIMEVAL delay;
|
||||
|
||||
delay.tv_sec = 0;
|
||||
delay.tv_usec = 0;
|
||||
|
||||
if (select(0, &m_fdsRecv, &m_fdsSend, NULL, &delay) == SOCKET_ERROR)
|
||||
return;
|
||||
}
|
||||
#pragma warning(pop)
|
||||
|
||||
bool CNetworkDatagram::CanRecv()
|
||||
{
|
||||
if (FD_ISSET(m_sock, &m_fdsRecv))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
int CNetworkDatagram::PeekRecvFrom(UINT uBufLen, void* pvBuf, SOCKADDR_IN* pkSockAddrIn)
|
||||
{
|
||||
int nSockAddrInLen=sizeof(SOCKADDR_IN);
|
||||
return recvfrom(m_sock, (char*)pvBuf, uBufLen, MSG_PEEK, (PSOCKADDR)pkSockAddrIn, &nSockAddrInLen);
|
||||
}
|
||||
|
||||
int CNetworkDatagram::RecvFrom(UINT uBufLen, void* pvBuf, SOCKADDR_IN* pkSockAddrIn)
|
||||
{
|
||||
int nSockAddrInLen=sizeof(SOCKADDR_IN);
|
||||
return recvfrom(m_sock, (char*)pvBuf, uBufLen, 0, (PSOCKADDR)pkSockAddrIn, &nSockAddrInLen);
|
||||
}
|
||||
|
||||
int CNetworkDatagram::SendTo(UINT uBufLen, const void* c_pvBuf, const SOCKADDR_IN& c_rkSockAddrIn)
|
||||
{
|
||||
return sendto(m_sock, (const char *)c_pvBuf, uBufLen, 0, (PSOCKADDR)&c_rkSockAddrIn, sizeof(SOCKADDR_IN));
|
||||
}
|
||||
|
||||
|
||||
void CNetworkDatagram::__Initialize()
|
||||
{
|
||||
m_sock=INVALID_SOCKET;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
class CNetworkDatagram
|
||||
{
|
||||
public:
|
||||
CNetworkDatagram();
|
||||
virtual ~CNetworkDatagram();
|
||||
|
||||
void Destroy();
|
||||
bool Create(UINT uPort);
|
||||
|
||||
void Update();
|
||||
|
||||
bool CanRecv();
|
||||
|
||||
int PeekRecvFrom(UINT uBufLen, void* pvBuf, SOCKADDR_IN* pkSockAddrIn);
|
||||
int RecvFrom(UINT uBufLen, void* pvBuf, SOCKADDR_IN* pkSockAddrIn);
|
||||
int SendTo(UINT uBufLen, const void* c_pvBuf, const SOCKADDR_IN& c_rkSockAddrIn);
|
||||
|
||||
private:
|
||||
void __Initialize();
|
||||
|
||||
private:
|
||||
SOCKET m_sock;
|
||||
|
||||
fd_set m_fdsRecv;
|
||||
fd_set m_fdsSend;
|
||||
};
|
||||
@@ -1,105 +0,0 @@
|
||||
#include "StdAfx.h"
|
||||
#include "NetDatagramReceiver.h"
|
||||
|
||||
BOOL CNetDatagramReceiver::Process()
|
||||
{
|
||||
m_recvBufCurrentPos = 0;
|
||||
m_recvBufCurrentSize = 0;
|
||||
|
||||
int irecvAddrLength = sizeof(SOCKADDR_IN);
|
||||
m_recvBufCurrentSize = recvfrom(m_Socket, (char *)m_recvBuf, m_recvBufSize, 0, (PSOCKADDR)&m_SockAddr, &irecvAddrLength);
|
||||
|
||||
if (m_recvBufCurrentSize <= 0)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CNetDatagramReceiver::Recv(void * pBuffer, int iSize)
|
||||
{
|
||||
if (!Peek(pBuffer, iSize))
|
||||
return FALSE;
|
||||
|
||||
m_recvBufCurrentPos += iSize;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CNetDatagramReceiver::Peek(void * pBuffer, int iSize)
|
||||
{
|
||||
if (m_recvBufCurrentSize < m_recvBufCurrentPos+iSize)
|
||||
return FALSE;
|
||||
|
||||
memcpy(pBuffer, m_recvBuf + m_recvBufCurrentPos, iSize);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CNetDatagramReceiver::isBind()
|
||||
{
|
||||
return m_isBind;
|
||||
}
|
||||
|
||||
BOOL CNetDatagramReceiver::Bind(DWORD /*dwAddress*/, WORD wPortIndex)
|
||||
{
|
||||
m_Socket = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
DWORD arg = 1;
|
||||
ioctlsocket(m_Socket, FIONBIO, &arg); // Non-blocking mode
|
||||
|
||||
memset(&m_SockAddr, 0, sizeof(SOCKADDR_IN));
|
||||
m_SockAddr.sin_family = AF_INET;
|
||||
// m_SockAddr.sin_addr.s_addr = dwAddress;
|
||||
m_SockAddr.sin_addr.s_addr = INADDR_ANY;
|
||||
m_SockAddr.sin_port = htons(wPortIndex);
|
||||
|
||||
if (bind(m_Socket, (PSOCKADDR)&m_SockAddr, sizeof(SOCKADDR_IN)) < 0)
|
||||
{
|
||||
Tracef("Failed binding socket\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
m_isBind = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void CNetDatagramReceiver::SetRecvBufferSize(int recvBufSize)
|
||||
{
|
||||
if (m_recvBuf)
|
||||
{
|
||||
if (m_recvBufSize>recvBufSize)
|
||||
return;
|
||||
|
||||
delete [] m_recvBuf;
|
||||
}
|
||||
m_recvBufSize=recvBufSize;
|
||||
m_recvBuf=new char[m_recvBufSize];
|
||||
}
|
||||
|
||||
void CNetDatagramReceiver::Clear()
|
||||
{
|
||||
|
||||
m_isBind = FALSE;
|
||||
|
||||
m_dwPortIndex = 1000;
|
||||
|
||||
m_Socket = 0;
|
||||
memset(&m_SockAddr, 0, sizeof(SOCKADDR_IN));
|
||||
|
||||
m_recvBufCurrentPos = 0;
|
||||
m_recvBufCurrentSize = 0;
|
||||
}
|
||||
|
||||
CNetDatagramReceiver::CNetDatagramReceiver()
|
||||
{
|
||||
m_recvBuf = NULL;
|
||||
m_recvBufSize = 0;
|
||||
|
||||
Clear();
|
||||
}
|
||||
CNetDatagramReceiver::~CNetDatagramReceiver()
|
||||
{
|
||||
if (m_recvBuf)
|
||||
delete [] m_recvBuf;
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef VC_EXTRALEAN
|
||||
|
||||
class CNetDatagramReceiver
|
||||
{
|
||||
public:
|
||||
CNetDatagramReceiver();
|
||||
virtual ~CNetDatagramReceiver();
|
||||
|
||||
void Clear();
|
||||
BOOL Bind(DWORD dwAddress, WORD wPortIndex);
|
||||
BOOL isBind();
|
||||
|
||||
BOOL Process();
|
||||
BOOL Recv(void * pBuffer, int iSize);
|
||||
BOOL Peek(void * pBuffer, int iSize);
|
||||
|
||||
void SetRecvBufferSize(int recvBufSize);
|
||||
|
||||
protected:
|
||||
BOOL m_isBind;
|
||||
|
||||
DWORD m_dwPortIndex;
|
||||
|
||||
SOCKET m_Socket;
|
||||
SOCKADDR_IN m_SockAddr;
|
||||
|
||||
int m_recvBufCurrentPos;
|
||||
int m_recvBufCurrentSize;
|
||||
|
||||
char* m_recvBuf;
|
||||
int m_recvBufSize;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,58 +0,0 @@
|
||||
#include "StdAfx.h"
|
||||
#include "NetDatagramSender.h"
|
||||
|
||||
BOOL CNetDatagramSender::SetSocket(const char * c_szIP, WORD wPortIndex)
|
||||
{
|
||||
return SetSocket(inet_addr(c_szIP), wPortIndex);
|
||||
}
|
||||
|
||||
BOOL CNetDatagramSender::SetSocket(DWORD dwAddress, WORD wPortIndex)
|
||||
{
|
||||
m_isSocket = TRUE;
|
||||
|
||||
m_dwAddress = dwAddress;
|
||||
m_wPortIndex = wPortIndex;
|
||||
|
||||
m_Socket = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
memset(&m_SockAddr, 0, sizeof(SOCKADDR_IN));
|
||||
m_SockAddr.sin_family = AF_INET;
|
||||
m_SockAddr.sin_addr.s_addr = dwAddress;
|
||||
m_SockAddr.sin_port = htons(wPortIndex);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CNetDatagramSender::Send(const void * pBuffer, int iSize)
|
||||
{
|
||||
assert(isSocket());
|
||||
|
||||
int iSendingLength = sendto(m_Socket, (const char *)pBuffer, iSize, 0, (PSOCKADDR)&m_SockAddr, sizeof(SOCKADDR_IN));
|
||||
if (iSendingLength < 0)
|
||||
{
|
||||
Tracef("Failed sending packet\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CNetDatagramSender::isSocket()
|
||||
{
|
||||
return m_isSocket;
|
||||
}
|
||||
|
||||
CNetDatagramSender::CNetDatagramSender()
|
||||
{
|
||||
m_isSocket = FALSE;
|
||||
|
||||
m_dwAddress = 0;
|
||||
m_wPortIndex = 1000;
|
||||
|
||||
m_Socket = 0;
|
||||
memset(&m_SockAddr, 0, sizeof(SOCKADDR_IN));
|
||||
}
|
||||
|
||||
CNetDatagramSender::~CNetDatagramSender()
|
||||
{
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef VC_EXTRALEAN
|
||||
|
||||
class CNetDatagramSender
|
||||
{
|
||||
public:
|
||||
CNetDatagramSender();
|
||||
virtual ~CNetDatagramSender();
|
||||
|
||||
BOOL isSocket();
|
||||
|
||||
BOOL SetSocket(const char * c_szIP, WORD wPortIndex);
|
||||
BOOL SetSocket(DWORD dwAddress, WORD wPortIndex);
|
||||
BOOL Send(const void * pBuffer, int iSize);
|
||||
|
||||
protected:
|
||||
BOOL m_isSocket;
|
||||
|
||||
WORD m_dwAddress;
|
||||
WORD m_wPortIndex;
|
||||
|
||||
SOCKET m_Socket;
|
||||
SOCKADDR_IN m_SockAddr;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -7,14 +7,12 @@ class CNetworkPacketHeaderMap
|
||||
public:
|
||||
typedef struct SPacketType
|
||||
{
|
||||
SPacketType(int iSize = 0, bool bFlag = false)
|
||||
SPacketType(int iSize = 0)
|
||||
: iPacketSize(iSize)
|
||||
{
|
||||
iPacketSize = iSize;
|
||||
isDynamicSizePacket = bFlag;
|
||||
}
|
||||
|
||||
int iPacketSize;
|
||||
bool isDynamicSizePacket;
|
||||
int iPacketSize; // Expected/minimum packet size (actual size from wire length field)
|
||||
} TPacketType;
|
||||
|
||||
public:
|
||||
|
||||
@@ -7,6 +7,11 @@
|
||||
#define _PACKETDUMP
|
||||
#endif
|
||||
|
||||
#ifdef _PACKETDUMP
|
||||
#include <unordered_map>
|
||||
#include "../UserInterface/Packet.h"
|
||||
#endif
|
||||
|
||||
bool CNetworkStream::IsSecurityMode()
|
||||
{
|
||||
return m_secureCipher.IsActivated();
|
||||
@@ -14,58 +19,29 @@ bool CNetworkStream::IsSecurityMode()
|
||||
|
||||
void CNetworkStream::DecryptPendingRecvData()
|
||||
{
|
||||
int remaining = m_recvBufInputPos - m_recvBufOutputPos;
|
||||
size_t remaining = m_recvBuf.ReadableBytes();
|
||||
if (remaining > 0 && m_secureCipher.IsActivated())
|
||||
{
|
||||
m_secureCipher.DecryptInPlace(m_recvBuf + m_recvBufOutputPos, remaining);
|
||||
}
|
||||
m_secureCipher.DecryptInPlace(m_recvBuf.DataAt(m_recvBuf.ReadPos()), remaining);
|
||||
}
|
||||
|
||||
void CNetworkStream::SetRecvBufferSize(int recvBufSize)
|
||||
{
|
||||
if (m_recvBuf)
|
||||
{
|
||||
if (m_recvBufSize > recvBufSize)
|
||||
return;
|
||||
|
||||
delete [] m_recvBuf;
|
||||
}
|
||||
m_recvBufSize = recvBufSize;
|
||||
m_recvBuf = new char[m_recvBufSize];
|
||||
m_recvBuf.Reserve(static_cast<size_t>(recvBufSize));
|
||||
}
|
||||
|
||||
void CNetworkStream::SetSendBufferSize(int sendBufSize)
|
||||
{
|
||||
if (m_sendBuf)
|
||||
{
|
||||
if (m_sendBufSize > sendBufSize)
|
||||
return;
|
||||
|
||||
delete [] m_sendBuf;
|
||||
}
|
||||
|
||||
m_sendBufSize = sendBufSize;
|
||||
m_sendBuf = new char[m_sendBufSize];
|
||||
m_sendBuf.Reserve(static_cast<size_t>(sendBufSize));
|
||||
}
|
||||
|
||||
bool CNetworkStream::__RecvInternalBuffer()
|
||||
{
|
||||
if (m_recvBufOutputPos > 0)
|
||||
{
|
||||
int recvBufDataSize = m_recvBufInputPos - m_recvBufOutputPos;
|
||||
if (recvBufDataSize > 0)
|
||||
{
|
||||
memmove(m_recvBuf, m_recvBuf + m_recvBufOutputPos, recvBufDataSize);
|
||||
}
|
||||
m_recvBuf.EnsureWritable(4096);
|
||||
|
||||
m_recvBufInputPos -= m_recvBufOutputPos;
|
||||
m_recvBufOutputPos = 0;
|
||||
}
|
||||
|
||||
int restSize = m_recvBufSize - m_recvBufInputPos;
|
||||
int restSize = static_cast<int>(m_recvBuf.WritableBytes());
|
||||
if (restSize > 0)
|
||||
{
|
||||
int recvSize = recv(m_sock, m_recvBuf + m_recvBufInputPos, restSize, 0);
|
||||
int recvSize = recv(m_sock, reinterpret_cast<char*>(m_recvBuf.WritePtr()), restSize, 0);
|
||||
|
||||
if (recvSize < 0)
|
||||
{
|
||||
@@ -80,47 +56,33 @@ bool CNetworkStream::__RecvInternalBuffer()
|
||||
else
|
||||
{
|
||||
if (m_secureCipher.IsActivated())
|
||||
{
|
||||
m_secureCipher.DecryptInPlace(m_recvBuf + m_recvBufInputPos, recvSize);
|
||||
}
|
||||
m_recvBufInputPos += recvSize;
|
||||
m_secureCipher.DecryptInPlace(m_recvBuf.WritePtr(), recvSize);
|
||||
|
||||
m_recvBuf.CommitWrite(recvSize);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CNetworkStream::__SendInternalBuffer()
|
||||
{
|
||||
int dataSize = __GetSendBufferSize();
|
||||
if (dataSize <= 0)
|
||||
return true;
|
||||
|
||||
int sendSize = send(m_sock, m_sendBuf + m_sendBufOutputPos, dataSize, 0);
|
||||
int sendSize = send(m_sock, reinterpret_cast<const char*>(m_sendBuf.ReadPtr()), dataSize, 0);
|
||||
if (sendSize < 0)
|
||||
return false;
|
||||
|
||||
m_sendBufOutputPos += sendSize;
|
||||
__PopSendBuffer();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CNetworkStream::__PopSendBuffer()
|
||||
{
|
||||
if (m_sendBufOutputPos <= 0)
|
||||
return;
|
||||
|
||||
int sendBufDataSize = m_sendBufInputPos - m_sendBufOutputPos;
|
||||
|
||||
if (sendBufDataSize > 0)
|
||||
{
|
||||
memmove(m_sendBuf, m_sendBuf + m_sendBufOutputPos, sendBufDataSize);
|
||||
int err = WSAGetLastError();
|
||||
TraceError("__SendInternalBuffer: send() failed, sock=%llu, dataSize=%d, error=%d",
|
||||
(unsigned long long)m_sock, dataSize, err);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_sendBufInputPos = sendBufDataSize;
|
||||
m_sendBufOutputPos = 0;
|
||||
m_sendBuf.Discard(sendSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma warning(push)
|
||||
@@ -163,7 +125,7 @@ void CNetworkStream::Process()
|
||||
return;
|
||||
}
|
||||
|
||||
if (FD_ISSET(m_sock, &fdsSend) && (m_sendBufInputPos > m_sendBufOutputPos))
|
||||
if (FD_ISSET(m_sock, &fdsSend) && (m_sendBuf.ReadableBytes() > 0))
|
||||
{
|
||||
if (!__SendInternalBuffer())
|
||||
{
|
||||
@@ -206,24 +168,20 @@ void CNetworkStream::Disconnect()
|
||||
|
||||
void CNetworkStream::Clear()
|
||||
{
|
||||
if (m_sock == INVALID_SOCKET)
|
||||
return;
|
||||
|
||||
// Always clean cipher state (erase key material promptly)
|
||||
m_secureCipher.CleanUp();
|
||||
|
||||
closesocket(m_sock);
|
||||
m_sock = INVALID_SOCKET;
|
||||
if (m_sock != INVALID_SOCKET)
|
||||
{
|
||||
closesocket(m_sock);
|
||||
m_sock = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
m_isOnline = false;
|
||||
m_connectLimitTime = 0;
|
||||
|
||||
m_recvBufInputPos = 0;
|
||||
m_recvBufOutputPos = 0;
|
||||
|
||||
m_sendBufInputPos = 0;
|
||||
m_sendBufOutputPos = 0;
|
||||
|
||||
m_SequenceGenerator.seed(SEQUENCE_SEED);
|
||||
m_recvBuf.Clear();
|
||||
m_sendBuf.Clear();
|
||||
}
|
||||
|
||||
bool CNetworkStream::Connect(const CNetworkAddress& c_rkNetAddr, int limitSec)
|
||||
@@ -294,251 +252,229 @@ bool CNetworkStream::Connect(const char* c_szAddr, int port, int /*limitSec*/)
|
||||
|
||||
void CNetworkStream::ClearRecvBuffer()
|
||||
{
|
||||
m_recvBufOutputPos = m_recvBufInputPos = 0;
|
||||
m_recvBuf.Clear();
|
||||
}
|
||||
|
||||
int CNetworkStream::GetRecvBufferSize()
|
||||
{
|
||||
return m_recvBufInputPos - m_recvBufOutputPos;
|
||||
return static_cast<int>(m_recvBuf.ReadableBytes());
|
||||
}
|
||||
|
||||
bool CNetworkStream::Peek(int size)
|
||||
{
|
||||
if (GetRecvBufferSize() < size)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return m_recvBuf.HasBytes(static_cast<size_t>(size));
|
||||
}
|
||||
|
||||
bool CNetworkStream::Peek(int size, char * pDestBuf)
|
||||
bool CNetworkStream::Peek(int size, char* pDestBuf)
|
||||
{
|
||||
if (GetRecvBufferSize() < size)
|
||||
return false;
|
||||
|
||||
memcpy(pDestBuf, m_recvBuf + m_recvBufOutputPos, size);
|
||||
return true;
|
||||
return m_recvBuf.Peek(pDestBuf, static_cast<size_t>(size));
|
||||
}
|
||||
|
||||
|
||||
#ifdef _PACKETDUMP
|
||||
const char * GetSendHeaderName(BYTE header)
|
||||
|
||||
static const char* GetHeaderName(uint16_t header)
|
||||
{
|
||||
static bool b = false;
|
||||
static std::string stringList[UCHAR_MAX+1];
|
||||
if (b==false)
|
||||
{
|
||||
for (DWORD i = 0; i < UCHAR_MAX+1; i++)
|
||||
{
|
||||
char buf[10];
|
||||
sprintf(buf,"%d",i);
|
||||
stringList[i] = buf;
|
||||
}
|
||||
stringList[2] = "HEADER_CG_ATTACK";
|
||||
stringList[3] = "HEADER_CG_CHAT";
|
||||
stringList[4] = "HEADER_CG_PLAYER_CREATE";
|
||||
stringList[5] = "HEADER_CG_PLAYER_DESTROY";
|
||||
stringList[6] = "HEADER_CG_PLAYER_SELECT";
|
||||
stringList[7] = "HEADER_CG_CHARACTER_MOVE";
|
||||
stringList[8] = "HEADER_CG_SYNC_POSITION";
|
||||
stringList[9] = "HEADER_CG_DIRECT_ENTER";
|
||||
stringList[10] = "HEADER_CG_ENTERGAME";
|
||||
stringList[11] = "HEADER_CG_ITEM_USE";
|
||||
stringList[12] = "HEADER_CG_ITEM_DROP";
|
||||
stringList[13] = "HEADER_CG_ITEM_MOVE";
|
||||
stringList[15] = "HEADER_CG_ITEM_PICKUP";
|
||||
stringList[16] = "HEADER_CG_QUICKSLOT_ADD";
|
||||
stringList[17] = "HEADER_CG_QUICKSLOT_DEL";
|
||||
stringList[18] = "HEADER_CG_QUICKSLOT_SWAP";
|
||||
stringList[19] = "HEADER_CG_WHISPER";
|
||||
stringList[20] = "HEADER_CG_ITEM_DROP2";
|
||||
stringList[26] = "HEADER_CG_ON_CLICK";
|
||||
stringList[27] = "HEADER_CG_EXCHANGE";
|
||||
stringList[28] = "HEADER_CG_CHARACTER_POSITION";
|
||||
stringList[29] = "HEADER_CG_SCRIPT_ANSWER";
|
||||
stringList[30] = "HEADER_CG_QUEST_INPUT_STRING";
|
||||
stringList[31] = "HEADER_CG_QUEST_CONFIRM";
|
||||
stringList[41] = "HEADER_CG_PVP";
|
||||
stringList[50] = "HEADER_CG_SHOP";
|
||||
stringList[51] = "HEADER_CG_FLY_TARGETING";
|
||||
stringList[52] = "HEADER_CG_USE_SKILL";
|
||||
stringList[53] = "HEADER_CG_ADD_FLY_TARGETING";
|
||||
stringList[54] = "HEADER_CG_SHOOT";
|
||||
stringList[55] = "HEADER_CG_MYSHOP";
|
||||
stringList[60] = "HEADER_CG_ITEM_USE_TO_ITEM";
|
||||
stringList[61] = "HEADER_CG_TARGET";
|
||||
stringList[65] = "HEADER_CG_WARP";
|
||||
stringList[66] = "HEADER_CG_SCRIPT_BUTTON";
|
||||
stringList[67] = "HEADER_CG_MESSENGER";
|
||||
stringList[69] = "HEADER_CG_MALL_CHECKOUT";
|
||||
stringList[70] = "HEADER_CG_SAFEBOX_CHECKIN";
|
||||
stringList[71] = "HEADER_CG_SAFEBOX_CHECKOUT";
|
||||
stringList[72] = "HEADER_CG_PARTY_INVITE";
|
||||
stringList[73] = "HEADER_CG_PARTY_INVITE_ANSWER";
|
||||
stringList[74] = "HEADER_CG_PARTY_REMOVE";
|
||||
stringList[75] = "HEADER_CG_PARTY_SET_STATE";
|
||||
stringList[76] = "HEADER_CG_PARTY_USE_SKILL";
|
||||
stringList[77] = "HEADER_CG_SAFEBOX_ITEM_MOVE";
|
||||
stringList[78] = "HEADER_CG_PARTY_PARAMETER";
|
||||
stringList[80] = "HEADER_CG_GUILD";
|
||||
stringList[81] = "HEADER_CG_ANSWER_MAKE_GUILD";
|
||||
stringList[82] = "HEADER_CG_FISHING";
|
||||
stringList[83] = "HEADER_CG_GIVE_ITEM";
|
||||
stringList[90] = "HEADER_CG_EMPIRE";
|
||||
stringList[96] = "HEADER_CG_REFINE";
|
||||
stringList[100] = "HEADER_CG_MARK_LOGIN";
|
||||
stringList[101] = "HEADER_CG_MARK_CRCLIST";
|
||||
stringList[102] = "HEADER_CG_MARK_UPLOAD";
|
||||
stringList[103] = "HEADER_CG_CRC_REPORT";
|
||||
stringList[105] = "HEADER_CG_HACK";
|
||||
stringList[106] = "HEADER_CG_CHANGE_NAME";
|
||||
stringList[107] = "HEADER_CG_SMS";
|
||||
stringList[108] = "HEADER_CG_MATRIX_CARD";
|
||||
stringList[109] = "HEADER_CG_LOGIN2";
|
||||
stringList[110] = "HEADER_CG_DUNGEON";
|
||||
stringList[111] = "HEADER_CG_LOGIN3";
|
||||
stringList[112] = "HEADER_CG_GUILD_SYMBOL_UPLOAD";
|
||||
stringList[113] = "HEADER_CG_GUILD_SYMBOL_CRC";
|
||||
stringList[114] = "HEADER_CG_SCRIPT_SELECT_ITEM";
|
||||
stringList[0xf9] = "HEADER_CG_KEY_RESPONSE";
|
||||
stringList[0xfc] = "HEADER_CG_TIME_SYNC";
|
||||
stringList[0xfd] = "HEADER_CG_CLIENT_VERSION";
|
||||
stringList[0xfe] = "HEADER_CG_PONG";
|
||||
stringList[0xff] = "HEADER_CG_HANDSHAKE";
|
||||
}
|
||||
return stringList[header].c_str();
|
||||
}
|
||||
static const std::unordered_map<uint16_t, const char*> s_headerNames = {
|
||||
// Control
|
||||
{ CG::PONG, "CG_PONG" },
|
||||
{ GC::PING, "GC_PING" },
|
||||
{ GC::PHASE, "GC_PHASE" },
|
||||
{ CG::KEY_RESPONSE, "CG_KEY_RESPONSE" },
|
||||
{ GC::KEY_CHALLENGE, "GC_KEY_CHALLENGE" },
|
||||
{ GC::KEY_COMPLETE, "GC_KEY_COMPLETE" },
|
||||
{ CG::CLIENT_VERSION, "CG_CLIENT_VERSION" },
|
||||
{ CG::STATE_CHECKER, "CG_STATE_CHECKER" },
|
||||
{ GC::RESPOND_CHANNELSTATUS, "GC_RESPOND_CHANNELSTATUS" },
|
||||
{ CG::TEXT, "CG_TEXT" },
|
||||
// Authentication
|
||||
{ CG::LOGIN2, "CG_LOGIN2" },
|
||||
{ CG::LOGIN3, "CG_LOGIN3" },
|
||||
{ CG::LOGIN_SECURE, "CG_LOGIN_SECURE" },
|
||||
{ GC::LOGIN_SUCCESS3, "GC_LOGIN_SUCCESS3" },
|
||||
{ GC::LOGIN_SUCCESS4, "GC_LOGIN_SUCCESS4" },
|
||||
{ GC::LOGIN_FAILURE, "GC_LOGIN_FAILURE" },
|
||||
{ GC::LOGIN_KEY, "GC_LOGIN_KEY" },
|
||||
{ GC::AUTH_SUCCESS, "GC_AUTH_SUCCESS" },
|
||||
{ GC::EMPIRE, "GC_EMPIRE" },
|
||||
{ CG::EMPIRE, "CG_EMPIRE" },
|
||||
{ CG::CHANGE_NAME, "CG_CHANGE_NAME" },
|
||||
{ GC::CHANGE_NAME, "GC_CHANGE_NAME" },
|
||||
// Character
|
||||
{ CG::CHARACTER_CREATE, "CG_CHARACTER_CREATE" },
|
||||
{ CG::CHARACTER_DELETE, "CG_CHARACTER_DELETE" },
|
||||
{ CG::CHARACTER_SELECT, "CG_CHARACTER_SELECT" },
|
||||
{ CG::ENTERGAME, "CG_ENTERGAME" },
|
||||
{ GC::CHARACTER_ADD, "GC_CHARACTER_ADD" },
|
||||
{ GC::CHARACTER_ADD2, "GC_CHARACTER_ADD2" },
|
||||
{ GC::CHAR_ADDITIONAL_INFO, "GC_CHAR_ADDITIONAL_INFO" },
|
||||
{ GC::CHARACTER_DEL, "GC_CHARACTER_DEL" },
|
||||
{ GC::CHARACTER_UPDATE, "GC_CHARACTER_UPDATE" },
|
||||
{ GC::CHARACTER_UPDATE2, "GC_CHARACTER_UPDATE2" },
|
||||
{ GC::CHARACTER_POSITION, "GC_CHARACTER_POSITION" },
|
||||
{ GC::PLAYER_CREATE_SUCCESS, "GC_PLAYER_CREATE_SUCCESS" },
|
||||
{ GC::PLAYER_CREATE_FAILURE, "GC_PLAYER_CREATE_FAILURE" },
|
||||
{ GC::PLAYER_DELETE_SUCCESS, "GC_PLAYER_DELETE_SUCCESS" },
|
||||
{ GC::PLAYER_DELETE_WRONG_SOCIAL_ID, "GC_PLAYER_DELETE_WRONG_SOCIAL_ID" },
|
||||
{ GC::MAIN_CHARACTER, "GC_MAIN_CHARACTER" },
|
||||
{ GC::PLAYER_POINTS, "GC_PLAYER_POINTS" },
|
||||
{ GC::PLAYER_POINT_CHANGE, "GC_PLAYER_POINT_CHANGE" },
|
||||
{ GC::STUN, "GC_STUN" },
|
||||
{ GC::DEAD, "GC_DEAD" },
|
||||
{ GC::CHANGE_SPEED, "GC_CHANGE_SPEED" },
|
||||
{ GC::WALK_MODE, "GC_WALK_MODE" },
|
||||
{ GC::SKILL_LEVEL, "GC_SKILL_LEVEL" },
|
||||
{ GC::SKILL_LEVEL_NEW, "GC_SKILL_LEVEL_NEW" },
|
||||
{ GC::SKILL_COOLTIME_END, "GC_SKILL_COOLTIME_END" },
|
||||
{ GC::CHANGE_SKILL_GROUP, "GC_CHANGE_SKILL_GROUP" },
|
||||
{ GC::VIEW_EQUIP, "GC_VIEW_EQUIP" },
|
||||
// Movement
|
||||
{ CG::MOVE, "CG_MOVE" },
|
||||
{ GC::MOVE, "GC_MOVE" },
|
||||
{ CG::SYNC_POSITION, "CG_SYNC_POSITION" },
|
||||
{ GC::SYNC_POSITION, "GC_SYNC_POSITION" },
|
||||
{ CG::WARP, "CG_WARP" },
|
||||
{ GC::WARP, "GC_WARP" },
|
||||
{ GC::MOTION, "GC_MOTION" },
|
||||
{ GC::DIG_MOTION, "GC_DIG_MOTION" },
|
||||
// Combat
|
||||
{ CG::ATTACK, "CG_ATTACK" },
|
||||
{ CG::USE_SKILL, "CG_USE_SKILL" },
|
||||
{ CG::SHOOT, "CG_SHOOT" },
|
||||
{ CG::FLY_TARGETING, "CG_FLY_TARGETING" },
|
||||
{ CG::ADD_FLY_TARGETING, "CG_ADD_FLY_TARGETING" },
|
||||
{ GC::DAMAGE_INFO, "GC_DAMAGE_INFO" },
|
||||
{ GC::FLY_TARGETING, "GC_FLY_TARGETING" },
|
||||
{ GC::ADD_FLY_TARGETING, "GC_ADD_FLY_TARGETING" },
|
||||
{ GC::CREATE_FLY, "GC_CREATE_FLY" },
|
||||
{ GC::PVP, "GC_PVP" },
|
||||
{ GC::DUEL_START, "GC_DUEL_START" },
|
||||
// Items
|
||||
{ CG::ITEM_USE, "CG_ITEM_USE" },
|
||||
{ CG::ITEM_DROP, "CG_ITEM_DROP" },
|
||||
{ CG::ITEM_DROP2, "CG_ITEM_DROP2" },
|
||||
{ CG::ITEM_MOVE, "CG_ITEM_MOVE" },
|
||||
{ CG::ITEM_PICKUP, "CG_ITEM_PICKUP" },
|
||||
{ CG::ITEM_USE_TO_ITEM, "CG_ITEM_USE_TO_ITEM" },
|
||||
{ CG::ITEM_GIVE, "CG_ITEM_GIVE" },
|
||||
{ CG::EXCHANGE, "CG_EXCHANGE" },
|
||||
{ CG::QUICKSLOT_ADD, "CG_QUICKSLOT_ADD" },
|
||||
{ CG::QUICKSLOT_DEL, "CG_QUICKSLOT_DEL" },
|
||||
{ CG::QUICKSLOT_SWAP, "CG_QUICKSLOT_SWAP" },
|
||||
{ CG::REFINE, "CG_REFINE" },
|
||||
{ CG::DRAGON_SOUL_REFINE, "CG_DRAGON_SOUL_REFINE" },
|
||||
{ GC::ITEM_DEL, "GC_ITEM_DEL" },
|
||||
{ GC::ITEM_SET, "GC_ITEM_SET" },
|
||||
{ GC::ITEM_USE, "GC_ITEM_USE" },
|
||||
{ GC::ITEM_DROP, "GC_ITEM_DROP" },
|
||||
{ GC::ITEM_UPDATE, "GC_ITEM_UPDATE" },
|
||||
{ GC::ITEM_GROUND_ADD, "GC_ITEM_GROUND_ADD" },
|
||||
{ GC::ITEM_GROUND_DEL, "GC_ITEM_GROUND_DEL" },
|
||||
{ GC::ITEM_OWNERSHIP, "GC_ITEM_OWNERSHIP" },
|
||||
{ GC::ITEM_GET, "GC_ITEM_GET" },
|
||||
{ GC::QUICKSLOT_ADD, "GC_QUICKSLOT_ADD" },
|
||||
{ GC::QUICKSLOT_DEL, "GC_QUICKSLOT_DEL" },
|
||||
{ GC::QUICKSLOT_SWAP, "GC_QUICKSLOT_SWAP" },
|
||||
{ GC::EXCHANGE, "GC_EXCHANGE" },
|
||||
{ GC::REFINE_INFORMATION, "GC_REFINE_INFORMATION" },
|
||||
{ GC::DRAGON_SOUL_REFINE, "GC_DRAGON_SOUL_REFINE" },
|
||||
// Chat
|
||||
{ CG::CHAT, "CG_CHAT" },
|
||||
{ CG::WHISPER, "CG_WHISPER" },
|
||||
{ GC::CHAT, "GC_CHAT" },
|
||||
{ GC::WHISPER, "GC_WHISPER" },
|
||||
// Social
|
||||
{ CG::PARTY_INVITE, "CG_PARTY_INVITE" },
|
||||
{ CG::PARTY_INVITE_ANSWER, "CG_PARTY_INVITE_ANSWER" },
|
||||
{ CG::PARTY_REMOVE, "CG_PARTY_REMOVE" },
|
||||
{ CG::PARTY_SET_STATE, "CG_PARTY_SET_STATE" },
|
||||
{ CG::PARTY_USE_SKILL, "CG_PARTY_USE_SKILL" },
|
||||
{ CG::PARTY_PARAMETER, "CG_PARTY_PARAMETER" },
|
||||
{ GC::PARTY_INVITE, "GC_PARTY_INVITE" },
|
||||
{ GC::PARTY_ADD, "GC_PARTY_ADD" },
|
||||
{ GC::PARTY_UPDATE, "GC_PARTY_UPDATE" },
|
||||
{ GC::PARTY_REMOVE, "GC_PARTY_REMOVE" },
|
||||
{ GC::PARTY_LINK, "GC_PARTY_LINK" },
|
||||
{ GC::PARTY_UNLINK, "GC_PARTY_UNLINK" },
|
||||
{ GC::PARTY_PARAMETER, "GC_PARTY_PARAMETER" },
|
||||
{ CG::GUILD, "CG_GUILD" },
|
||||
{ CG::ANSWER_MAKE_GUILD, "CG_ANSWER_MAKE_GUILD" },
|
||||
{ CG::GUILD_SYMBOL_UPLOAD, "CG_GUILD_SYMBOL_UPLOAD" },
|
||||
{ CG::SYMBOL_CRC, "CG_SYMBOL_CRC" },
|
||||
{ GC::GUILD, "GC_GUILD" },
|
||||
{ GC::REQUEST_MAKE_GUILD, "GC_REQUEST_MAKE_GUILD" },
|
||||
{ GC::SYMBOL_DATA, "GC_SYMBOL_DATA" },
|
||||
{ CG::MESSENGER, "CG_MESSENGER" },
|
||||
{ GC::MESSENGER, "GC_MESSENGER" },
|
||||
{ GC::LOVER_INFO, "GC_LOVER_INFO" },
|
||||
{ GC::LOVE_POINT_UPDATE, "GC_LOVE_POINT_UPDATE" },
|
||||
// Shop / Trade
|
||||
{ CG::SHOP, "CG_SHOP" },
|
||||
{ CG::MYSHOP, "CG_MYSHOP" },
|
||||
{ GC::SHOP, "GC_SHOP" },
|
||||
{ GC::SHOP_SIGN, "GC_SHOP_SIGN" },
|
||||
{ CG::SAFEBOX_CHECKIN, "CG_SAFEBOX_CHECKIN" },
|
||||
{ CG::SAFEBOX_CHECKOUT, "CG_SAFEBOX_CHECKOUT" },
|
||||
{ CG::SAFEBOX_ITEM_MOVE, "CG_SAFEBOX_ITEM_MOVE" },
|
||||
{ GC::SAFEBOX_SET, "GC_SAFEBOX_SET" },
|
||||
{ GC::SAFEBOX_DEL, "GC_SAFEBOX_DEL" },
|
||||
{ GC::SAFEBOX_WRONG_PASSWORD, "GC_SAFEBOX_WRONG_PASSWORD" },
|
||||
{ GC::SAFEBOX_SIZE, "GC_SAFEBOX_SIZE" },
|
||||
{ GC::SAFEBOX_MONEY_CHANGE, "GC_SAFEBOX_MONEY_CHANGE" },
|
||||
{ CG::MALL_CHECKOUT, "CG_MALL_CHECKOUT" },
|
||||
{ GC::MALL_OPEN, "GC_MALL_OPEN" },
|
||||
{ GC::MALL_SET, "GC_MALL_SET" },
|
||||
{ GC::MALL_DEL, "GC_MALL_DEL" },
|
||||
// Quest
|
||||
{ CG::SCRIPT_ANSWER, "CG_SCRIPT_ANSWER" },
|
||||
{ CG::SCRIPT_BUTTON, "CG_SCRIPT_BUTTON" },
|
||||
{ CG::SCRIPT_SELECT_ITEM, "CG_SCRIPT_SELECT_ITEM" },
|
||||
{ CG::QUEST_INPUT_STRING, "CG_QUEST_INPUT_STRING" },
|
||||
{ CG::QUEST_CONFIRM, "CG_QUEST_CONFIRM" },
|
||||
{ CG::QUEST_CANCEL, "CG_QUEST_CANCEL" },
|
||||
{ GC::SCRIPT, "GC_SCRIPT" },
|
||||
{ GC::QUEST_CONFIRM, "GC_QUEST_CONFIRM" },
|
||||
{ GC::QUEST_INFO, "GC_QUEST_INFO" },
|
||||
// UI / Effects
|
||||
{ CG::TARGET, "CG_TARGET" },
|
||||
{ CG::ON_CLICK, "CG_ON_CLICK" },
|
||||
{ GC::TARGET, "GC_TARGET" },
|
||||
{ GC::TARGET_UPDATE, "GC_TARGET_UPDATE" },
|
||||
{ GC::TARGET_DELETE, "GC_TARGET_DELETE" },
|
||||
{ GC::TARGET_CREATE_NEW, "GC_TARGET_CREATE_NEW" },
|
||||
{ GC::AFFECT_ADD, "GC_AFFECT_ADD" },
|
||||
{ GC::AFFECT_REMOVE, "GC_AFFECT_REMOVE" },
|
||||
{ GC::SEPCIAL_EFFECT, "GC_SPECIAL_EFFECT" },
|
||||
{ GC::SPECIFIC_EFFECT, "GC_SPECIFIC_EFFECT" },
|
||||
{ GC::MOUNT, "GC_MOUNT" },
|
||||
{ GC::OWNERSHIP, "GC_OWNERSHIP" },
|
||||
{ GC::NPC_POSITION, "GC_NPC_POSITION" },
|
||||
{ CG::CHARACTER_POSITION, "CG_CHARACTER_POSITION" },
|
||||
// World
|
||||
{ CG::FISHING, "CG_FISHING" },
|
||||
{ CG::DUNGEON, "CG_DUNGEON" },
|
||||
{ CG::HACK, "CG_HACK" },
|
||||
{ GC::FISHING, "GC_FISHING" },
|
||||
{ GC::DUNGEON, "GC_DUNGEON" },
|
||||
{ GC::LAND_LIST, "GC_LAND_LIST" },
|
||||
{ GC::TIME, "GC_TIME" },
|
||||
{ GC::CHANNEL, "GC_CHANNEL" },
|
||||
{ GC::MARK_UPDATE, "GC_MARK_UPDATE" },
|
||||
// Guild Marks
|
||||
{ CG::MARK_LOGIN, "CG_MARK_LOGIN" },
|
||||
{ CG::MARK_CRCLIST, "CG_MARK_CRCLIST" },
|
||||
{ CG::MARK_UPLOAD, "CG_MARK_UPLOAD" },
|
||||
{ CG::MARK_IDXLIST, "CG_MARK_IDXLIST" },
|
||||
{ GC::MARK_BLOCK, "GC_MARK_BLOCK" },
|
||||
{ GC::MARK_IDXLIST, "GC_MARK_IDXLIST" },
|
||||
};
|
||||
|
||||
const char * GetRecvHeaderName(BYTE header)
|
||||
{
|
||||
static bool b = false;
|
||||
static std::string stringList[UCHAR_MAX+1];
|
||||
if (b==false)
|
||||
{
|
||||
for (DWORD i = 0; i < UCHAR_MAX+1; i++)
|
||||
{
|
||||
char buf[10];
|
||||
sprintf(buf,"%d",i);
|
||||
stringList[i] = buf;
|
||||
}
|
||||
stringList[1] = "HEADER_GC_CHARACTER_ADD";
|
||||
stringList[2] = "HEADER_GC_CHARACTER_DEL";
|
||||
stringList[3] = "HEADER_GC_CHARACTER_MOVE";
|
||||
stringList[4] = "HEADER_GC_CHAT";
|
||||
stringList[5] = "HEADER_GC_SYNC_POSITION";
|
||||
stringList[6] = "HEADER_GC_LOGIN_SUCCESS";
|
||||
stringList[7] = "HEADER_GC_LOGIN_FAILURE";
|
||||
stringList[8] = "HEADER_GC_PLAYER_CREATE_SUCCESS";
|
||||
stringList[9] = "HEADER_GC_PLAYER_CREATE_FAILURE";
|
||||
stringList[10] = "HEADER_GC_PLAYER_DELETE_SUCCESS";
|
||||
stringList[11] = "HEADER_GC_PLAYER_DELETE_WRONG_SOCIAL_ID";
|
||||
auto it = s_headerNames.find(header);
|
||||
if (it != s_headerNames.end())
|
||||
return it->second;
|
||||
|
||||
stringList[13] = "HEADER_GC_STUN";
|
||||
stringList[14] = "HEADER_GC_DEAD";
|
||||
stringList[15] = "HEADER_GC_MAIN_CHARACTER";
|
||||
stringList[16] = "HEADER_GC_PLAYER_POINTS";
|
||||
stringList[17] = "HEADER_GC_PLAYER_POINT_CHANGE";
|
||||
stringList[18] = "HEADER_GC_CHANGE_SPEED";
|
||||
stringList[19] = "HEADER_GC_CHARACTER_UPDATE";
|
||||
stringList[20] = "HEADER_GC_ITEM_DEL";
|
||||
stringList[21] = "HEADER_GC_ITEM_SET";
|
||||
stringList[22] = "HEADER_GC_ITEM_USE";
|
||||
stringList[23] = "HEADER_GC_ITEM_DROP";
|
||||
stringList[25] = "HEADER_GC_ITEM_UPDATE";
|
||||
stringList[26] = "HEADER_GC_ITEM_GROUND_ADD";
|
||||
stringList[27] = "HEADER_GC_ITEM_GROUND_DEL";
|
||||
stringList[28] = "HEADER_GC_QUICKSLOT_ADD";
|
||||
stringList[29] = "HEADER_GC_QUICKSLOT_DEL";
|
||||
stringList[30] = "HEADER_GC_QUICKSLOT_SWAP";
|
||||
stringList[31] = "HEADER_GC_ITEM_OWNERSHIP";
|
||||
stringList[33] = "HEADER_GC_ITEM_UNBIND_TIME";
|
||||
stringList[34] = "HEADER_GC_WHISPER";
|
||||
stringList[35] = "HEADER_GC_ALERT";
|
||||
stringList[36] = "HEADER_GC_MOTION";
|
||||
stringList[38] = "HEADER_GC_SHOP";
|
||||
stringList[39] = "HEADER_GC_SHOP_SIGN";
|
||||
stringList[41] = "HEADER_GC_PVP";
|
||||
stringList[42] = "HEADER_GC_EXCHANGE";
|
||||
stringList[43] = "HEADER_GC_CHARACTER_POSITION";
|
||||
stringList[44] = "HEADER_GC_PING";
|
||||
stringList[45] = "HEADER_GC_SCRIPT";
|
||||
stringList[46] = "HEADER_GC_QUEST_CONFIRM";
|
||||
|
||||
stringList[61] = "HEADER_GC_MOUNT";
|
||||
stringList[62] = "HEADER_GC_OWNERSHIP";
|
||||
stringList[63] = "HEADER_GC_TARGET";
|
||||
stringList[65] = "HEADER_GC_WARP";
|
||||
stringList[69] = "HEADER_GC_ADD_FLY_TARGETING";
|
||||
|
||||
stringList[70] = "HEADER_GC_CREATE_FLY";
|
||||
stringList[71] = "HEADER_GC_FLY_TARGETING";
|
||||
stringList[72] = "HEADER_GC_SKILL_LEVEL";
|
||||
stringList[73] = "HEADER_GC_SKILL_COOLTIME_END";
|
||||
stringList[74] = "HEADER_GC_MESSENGER";
|
||||
stringList[75] = "HEADER_GC_GUILD";
|
||||
stringList[76] = "HEADER_GC_SKILL_LEVEL_NEW";
|
||||
stringList[77] = "HEADER_GC_PARTY_INVITE";
|
||||
stringList[78] = "HEADER_GC_PARTY_ADD";
|
||||
stringList[79] = "HEADER_GC_PARTY_UPDATE";
|
||||
stringList[80] = "HEADER_GC_PARTY_REMOVE";
|
||||
stringList[81] = "HEADER_GC_QUEST_INFO";
|
||||
stringList[82] = "HEADER_GC_REQUEST_MAKE_GUILD";
|
||||
stringList[83] = "HEADER_GC_PARTY_PARAMETER";
|
||||
stringList[84] = "HEADER_GC_SAFEBOX_MONEY_CHANGE";
|
||||
stringList[85] = "HEADER_GC_SAFEBOX_SET";
|
||||
stringList[86] = "HEADER_GC_SAFEBOX_DEL";
|
||||
stringList[87] = "HEADER_GC_SAFEBOX_WRONG_PASSWORD";
|
||||
stringList[88] = "HEADER_GC_SAFEBOX_SIZE";
|
||||
stringList[89] = "HEADER_GC_FISHING";
|
||||
stringList[90] = "HEADER_GC_EMPIRE";
|
||||
stringList[91] = "HEADER_GC_PARTY_LINK";
|
||||
stringList[92] = "HEADER_GC_PARTY_UNLINK";
|
||||
|
||||
stringList[95] = "HEADER_GC_REFINE_INFORMATION";
|
||||
stringList[96] = "HEADER_GC_OBSERVER_ADD";
|
||||
stringList[97] = "HEADER_GC_OBSERVER_REMOVE";
|
||||
stringList[98] = "HEADER_GC_OBSERVER_MOVE";
|
||||
stringList[99] = "HEADER_GC_VIEW_EQUIP";
|
||||
stringList[100] = "HEADER_GC_MARK_BLOCK";
|
||||
stringList[101] = "HEADER_GC_MARK_DIFF_DATA";
|
||||
|
||||
stringList[106] = "HEADER_GC_TIME";
|
||||
stringList[107] = "HEADER_GC_CHANGE_NAME";
|
||||
stringList[110] = "HEADER_GC_DUNGEON";
|
||||
stringList[111] = "HEADER_GC_WALK_MODE";
|
||||
stringList[112] = "HEADER_GC_CHANGE_SKILL_GROUP";
|
||||
stringList[113] = "HEADER_GC_MAIN_CHARACTER_NEW";
|
||||
stringList[114] = "HEADER_GC_USE_POTION";
|
||||
stringList[115] = "HEADER_GC_NPC_POSITION";
|
||||
stringList[116] = "HEADER_GC_MATRIX_CARD";
|
||||
stringList[117] = "HEADER_GC_CHARACTER_UPDATE2";
|
||||
stringList[118] = "HEADER_GC_LOGIN_KEY";
|
||||
stringList[119] = "HEADER_GC_REFINE_INFORMATION_NEW";
|
||||
stringList[120] = "HEADER_GC_CHARACTER_ADD2";
|
||||
stringList[121] = "HEADER_GC_CHANNEL";
|
||||
stringList[122] = "HEADER_GC_MALL_OPEN";
|
||||
stringList[123] = "HEADER_GC_TARGET_UPDATE";
|
||||
stringList[124] = "HEADER_GC_TARGET_DELETE";
|
||||
stringList[125] = "HEADER_GC_TARGET_CREATE_NEW";
|
||||
stringList[126] = "HEADER_GC_AFFECT_ADD";
|
||||
stringList[127] = "HEADER_GC_AFFECT_REMOVE";
|
||||
stringList[128] = "HEADER_GC_MALL_SET";
|
||||
stringList[129] = "HEADER_GC_MALL_DEL";
|
||||
stringList[130] = "HEADER_GC_LAND_LIST";
|
||||
stringList[131] = "HEADER_GC_LOVER_INFO";
|
||||
stringList[132] = "HEADER_GC_LOVE_POINT_UPDATE";
|
||||
stringList[133] = "HEADER_GC_GUILD_SYMBOL_DATA";
|
||||
stringList[134] = "HEADER_GC_DIG_MOTION";
|
||||
stringList[135] = "HEADER_GC_DAMAGE_INFO";
|
||||
stringList[136] = "HEADER_GC_CHAR_ADDITIONAL_INFO";
|
||||
stringList[150] = "HEADER_GC_AUTH_SUCCESS";
|
||||
stringList[0xf7] = "HEADER_GC_KEY_COMPLETE";
|
||||
stringList[0xf8] = "HEADER_GC_KEY_CHALLENGE";
|
||||
stringList[0xfc] = "HEADER_GC_HANDSHAKE_OK";
|
||||
stringList[0xfd] = "HEADER_GC_PHASE";
|
||||
stringList[0xfe] = "HEADER_GC_BINDUDP";
|
||||
stringList[0xff] = "HEADER_GC_HANDSHAKE";
|
||||
}
|
||||
return stringList[header].c_str();
|
||||
static thread_local char buf[16];
|
||||
snprintf(buf, sizeof(buf), "0x%04X", header);
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -548,7 +484,7 @@ bool CNetworkStream::Recv(int size)
|
||||
if (!Peek(size))
|
||||
return false;
|
||||
|
||||
m_recvBufOutputPos += size;
|
||||
m_recvBuf.Discard(static_cast<size_t>(size));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -575,46 +511,61 @@ bool CNetworkStream::Recv(int size, char * pDestBuf)
|
||||
return false;
|
||||
|
||||
#ifdef _PACKETDUMP
|
||||
if (*pDestBuf != 0)
|
||||
if (size >= 2)
|
||||
{
|
||||
const auto kHeader = *pDestBuf;
|
||||
TraceError("RECV< %s %u(0x%X) (%d)", GetRecvHeaderName(kHeader), kHeader, kHeader, size);
|
||||
const uint16_t kHeader = *reinterpret_cast<const uint16_t*>(pDestBuf);
|
||||
TraceError("RECV< %s 0x%04X (%d bytes)", GetHeaderName(kHeader), kHeader, size);
|
||||
|
||||
const auto contents = dump_hex(reinterpret_cast<const uint8_t*>(pDestBuf), size);
|
||||
TraceError("%s", contents.c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
m_recvBufOutputPos += size;
|
||||
m_recvBuf.Discard(static_cast<size_t>(size));
|
||||
return true;
|
||||
}
|
||||
|
||||
int CNetworkStream::__GetSendBufferSize()
|
||||
{
|
||||
return m_sendBufInputPos - m_sendBufOutputPos;
|
||||
return static_cast<int>(m_sendBuf.ReadableBytes());
|
||||
}
|
||||
|
||||
|
||||
bool CNetworkStream::Send(int size, const char * pSrcBuf)
|
||||
{
|
||||
int sendBufRestSize = m_sendBufSize - m_sendBufInputPos;
|
||||
if ((size + 1) > sendBufRestSize)
|
||||
return false;
|
||||
|
||||
memcpy(m_sendBuf + m_sendBufInputPos, pSrcBuf, size);
|
||||
|
||||
if (m_secureCipher.IsActivated())
|
||||
// Track packet sends: detect new packet start by checking [header:2][length:2] framing
|
||||
if (size >= 4)
|
||||
{
|
||||
m_secureCipher.EncryptInPlace(m_sendBuf + m_sendBufInputPos, size);
|
||||
const uint16_t wHeader = *reinterpret_cast<const uint16_t*>(pSrcBuf);
|
||||
const uint16_t wLength = *reinterpret_cast<const uint16_t*>(pSrcBuf + 2);
|
||||
|
||||
if (wHeader != 0 && wLength >= 4)
|
||||
{
|
||||
auto& e = m_aSentPacketLog[m_dwSentPacketSeq % SENT_PACKET_LOG_SIZE];
|
||||
e.seq = m_dwSentPacketSeq;
|
||||
e.header = wHeader;
|
||||
e.length = wLength;
|
||||
m_dwSentPacketSeq++;
|
||||
}
|
||||
}
|
||||
|
||||
m_sendBufInputPos += size;
|
||||
m_sendBuf.EnsureWritable(static_cast<size_t>(size));
|
||||
|
||||
// Copy data to send buffer
|
||||
std::memcpy(m_sendBuf.WritePtr(), pSrcBuf, static_cast<size_t>(size));
|
||||
|
||||
// Encrypt in-place before committing
|
||||
if (m_secureCipher.IsActivated())
|
||||
{
|
||||
m_secureCipher.EncryptInPlace(m_sendBuf.WritePtr(), size);
|
||||
}
|
||||
|
||||
m_sendBuf.CommitWrite(static_cast<size_t>(size));
|
||||
|
||||
#ifdef _PACKETDUMP
|
||||
if (*pSrcBuf != 0)
|
||||
if (size >= 2)
|
||||
{
|
||||
const auto kHeader = *pSrcBuf;
|
||||
TraceError("SEND> %s %u(0x%X) (%d)", GetSendHeaderName(kHeader), kHeader, kHeader, size);
|
||||
const uint16_t kHeader = *reinterpret_cast<const uint16_t*>(pSrcBuf);
|
||||
TraceError("SEND> %s 0x%04X (%d bytes)", GetHeaderName(kHeader), kHeader, size);
|
||||
|
||||
const auto contents = dump_hex(reinterpret_cast<const uint8_t*>(pSrcBuf), size);
|
||||
TraceError("%s", contents.c_str());
|
||||
@@ -652,25 +603,6 @@ bool CNetworkStream::IsOnline()
|
||||
return m_isOnline;
|
||||
}
|
||||
|
||||
void CNetworkStream::SetPacketSequenceMode(bool isOn)
|
||||
{
|
||||
m_bUseSequence = isOn;
|
||||
}
|
||||
|
||||
bool CNetworkStream::SendSequence()
|
||||
{
|
||||
if (!m_bUseSequence)
|
||||
return true;
|
||||
|
||||
BYTE bSeq = m_SequenceGenerator(UINT8_MAX + 1);
|
||||
return Send(sizeof(BYTE), &bSeq);
|
||||
}
|
||||
|
||||
uint8_t CNetworkStream::GetNextSequence()
|
||||
{
|
||||
return m_SequenceGenerator(UINT8_MAX + 1);
|
||||
}
|
||||
|
||||
bool CNetworkStream::OnProcess()
|
||||
{
|
||||
return true;
|
||||
@@ -694,6 +626,96 @@ void CNetworkStream::OnConnectFailure()
|
||||
Tracen("Failed to connect.");
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Control-plane packet handlers (shared by all connection types)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
bool CNetworkStream::RecvKeyChallenge()
|
||||
{
|
||||
TPacketGCKeyChallenge packet;
|
||||
if (!Recv(sizeof(packet), &packet))
|
||||
return false;
|
||||
|
||||
Tracen("KEY_CHALLENGE RECV");
|
||||
|
||||
SecureCipher& cipher = GetSecureCipher();
|
||||
if (!cipher.Initialize())
|
||||
{
|
||||
TraceError("SecureCipher initialization failed");
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!cipher.ComputeClientKeys(packet.server_pk))
|
||||
{
|
||||
TraceError("Failed to compute client session keys");
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
TPacketCGKeyResponse response;
|
||||
response.header = CG::KEY_RESPONSE;
|
||||
response.length = sizeof(response);
|
||||
cipher.GetPublicKey(response.client_pk);
|
||||
cipher.ComputeChallengeResponse(packet.challenge, response.challenge_response);
|
||||
|
||||
if (!Send(sizeof(response), &response))
|
||||
{
|
||||
TraceError("Failed to send key response");
|
||||
return false;
|
||||
}
|
||||
|
||||
Tracen("KEY_RESPONSE SENT");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CNetworkStream::RecvKeyComplete()
|
||||
{
|
||||
TPacketGCKeyComplete packet;
|
||||
if (!Recv(sizeof(packet), &packet))
|
||||
return false;
|
||||
|
||||
SecureCipher& cipher = GetSecureCipher();
|
||||
|
||||
uint8_t decrypted_token[SecureCipher::SESSION_TOKEN_SIZE];
|
||||
if (!cipher.DecryptToken(packet.encrypted_token, sizeof(packet.encrypted_token),
|
||||
packet.nonce, decrypted_token))
|
||||
{
|
||||
TraceError("Failed to decrypt session token");
|
||||
Disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
cipher.SetSessionToken(decrypted_token);
|
||||
cipher.SetActivated(true);
|
||||
DecryptPendingRecvData();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CNetworkStream::RecvPingPacket()
|
||||
{
|
||||
TPacketGCPing kPacketPing;
|
||||
if (!Recv(sizeof(kPacketPing), &kPacketPing))
|
||||
return false;
|
||||
|
||||
return SendPongPacket();
|
||||
}
|
||||
|
||||
bool CNetworkStream::SendPongPacket()
|
||||
{
|
||||
TPacketCGPong kPacketPong;
|
||||
kPacketPong.header = CG::PONG;
|
||||
kPacketPong.length = sizeof(kPacketPong);
|
||||
|
||||
if (!Send(sizeof(kPacketPong), &kPacketPong))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
CNetworkStream::CNetworkStream()
|
||||
{
|
||||
m_sock = INVALID_SOCKET;
|
||||
@@ -701,33 +723,9 @@ CNetworkStream::CNetworkStream()
|
||||
m_isOnline = false;
|
||||
m_connectLimitTime = 0;
|
||||
|
||||
m_recvBuf = NULL;
|
||||
m_recvBufSize = 0;
|
||||
m_recvBufOutputPos = 0;
|
||||
m_recvBufInputPos = 0;
|
||||
|
||||
m_sendBuf = NULL;
|
||||
m_sendBufSize = 0;
|
||||
m_sendBufOutputPos = 0;
|
||||
m_sendBufInputPos = 0;
|
||||
|
||||
m_SequenceGenerator.seed(SEQUENCE_SEED);
|
||||
m_bUseSequence = false;
|
||||
}
|
||||
|
||||
CNetworkStream::~CNetworkStream()
|
||||
{
|
||||
Clear();
|
||||
|
||||
if (m_recvBuf)
|
||||
{
|
||||
delete [] m_recvBuf;
|
||||
m_recvBuf = NULL;
|
||||
}
|
||||
|
||||
if (m_sendBuf)
|
||||
{
|
||||
delete [] m_sendBuf;
|
||||
m_sendBuf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,9 @@
|
||||
|
||||
#include "EterBase/SecureCipher.h"
|
||||
#include "NetAddress.h"
|
||||
#include "RingBuffer.h"
|
||||
#include "ControlPackets.h"
|
||||
|
||||
#include <pcg_random.hpp>
|
||||
|
||||
#define SEQUENCE_SEED 0
|
||||
|
||||
class CNetworkStream
|
||||
{
|
||||
@@ -44,10 +43,6 @@ class CNetworkStream
|
||||
|
||||
bool IsOnline();
|
||||
|
||||
void SetPacketSequenceMode(bool isOn);
|
||||
bool SendSequence();
|
||||
uint8_t GetNextSequence();
|
||||
|
||||
protected:
|
||||
virtual void OnConnectSuccess();
|
||||
virtual void OnConnectFailure();
|
||||
@@ -58,8 +53,6 @@ class CNetworkStream
|
||||
bool __SendInternalBuffer();
|
||||
bool __RecvInternalBuffer();
|
||||
|
||||
void __PopSendBuffer();
|
||||
|
||||
int __GetSendBufferSize();
|
||||
|
||||
// Secure cipher methods (libsodium)
|
||||
@@ -71,18 +64,31 @@ class CNetworkStream
|
||||
// Must be called after activating the cipher mid-stream
|
||||
void DecryptPendingRecvData();
|
||||
|
||||
// Control-plane packet handlers (shared by all connection types)
|
||||
virtual bool RecvKeyChallenge();
|
||||
virtual bool RecvKeyComplete();
|
||||
bool RecvPingPacket();
|
||||
bool SendPongPacket();
|
||||
|
||||
// Packet send tracking (for debug sequence correlation)
|
||||
protected:
|
||||
struct SentPacketLogEntry
|
||||
{
|
||||
uint32_t seq;
|
||||
uint16_t header;
|
||||
uint16_t length;
|
||||
};
|
||||
|
||||
static constexpr size_t SENT_PACKET_LOG_SIZE = 32;
|
||||
|
||||
SentPacketLogEntry m_aSentPacketLog[SENT_PACKET_LOG_SIZE] = {};
|
||||
uint32_t m_dwSentPacketSeq = 0;
|
||||
|
||||
private:
|
||||
time_t m_connectLimitTime;
|
||||
|
||||
char* m_recvBuf;
|
||||
int m_recvBufSize;
|
||||
int m_recvBufInputPos;
|
||||
int m_recvBufOutputPos;
|
||||
|
||||
char* m_sendBuf;
|
||||
int m_sendBufSize;
|
||||
int m_sendBufInputPos;
|
||||
int m_sendBufOutputPos;
|
||||
RingBuffer m_recvBuf;
|
||||
RingBuffer m_sendBuf;
|
||||
|
||||
bool m_isOnline;
|
||||
|
||||
@@ -93,7 +99,4 @@ class CNetworkStream
|
||||
|
||||
CNetworkAddress m_addr;
|
||||
|
||||
// Sequence
|
||||
pcg32 m_SequenceGenerator;
|
||||
bool m_bUseSequence;
|
||||
};
|
||||
|
||||
157
src/EterLib/PacketReader.h
Normal file
157
src/EterLib/PacketReader.h
Normal file
@@ -0,0 +1,157 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
// PacketReader: Safe, bounds-checked packet deserialization from a read-only buffer.
|
||||
// Used to parse incoming packets after the dispatch loop validates the header and length.
|
||||
//
|
||||
// Usage:
|
||||
// PacketReader r(packetData, packetLength);
|
||||
// uint16_t header = r.ReadU16();
|
||||
// uint16_t length = r.ReadU16();
|
||||
// uint8_t chatType = r.ReadU8();
|
||||
// char message[128];
|
||||
// r.ReadString(message, sizeof(message));
|
||||
|
||||
class PacketReader
|
||||
{
|
||||
public:
|
||||
PacketReader(const void* data, size_t size)
|
||||
: m_buf(static_cast<const uint8_t*>(data))
|
||||
, m_size(size)
|
||||
, m_pos(0)
|
||||
{
|
||||
assert(data != nullptr || size == 0);
|
||||
}
|
||||
|
||||
// --- Read primitives ---
|
||||
|
||||
uint8_t ReadU8()
|
||||
{
|
||||
assert(m_pos + sizeof(uint8_t) <= m_size);
|
||||
return m_buf[m_pos++];
|
||||
}
|
||||
|
||||
uint16_t ReadU16()
|
||||
{
|
||||
assert(m_pos + sizeof(uint16_t) <= m_size);
|
||||
uint16_t v;
|
||||
std::memcpy(&v, m_buf + m_pos, sizeof(v));
|
||||
m_pos += sizeof(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
uint32_t ReadU32()
|
||||
{
|
||||
assert(m_pos + sizeof(uint32_t) <= m_size);
|
||||
uint32_t v;
|
||||
std::memcpy(&v, m_buf + m_pos, sizeof(v));
|
||||
m_pos += sizeof(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
int8_t ReadI8() { return static_cast<int8_t>(ReadU8()); }
|
||||
int16_t ReadI16() { return static_cast<int16_t>(ReadU16()); }
|
||||
int32_t ReadI32() { return static_cast<int32_t>(ReadU32()); }
|
||||
|
||||
uint64_t ReadU64()
|
||||
{
|
||||
assert(m_pos + sizeof(uint64_t) <= m_size);
|
||||
uint64_t v;
|
||||
std::memcpy(&v, m_buf + m_pos, sizeof(v));
|
||||
m_pos += sizeof(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
float ReadFloat()
|
||||
{
|
||||
assert(m_pos + sizeof(float) <= m_size);
|
||||
float v;
|
||||
std::memcpy(&v, m_buf + m_pos, sizeof(v));
|
||||
m_pos += sizeof(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
// Read raw bytes
|
||||
bool ReadBytes(void* dest, size_t len)
|
||||
{
|
||||
if (m_pos + len > m_size)
|
||||
return false;
|
||||
std::memcpy(dest, m_buf + m_pos, len);
|
||||
m_pos += len;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Read a fixed-length string (null-terminated in dest)
|
||||
bool ReadString(char* dest, size_t fixedLen)
|
||||
{
|
||||
if (m_pos + fixedLen > m_size)
|
||||
return false;
|
||||
std::memcpy(dest, m_buf + m_pos, fixedLen);
|
||||
dest[fixedLen - 1] = '\0'; // ensure null termination
|
||||
m_pos += fixedLen;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Skip bytes without reading
|
||||
bool Skip(size_t len)
|
||||
{
|
||||
if (m_pos + len > m_size)
|
||||
return false;
|
||||
m_pos += len;
|
||||
return true;
|
||||
}
|
||||
|
||||
// --- Peek (non-consuming) ---
|
||||
|
||||
uint8_t PeekU8() const
|
||||
{
|
||||
assert(m_pos + sizeof(uint8_t) <= m_size);
|
||||
return m_buf[m_pos];
|
||||
}
|
||||
|
||||
uint16_t PeekU16() const
|
||||
{
|
||||
assert(m_pos + sizeof(uint16_t) <= m_size);
|
||||
uint16_t v;
|
||||
std::memcpy(&v, m_buf + m_pos, sizeof(v));
|
||||
return v;
|
||||
}
|
||||
|
||||
uint16_t PeekU16At(size_t offset) const
|
||||
{
|
||||
assert(offset + sizeof(uint16_t) <= m_size);
|
||||
uint16_t v;
|
||||
std::memcpy(&v, m_buf + offset, sizeof(v));
|
||||
return v;
|
||||
}
|
||||
|
||||
// --- Read struct (for backward compatibility during migration) ---
|
||||
// Reads a struct directly via memcpy. Use sparingly — prefer typed reads.
|
||||
template<typename T>
|
||||
bool ReadStruct(T& out)
|
||||
{
|
||||
if (m_pos + sizeof(T) > m_size)
|
||||
return false;
|
||||
std::memcpy(&out, m_buf + m_pos, sizeof(T));
|
||||
m_pos += sizeof(T);
|
||||
return true;
|
||||
}
|
||||
|
||||
// --- State ---
|
||||
|
||||
bool HasBytes(size_t n) const { return (m_pos + n) <= m_size; }
|
||||
size_t Remaining() const { return m_size - m_pos; }
|
||||
size_t Position() const { return m_pos; }
|
||||
size_t Size() const { return m_size; }
|
||||
const uint8_t* Current() const { return m_buf + m_pos; }
|
||||
|
||||
void Reset() { m_pos = 0; }
|
||||
|
||||
private:
|
||||
const uint8_t* m_buf;
|
||||
size_t m_size;
|
||||
size_t m_pos;
|
||||
};
|
||||
139
src/EterLib/PacketWriter.h
Normal file
139
src/EterLib/PacketWriter.h
Normal file
@@ -0,0 +1,139 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
// PacketWriter: Safe, bounds-checked packet serialization into a fixed buffer.
|
||||
// Used to build outgoing packets before writing to the send buffer.
|
||||
//
|
||||
// Usage:
|
||||
// uint8_t buf[128];
|
||||
// PacketWriter w(buf, sizeof(buf));
|
||||
// w.WriteU16(CG::CHAT);
|
||||
// w.WriteU16(0); // placeholder for length
|
||||
// w.WriteU8(chatType);
|
||||
// w.WriteString(message, 128);
|
||||
// w.PatchU16(2, w.Written()); // patch length at offset 2
|
||||
// stream.Send(w.Written(), buf);
|
||||
|
||||
class PacketWriter
|
||||
{
|
||||
public:
|
||||
PacketWriter(void* buf, size_t capacity)
|
||||
: m_buf(static_cast<uint8_t*>(buf))
|
||||
, m_capacity(capacity)
|
||||
, m_pos(0)
|
||||
{
|
||||
assert(buf != nullptr);
|
||||
assert(capacity > 0);
|
||||
}
|
||||
|
||||
// --- Write primitives ---
|
||||
|
||||
bool WriteU8(uint8_t v)
|
||||
{
|
||||
if (m_pos + sizeof(v) > m_capacity)
|
||||
return false;
|
||||
m_buf[m_pos++] = v;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteU16(uint16_t v)
|
||||
{
|
||||
if (m_pos + sizeof(v) > m_capacity)
|
||||
return false;
|
||||
std::memcpy(m_buf + m_pos, &v, sizeof(v));
|
||||
m_pos += sizeof(v);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteU32(uint32_t v)
|
||||
{
|
||||
if (m_pos + sizeof(v) > m_capacity)
|
||||
return false;
|
||||
std::memcpy(m_buf + m_pos, &v, sizeof(v));
|
||||
m_pos += sizeof(v);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteI8(int8_t v) { return WriteU8(static_cast<uint8_t>(v)); }
|
||||
bool WriteI16(int16_t v) { return WriteU16(static_cast<uint16_t>(v)); }
|
||||
bool WriteI32(int32_t v) { return WriteU32(static_cast<uint32_t>(v)); }
|
||||
|
||||
bool WriteU64(uint64_t v)
|
||||
{
|
||||
if (m_pos + sizeof(v) > m_capacity)
|
||||
return false;
|
||||
std::memcpy(m_buf + m_pos, &v, sizeof(v));
|
||||
m_pos += sizeof(v);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteFloat(float v)
|
||||
{
|
||||
if (m_pos + sizeof(v) > m_capacity)
|
||||
return false;
|
||||
std::memcpy(m_buf + m_pos, &v, sizeof(v));
|
||||
m_pos += sizeof(v);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Write raw bytes
|
||||
bool WriteBytes(const void* data, size_t len)
|
||||
{
|
||||
if (len == 0)
|
||||
return true;
|
||||
if (m_pos + len > m_capacity)
|
||||
return false;
|
||||
std::memcpy(m_buf + m_pos, data, len);
|
||||
m_pos += len;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Write a fixed-length null-padded string
|
||||
bool WriteString(const char* str, size_t fixedLen)
|
||||
{
|
||||
if (m_pos + fixedLen > m_capacity)
|
||||
return false;
|
||||
|
||||
size_t srcLen = str ? std::strlen(str) : 0;
|
||||
size_t copyLen = (srcLen < fixedLen) ? srcLen : (fixedLen - 1);
|
||||
|
||||
std::memcpy(m_buf + m_pos, str, copyLen);
|
||||
std::memset(m_buf + m_pos + copyLen, 0, fixedLen - copyLen);
|
||||
m_pos += fixedLen;
|
||||
return true;
|
||||
}
|
||||
|
||||
// --- Patch: overwrite data at a previous offset ---
|
||||
|
||||
bool PatchU16(size_t offset, uint16_t v)
|
||||
{
|
||||
if (offset + sizeof(v) > m_pos)
|
||||
return false;
|
||||
std::memcpy(m_buf + offset, &v, sizeof(v));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PatchU32(size_t offset, uint32_t v)
|
||||
{
|
||||
if (offset + sizeof(v) > m_pos)
|
||||
return false;
|
||||
std::memcpy(m_buf + offset, &v, sizeof(v));
|
||||
return true;
|
||||
}
|
||||
|
||||
// --- State ---
|
||||
|
||||
size_t Written() const { return m_pos; }
|
||||
size_t Remaining() const { return m_capacity - m_pos; }
|
||||
const uint8_t* Data() const { return m_buf; }
|
||||
|
||||
void Reset() { m_pos = 0; }
|
||||
|
||||
private:
|
||||
uint8_t* m_buf;
|
||||
size_t m_capacity;
|
||||
size_t m_pos;
|
||||
};
|
||||
@@ -1,264 +1 @@
|
||||
#pragma once
|
||||
|
||||
#include "EterBase/Timer.h"
|
||||
#include "EterBase/Debug.h"
|
||||
|
||||
/*
|
||||
class CProfiler : public CSingleton<CProfiler>
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
STACK_DATA_MAX_NUM = 64,
|
||||
};
|
||||
|
||||
public:
|
||||
typedef struct SProfileStackData
|
||||
{
|
||||
int iCallStep;
|
||||
long iStartTime;
|
||||
long iEndTime;
|
||||
|
||||
std::string strName;
|
||||
} TProfileStackData;
|
||||
typedef struct SProfileAccumulationData
|
||||
{
|
||||
int iStartTime;
|
||||
int iCallingCount;
|
||||
int iCollapsedTime;
|
||||
|
||||
std::string strName;
|
||||
} TProfileAccumulationData;
|
||||
|
||||
typedef std::map<std::string, CGraphicTextInstance*> TGraphicTextInstanceMap;
|
||||
typedef std::map<std::string, TProfileAccumulationData> TProfileAccumulationDataMap;
|
||||
|
||||
public:
|
||||
CProfiler()
|
||||
{
|
||||
Clear();
|
||||
m_ProfileAccumulationDataMap.clear();
|
||||
}
|
||||
virtual ~CProfiler()
|
||||
{
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
m_ProfileStackDataCount = 0;
|
||||
m_iCallStep = 0;
|
||||
|
||||
TProfileAccumulationDataMap::iterator itor = m_ProfileAccumulationDataMap.begin();
|
||||
for (; itor != m_ProfileAccumulationDataMap.end(); ++itor)
|
||||
{
|
||||
TProfileAccumulationData & rData = itor->second;
|
||||
rData.iCallingCount = 0;
|
||||
rData.iCollapsedTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Push(const char * c_szName)
|
||||
{
|
||||
assert(m_ProfileStackDataCount < STACK_DATA_MAX_NUM);
|
||||
TProfileStackData & rProfileStackData = m_ProfileStackDatas[m_ProfileStackDataCount++];
|
||||
|
||||
rProfileStackData.iCallStep = m_iCallStep;
|
||||
rProfileStackData.iStartTime = ELTimer_GetMSec();
|
||||
rProfileStackData.strName = c_szName;
|
||||
|
||||
++m_iCallStep;
|
||||
|
||||
TGraphicTextInstanceMap::iterator itor = m_GraphicTextInstanceMap.find(c_szName);
|
||||
|
||||
if (m_GraphicTextInstanceMap.end() == itor)
|
||||
{
|
||||
CGraphicTextInstance * pGraphicTextInstance = CGraphicTextInstance::New();
|
||||
|
||||
CResource * pResource = CResourceManager::Instance().GetResourcePointer("굴림체.fnt");
|
||||
pGraphicTextInstance->Clear();
|
||||
pGraphicTextInstance->SetTextPointer(static_cast<CGraphicText*>(pResource));
|
||||
|
||||
m_GraphicTextInstanceMap.insert(TGraphicTextInstanceMap::value_type(c_szName, pGraphicTextInstance));
|
||||
}
|
||||
}
|
||||
void Pop(const char * c_szName)
|
||||
{
|
||||
TProfileStackData * pProfileStackData;
|
||||
|
||||
if (!GetProfileStackDataPointer(c_szName, &pProfileStackData))
|
||||
{
|
||||
assert(!"The name doesn't exist");
|
||||
return;
|
||||
}
|
||||
|
||||
pProfileStackData->iEndTime = ELTimer_GetMSec();
|
||||
|
||||
--m_iCallStep;
|
||||
}
|
||||
|
||||
void PushAccumulation(const char * c_szName)
|
||||
{
|
||||
TProfileAccumulationDataMap::iterator itor = m_ProfileAccumulationDataMap.find(c_szName);
|
||||
|
||||
if (itor == m_ProfileAccumulationDataMap.end())
|
||||
{
|
||||
TProfileAccumulationData ProfileAccumulationData;
|
||||
ProfileAccumulationData.iCollapsedTime = 0;
|
||||
ProfileAccumulationData.iCallingCount = 0;
|
||||
ProfileAccumulationData.strName = c_szName;
|
||||
m_ProfileAccumulationDataMap.insert(TProfileAccumulationDataMap::value_type(c_szName, ProfileAccumulationData));
|
||||
|
||||
itor = m_ProfileAccumulationDataMap.find(c_szName);
|
||||
|
||||
/////
|
||||
|
||||
CGraphicTextInstance * pGraphicTextInstance = m_GraphicTextInstancePool.Alloc();
|
||||
|
||||
CResource * pResource = CResourceManager::Instance().GetResourcePointer("굴림체.fnt");
|
||||
pGraphicTextInstance->Clear();
|
||||
pGraphicTextInstance->SetTextPointer(static_cast<CGraphicText*>(pResource));
|
||||
|
||||
m_GraphicTextInstanceMap.insert(TGraphicTextInstanceMap::value_type(c_szName, pGraphicTextInstance));
|
||||
}
|
||||
|
||||
TProfileAccumulationData & rData = itor->second;
|
||||
rData.iStartTime = ELTimer_GetMSec();
|
||||
}
|
||||
|
||||
void PopAccumulation(const char * c_szName)
|
||||
{
|
||||
TProfileAccumulationDataMap::iterator itor = m_ProfileAccumulationDataMap.find(c_szName);
|
||||
|
||||
if (itor == m_ProfileAccumulationDataMap.end())
|
||||
return;
|
||||
|
||||
TProfileAccumulationData & rData = itor->second;
|
||||
rData.iCollapsedTime += ELTimer_GetMSec() - rData.iStartTime;
|
||||
++rData.iCallingCount;
|
||||
}
|
||||
|
||||
void ProfileByConsole()
|
||||
{
|
||||
for (int i = 0; i < m_ProfileStackDataCount; ++i)
|
||||
{
|
||||
TProfileStackData & rProfileStackData = m_ProfileStackDatas[i];
|
||||
|
||||
// for (int i = 0; i < rProfileStackData.iCallStep; ++i)
|
||||
// Tracef("\t");
|
||||
|
||||
Tracef("%-10s: %2d\t", rProfileStackData.strName.c_str(), rProfileStackData.iEndTime - rProfileStackData.iStartTime);
|
||||
}
|
||||
Tracef("\n");
|
||||
}
|
||||
|
||||
void ProfileOneStackDataByConsole(const char * c_szName)
|
||||
{
|
||||
TProfileStackData * pProfileStackData;
|
||||
|
||||
if (!GetProfileStackDataPointer(c_szName, &pProfileStackData))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Tracef("%-10s: %3d\n", pProfileStackData->strName.c_str(), pProfileStackData->iEndTime - pProfileStackData->iStartTime);
|
||||
}
|
||||
|
||||
void ProfileOneAccumulationDataByConsole(const char * c_szName)
|
||||
{
|
||||
TProfileAccumulationDataMap::iterator itor = m_ProfileAccumulationDataMap.find(c_szName);
|
||||
if (itor == m_ProfileAccumulationDataMap.end())
|
||||
return;
|
||||
|
||||
TProfileAccumulationData & rData = itor->second;
|
||||
Tracef("%-10s : [CollapsedTime : %3d] / [CallingCount : %3d]\n", rData.strName.c_str(),
|
||||
rData.iCollapsedTime,
|
||||
rData.iCallingCount);
|
||||
}
|
||||
|
||||
void ProfileByScreen()
|
||||
{
|
||||
float fxPosition = 0;
|
||||
float fyPosition = 10;
|
||||
|
||||
char szText[128];
|
||||
|
||||
for (int i = 0; i < m_ProfileStackDataCount; ++i)
|
||||
{
|
||||
TProfileStackData & rProfileStackData = m_ProfileStackDatas[i];
|
||||
|
||||
TGraphicTextInstanceMap::iterator itor = m_GraphicTextInstanceMap.find(rProfileStackData.strName);
|
||||
|
||||
if (m_GraphicTextInstanceMap.end() != itor)
|
||||
{
|
||||
CGraphicTextInstance * pGraphicTextInstance = itor->second;
|
||||
|
||||
fxPosition = 10 + (float) rProfileStackData.iCallStep * 10 * 4;
|
||||
|
||||
sprintf(szText, "%-10s : %3d", rProfileStackData.strName.c_str(), rProfileStackData.iEndTime - rProfileStackData.iStartTime);
|
||||
|
||||
pGraphicTextInstance->SetColor(0.7f, 0.7f, 0.7f);
|
||||
pGraphicTextInstance->SetValue(szText, strlen(szText));
|
||||
pGraphicTextInstance->SetPosition(fxPosition, fyPosition);
|
||||
pGraphicTextInstance->Update();
|
||||
pGraphicTextInstance->Render();
|
||||
|
||||
fyPosition += 17;
|
||||
}
|
||||
}
|
||||
|
||||
fxPosition = 10;
|
||||
fyPosition += 10;
|
||||
TProfileAccumulationDataMap::iterator itor = m_ProfileAccumulationDataMap.begin();
|
||||
for (; itor != m_ProfileAccumulationDataMap.end(); ++itor)
|
||||
{
|
||||
TProfileAccumulationData & rData = itor->second;
|
||||
TGraphicTextInstanceMap::iterator itor = m_GraphicTextInstanceMap.find(rData.strName);
|
||||
|
||||
if (m_GraphicTextInstanceMap.end() != itor)
|
||||
{
|
||||
CGraphicTextInstance * pGraphicTextInstance = itor->second;
|
||||
|
||||
sprintf(szText, "%-10s : [CollapsedTime : %3d] / [CallingCount : %3d]", rData.strName.c_str(),
|
||||
rData.iCollapsedTime,
|
||||
rData.iCallingCount);
|
||||
|
||||
pGraphicTextInstance->SetColor(0.7f, 0.7f, 0.7f);
|
||||
pGraphicTextInstance->SetValue(szText, strlen(szText));
|
||||
pGraphicTextInstance->SetPosition(fxPosition, fyPosition);
|
||||
pGraphicTextInstance->Update();
|
||||
pGraphicTextInstance->Render();
|
||||
|
||||
fyPosition += 17;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
bool GetProfileStackDataPointer(const char * c_szName, TProfileStackData ** ppProfileStackData)
|
||||
{
|
||||
for (int i = 0; i < m_ProfileStackDataCount; ++i)
|
||||
{
|
||||
if (0 == m_ProfileStackDatas[i].strName.compare(c_szName))
|
||||
{
|
||||
*ppProfileStackData = &m_ProfileStackDatas[i];
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Profile Stack Data
|
||||
int m_ProfileStackDataCount;
|
||||
TProfileStackData m_ProfileStackDatas[STACK_DATA_MAX_NUM];
|
||||
|
||||
// Profile Increase Data
|
||||
TProfileAccumulationDataMap m_ProfileAccumulationDataMap;
|
||||
|
||||
int m_iCallStep;
|
||||
|
||||
TGraphicTextInstanceMap m_GraphicTextInstanceMap;
|
||||
};
|
||||
*/
|
||||
191
src/EterLib/RingBuffer.h
Normal file
191
src/EterLib/RingBuffer.h
Normal file
@@ -0,0 +1,191 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
|
||||
class RingBuffer
|
||||
{
|
||||
public:
|
||||
explicit RingBuffer(size_t initialCapacity = 0)
|
||||
{
|
||||
if (initialCapacity > 0)
|
||||
m_data.resize(initialCapacity);
|
||||
}
|
||||
|
||||
~RingBuffer() = default;
|
||||
|
||||
// Non-copyable, movable
|
||||
RingBuffer(const RingBuffer&) = delete;
|
||||
RingBuffer& operator=(const RingBuffer&) = delete;
|
||||
RingBuffer(RingBuffer&&) noexcept = default;
|
||||
RingBuffer& operator=(RingBuffer&&) noexcept = default;
|
||||
|
||||
// --- Capacity ---
|
||||
|
||||
size_t ReadableBytes() const { return m_writePos - m_readPos; }
|
||||
size_t WritableBytes() const { return m_data.size() - m_writePos; }
|
||||
size_t Capacity() const { return m_data.size(); }
|
||||
|
||||
void Reserve(size_t capacity)
|
||||
{
|
||||
if (capacity > m_data.size())
|
||||
{
|
||||
Compact();
|
||||
m_data.resize(capacity);
|
||||
}
|
||||
}
|
||||
|
||||
void EnsureWritable(size_t len)
|
||||
{
|
||||
if (WritableBytes() >= len)
|
||||
return;
|
||||
|
||||
// Try compaction first
|
||||
Compact();
|
||||
if (WritableBytes() >= len)
|
||||
return;
|
||||
|
||||
// Must grow
|
||||
size_t needed = m_writePos + len;
|
||||
size_t newSize = m_data.size();
|
||||
if (newSize == 0)
|
||||
newSize = 1024;
|
||||
while (newSize < needed)
|
||||
newSize *= 2;
|
||||
|
||||
m_data.resize(newSize);
|
||||
}
|
||||
|
||||
// --- Write operations ---
|
||||
|
||||
void Write(const void* data, size_t len)
|
||||
{
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
assert(data != nullptr);
|
||||
EnsureWritable(len);
|
||||
std::memcpy(m_data.data() + m_writePos, data, len);
|
||||
m_writePos += len;
|
||||
}
|
||||
|
||||
// Direct write access for socket recv()
|
||||
uint8_t* WritePtr()
|
||||
{
|
||||
return m_data.data() + m_writePos;
|
||||
}
|
||||
|
||||
void CommitWrite(size_t len)
|
||||
{
|
||||
assert(m_writePos + len <= m_data.size());
|
||||
m_writePos += len;
|
||||
}
|
||||
|
||||
// --- Read operations ---
|
||||
|
||||
bool HasBytes(size_t n) const { return ReadableBytes() >= n; }
|
||||
|
||||
bool Peek(void* dest, size_t len) const
|
||||
{
|
||||
if (ReadableBytes() < len)
|
||||
return false;
|
||||
|
||||
std::memcpy(dest, m_data.data() + m_readPos, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Peek at a specific offset from read position (non-consuming)
|
||||
bool PeekAt(size_t offset, void* dest, size_t len) const
|
||||
{
|
||||
if (ReadableBytes() < offset + len)
|
||||
return false;
|
||||
|
||||
std::memcpy(dest, m_data.data() + m_readPos + offset, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Read(void* dest, size_t len)
|
||||
{
|
||||
if (!Peek(dest, len))
|
||||
return false;
|
||||
|
||||
m_readPos += len;
|
||||
MaybeCompact();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Discard bytes without reading them
|
||||
bool Discard(size_t len)
|
||||
{
|
||||
if (ReadableBytes() < len)
|
||||
return false;
|
||||
|
||||
m_readPos += len;
|
||||
MaybeCompact();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Direct read access for socket send() and packet processing
|
||||
const uint8_t* ReadPtr() const
|
||||
{
|
||||
return m_data.data() + m_readPos;
|
||||
}
|
||||
|
||||
size_t ReadPos() const { return m_readPos; }
|
||||
size_t WritePos() const { return m_writePos; }
|
||||
|
||||
// --- Encryption support ---
|
||||
// Get writable pointer to already-written data at a specific position
|
||||
// Used for in-place encryption of data that was just written
|
||||
uint8_t* DataAt(size_t pos)
|
||||
{
|
||||
assert(pos < m_data.size());
|
||||
return m_data.data() + pos;
|
||||
}
|
||||
|
||||
// --- Reset ---
|
||||
|
||||
void Clear()
|
||||
{
|
||||
m_readPos = 0;
|
||||
m_writePos = 0;
|
||||
}
|
||||
|
||||
// --- Compaction ---
|
||||
|
||||
void Compact()
|
||||
{
|
||||
if (m_readPos == 0)
|
||||
return;
|
||||
|
||||
size_t readable = ReadableBytes();
|
||||
if (readable > 0)
|
||||
std::memmove(m_data.data(), m_data.data() + m_readPos, readable);
|
||||
|
||||
m_readPos = 0;
|
||||
m_writePos = readable;
|
||||
}
|
||||
|
||||
private:
|
||||
void MaybeCompact()
|
||||
{
|
||||
// Compact when read position passes halfway and there's no readable data
|
||||
// or when read position is more than half the buffer
|
||||
if (m_readPos == m_writePos)
|
||||
{
|
||||
m_readPos = 0;
|
||||
m_writePos = 0;
|
||||
}
|
||||
else if (m_readPos > m_data.size() / 2)
|
||||
{
|
||||
Compact();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint8_t> m_data;
|
||||
size_t m_readPos = 0;
|
||||
size_t m_writePos = 0;
|
||||
};
|
||||
Reference in New Issue
Block a user