Restructure repository to include all source folders

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>
This commit is contained in:
2025-11-29 20:17:20 +09:00
parent 5d3cd64a25
commit dd97ddec92
11602 changed files with 1446576 additions and 0 deletions

View File

@@ -0,0 +1,443 @@
#include "stdafx.h"
#include "ClientEventHandler.h"
#include <Network/Packet/PacketBase.h>
#include <Network/Packet/PacketCommand.h>
#include <Network/Packet/PacketStruct/ServerPacket.h>
#include <Network/XORCrypt/XORCrypt.h>
#include <Network/ClientNetwork/Session.h>
#include <Utility/Compress/MiniLZO/miniLZOWrapper.h>
#include <Thread/ThreadMgr.h>
#include <mmsystem.h>
#include "GMMemory.h"
namespace ClientNet
{
CClientEventHandler::CClientEventHandler()
: m_lpEventHandlerMgr(0),
m_dwHandlerID(0), m_dwSessionID(0),
m_bCloseCalled(false)
{
}
CClientEventHandler::~CClientEventHandler()
{
}
bool CClientEventHandler::SendPacket(CNetworkMsgBlock* lpMsgBlock)
{
return (0 != m_lpEventHandlerMgr) ?
m_lpEventHandlerMgr->SendPacket(this, lpMsgBlock) : false;
}
CClientEventHandlerMgr::CClientEventHandlerMgr()
: m_dwMaxEventHandlerID(0), m_bExit(FALSE)
{
m_SessionMgr.SetDispatchQueue(m_LockedMsgQueue);
CThreadMgr::Run(this);
}
CClientEventHandlerMgr::~CClientEventHandlerMgr()
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Handler<65><72> <20><><EFBFBD>ؼ<EFBFBD>, Close<73><65> ȣ<><C8A3><EFBFBD>Ѵ<EFBFBD>.
ClientEventHanderMap::iterator pos = m_ClientEventHandlerMap.begin();
ClientEventHanderMap::iterator end = m_ClientEventHandlerMap.end();
for(; pos != end; ++pos)
{
Close(pos->second);
}
// 2<>ʵ<EFBFBD><CAB5><EFBFBD> <20><><EFBFBD>ؼ<EFBFBD><D8BC><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><20><><EFBFBD>ٸ<EFBFBD><D9B8><EFBFBD>.
DWORD dwLastTime = timeGetTime();
do
{
HandleEvents(0xFFFFFFFF);
Sleep(100);
}
while(timeGetTime() - dwLastTime < 5000 && !m_ClientEventHandlerMap.empty());
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
End();
CThreadMgr::Stop(this, 2000);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
pos = m_ClientEventHandlerMap.begin();
end = m_ClientEventHandlerMap.end();
for(; pos != end; ++pos)
{
delete pos->second;
}
}
void CClientEventHandlerMgr::HandleEvents(unsigned long dwProcessPerCall)
{
m_LockedMsgQueue.GetMessages(m_LocalMsgQueue, ULONG_MAX);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>޽<EFBFBD><DEBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ó<><C3B3><EFBFBD>Ѵ<EFBFBD>.
CNetworkMsgBlock* lpMsgBlock = 0;
ClientEventHanderMap::iterator pos;
ClientEventHanderMap::iterator end = m_ClientEventHandlerMap.end();
for (DWORD dwCount = 0; dwCount < dwProcessPerCall; ++dwCount)
{
lpMsgBlock = m_LocalMsgQueue.Dequeue();
if(0 == lpMsgBlock)
{
break;
}
pos = m_ClientEventHandlerMap.find(lpMsgBlock->GetID());
if(pos != end)
{
// <20>̹<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Handler<65><72> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>̴<EFBFBD>.
CClientEventHandler* lpHandler = pos->second;
switch(lpMsgBlock->GetMsgType())
{
case NET_MSG_ACK_DISPATCH:
if (-1 == lpHandler->OnDispatch(
reinterpret_cast<PktBase*>(lpMsgBlock->rd_ptr()), lpMsgBlock->GetAddress()))
{
Close(lpHandler);
}
break;
case NET_MSG_ACK_OPEN:
{
// <20>ɵ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD> Handler<65><72> <20>̹<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
int nErrorCode = 0;
DWORD dwSessionID = 0;
lpMsgBlock->pop(nErrorCode);
lpMsgBlock->pop(dwSessionID);
lpHandler->SetSessionID(dwSessionID);
if(-1 == lpHandler->OnOpen(nErrorCode))
{
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD> <20>ݱ⸦ ȣ<><C8A3><EFBFBD>Ѵ<EFBFBD>.
if(0 == nErrorCode)
{
Close(lpHandler);
}
}
if (0 != nErrorCode)
{
lpHandler->OnClose();
}
}
break;
case NET_MSG_ACK_CLOSE:
lpHandler->OnClose();
// <20>ڵ鷯<DAB5><E9B7AF> <20><><EFBFBD><EFBFBD><EFBFBD>մϴ<D5B4>.
delete lpHandler;
m_ClientEventHandlerMap.erase(pos);
end = m_ClientEventHandlerMap.end();
break;
}
}
else
{
// TODO : Accept<70><74> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD>, Handler<65><72> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʴ´<CAB4>. <20><><EFBFBD><EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20>̰<EFBFBD><CCB0><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ְ<EFBFBD>,
// <20>޽<EFBFBD><DEBD><EFBFBD><EFBFBD><EFBFBD> <20>ѹ<EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.(CThreadEventHandler<65><72> EventID<49><44> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20>ֵ<EFBFBD><D6B5><EFBFBD>..)
}
lpMsgBlock->SetMsgType(NET_MSG_FREE);
CNetworkMsgPool::GetInstance().FreeNetworkMsgBlock(lpMsgBlock);
}
}
bool CClientEventHandlerMgr::Connect(INET_Addr& connAddr, CClientEventHandler* lpEventHandler)
{
if (0 == lpEventHandler)
{
fprintf(stderr, "CClientEventHandlerMgr::Connect - EventHandler is NULL\n");
return false;
}
CNetworkMsgBlock* lpMsgBlock =
CNetworkMsgPool::GetInstance().GetNetworkMsgBlock(1, connAddr);
if(0 == lpMsgBlock || !lpMsgBlock->is_valid())
{
fprintf(stderr, "CClientEventHandlerMgr::Connect - NetMsgBlock Create Failed\n");
return false;
}
DWORD dwHandlerID = 0;
ClientEventHanderMap::iterator pos;
ClientEventHanderMap::iterator end = m_ClientEventHandlerMap.end();
do
{
// <20><> <20><><EFBFBD><EFBFBD>ID<49><44> ã<>´<EFBFBD>.
dwHandlerID = ++m_dwMaxEventHandlerID;
pos = m_ClientEventHandlerMap.find(dwHandlerID);
}
while(pos != end);
m_ClientEventHandlerMap.insert(
ClientEventHanderMap::value_type(dwHandlerID, lpEventHandler));
lpEventHandler->SetHandlerID(dwHandlerID);
lpEventHandler->SetPeerAddress(connAddr);
lpEventHandler->SetEventHandlerMgr(this);
lpMsgBlock->SetAddress(connAddr);
lpMsgBlock->SetMsgType(NET_MSG_REQ_TCP_OPEN);
lpMsgBlock->SetID(dwHandlerID);
m_SessionMgr.PutMessage(lpMsgBlock);
return true;
}
bool CClientEventHandlerMgr::Close(CClientEventHandler* lpEventHandler)
{
CNetworkMsgBlock* lpMsgBlock =
CNetworkMsgPool::GetInstance().GetNetworkMsgBlock(1, INET_Addr());
if(0 == lpMsgBlock || !lpMsgBlock->is_valid())
{
fprintf(stderr, "CClientEventHandlerMgr::Close - NetMsgBlock Create Failed\n");
return false;
}
lpEventHandler->SetCloseCalled();
lpMsgBlock->SetMsgType(NET_MSG_REQ_CLOSE);
lpMsgBlock->SetID(lpEventHandler->GetSessionID());
m_SessionMgr.PutMessage(lpMsgBlock);
return true;
}
bool CClientEventHandlerMgr::SendPacket(CClientEventHandler* lpEventHandler, CNetworkMsgBlock* lpMsgBlock)
{
if (0 != lpEventHandler && 0 != lpMsgBlock)
{
lpMsgBlock->SetMsgType(NET_MSG_REQ_SEND);
lpMsgBlock->SetID(lpEventHandler->GetSessionID());
m_SessionMgr.PutMessage(lpMsgBlock);
return true;
}
return false;
}
unsigned int CClientEventHandlerMgr::Run()
{
while(!InterlockedCompareExchange(&m_bExit, TRUE, TRUE))
{
m_SessionMgr.HandleEvents(1000);
}
return true;
}
BOOL CClientEventHandlerMgr::End()
{
InterlockedExchange(&m_bExit, TRUE);
return TRUE;
}
CThreadEventHandler::CThreadEventHandler(CLockedMsgQueue& LockedMsgQueue, DWORD dwClientHandlerID)
: m_LockedMsgQueue(LockedMsgQueue),
m_Crypt(CXORCrypt::GetInstance()),
m_dwClientHandlerID(dwClientHandlerID),
CEventHandler(60) // 1<>и<EFBFBD><D0B8><EFBFBD> ȣ<><C8A3><EFBFBD>Ѵ<EFBFBD>.
{
}
// <20><>Ŷ<EFBFBD><C5B6> <20>޾<EFBFBD><DEBE><EFBFBD> <20><> <20>Ҹ<EFBFBD><D2B8><EFBFBD>. <20><>ü<EFBFBD><C3BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>޽<EFBFBD><DEBD><EFBFBD> ť<><C5A5><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
int CThreadEventHandler::OnReceived(CNetworkMsgBlock& msg_block)
{
const int MAX_PACKET_PER_RECV = 32;
char* rd_ptr = 0;
PktBase* lpPktBase = 0;
DWORD length = static_cast<unsigned long>(msg_block.length());
DWORD decompress_len = 0;
CNetworkMsgBlock* lpNewMsgBlock = 0;
CNetworkMsgPool& netMessagePool = CNetworkMsgPool::GetInstance();
CNetworkMsgQueue netMsgQueue;
while(sizeof(PktBase) <= length)
{
rd_ptr = msg_block.rd_ptr();
lpPktBase = reinterpret_cast<PktBase*>(rd_ptr);
// <20><>Ŷ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> vaild<6C><64><EFBFBD><EFBFBD> Ȯ<><C8AE><EFBFBD>Ѵ<EFBFBD>. invalid<69><64> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>׳<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
if(StartBit != lpPktBase->GetStartBit())
{
fprintf(stderr, "CClientEventHandler::OnReceived - Packet header is invalid. Not equal startbit\n");
return -1;
}
// <20><>Ŷ <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ڵ<EFBFBD>
m_Crypt.DecodeHeader(rd_ptr + 1, sizeof(PktBase) - 1, 0, 0);
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
const PktBase::CMDType nPacketCMD = lpPktBase->GetCmd();
const PktBase::LengthType nPacketLength = lpPktBase->GetLen();
if(length < nPacketLength)
{
// <20><>ü <20><>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD><EFBFBD><20>Ľ<EFBFBD><C4BD><EFBFBD> <20>ϱ<CFB1><E2BFA1> <20><><EFBFBD>ڶ<EFBFBD>. <20>ٽ<EFBFBD> <20><><EFBFBD>ڵ<EFBFBD> <20><> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ٸ<EFBFBD>
m_Crypt.EncodeHeader(rd_ptr + 1, sizeof(PktBase) - 1, 0, 0);
break;
}
else
{
// <20><>Ŷ <20><><EFBFBD>ڵ<EFBFBD>.
if(lpPktBase->IsCrypt())
{
m_Crypt.DecodePacket(rd_ptr + sizeof(PktBase),
nPacketLength - sizeof(PktBase), lpPktBase->GetCodePage());
}
// <20><>Ŷ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
if(lpPktBase->IsCompress())
{
decompress_len = PktMaxLen - sizeof(PktBase);
lpNewMsgBlock = netMessagePool.GetNetworkMsgBlock(PktMaxLen, msg_block.GetAddress());
if(0 == lpNewMsgBlock)
{
fprintf(stderr, "CClientEventHandler::OnReceived - Create NetworkMsgBlock Failed for Decompress\n");
return -1;
}
char* szDecompressedPacket = lpNewMsgBlock->wr_ptr();
memcpy(szDecompressedPacket, lpPktBase, sizeof(PktBase));
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ۿ<EFBFBD><DBBF><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
if(!CMiniLZO::Decompress(rd_ptr + sizeof(PktBase), nPacketLength - sizeof(PktBase),
szDecompressedPacket + sizeof(PktBase), &decompress_len))
{
netMessagePool.FreeNetworkMsgBlock(lpNewMsgBlock);
fprintf(stderr, "CClientEventHandler::OnReceived - Decompress Packet Failed\n");
return -1;
}
lpNewMsgBlock->wr_ptr(decompress_len + sizeof(PktBase));
lpPktBase = reinterpret_cast<PktBase*>(lpNewMsgBlock->rd_ptr());
lpPktBase->SetLen(static_cast<PktBase::LengthType>(decompress_len + sizeof(PktBase)));
}
else
{
lpNewMsgBlock = netMessagePool.GetNetworkMsgBlock(nPacketLength, msg_block.GetAddress());
if(0 == lpNewMsgBlock)
{
fprintf(stderr, "CClientEventHandler::OnReceived - Create NetworkMsgBlock Failed for Enqueue\n");
return -1;
}
memcpy(lpNewMsgBlock->wr_ptr(), rd_ptr, nPacketLength);
lpNewMsgBlock->wr_ptr(nPacketLength);
}
lpNewMsgBlock->SetMsgType(NET_MSG_ACK_DISPATCH);
lpNewMsgBlock->SetID(m_dwClientHandlerID);
netMsgQueue.Enqueue(lpNewMsgBlock);
length -= nPacketLength;
msg_block.rd_ptr(nPacketLength);
}
}
m_LockedMsgQueue.PutMessages(netMsgQueue);
return 0;
}
int CThreadEventHandler::OnOpen(CSession& ConnSession, int iErrorCode)
{
CNetworkMsgBlock* lpNewMsgBlock =
CNetworkMsgPool::GetInstance().GetNetworkMsgBlock(
sizeof(int) + sizeof(unsigned long), INET_Addr());
if(0 == lpNewMsgBlock)
{
fprintf(stderr, "CThreadEventHandler::OnOpen - NetMsgBlock Create Failed\n");
return -1;
}
lpNewMsgBlock->SetMsgType(NET_MSG_ACK_OPEN);
lpNewMsgBlock->SetID(m_dwClientHandlerID);
lpNewMsgBlock->push(iErrorCode);
lpNewMsgBlock->push(ConnSession.GetSessionID());
m_LockedMsgQueue.PutMessage(lpNewMsgBlock);
return 0;
}
int CThreadEventHandler::OnClose(CSession& CloseSession)
{
CNetworkMsgBlock* lpNewMsgBlock =
CNetworkMsgPool::GetInstance().GetNetworkMsgBlock(1, INET_Addr());
if(0 == lpNewMsgBlock)
{
fprintf(stderr, "CThreadEventHandler::OnClose - NetMsgBlock Create Failed\n");
return -1;
}
lpNewMsgBlock->SetMsgType(NET_MSG_ACK_CLOSE);
lpNewMsgBlock->SetID(m_dwClientHandlerID);
m_LockedMsgQueue.PutMessage(lpNewMsgBlock);
return 0;
}
int CThreadEventHandler::OnTimeout(CSession& Session)
{
// Ping<6E><67> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
ClientNet::CNetworkMsgBlock* lpMsgBlock =
CNetworkMsgPool::GetInstance().GetNetworkMsgBlock(sizeof(PktSyP), INET_Addr());
if(0 != lpMsgBlock)
{
PktSyP* lpSyPAckPt = reinterpret_cast<PktSyP*>(lpMsgBlock->wr_ptr());
lpSyPAckPt->m_dwTickTime = timeGetTime();
if (lpMsgBlock->WrapCrypt(sizeof(PktSyP), CmdSysPing, 0))
{
Session.SendPending(lpMsgBlock);
}
else
{
CNetworkMsgPool::GetInstance().FreeNetworkMsgBlock(lpMsgBlock);
}
}
return 0;
}
}

View File

@@ -0,0 +1,117 @@
#ifndef _GAMA_CLIENT_EVENT_HANDLER_DERIVED_H_
#define _GAMA_CLIENT_EVENT_HANDLER_DERIVED_H_
#include <Thread/Lock.h>
#include <Thread/Thread.h>
#include <Network/ClientNetwork/EventHandler.h>
#include <Network/ClientNetwork/NetworkMsgBlock.h>
#include <Network/ClientNetwork/SessionMgr.h>
#include <map>
// forward decl.
struct PktBase;
class CXORCrypt;
namespace ClientNet
{
class CSessionMgr;
class CClientEventHandlerMgr;
// Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ<EFBFBD><C6AE> <20>̺<EFBFBD>Ʈ <20>ڵ鷯
class CClientEventHandler
{
public:
CClientEventHandler();
virtual ~CClientEventHandler();
virtual int OnDispatch(PktBase* lpPktBase, INET_Addr& peerAddr) = 0;
virtual int OnOpen(int iErrorCode) = 0;
virtual int OnClose() = 0;
DWORD GetHandlerID() const { return m_dwHandlerID; }
DWORD GetSessionID() const { return m_dwSessionID; }
INET_Addr& GetPeerAddress() { return m_peerAddress; }
bool IsCloseCalled() { return m_bCloseCalled; }
bool SendPacket(CNetworkMsgBlock* lpMsgBlock);
private:
void SetHandlerID(DWORD dwHandlerID) { m_dwHandlerID = dwHandlerID; }
void SetSessionID(DWORD dwSessionID) { m_dwSessionID = dwSessionID; }
void SetCloseCalled() { m_bCloseCalled = true; }
void SetPeerAddress(INET_Addr& peerAddress) { m_peerAddress = peerAddress; }
void SetEventHandlerMgr(CClientEventHandlerMgr* lpEventHandlerMgr) { m_lpEventHandlerMgr = lpEventHandlerMgr; }
CClientEventHandlerMgr* m_lpEventHandlerMgr;
DWORD m_dwHandlerID;
DWORD m_dwSessionID;
INET_Addr m_peerAddress;
bool m_bCloseCalled;
// <20><><EFBFBD><EFBFBD> ID<49><44><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ؼ<EFBFBD> <20>ʿ<EFBFBD><CABF><EFBFBD>.
friend class CClientEventHandlerMgr;
};
// Ŭ<><C5AC><EFBFBD>̾<EFBFBD>Ʈ <20>ڵ鷯 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
class CClientEventHandlerMgr : public CThread
{
public:
CClientEventHandlerMgr();
virtual ~CClientEventHandlerMgr();
bool Connect(INET_Addr& connAddr, CClientEventHandler* lpEventHandler);
bool Close(CClientEventHandler* lpEventHandler);
bool SendPacket(CClientEventHandler* lpEventHandler, CNetworkMsgBlock* lpMsgBlock);
void HandleEvents(unsigned long dwProcessPerCall);
private:
virtual unsigned int Run(); // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ǵ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ִ´<D6B4>.
virtual BOOL End(); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20>ִ<EFBFBD> <20><>ƾ<EFBFBD><C6BE> <20>ִ´<D6B4>.
typedef std::map<DWORD, CClientEventHandler*> ClientEventHanderMap;
CLockedMsgQueue m_LockedMsgQueue;
CNetworkMsgQueue m_LocalMsgQueue;
ClientEventHanderMap m_ClientEventHandlerMap;
DWORD m_dwMaxEventHandlerID;
LONG m_bExit;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ο<EFBFBD><CEBF><EFBFBD> <20><><EFBFBD><EFBFBD>.
CSessionMgr m_SessionMgr;
};
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>̺<EFBFBD>Ʈ <20>ڵ鷯
class CThreadEventHandler : public CEventHandler
{
public:
CThreadEventHandler(CLockedMsgQueue& LockedMsgQueue, DWORD dwClientHandlerID);
virtual int OnReceived(CNetworkMsgBlock& msg_block);
virtual int OnDispatch(CSession& ReceivedSession) { return 0; }
virtual int OnOpen(CSession& ConnSession, int iErrorCode);
virtual int OnClose(CSession& CloseSession);
virtual int OnTimeout(CSession& Session);
private:
CLockedMsgQueue& m_LockedMsgQueue;
CXORCrypt& m_Crypt;
DWORD m_dwClientHandlerID;
};
};
#endif

View File

@@ -0,0 +1,49 @@
#ifndef _GAMA_CLIENT_EVENT_HANDLER_H_
#define _GAMA_CLIENT_EVENT_HANDLER_H_
namespace ClientNet
{
// forward decl.
class CSession;
class CNetworkMsgBlock;
class CEventHandler
{
public:
CEventHandler(DWORD dwTimeoutSec = 1)
: m_dwTimeoutSec(dwTimeoutSec), m_dwLastCalled(0)
{
}
virtual ~CEventHandler() { }
virtual int OnReceived(CNetworkMsgBlock& msg_block) = 0; // <20><>Ŷ<EFBFBD><C5B6> <20>޾<EFBFBD><DEBE><EFBFBD> <20><> <20>Ҹ<EFBFBD><D2B8><EFBFBD>.
virtual int OnOpen(CSession& ConnSession, int iErrorCode) = 0; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ϸ<EFBFBD><CFB7>Ǿ<EFBFBD><C7BE><EFBFBD> <20><> <20>Ҹ<EFBFBD><D2B8><EFBFBD>. (<28><><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD>. UDP<44><50> <20>ش<EFBFBD> <20><><EFBFBD><EFBFBD>)
virtual int OnClose(CSession& CloseSession) = 0; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20>Ҹ<EFBFBD><D2B8><EFBFBD>. (UDP<44><50> <20>ش<EFBFBD> <20><><EFBFBD><EFBFBD>)
virtual int OnDispatch(CSession& ReceivedSession) = 0; // <20>޽<EFBFBD><DEBD><EFBFBD><EFBFBD><EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20><> <20>Ҹ<EFBFBD><D2B8><EFBFBD>.
virtual int OnTimeout(CSession& Session) = 0; // <20><><EFBFBD><EFBFBD> <20>ð<EFBFBD><C3B0><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ȣ<><C8A3><EFBFBD>ȴ<EFBFBD>. <20><EFBFBD><E2BABB> <20><><EFBFBD>ʸ<EFBFBD><CAB8><EFBFBD> <20>Ҹ<EFBFBD><D2B8><EFBFBD>.
bool IsTimeout(DWORD dwCurrentTime) const
{
return (0 == m_dwLastCalled) ||
(m_dwLastCalled + (m_dwTimeoutSec * 1000) < dwCurrentTime);
}
void UpdateTimeoutCalled(DWORD dwCurrentTime)
{
m_dwLastCalled = dwCurrentTime;
if (0 == m_dwLastCalled) { ++m_dwLastCalled; }
}
protected:
DWORD m_dwTimeoutSec;
DWORD m_dwLastCalled;
};
};
#endif

View File

@@ -0,0 +1,104 @@
#include "stdafx.h"
#include "MessageBlock.h"
#include <xmemory>
#include "GMMemory.h"
CMessageBlock::CMessageBlock()
: internal_buffer_(0), rd_ptr_(0), wr_ptr_(0), buffer_size_(0)
{
}
CMessageBlock::CMessageBlock(size_t n)
: internal_buffer_(0), rd_ptr_(0), wr_ptr_(0), buffer_size_(0)
{
init(n);
}
CMessageBlock::~CMessageBlock()
{
destroy();
}
bool CMessageBlock::init(size_t n)
{
if(buffer_size_ < n)
{
destroy();
internal_buffer_ = new char[n];
}
rd_ptr_ = wr_ptr_ = internal_buffer_;
buffer_size_ = n;
return (0 != internal_buffer_);
}
void CMessageBlock::destroy()
{
if(NULL != internal_buffer_)
{
delete [] internal_buffer_;
}
buffer_size_ = 0;
rd_ptr_ = wr_ptr_ = internal_buffer_ = 0;
}
bool CMessageBlock::push(const void* ptr, size_t n)
{
if(NULL != wr_ptr_ && n <= capacity() - length())
{
memcpy(wr_ptr_, ptr, n);
wr_ptr_ += n;
return true;
}
return false;
}
void CMessageBlock::pop_read_data()
{
if(NULL != internal_buffer_)
{
size_t n = length();
memmove(internal_buffer_, rd_ptr_, n);
wr_ptr_ = internal_buffer_ + n;
rd_ptr_ = internal_buffer_;
}
}
CMessageBlock* CMessageBlock::clone(CMessageBlock& msg_block)
{
CMessageBlock* lpMessageBlock = new CMessageBlock(msg_block.length());
if(NULL != lpMessageBlock)
{
memcpy(lpMessageBlock->wr_ptr(), msg_block.rd_ptr(), msg_block.length());
lpMessageBlock->wr_ptr(msg_block.length());
return lpMessageBlock;
}
return NULL;
}
bool CMessageBlock::resize(size_t n)
{
char* temp_buffer = new char[n];
if(NULL != temp_buffer)
{
memcpy(temp_buffer, internal_buffer_,
(buffer_size_ < n) ? n : buffer_size_);
rd_ptr_ = temp_buffer + (rd_ptr_ - internal_buffer_);
wr_ptr_ = temp_buffer + (wr_ptr_ - internal_buffer_);
std::swap(internal_buffer_,temp_buffer);
delete [] temp_buffer;
return true;
}
return false;
}

View File

@@ -0,0 +1,82 @@
#ifndef _CLIENTSOCKET_MESSAGE_BLOCK_H_
#define _CLIENTSOCKET_MESSAGE_BLOCK_H_
class CMessageBlock
{
public:
explicit CMessageBlock();
explicit CMessageBlock(size_t n);
virtual ~CMessageBlock();
bool is_valid() { return 0 != internal_buffer_; }
// <20>б<EFBFBD> - <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
char* rd_ptr() const { return rd_ptr_; }
void rd_ptr(size_t n) { rd_ptr_ += n; }
void rd_ptr(char* ptr) { rd_ptr_ = ptr; }
char* wr_ptr() const { return wr_ptr_; }
void wr_ptr(size_t n) { wr_ptr_ += n; }
void wr_ptr(char* ptr) { wr_ptr_ = ptr; }
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(past-end) <20><> <20><><EFBFBD><EFBFBD>.
char* begin() const { return internal_buffer_; }
char* end() const { return internal_buffer_ + buffer_size_; }
// <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> <20><><EFBFBD>۷<EFBFBD> <20><><EFBFBD><EFBFBD>.
bool push(const void* ptr, size_t n);
template<typename T>
bool push(const T& t)
{
if(0 != wr_ptr_ && sizeof(T) <= capacity() - length())
{
memcpy(wr_ptr_, &t, sizeof(T));
wr_ptr_ += sizeof(T);
return true;
}
return false;
}
template<typename T>
bool pop(T& t)
{
if(0 != rd_ptr_ && sizeof(T) <= length())
{
memcpy(&t, rd_ptr_, sizeof(T));
rd_ptr_ += sizeof(T);
return true;
}
return false;
}
// <20>̹<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><CDB5><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. <20><> <20><><EFBFBD><EFBFBD><EFBFBD>͵<EFBFBD><CDB5><EFBFBD> <20><>ȿȭ<C8BF><C8AD>.
void pop_read_data();
size_t length() const { return wr_ptr_ - rd_ptr_; } // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
size_t capacity() const { return buffer_size_; } // <20><><EFBFBD><EFBFBD> ũ<><C5A9>
size_t remain() const { return internal_buffer_ + buffer_size_ - wr_ptr_; } // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD> <20>ڽ<EFBFBD><DABD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
static CMessageBlock* clone(CMessageBlock& msg_block);
// <20><><EFBFBD><EFBFBD> ũ<><20>ø<EFBFBD><C3B8><EFBFBD>.
bool resize(size_t n);
// <20>ʱ<EFBFBD>ȭ
bool init(size_t n);
private:
void destroy();
char* internal_buffer_;
char* rd_ptr_;
char* wr_ptr_;
size_t buffer_size_;
};
#endif

View File

@@ -0,0 +1,543 @@
#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();
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ڵ<EFBFBD>
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();
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ڵ<EFBFBD>
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();
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ڵ<EFBFBD>
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();
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ڵ<EFBFBD>
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();
// <20><><EFBFBD>ڵ<EFBFBD> <20><><EFBFBD><EFBFBD>
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;
}
}
}

View File

@@ -0,0 +1,167 @@
#ifndef _GAMA_CLIENT_NETWORK_BLOCK_MSG_
#define _GAMA_CLIENT_NETWORK_BLOCK_MSG_
#include <Thread/Lock.h>
#include <Network/Address/INET_Addr.h>
#include "MessageBlock.h"
#include <list>
namespace ClientNet
{
enum NetMsgType
{
NET_MSG_FREE,
NET_MSG_ACK_OPEN,
NET_MSG_ACK_CLOSE,
NET_MSG_ACK_DISPATCH,
NET_MSG_REQ_TCP_OPEN,
NET_MSG_REQ_UDP_OPEN,
NET_MSG_REQ_CLOSE,
NET_MSG_REQ_SEND
};
// Network Message Block
class CNetworkMsgBlock : public CMessageBlock
{
public:
void SetMsgType(NetMsgType eMsgType) { m_eMsgType = eMsgType; }
NetMsgType GetMsgType() const { return m_eMsgType; }
void SetID(DWORD dwID) { m_dwID = dwID; }
DWORD GetID() const { return m_dwID; }
INET_Addr& GetAddress() { return m_dstaddr; }
void SetAddress(INET_Addr& addr) { m_dstaddr = addr; }
bool WrapHeader(unsigned short usUsed_In, unsigned char cCMD_In, unsigned short usState_In, unsigned short usError_In);
bool WrapCryptOld(unsigned short usUsed_In, unsigned char cCMD_In, unsigned short usState_In, unsigned short usError_In);
bool WrapCryptOld(unsigned short usUsed_In, unsigned char cCMD_In, unsigned long Tick_In);
bool WrapCrypt(unsigned short usUsed_In, unsigned char cCMD_In, unsigned short usState_In, unsigned short usError_In);
bool WrapCrypt(unsigned short usUsed_In, unsigned char cCMD_In, unsigned long Tick_In);
bool WrapCompress(char* lpSourceData, unsigned short usSourceLength, unsigned char cCMD_In, unsigned short usState_In, unsigned short usError_In);
static unsigned long GetMinCompressSize(unsigned short usSourceLength);
CNetworkMsgBlock* next() { return m_next; }
private:
void next(CNetworkMsgBlock* next) { m_next = next; }
explicit CNetworkMsgBlock(size_t n);
explicit CNetworkMsgBlock(size_t n, INET_Addr& addr);
virtual ~CNetworkMsgBlock();
INET_Addr m_dstaddr;
NetMsgType m_eMsgType;
DWORD m_dwID;
CNetworkMsgBlock* m_next;
friend class CSession;
friend class CNetworkMsgQueue;
friend class CNetworkMsgPool;
};
// Network Message Queue
class CNetworkMsgQueue
{
public:
CNetworkMsgQueue();
~CNetworkMsgQueue();
void clear();
CNetworkMsgBlock* GetHead() { return m_lpListHead; }
CNetworkMsgBlock* GetTail() { return m_lpListTail; }
long GetQueuedNum() { return m_nListNum; }
void Enqueue(CNetworkMsgBlock* lpMsgBlock, bool bPendHead = false);
CNetworkMsgBlock* Dequeue();
private:
CNetworkMsgBlock* m_lpListHead;
CNetworkMsgBlock* m_lpListTail;
long m_nListNum;
};
class CNetworkMsgPool
{
public:
static CNetworkMsgPool& GetInstance();
CNetworkMsgBlock* GetNetworkMsgBlock(unsigned long dwSize, INET_Addr& addr);
void FreeNetworkMsgBlock(CNetworkMsgBlock* lpMsgBlock);
void FreeNetworkMsgBlock(CNetworkMsgQueue& msgQueue);
private:
CNetworkMsgPool();
~CNetworkMsgPool();
typedef CCSLock MsgBlockLock;
typedef std::list<CNetworkMsgBlock*> MsgBlockList;
MsgBlockLock m_MsgBlockLock;
MsgBlockList m_MsgBlockList;
DWORD m_dwMaxBlockNum;
};
class CLockedMsgQueue
{
public:
typedef CCSLock MsgQueueLock;
virtual ~CLockedMsgQueue();
CNetworkMsgBlock* GetMessage();
void GetMessages(CNetworkMsgQueue& msgQueue, DWORD dwItemNum);
void PutMessage(CNetworkMsgBlock* lpMsg, bool bPendHead = false);
void PutMessages(CNetworkMsgQueue& msgQueue);
private:
MsgQueueLock m_MsgQueueLock;
CNetworkMsgQueue m_MessageQueue;
};
class CUnboundedWaitableMsgQueue
{
public:
typedef CCSLock MsgQueueLock;
CUnboundedWaitableMsgQueue();
virtual ~CUnboundedWaitableMsgQueue();
const HANDLE GetQueueHandle() const { return m_hNotEmpty; }
DWORD WaitForNotEmptyQueue(DWORD dwMilliseconds = INFINITE);
CNetworkMsgBlock* GetMessage();
void GetMessages(CNetworkMsgQueue& msgQueue, DWORD dwItemNum);
void PutMessage(CNetworkMsgBlock* lpMsg, bool bPendHead = false);
void PutMessages(CNetworkMsgQueue& msgQueue);
private:
void InternalSetNotEmpty();
void InternalResetNotEmpty();
HANDLE m_hNotEmpty; // Auto-reset Event
bool m_bNotEmpty;
MsgQueueLock m_MsgQueueLock;
CNetworkMsgQueue m_MessageQueue;
};
}
#endif

View File

@@ -0,0 +1,24 @@
#ifndef _GAMA_CLIENT_NET_NULL_HANDLER_H_
#define _GAMA_CLIENT_NET_NULL_HANDLER_H_
#include "ClientEventHandler.h"
namespace ClientNet
{
class CNullClientEventHandler : public CClientEventHandler
{
public:
static CNullClientEventHandler& GetInstance()
{
static CNullClientEventHandler nullHandler;
return nullHandler;
}
virtual int OnDispatch(PktBase* lpPktBase, INET_Addr& peerAddr) { return 0; }
virtual int OnOpen(int iErrorCode) { return 0; }
virtual int OnClose() { return 0; }
};
}
#endif

View File

@@ -0,0 +1,36 @@
#ifndef _GAMA_CLIENT_NULL_SESSION_H_
#define _GAMA_CLIENT_NULL_SESSION_H_
#include "Session.h"
#include "NullHandler.h"
#include <cstdio>
namespace ClientNet
{
class NullSession : public CSession
{
public:
NullSession(CSessionMgr& SessionMgr)
: CSession(SessionMgr, &NullHandler::GetInstance())
{
}
virtual ~NullSession() { m_lpEventHandler = NULL; }
virtual CNetworkMsgBlock* GetNetworkMsgBlock(unsigned long dwSize, INET_Addr& addr, unsigned char cCmd)
{
fprintf(stderr, "SessionName:%s\tCmd:0x%02x\tReqSize:%6u\tNullSession cannot create message block!.\n",
GetSessionName(), cCmd, dwSize);
return NULL;
}
virtual int Open(INET_Addr& addr) { return 0; }
virtual int Open(INET_Addr& addr, SOCKET hSocket) { return 0; } // Passive Socket
virtual int Recv() { return 0; }
virtual int Send(unsigned long dwMaxSendCount) { return 0; }
};
}
#endif

View File

@@ -0,0 +1,124 @@
#include "stdafx.h"
#include "Session.h"
#include "SessionMgr.h"
#include "EventHandler.h"
#include <cstdio>
#include "GMMemory.h"
const int RECEIVE_BLOCK_SIZE = 65535;
const int MAX_RECV_NUM_PER_PULSE = 20;
const int MAX_SEND_NUM_PER_PULSE = 20;
namespace ClientNet
{
enum SessionFlags
{
SHUTDOWN_CALLED = (1 << 1),
CLOSE_CALLED = (1 << 2)
};
}
ClientNet::CSession::CSession(DWORD dwSessionID, CEventHandler* lpEventHandler)
: m_dwSessionID(dwSessionID),
m_hSocket(INVALID_SOCKET),
m_hEvent(WSACreateEvent()),
m_lpEventHandler(lpEventHandler),
m_Received(RECEIVE_BLOCK_SIZE),
m_dwMaxRecvNumPerPulse(MAX_RECV_NUM_PER_PULSE),
m_dwMaxSendNumPerPulse(MAX_SEND_NUM_PER_PULSE),
m_dwFlags(0)
{
memset(m_szSessionName, 0, sizeof(char) * MAX_SESSION_NAME);
}
ClientNet::CSession::~CSession()
{
Close();
if(WSA_INVALID_EVENT != m_hEvent)
{
WSACloseEvent(m_hEvent);
m_hEvent = WSA_INVALID_EVENT;
}
delete m_lpEventHandler;
m_lpEventHandler = 0;
}
bool ClientNet::CSession::IsValid()
{
if(NULL == m_lpEventHandler)
{
fprintf(stderr, "ClientNet::CSession::IsValid - Handler is Invalid (NULL)\n");
return false;
}
if(WSA_INVALID_EVENT == m_hEvent)
{
fprintf(stderr, "ClientNet::CSession::IsValid - Event is Invalid (WSA_INVALID_EVENT)\n");
return false;
}
if(!m_Received.is_valid())
{
fprintf(stderr, "ClientNet::CSession::IsValid - Receive MsgBlock is Invalid\n");
return false;
}
return true;
}
int ClientNet::CSession::Shutdown(int how)
{
if(INVALID_SOCKET != m_hSocket)
{
bool bFailed = false;
while(!bFailed && 0 != m_SendQueue.GetQueuedNum())
{
bFailed = (0 == Send(0xFFFFFFFF)) ? false : true;
}
m_dwFlags |= SHUTDOWN_CALLED;
if(SOCKET_ERROR == shutdown(m_hSocket, how))
{
return -1;
}
}
return 0;
}
int ClientNet::CSession::Close()
{
if(INVALID_SOCKET != m_hSocket)
{
Shutdown(SD_SEND);
if(SOCKET_ERROR == closesocket(m_hSocket))
{
fprintf(stderr, "ClientNet::CSession::Close - closesocket error : %d\n", WSAGetLastError());
return -1;
}
m_hSocket = INVALID_SOCKET;
m_dwFlags |= CLOSE_CALLED;
}
return 0;
}
bool ClientNet::CSession::IsShutdownCalled() const
{
return SHUTDOWN_CALLED == (m_dwFlags & SHUTDOWN_CALLED);
}
bool ClientNet::CSession::IsCloseCalled() const
{
return CLOSE_CALLED == (m_dwFlags & CLOSE_CALLED);
}

View File

@@ -0,0 +1,79 @@
#ifndef _GAMA_CLIENT_SESSION_H_
#define _GAMA_CLIENT_SESSION_H_
#include <winsock2.h>
#include <windows.h>
#include <Network/Address/INET_Addr.h>
#include "NetworkMsgBlock.h"
namespace ClientNet
{
// forward decl;
class CSessionMgr;
class CEventHandler;
class CSession
{
public:
enum
{
MAX_SESSION_NAME = 16
};
CSession(DWORD dwSessionID, CEventHandler* lpEventHandler);
virtual ~CSession();
DWORD GetSessionID() const { return m_dwSessionID; }
SOCKET GetSocket() const { return m_hSocket; }
WSAEVENT GetEvent() const { return m_hEvent; }
INET_Addr& GetPeerAddress() { return m_PeerAddress; }
CEventHandler* GetEventHandler() { return m_lpEventHandler; }
void SetEventHandler(CEventHandler* lpEventHandler) { m_lpEventHandler = lpEventHandler; }
bool IsValid();
// Active Mode
int Open(const char* addr, unsigned short port) { return Open(INET_Addr(addr, port)); }
virtual int Open(INET_Addr& addr) = 0; // Active Socket
virtual int Open(INET_Addr& addr, SOCKET hSocket) = 0; // Passive Socket
virtual int Recv() = 0;
virtual int Send(unsigned long dwMaxSendCount) = 0;
int Send() { return Send(m_dwMaxSendNumPerPulse); }
void SendPending(CNetworkMsgBlock* lpMsgBlock) { m_SendQueue.Enqueue(lpMsgBlock); Send(1); }
int Shutdown(int how);
int Close();
bool IsShutdownCalled() const;
bool IsCloseCalled() const;
const char* GetSessionName() { return m_szSessionName; }
protected:
DWORD m_dwSessionID;
SOCKET m_hSocket;
WSAEVENT m_hEvent;
CEventHandler* m_lpEventHandler;
unsigned long m_dwMaxRecvNumPerPulse;
unsigned long m_dwMaxSendNumPerPulse;
unsigned long m_dwFlags;
INET_Addr m_PeerAddress;
CNetworkMsgQueue m_SendQueue;
CNetworkMsgBlock m_Received;
char m_szSessionName[MAX_SESSION_NAME];
};
}
#endif

View File

@@ -0,0 +1,405 @@
#include "stdafx.h"
#include "SessionMgr.h"
#include "ClientEventHandler.h"
#include "TCPSession.h"
#include "UDPSession.h"
#include <algorithm>
#include <ctime>
#include <mmsystem.h>
#include "GMMemory.h"
const int MAX_DEFAULT_BLOCK_NUM = 100;
const int DEFAULT_BLOCK_SIZE = 16384;
namespace ClientNet
{
CSessionMgr::CSessionMgr()
: m_dwMaxSessionID(0), m_lpLockedMsgQueue(0)
{
memset(m_hHandleSet, 0, sizeof(HANDLE) * MAXIMUM_WAIT_OBJECTS);
WSADATA wsaData;
WSAStartup(0x0202, &wsaData);
RearrangeHandleSet();
}
CSessionMgr::~CSessionMgr()
{
SessionMap::iterator end = m_SessionMap.end();
SessionMap::iterator pos = m_SessionMap.begin();
for(;pos != end; ++pos)
{
delete pos->second;
}
m_SessionMap.clear();
WSACleanup();
}
int CSessionMgr::Connect(INET_Addr& address, NetMsgType eNetMsgType, DWORD dwHandlerID)
{
if (MAXIMUM_WAIT_OBJECTS + 1 <= m_SessionMap.size())
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʹ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD>.
return -1;
}
if (0 == m_lpLockedMsgQueue)
{
// <20>޽<EFBFBD><DEBD><EFBFBD> ť<><C5A5> <20><><EFBFBD>õ<EFBFBD><C3B5><EFBFBD> <20>ʾҽ<CABE><D2BD>ϴ<EFBFBD>.
return -1;
}
DWORD dwSessionID = 0;
SessionMap::iterator pos;
SessionMap::iterator end = m_SessionMap.end();
do
{
// <20><> <20><><EFBFBD><EFBFBD>ID<49><44> ã<>´<EFBFBD>.
dwSessionID = ++m_dwMaxSessionID;
pos = m_SessionMap.find(dwSessionID);
}
while(pos != end);
// <20><><EFBFBD><EFBFBD>, Ÿ<>Կ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> UDP<44><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20>ְ<EFBFBD> <20>Ѵ<EFBFBD>.
CSession* lpSession = 0;
#include "GMUndefNew.h"
CEventHandler* lpEventHandler =
new (std::nothrow) CThreadEventHandler(*m_lpLockedMsgQueue, dwHandlerID);
#include "GMRedefNew.h"
if(0 == lpEventHandler)
{
// <20>̺<EFBFBD>Ʈ <20>ڵ鷯 <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
return -1;
}
switch(eNetMsgType)
{
case NET_MSG_REQ_TCP_OPEN:
#include "GMUndefNew.h"
lpSession = new (std::nothrow) CTCPSession(dwSessionID, lpEventHandler);
#include "GMRedefNew.h"
break;
case NET_MSG_REQ_UDP_OPEN:
#include "GMUndefNew.h"
lpSession = new (std::nothrow) CUDPSession(dwSessionID, lpEventHandler);
#include "GMRedefNew.h"
break;
}
if(0 == lpSession || -1 == lpSession->Open(address))
{
delete lpSession;
return -1;
}
m_SessionMap.insert(SessionMap::value_type(dwSessionID, lpSession));
return 0;
}
void CSessionMgr::RearrangeHandleSet()
{
SessionMap::iterator pos = m_SessionMap.begin();
SessionMap::iterator end = m_SessionMap.end();
m_hHandleSet[0] = GetQueueHandle();
for (DWORD dwHandleIndex = 1; pos != end; ++pos, ++dwHandleIndex)
{
m_hHandleSet[dwHandleIndex] = pos->second->GetEvent();
}
}
int CSessionMgr::HandleEvents(DWORD dwMilliseconds)
{
SessionMap::iterator pos = m_SessionMap.begin();
SessionMap::iterator end = m_SessionMap.end();
CEventHandler* lpEventHandler = 0;
DWORD dwResult = WaitForMultipleObjects(
m_SessionMap.size() + 1, m_hHandleSet, FALSE, dwMilliseconds);
if (WAIT_FAILED != dwResult)
{
// Ÿ<>Ӿƿ<D3BE> <20>ɷȴ<C9B7> <20>ϴ<EFBFBD><CFB4><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD>и<EFBFBD> <20>ƴϸ<C6B4> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD>Ƽ<EFBFBD> üũ<C3BC><C5A9> <20><>.
unsigned long dwRemoveCount = 0;
// ť <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
if (-1 == HandleMsgQueue())
{
++dwRemoveCount;
}
// <20><>Ŷ ó<><C3B3><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
for (; pos != end;)
{
bool bRemove = false;
CSession* lpSession = pos->second;
lpEventHandler = lpSession->GetEventHandler();
if(0 == lpEventHandler)
{
fprintf(stderr, "CSessionMgr::HandleEvents - Session event handler is null\n");
bRemove = true;
}
else
{
int rc = WaitForSingleObject(lpSession->GetEvent(), 0);
if(WAIT_FAILED == rc)
{
fprintf(stderr, "CSessionMgr::HandleEvents - WaitForSingleObject failed : %d\n",
WSAGetLastError());
}
else if(WAIT_TIMEOUT != rc && -1 == HandleIO(lpSession))
{
bRemove = true;
}
}
if (-1 == lpEventHandler->OnDispatch(*lpSession))
{
bRemove = true;
}
DWORD dwCurrentTime = timeGetTime();
if (lpEventHandler->IsTimeout(dwCurrentTime))
{
if(-1 == lpEventHandler->OnTimeout(*lpSession))
{
bRemove = true;
}
lpEventHandler->UpdateTimeoutCalled(dwCurrentTime);
}
if (bRemove)
{
lpEventHandler->OnDispatch(*lpSession);
lpEventHandler->OnClose(*lpSession);
lpSession->Send();
lpSession->Close();
delete lpSession;
pos = m_SessionMap.erase(pos);
++dwRemoveCount;
}
else
{
++pos;
}
}
if (0 < dwRemoveCount)
{
RearrangeHandleSet();
}
}
return 0;
}
int CSessionMgr::HandleIO(CSession* lpSession)
{
WSANETWORKEVENTS netEvents;
memset(&netEvents, 0, sizeof(WSANETWORKEVENTS));
CEventHandler* lpEventHandler = lpSession->GetEventHandler();
// Enumerate the events
int rc = WSAEnumNetworkEvents(lpSession->GetSocket(), lpSession->GetEvent(), &netEvents);
if (SOCKET_ERROR == rc)
{
fprintf(stderr, "CSessionMgr::HandleIO - WSAEnumNetworkEvents failed: %d\n", WSAGetLastError());
return -1;
}
if (netEvents.lNetworkEvents & FD_CONNECT)
{
fprintf(stderr, "CSessionMgr::HandleIO - Connect : %d\n", netEvents.iErrorCode[FD_CONNECT_BIT]);
lpEventHandler->OnOpen(*lpSession, netEvents.iErrorCode[FD_CONNECT_BIT]);
}
if (netEvents.lNetworkEvents & FD_READ)
{
// Check for read error
if (netEvents.iErrorCode[FD_READ_BIT] == 0)
{
if (-1 == lpSession->Recv())
{
return -1;
}
}
else
{
fprintf(stderr, "CSessionMgr::HandleIO - FD_READ error %d\n",
netEvents.iErrorCode[FD_READ_BIT]);
return -1;
}
}
if (netEvents.lNetworkEvents & FD_WRITE)
{
// Check for write error
if (netEvents.iErrorCode[FD_WRITE_BIT] == 0)
{
if (-1 == lpSession->Send())
{
return -1;
}
}
else
{
fprintf(stderr, "CSessionMgr::HandleIO - FD_WRITE error %d\n",
netEvents.iErrorCode[FD_WRITE_BIT]);
return -1;
}
}
if (netEvents.lNetworkEvents & FD_CLOSE)
{
if (netEvents.iErrorCode[FD_CLOSE_BIT] == 0)
{
while(1)
{
// <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>д´<D0B4>.
rc = lpSession->Recv();
if(-1 == rc)
{
lpSession->Close();
return -1;
}
else if (rc != 0)
{
continue;
}
else
{
break;
}
}
// <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
if(-1 == lpSession->Send())
{
return -1;
}
}
else
{
fprintf(stderr, "CSessionMgr::HandleIO - FD_CLOSE error %d\n",
netEvents.iErrorCode[FD_CLOSE_BIT]);
return -1;
}
}
return 0;
}
int CSessionMgr::HandleMsgQueue()
{
CNetworkMsgQueue netMsgQueue;
GetMessages(netMsgQueue, 0xFFFFFFFF);
CNetworkMsgBlock* lpMsgBlock = 0;
DWORD dwHandleSetChange = 0;
DWORD dwEventHandlerID = 0;
SessionMap::iterator pos;
while (0 != (lpMsgBlock = netMsgQueue.Dequeue()))
{
bool bDeleteMsg = true;
switch(lpMsgBlock->GetMsgType())
{
case NET_MSG_REQ_TCP_OPEN:
case NET_MSG_REQ_UDP_OPEN:
dwEventHandlerID = lpMsgBlock->GetID();
if(0 == Connect(lpMsgBlock->GetAddress(),
lpMsgBlock->GetMsgType(), dwEventHandlerID))
{
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>. <20>ڵ<EFBFBD> set<65><74> <20><><EFBFBD><EFBFBD><EFBFBD>Ǿ<EFBFBD><C7BE><EFBFBD>. (<28>ݹ<EFBFBD><DDB9><EFBFBD> <20><><EFBFBD>߿<EFBFBD> OnOpenȣ<6E><C8A3><EFBFBD><EFBFBD> <20>߻<EFBFBD><DFBB>Ѵ<EFBFBD>)
++dwHandleSetChange;
}
else
{
// <20><><EFBFBD><EFBFBD> <20>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>̴<EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Callback<63><6B><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
int nError = WSAGetLastError();
if (0 == nError) { nError = INT_MAX; }
if(0 != m_lpLockedMsgQueue)
{
CNetworkMsgBlock* lpAckMsgBlock =
CNetworkMsgPool::GetInstance().GetNetworkMsgBlock(sizeof(int), INET_Addr());
if(0 != lpAckMsgBlock)
{
lpAckMsgBlock->SetID(dwEventHandlerID);
lpAckMsgBlock->SetMsgType(NET_MSG_ACK_OPEN);
lpAckMsgBlock->push(nError);
m_lpLockedMsgQueue->PutMessage(lpAckMsgBlock);
}
}
}
break;
case NET_MSG_REQ_CLOSE:
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ã<><C3A3> Shutdown/Close<73><65> ȣ<><C8A3><EFBFBD>Ѵ<EFBFBD>. (<28>ݹ<EFBFBD><DDB9><EFBFBD> <20><><EFBFBD>߿<EFBFBD> OnCloseȣ<65><C8A3><EFBFBD><EFBFBD> <20>߻<EFBFBD><DFBB>Ѵ<EFBFBD>)
pos = m_SessionMap.find(lpMsgBlock->GetID());
if (pos != m_SessionMap.end())
{
pos->second->Close();
}
break;
case NET_MSG_REQ_SEND:
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ã<><C3A3> <20><>Ŷ<EFBFBD><C5B6> <20><><EFBFBD><EFBFBD> ť<><C5A5> <20>ִ´<D6B4>. (<28>ݹ<EFBFBD><DDB9><EFBFBD> <20><><EFBFBD><EFBFBD>.)
pos = m_SessionMap.find(lpMsgBlock->GetID());
if (pos != m_SessionMap.end())
{
pos->second->SendPending(lpMsgBlock);
bDeleteMsg = false;
}
break;
}
if (bDeleteMsg)
{
lpMsgBlock->SetMsgType(NET_MSG_FREE);
CNetworkMsgPool::GetInstance().FreeNetworkMsgBlock(lpMsgBlock);
}
}
return (0 < dwHandleSetChange) ? -1 : 0;
}
}

View File

@@ -0,0 +1,48 @@
#ifndef _GAMA_CLIENT_SESSION_MGR_H_
#define _GAMA_CLIENT_SESSION_MGR_H_
#include "NetworkMsgBlock.h"
#include <map>
#pragma comment(lib, "ws2_32")
namespace ClientNet
{
class CSession;
class CSessionMgr : public CUnboundedWaitableMsgQueue
{
public:
CSessionMgr();
~CSessionMgr();
void SetDispatchQueue(CLockedMsgQueue& LockedMsgQueue) { m_lpLockedMsgQueue = &LockedMsgQueue; }
CLockedMsgQueue* GetDispatchQueue() { return m_lpLockedMsgQueue; }
int HandleEvents(DWORD dwMilliseconds = INFINITE);
private:
void RearrangeHandleSet();
// <20>ش<EFBFBD> <20><><EFBFBD>ǿ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> -1, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 0<><30> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
int Connect(INET_Addr& address, NetMsgType eNetMsgType, DWORD dwHandlerID);
int HandleIO(CSession* lpSession);
// <20>޽<EFBFBD><DEBD><EFBFBD> ť<><C5A5> <20><>Ŷ<EFBFBD><C5B6> ó<><C3B3><EFBFBD>Ѵ<EFBFBD>. HandleSet<65><74> <20><>ȭ<EFBFBD><C8AD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> -1<><31> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
int HandleMsgQueue();
typedef std::map<DWORD, CSession*> SessionMap;
DWORD m_dwMaxSessionID;
DWORD m_dwLastTimeoutCall;
CLockedMsgQueue* m_lpLockedMsgQueue;
SessionMap m_SessionMap;
HANDLE m_hHandleSet[MAXIMUM_WAIT_OBJECTS];
};
}
#endif

View File

@@ -0,0 +1,200 @@
#include "stdafx.h"
#include "TCPSession.h"
#include "SessionMgr.h"
#include "EventHandler.h"
#include <cstdio>
#include "GMMemory.h"
ClientNet::CTCPSession::CTCPSession(DWORD dwSessionID, CEventHandler* lpEventHandler)
: CSession(dwSessionID, lpEventHandler), m_bClosing(FALSE)
{
}
ClientNet::CTCPSession::~CTCPSession()
{
}
int ClientNet::CTCPSession::Open(INET_Addr& addr)
{
if(!IsValid())
{
fprintf(stderr, "ClientNet::CTCPSession::Open - Invalid Session, Can't open now.\n");
return -1;
}
if(INVALID_SOCKET != m_hSocket)
{
Close();
}
m_hSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, NULL, WSA_FLAG_OVERLAPPED);
if(INVALID_SOCKET == m_hSocket)
{
fprintf(stderr, "ClientNet::CTCPSession::Open - Socket create error : %d\n", WSAGetLastError());
return -1;
}
// EventSelect
int rc = WSAEventSelect(m_hSocket, m_hEvent, FD_CONNECT | FD_READ | FD_WRITE | FD_CLOSE);
if(SOCKET_ERROR == rc)
{
fprintf(stderr, "ClientNet::CTCPSession::Open - EventSelect error : %d\n", WSAGetLastError());
return -1;
}
// connect
rc = connect(m_hSocket, &addr.get_addr(), addr.get_size());
if(SOCKET_ERROR == rc)
{
int nError = WSAGetLastError();
if(WSAEWOULDBLOCK != nError)
{
fprintf(stderr, "ClientNet::CTCPSession::Open - Connect error : %d\n", nError);
return -1;
}
}
m_PeerAddress = addr;
return 0;
}
int ClientNet::CTCPSession::Open(INET_Addr& addr, SOCKET hSocket)
{
if(!IsValid())
{
fprintf(stderr, "ClientNet::CTCPSession::Open - Invalid Session, Can't open now.\n");
return -1;
}
if(INVALID_SOCKET == hSocket)
{
fprintf(stderr, "ClientNet::CTCPSession::Open - Invalid Socket, Can't open now.\n");
return -1;
}
Close();
m_hSocket = hSocket;
// EventSelect
int rc = WSAEventSelect(m_hSocket, m_hEvent, FD_READ | FD_WRITE | FD_CLOSE);
if(SOCKET_ERROR == rc)
{
fprintf(stderr, "ClientNet::CTCPSession::Open - EventSelect error : %d\n", WSAGetLastError());
return -1;
}
m_PeerAddress = addr;
return m_lpEventHandler->OnOpen(*this, 0);
}
int ClientNet::CTCPSession::Recv()
{
WSABUF wsaBuf;
for(unsigned long dwReadCount = 0;
dwReadCount < m_dwMaxRecvNumPerPulse || 0 == m_Received.remain();
++dwReadCount)
{
wsaBuf.buf = m_Received.wr_ptr();
wsaBuf.len = static_cast<unsigned long>(m_Received.remain());
DWORD dwReceived = 0;
DWORD dwFlags = 0;
int rc = WSARecv(m_hSocket, &wsaBuf, 1, &dwReceived, &dwFlags, NULL, NULL);
if(SOCKET_ERROR == rc)
{
if(WSAEWOULDBLOCK != WSAGetLastError())
{
fprintf(stderr, "ClientNet::CTCPSession::Recv - WSARecv error : %d\n", WSAGetLastError());
return -1;
}
else
{
return 0;
}
}
m_Received.wr_ptr(dwReceived);
if(-1 == m_lpEventHandler->OnReceived(m_Received))
{
fprintf(stderr, "ClientNet::CTCPSession::Recv - TCP Packet is Invalid\n");
}
m_Received.pop_read_data();
if(0 == dwReceived)
{
m_bClosing = TRUE;
if(0 == m_SendQueue.GetQueuedNum())
{
return -1;
}
}
}
return 0;
}
int ClientNet::CTCPSession::Send(unsigned long dwMaxSendCount)
{
CNetworkMsgBlock* lpMsgBlock = m_SendQueue.Dequeue();
WSABUF wsaBuf;
DWORD dwSendCompleted = 0;
DWORD dwFlags = 0;
int rc = 0;
for(unsigned long dwSendCount = 0;
NULL != lpMsgBlock && dwSendCount < dwMaxSendCount; ++dwSendCount)
{
wsaBuf.buf = lpMsgBlock->rd_ptr();
wsaBuf.len = static_cast<unsigned long>(lpMsgBlock->length());
dwSendCompleted = 0;
rc = WSASend(m_hSocket, &wsaBuf, 1, &dwSendCompleted, dwFlags, NULL, NULL);
if(SOCKET_ERROR == rc)
{
if(WSAEWOULDBLOCK != WSAGetLastError())
{
fprintf(stderr, "ClientNet::CTCPSession::Send - WSASend error : %d\n", WSAGetLastError());
}
else
{
// WSAEWOULDBLOCK is NOT error
rc = 0;
}
break;
}
lpMsgBlock->rd_ptr(dwSendCompleted);
if(0 == lpMsgBlock->length())
{
CNetworkMsgPool::GetInstance().FreeNetworkMsgBlock(lpMsgBlock);
lpMsgBlock = m_SendQueue.Dequeue();
}
}
if(NULL != lpMsgBlock)
{
m_SendQueue.Enqueue(lpMsgBlock, true);
}
if(m_bClosing && 0 == m_SendQueue.GetQueuedNum())
{
return -1;
}
return (SOCKET_ERROR != rc) ? 0 : -1;
}

View File

@@ -0,0 +1,28 @@
#ifndef _GAMA_CLIENT_TCP_SESSION_H_
#include "Session.h"
namespace ClientNet
{
class CTCPSession : public CSession
{
public:
CTCPSession(DWORD dwSessionID, CEventHandler* lpEventHandler);
virtual ~CTCPSession();
virtual int Open(INET_Addr& addr); // Active Socket
virtual int Open(INET_Addr& addr, SOCKET hSocket); // Passive Socket
virtual int Recv();
virtual int Send(unsigned long dwMaxSendCount);
protected:
BOOL m_bClosing;
};
}
#endif

View File

@@ -0,0 +1,156 @@
#include "stdafx.h"
#include "UDPSession.h"
#include "SessionMgr.h"
#include "EventHandler.h"
#include <cstdio>
#include "GMMemory.h"
ClientNet::CUDPSession::CUDPSession(DWORD dwSessionID, CEventHandler* lpEventHandler)
: CSession(dwSessionID, lpEventHandler)
{
}
ClientNet::CUDPSession::~CUDPSession()
{
}
int ClientNet::CUDPSession::Open(INET_Addr& addr)
{
if(INVALID_SOCKET != m_hSocket)
{
Close();
}
m_hSocket = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, NULL, WSA_FLAG_OVERLAPPED);
if(INVALID_SOCKET == m_hSocket)
{
fprintf(stderr, "ClientNet::CUDPSession::Open - Socket create error : %d\n", WSAGetLastError());
return -1;
}
BOOL bReuseAddr = TRUE;
int rc = setsockopt(m_hSocket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<char*>(&bReuseAddr), sizeof(BOOL));
if(SOCKET_ERROR == rc)
{
fprintf(stderr, "ClientNet::CUDPSession::Open - setsockopt error : %d\n", WSAGetLastError());
return -1;
}
rc = bind(m_hSocket, &addr.get_addr(), addr.get_size());
if(SOCKET_ERROR == rc)
{
fprintf(stderr, "ClientNet::CUDPSession::Open - bind error : %d\n", WSAGetLastError());
return -1;
}
// EventSelect
rc = WSAEventSelect(m_hSocket, m_hEvent, FD_READ | FD_WRITE);
if(SOCKET_ERROR == rc)
{
fprintf(stderr, "ClientNet::CUDPSession::Open - EventSelect error : %d\n", WSAGetLastError());
return -1;
}
return 0;
}
int ClientNet::CUDPSession::Recv()
{
WSABUF wsaBuf;
for(unsigned long dwReadCount = 0;
dwReadCount < m_dwMaxRecvNumPerPulse || 0 == m_Received.remain();
++dwReadCount)
{
wsaBuf.buf = m_Received.wr_ptr();
wsaBuf.len = static_cast<unsigned long>(m_Received.remain());
DWORD dwReceived = 0;
DWORD dwFlags = 0;
INET_Addr& addr = m_Received.GetAddress();
int addr_size = INET_Addr::get_addr_buffer_size();
int rc = WSARecvFrom(m_hSocket, &wsaBuf, 1, &dwReceived, &dwFlags,
&addr.get_addr(), &addr_size, NULL, NULL);
if(SOCKET_ERROR == rc)
{
if(WSAEWOULDBLOCK != WSAGetLastError())
{
fprintf(stderr, "ClientNet::CUDPSession::Recv - WSARecvFrom error : %d\n", WSAGetLastError());
}
return 0;
}
addr.set_size(addr_size);
m_Received.wr_ptr(dwReceived);
if(-1 == m_lpEventHandler->OnReceived(m_Received) || 0 != m_Received.length())
{
fprintf(stderr, "ClientNet::CUDPSession::Recv - UDP packet is invalid\n");
}
m_Received.pop_read_data();
}
return 0;
}
int ClientNet::CUDPSession::Send(unsigned long dwMaxSendCount)
{
CNetworkMsgBlock* lpMsgBlock = m_SendQueue.Dequeue();
WSABUF wsaBuf;
DWORD dwSendCompleted = 0;
DWORD dwFlags = 0;
int rc = 0;
for(unsigned long dwSendCount = 0;
NULL != lpMsgBlock && dwSendCount < dwMaxSendCount; ++dwSendCount)
{
wsaBuf.buf = lpMsgBlock->rd_ptr();
wsaBuf.len = static_cast<unsigned long>(lpMsgBlock->length());
dwSendCompleted = 0;
INET_Addr& addr = lpMsgBlock->GetAddress();
rc = WSASendTo(m_hSocket, &wsaBuf, 1, &dwSendCompleted, dwFlags,
&addr.get_addr(), addr.get_size(), NULL, NULL);
if(SOCKET_ERROR == rc)
{
rc = 0;
if(WSAEWOULDBLOCK == WSAGetLastError())
{
// WSAEWOULDBLOCK<43≯<EFBFBD> <20><><EFBFBD>߿<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
break;
}
else
{
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><>Ŷ<EFBFBD><C5B6> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
fprintf(stderr, "ClientNet::CUDPSession::Send - WSASendTo error : %d\n", WSAGetLastError());
}
}
CNetworkMsgPool::GetInstance().FreeNetworkMsgBlock(lpMsgBlock);
lpMsgBlock = m_SendQueue.Dequeue();
}
if(NULL != lpMsgBlock)
{
m_SendQueue.Enqueue(lpMsgBlock, true);
}
return (SOCKET_ERROR != rc) ? 0 : -1;
}

View File

@@ -0,0 +1,27 @@
#ifndef _GAMA_CLIENT_UDP_SESSION_H_
#define _GAMA_CLIENT_UDP_SESSION_H_
#include "Session.h"
namespace ClientNet
{
class CSessionMgr;
class CUDPSession : public CSession
{
public:
CUDPSession(DWORD dwSessionID, CEventHandler* lpEventHandler);
virtual ~CUDPSession();
virtual int Open(INET_Addr& addr);
virtual int Open(INET_Addr& addr, SOCKET hSocket) { return -1; }
virtual int Recv();
virtual int Send(unsigned long dwMaxSendCount);
};
}
#endif