Move git root from Client/ to src/ to track all source code: - Client: Game client source (moved to Client/Client/) - Server: Game server source - GameTools: Development tools - CryptoSource: Encryption utilities - database: Database scripts - Script: Game scripts - rylCoder_16.02.2008_src: Legacy coder tools - GMFont, Game: Additional resources 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
543 lines
14 KiB
C++
543 lines
14 KiB
C++
#include "stdafx.h"
|
|
#include "NetworkMsgBlock.h"
|
|
#include <Network/Packet/PacketBase.h>
|
|
#include <Network/XORCrypt/XORCrypt.h>
|
|
#include <Utility/Compress/MiniLZO/miniLZOWrapper.h>
|
|
|
|
#include <cstdio>
|
|
#include "GMMemory.h"
|
|
|
|
|
|
namespace ClientNet
|
|
{
|
|
|
|
CNetworkMsgBlock::CNetworkMsgBlock(size_t n)
|
|
: CMessageBlock(n), m_next(0),
|
|
m_eMsgType(NET_MSG_FREE), m_dwID(0)
|
|
{
|
|
|
|
}
|
|
|
|
CNetworkMsgBlock::CNetworkMsgBlock(size_t n, INET_Addr& addr)
|
|
: CMessageBlock(n), m_dstaddr(addr), m_next(0),
|
|
m_eMsgType(NET_MSG_FREE), m_dwID(0)
|
|
{
|
|
|
|
|
|
}
|
|
|
|
CNetworkMsgBlock::~CNetworkMsgBlock()
|
|
{
|
|
|
|
|
|
}
|
|
|
|
bool CNetworkMsgBlock::WrapHeader(unsigned short usUsed_In, unsigned char cCMD_In,
|
|
unsigned short usState_In, unsigned short usError_In)
|
|
{
|
|
char* lpBuffer = rd_ptr();
|
|
|
|
if(NULL != lpBuffer && sizeof(PktBase) <= usUsed_In && usUsed_In <= remain())
|
|
{
|
|
reinterpret_cast<PktBase*>(lpBuffer)->InitPtHead(usUsed_In, cCMD_In, usState_In, usError_In);
|
|
CXORCrypt::GetInstance().EncodeHeader(lpBuffer + 1, sizeof(PktBase) - 1, 0, 0);
|
|
|
|
wr_ptr(usUsed_In);
|
|
return true;
|
|
}
|
|
|
|
fprintf(stderr, "CNetworkMsgBlock::WrapHeader - Packet wrapping error. CMD:0x%02x, usUsed:%d, capacity:%d\n",
|
|
cCMD_In, usUsed_In, capacity());
|
|
return false;
|
|
}
|
|
|
|
|
|
bool CNetworkMsgBlock::WrapCryptOld(unsigned short usUsed_In, unsigned char cCMD_In,
|
|
unsigned long Tick_In)
|
|
{
|
|
char* lpBuffer = rd_ptr();
|
|
|
|
if(NULL != lpBuffer && sizeof(PktBase) <= usUsed_In && usUsed_In <= remain())
|
|
{
|
|
CXORCrypt& Crypt = CXORCrypt::GetInstance();
|
|
DWORD dwCodePage = Crypt.GetCodePage(1);
|
|
|
|
if(Crypt.EncodePacket(lpBuffer + sizeof(PktBase), usUsed_In - sizeof(PktBase), dwCodePage))
|
|
{
|
|
PktBase* lpPktBase = reinterpret_cast<PktBase*>(lpBuffer);
|
|
|
|
lpPktBase->InitPtHead(usUsed_In, cCMD_In, Tick_In);
|
|
lpPktBase->SetCodePage(dwCodePage);
|
|
lpPktBase->SetCrypt();
|
|
|
|
// Çì´õ ÀÎÄÚµù
|
|
Crypt.EncodeHeader(lpBuffer + 1, sizeof(PktBase) - 1, 0, 0);
|
|
|
|
wr_ptr(usUsed_In);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
fprintf(stderr, "CNetworkMsgBlock::WrapCrypt - Packet wrapping error. CMD:0x%02x, usUsed:%d, capacity:%d\n",
|
|
cCMD_In, usUsed_In, capacity());
|
|
return false;
|
|
}
|
|
|
|
|
|
bool CNetworkMsgBlock::WrapCryptOld(unsigned short usUsed_In, unsigned char cCMD_In,
|
|
unsigned short usState_In, unsigned short usError_In)
|
|
{
|
|
char* lpBuffer = rd_ptr();
|
|
|
|
if(NULL != lpBuffer && sizeof(PktBase) <= usUsed_In && usUsed_In <= remain())
|
|
{
|
|
CXORCrypt& Crypt = CXORCrypt::GetInstance();
|
|
DWORD dwCodePage = Crypt.GetCodePage(1);
|
|
|
|
if(Crypt.EncodePacket(lpBuffer + sizeof(PktBase), usUsed_In - sizeof(PktBase), dwCodePage))
|
|
{
|
|
PktBase* lpPktBase = reinterpret_cast<PktBase*>(lpBuffer);
|
|
|
|
lpPktBase->InitPtHead(usUsed_In, cCMD_In, usState_In, usError_In);
|
|
lpPktBase->SetCodePage(dwCodePage);
|
|
lpPktBase->SetCrypt();
|
|
|
|
// Çì´õ ÀÎÄÚµù
|
|
Crypt.EncodeHeader(lpBuffer + 1, sizeof(PktBase) - 1, 0, 0);
|
|
|
|
wr_ptr(usUsed_In);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
fprintf(stderr, "CNetworkMsgBlock::WrapCrypt - Packet wrapping error. CMD:0x%02x, usUsed:%d, capacity:%d\n",
|
|
cCMD_In, usUsed_In, capacity());
|
|
return false;
|
|
}
|
|
|
|
bool CNetworkMsgBlock::WrapCrypt(unsigned short usUsed_In, unsigned char cCMD_In,
|
|
unsigned long Tick_In)
|
|
{
|
|
char* lpBuffer = rd_ptr();
|
|
|
|
if(NULL != lpBuffer && sizeof(PktBase) <= usUsed_In && usUsed_In <= remain())
|
|
{
|
|
CXORCrypt& Crypt = CXORCrypt::GetInstance();
|
|
DWORD dwCodePage = Crypt.GetCodePage();
|
|
|
|
if(Crypt.EncodePacket(lpBuffer + sizeof(PktBase), usUsed_In - sizeof(PktBase), dwCodePage))
|
|
{
|
|
PktBase* lpPktBase = reinterpret_cast<PktBase*>(lpBuffer);
|
|
|
|
lpPktBase->InitPtHead(usUsed_In, cCMD_In, Tick_In);
|
|
lpPktBase->SetCodePage(dwCodePage);
|
|
lpPktBase->SetCrypt();
|
|
|
|
// Çì´õ ÀÎÄÚµù
|
|
Crypt.EncodeHeader(lpBuffer + 1, sizeof(PktBase) - 1, 0, 0);
|
|
|
|
wr_ptr(usUsed_In);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
fprintf(stderr, "CNetworkMsgBlock::WrapCrypt - Packet wrapping error. CMD:0x%02x, usUsed:%d, capacity:%d\n",
|
|
cCMD_In, usUsed_In, capacity());
|
|
return false;
|
|
}
|
|
|
|
|
|
bool CNetworkMsgBlock::WrapCrypt(unsigned short usUsed_In, unsigned char cCMD_In,
|
|
unsigned short usState_In, unsigned short usError_In)
|
|
{
|
|
char* lpBuffer = rd_ptr();
|
|
|
|
if(NULL != lpBuffer && sizeof(PktBase) <= usUsed_In && usUsed_In <= remain())
|
|
{
|
|
CXORCrypt& Crypt = CXORCrypt::GetInstance();
|
|
DWORD dwCodePage = Crypt.GetCodePage();
|
|
|
|
if(Crypt.EncodePacket(lpBuffer + sizeof(PktBase), usUsed_In - sizeof(PktBase), dwCodePage))
|
|
{
|
|
PktBase* lpPktBase = reinterpret_cast<PktBase*>(lpBuffer);
|
|
|
|
lpPktBase->InitPtHead(usUsed_In, cCMD_In, usState_In, usError_In);
|
|
lpPktBase->SetCodePage(dwCodePage);
|
|
lpPktBase->SetCrypt();
|
|
|
|
// Çì´õ ÀÎÄÚµù
|
|
Crypt.EncodeHeader(lpBuffer + 1, sizeof(PktBase) - 1, 0, 0);
|
|
|
|
wr_ptr(usUsed_In);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
fprintf(stderr, "CNetworkMsgBlock::WrapCrypt - Packet wrapping error. CMD:0x%02x, usUsed:%d, capacity:%d\n",
|
|
cCMD_In, usUsed_In, capacity());
|
|
return false;
|
|
}
|
|
|
|
unsigned long CNetworkMsgBlock::GetMinCompressSize(unsigned short usSourceLength)
|
|
{
|
|
return usSourceLength + (usSourceLength / 64) + 16 + 3;
|
|
}
|
|
|
|
bool CNetworkMsgBlock::WrapCompress(char* lpSourceData, unsigned short usSourceLength,
|
|
unsigned char cCMD_In, unsigned short usState_In,
|
|
unsigned short usError_In)
|
|
{
|
|
unsigned long dwDstBufferSize = static_cast<unsigned long>(remain());
|
|
|
|
if(usSourceLength < sizeof(PktBase) || PktMaxLen < usSourceLength)
|
|
{
|
|
fprintf(stderr, "CNetworkMsgBlock::WrapCompress - Packet wrapping error. CMD:0x%02x, usSourceLength:%d, dwDstBufferSize:%d\n",
|
|
cCMD_In, usSourceLength, dwDstBufferSize);
|
|
}
|
|
else
|
|
{
|
|
if(dwDstBufferSize < sizeof(PktBase) || dwDstBufferSize < GetMinCompressSize(usSourceLength))
|
|
{
|
|
fprintf(stderr, "CNetworkMsgBlock::WrapCompress - Too small buffer size. CMD:0x%02x, usSourceLength:%d, dwDstBufferSize:%d\n",
|
|
cCMD_In, usSourceLength, dwDstBufferSize);
|
|
}
|
|
else
|
|
{
|
|
char* lpDstBuffer = rd_ptr();
|
|
unsigned long dwCompressedSize = dwDstBufferSize - sizeof(PktBase);
|
|
|
|
if(!CMiniLZO::Compress(lpSourceData + sizeof(PktBase), usSourceLength - sizeof(PktBase),
|
|
lpDstBuffer + sizeof(PktBase), &dwCompressedSize))
|
|
{
|
|
fprintf(stderr, "CNetworkMsgBlock::WrapCompress - Packet Compress failed. CMD:0x%02x, usSourceLength:%d, "
|
|
"dwDstBufferSize:%d\n", cCMD_In, usSourceLength, dwDstBufferSize);
|
|
}
|
|
else
|
|
{
|
|
if(dwDstBufferSize <= dwCompressedSize)
|
|
{
|
|
fprintf(stderr, "CNetworkMsgBlock::WrapCompress - Compressed size is over than buffer size."
|
|
"CMD:0x%02x, dwDstBufferSize:%d, dwCompressedSize:%d\n", cCMD_In, dwDstBufferSize, dwCompressedSize);
|
|
}
|
|
|
|
dwCompressedSize += sizeof(PktBase);
|
|
|
|
PktBase* lpPktDst = reinterpret_cast<PktBase*>(lpDstBuffer);
|
|
lpPktDst->InitPtHead(static_cast<PktBase::LengthType>(dwCompressedSize), cCMD_In, usState_In, usError_In);
|
|
lpPktDst->SetCompress();
|
|
|
|
// ÀÎÄÚµù Çì´õ
|
|
CXORCrypt::GetInstance().EncodeHeader(lpDstBuffer + 1, sizeof(PktBase) - 1, 0, 0);
|
|
|
|
wr_ptr(dwCompressedSize);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CNetworkMsgQueue::CNetworkMsgQueue()
|
|
: m_lpListHead(NULL), m_lpListTail(NULL), m_nListNum(0)
|
|
{
|
|
|
|
}
|
|
|
|
CNetworkMsgQueue::~CNetworkMsgQueue()
|
|
{
|
|
clear();
|
|
}
|
|
|
|
void CNetworkMsgQueue::clear()
|
|
{
|
|
CNetworkMsgPool::GetInstance().FreeNetworkMsgBlock(*this);
|
|
}
|
|
|
|
void CNetworkMsgQueue::Enqueue(CNetworkMsgBlock* lpMsgBlock, bool bPendHead)
|
|
{
|
|
if(NULL != lpMsgBlock)
|
|
{
|
|
if(m_lpListHead == NULL)
|
|
{
|
|
m_lpListHead = m_lpListTail = lpMsgBlock;
|
|
lpMsgBlock->next(NULL);
|
|
}
|
|
else if(!bPendHead)
|
|
{
|
|
m_lpListTail->next(lpMsgBlock);
|
|
m_lpListTail = lpMsgBlock;
|
|
lpMsgBlock->next(NULL);
|
|
}
|
|
else
|
|
{
|
|
lpMsgBlock->next(m_lpListHead);
|
|
m_lpListHead = lpMsgBlock;
|
|
}
|
|
|
|
++m_nListNum;
|
|
}
|
|
}
|
|
|
|
CNetworkMsgBlock* CNetworkMsgQueue::Dequeue()
|
|
{
|
|
CNetworkMsgBlock* lpMsgBlock = NULL;
|
|
|
|
if(m_lpListTail != NULL)
|
|
{
|
|
lpMsgBlock = m_lpListHead;
|
|
m_lpListHead = m_lpListHead->next();
|
|
|
|
if(m_lpListTail == lpMsgBlock)
|
|
{
|
|
m_lpListTail = NULL;
|
|
}
|
|
|
|
lpMsgBlock->next(NULL);
|
|
--m_nListNum;
|
|
}
|
|
|
|
return lpMsgBlock;
|
|
}
|
|
|
|
|
|
CNetworkMsgBlock* CNetworkMsgPool::GetNetworkMsgBlock(unsigned long dwSize, INET_Addr& addr)
|
|
{
|
|
MsgBlockLock::Syncronize sync(m_MsgBlockLock);
|
|
|
|
CNetworkMsgBlock* lpMsgBlock = 0;
|
|
|
|
if (m_MsgBlockList.empty())
|
|
{
|
|
lpMsgBlock = new CNetworkMsgBlock(dwSize);
|
|
}
|
|
else
|
|
{
|
|
lpMsgBlock = m_MsgBlockList.front();
|
|
m_MsgBlockList.pop_front();
|
|
|
|
if (0 != lpMsgBlock)
|
|
{
|
|
lpMsgBlock->init(dwSize);
|
|
}
|
|
}
|
|
|
|
if (0 != lpMsgBlock && lpMsgBlock->is_valid()
|
|
&& dwSize <= lpMsgBlock->capacity())
|
|
{
|
|
return lpMsgBlock;
|
|
}
|
|
|
|
delete lpMsgBlock;
|
|
return 0;
|
|
}
|
|
|
|
void CNetworkMsgPool::FreeNetworkMsgBlock(CNetworkMsgBlock* lpMsgBlock)
|
|
{
|
|
MsgBlockLock::Syncronize sync(m_MsgBlockLock);
|
|
|
|
if (0 != lpMsgBlock)
|
|
{
|
|
if (m_MsgBlockList.size() < m_dwMaxBlockNum)
|
|
{
|
|
m_MsgBlockList.push_back(lpMsgBlock);
|
|
}
|
|
else
|
|
{
|
|
delete lpMsgBlock;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CNetworkMsgPool::FreeNetworkMsgBlock(CNetworkMsgQueue& msgQueue)
|
|
{
|
|
MsgBlockLock::Syncronize sync(m_MsgBlockLock);
|
|
|
|
CNetworkMsgBlock* lpMsgBlock = 0;
|
|
|
|
while (0 != (lpMsgBlock = msgQueue.Dequeue()))
|
|
{
|
|
if (m_MsgBlockList.size() < m_dwMaxBlockNum)
|
|
{
|
|
m_MsgBlockList.push_back(lpMsgBlock);
|
|
}
|
|
else
|
|
{
|
|
delete lpMsgBlock;
|
|
}
|
|
}
|
|
}
|
|
|
|
CNetworkMsgPool& CNetworkMsgPool::GetInstance()
|
|
{
|
|
static CNetworkMsgPool msgPool;
|
|
return msgPool;
|
|
}
|
|
|
|
CNetworkMsgPool::CNetworkMsgPool()
|
|
: m_dwMaxBlockNum(50)
|
|
{
|
|
|
|
}
|
|
|
|
CNetworkMsgPool::~CNetworkMsgPool()
|
|
{
|
|
MsgBlockLock::Syncronize sync(m_MsgBlockLock);
|
|
|
|
MsgBlockList::iterator pos = m_MsgBlockList.begin();
|
|
MsgBlockList::iterator end = m_MsgBlockList.end();
|
|
|
|
for(; pos != end; ++pos)
|
|
{
|
|
delete *pos;
|
|
}
|
|
|
|
m_MsgBlockList.clear();
|
|
}
|
|
|
|
|
|
|
|
CLockedMsgQueue::~CLockedMsgQueue()
|
|
{
|
|
MsgQueueLock::Syncronize sync(m_MsgQueueLock);
|
|
m_MessageQueue.clear();
|
|
}
|
|
|
|
CNetworkMsgBlock* CLockedMsgQueue::GetMessage()
|
|
{
|
|
MsgQueueLock::Syncronize sync(m_MsgQueueLock);
|
|
return m_MessageQueue.Dequeue();
|
|
}
|
|
|
|
|
|
void CLockedMsgQueue::GetMessages(CNetworkMsgQueue& msgQueue, DWORD dwItemNum)
|
|
{
|
|
CNetworkMsgBlock* lpMsg = 0;
|
|
|
|
MsgQueueLock::Syncronize sync(m_MsgQueueLock);
|
|
|
|
for(DWORD dwCount = 0; dwCount < dwItemNum; ++dwCount)
|
|
{
|
|
if(0 != (lpMsg = m_MessageQueue.Dequeue()))
|
|
{
|
|
msgQueue.Enqueue(lpMsg);
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CLockedMsgQueue::PutMessage(CNetworkMsgBlock* lpMsg, bool bPendHead)
|
|
{
|
|
MsgQueueLock::Syncronize sync(m_MsgQueueLock);
|
|
m_MessageQueue.Enqueue(lpMsg, bPendHead);
|
|
}
|
|
|
|
void CLockedMsgQueue::PutMessages(CNetworkMsgQueue& msgQueue)
|
|
{
|
|
CNetworkMsgBlock* lpMsg = 0;
|
|
|
|
MsgQueueLock::Syncronize sync(m_MsgQueueLock);
|
|
while(0 != (lpMsg = msgQueue.Dequeue()))
|
|
{
|
|
m_MessageQueue.Enqueue(lpMsg);
|
|
}
|
|
}
|
|
|
|
|
|
CUnboundedWaitableMsgQueue::CUnboundedWaitableMsgQueue()
|
|
{
|
|
// Create Auto-Reset Event
|
|
m_hNotEmpty = CreateEvent(0, FALSE, FALSE, 0);
|
|
}
|
|
|
|
CUnboundedWaitableMsgQueue::~CUnboundedWaitableMsgQueue()
|
|
{
|
|
CloseHandle(m_hNotEmpty);
|
|
}
|
|
|
|
DWORD CUnboundedWaitableMsgQueue::WaitForNotEmptyQueue(DWORD dwMilliseconds)
|
|
{
|
|
return WaitForSingleObject(m_hNotEmpty, dwMilliseconds);
|
|
}
|
|
|
|
CNetworkMsgBlock* CUnboundedWaitableMsgQueue::GetMessage()
|
|
{
|
|
MsgQueueLock::Syncronize sync(m_MsgQueueLock);
|
|
CNetworkMsgBlock* lpMsg = m_MessageQueue.Dequeue();
|
|
|
|
InternalResetNotEmpty();
|
|
|
|
return lpMsg;
|
|
}
|
|
|
|
void CUnboundedWaitableMsgQueue::GetMessages(CNetworkMsgQueue& msgQueue, DWORD dwItemNum)
|
|
{
|
|
CNetworkMsgBlock* lpMsg = 0;
|
|
|
|
MsgQueueLock::Syncronize sync(m_MsgQueueLock);
|
|
|
|
for(DWORD dwCount = 0; dwCount < dwItemNum; ++dwCount)
|
|
{
|
|
if(0 != (lpMsg = m_MessageQueue.Dequeue()))
|
|
{
|
|
msgQueue.Enqueue(lpMsg);
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
InternalResetNotEmpty();
|
|
}
|
|
|
|
void CUnboundedWaitableMsgQueue::PutMessage(CNetworkMsgBlock* lpMsg, bool bPendHead)
|
|
{
|
|
MsgQueueLock::Syncronize sync(m_MsgQueueLock);
|
|
m_MessageQueue.Enqueue(lpMsg, bPendHead);
|
|
|
|
InternalSetNotEmpty();
|
|
}
|
|
|
|
void CUnboundedWaitableMsgQueue::PutMessages(CNetworkMsgQueue& msgQueue)
|
|
{
|
|
CNetworkMsgBlock* lpMsg = 0;
|
|
|
|
MsgQueueLock::Syncronize sync(m_MsgQueueLock);
|
|
while(0 != (lpMsg = msgQueue.Dequeue()))
|
|
{
|
|
m_MessageQueue.Enqueue(lpMsg);
|
|
}
|
|
|
|
InternalSetNotEmpty();
|
|
}
|
|
|
|
void CUnboundedWaitableMsgQueue::InternalSetNotEmpty()
|
|
{
|
|
if(!m_bNotEmpty && 0 != m_MessageQueue.GetQueuedNum())
|
|
{
|
|
SetEvent(m_hNotEmpty); m_bNotEmpty = true;
|
|
}
|
|
}
|
|
|
|
void CUnboundedWaitableMsgQueue::InternalResetNotEmpty()
|
|
{
|
|
if(m_bNotEmpty && 0 == m_MessageQueue.GetQueuedNum())
|
|
{
|
|
ResetEvent(m_hNotEmpty);
|
|
m_bNotEmpty = false;
|
|
}
|
|
}
|
|
|
|
|
|
} |