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,36 @@
#include "stdafx.h"
#include "INET_Addr.h"
#include "GMMemory.h"
void INET_Addr::set_addr(const char* addr, const unsigned short port)
{
memset(&m_SockAddr, 0, sizeof(sockaddr));
sockaddr_in& addr_in = *reinterpret_cast<sockaddr_in*>(&m_SockAddr);
addr_in.sin_family = AF_INET;
addr_in.sin_addr.s_addr = (NULL == addr) ? htonl(INADDR_ANY) : inet_addr(addr);
addr_in.sin_port = (0 == port) ? 0 : htons(port);
m_iAddrLen = sizeof(sockaddr_in);
}
void INET_Addr::set_addr(const sockaddr& addr, const int size)
{
m_SockAddr = addr;
m_iAddrLen = size;
}
void INET_Addr::set_addr(const IN_ADDR addr, const unsigned short port)
{
memset(&m_SockAddr, 0, sizeof(sockaddr));
sockaddr_in& addr_in = *reinterpret_cast<sockaddr_in*>(&m_SockAddr);
addr_in.sin_family = AF_INET;
addr_in.sin_addr = addr;
addr_in.sin_port = (0 == port) ? 0 : htons(port);
m_iAddrLen = sizeof(sockaddr_in);
}

View File

@@ -0,0 +1,48 @@
#ifndef _GAMA_INET_ADDR_
#define _GAMA_INET_ADDR_
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <winsock2.h>
#include <windows.h>
class INET_Addr
{
public:
INET_Addr() : m_iAddrLen(0) { memset(&m_SockAddr, 0, sizeof(SOCKADDR)); }
INET_Addr(const char* addr, unsigned short port) { set_addr(addr, port); }
INET_Addr(IN_ADDR addr, unsigned short port) { set_addr(addr, port); }
INET_Addr(sockaddr& addr, int size) { set_addr(addr, size); }
~INET_Addr() { }
void clear() { m_iAddrLen = 0; memset(&m_SockAddr, 0, sizeof(SOCKADDR)); }
void set_addr(const char* addr, const unsigned short port);
void set_addr(const IN_ADDR addr, const unsigned short port);
void set_addr(const sockaddr& addr, const int size);
// Winsock<63>Լ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ؼ<EFBFBD> const<73><74> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʾ<EFBFBD><CABE><EFBFBD>.
sockaddr& get_addr() { return m_SockAddr; }
const sockaddr_in& get_addr_in() const { return reinterpret_cast<const sockaddr_in&>(m_SockAddr); }
unsigned short get_port_in() const { return ntohs(reinterpret_cast<const sockaddr_in&>(m_SockAddr).sin_port); }
const char* get_addr_string() const { return inet_ntoa(reinterpret_cast<const sockaddr_in&>(m_SockAddr).sin_addr); }
int get_size() const { return m_iAddrLen; }
int* get_size_ptr() { return &m_iAddrLen; }
void set_size(int n) { m_iAddrLen = n; }
static int get_addr_buffer_size() { return sizeof(sockaddr); }
private:
sockaddr m_SockAddr;
int m_iAddrLen;
};
#endif

View File

@@ -0,0 +1,31 @@
#include "stdafx.h"
#include "Dispatch.h"
#include "../Session/Session.h"
#include "../../Stream/Buffer/Buffer.h"
#include "../../Stream/Buffer/BufferFactory.h"
#include "PoolDispatchFactory.h"
#include "../../Log/ServerLog.h"
void CEchoDispatch::Connected()
{
DETLOG1(g_Log, "this:0x%p Connected", this);
}
void CEchoDispatch::Disconnected()
{
DETLOG1(g_Log, "this:0x%p Disconnected", this);
}
bool CEchoDispatch::ParsePacket (char* const lpStream_In, unsigned long* dwStreamSIze_InOut)
{
unsigned long dwReceived = *dwStreamSIze_InOut;
CBuffer* lpEchoBuffer = CREATE_BUFFER(m_Session.GetPolicy().GetBufferFactory(), dwReceived);
memcpy(lpEchoBuffer->wr_ptr(), lpStream_In, dwReceived);
lpEchoBuffer->wr_ptr(dwReceived);
return m_Session.SendPending(lpEchoBuffer);
}

View File

@@ -0,0 +1,91 @@
#ifndef _GAMA_SERVER_NETWORK_DISPATCH_H_
#define _GAMA_SERVER_NETWORK_DISPATCH_H_
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
class CSession;
// Session<6F><6E><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> DispatchŬ<68><C5AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̽<EFBFBD>.
class CPacketDispatch
{
public:
CPacketDispatch(CSession& Session) : m_Session(Session) { }
virtual ~CPacketDispatch() { }
// In : char* const lpStream_In <20><><EFBFBD><EFBFBD> <20><>Ʈ<EFBFBD><C6AE>
// unsigned long* dwStreamSize_InOut <20><><EFBFBD><EFBFBD> <20><>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD>
// out : Return <20><>Ŷ <20>Ľ<EFBFBD> <20><><EFBFBD><EFBFBD> / <20><><EFBFBD><EFBFBD>(<28><><EFBFBD>н<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>)
// unsigned long* dwStreamSize_InOut <20>Ľ<EFBFBD><C4BD><EFBFBD> <20><><EFBFBD><EFBFBD>
virtual bool ParsePacket(char* const lpStream_In, unsigned long* dwStreamSize_InOut) = 0;
virtual bool Dispatch() = 0;
virtual void Connected() { }
virtual void Disconnected() { }
CSession& GetSession() { return m_Session; }
protected:
CSession& m_Session;
};
class CDispatchFactory
{
public:
virtual ~CDispatchFactory() = 0;
virtual CPacketDispatch* CreateDispatch(CSession& Session) = 0;
virtual void DeleteDispatch(CPacketDispatch* lpDispatch) = 0;
};
inline CDispatchFactory::~CDispatchFactory() { }
template<typename DispatchType>
class CDefaultDispatchFactory : public CDispatchFactory
{
public:
virtual ~CDefaultDispatchFactory() { }
virtual CPacketDispatch* CreateDispatch(CSession& Session) { return new DispatchType(Session); }
virtual void DeleteDispatch(CPacketDispatch* lpDispatch) { delete lpDispatch; }
};
// -----------------------------------------------------------------------
// <20>׽<EFBFBD>Ʈ<EFBFBD><C6AE> Sample Dispatchers....
// <20><><EFBFBD><EFBFBD> <20><>Ŷ<EFBFBD><C5B6> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. ó<><C3B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ʴ´<CAB4>.
class CNullDispatch : public CPacketDispatch
{
public:
CNullDispatch(CSession& Session) : CPacketDispatch(Session) { }
virtual ~CNullDispatch() { }
virtual bool ParsePacket (char* const lpStream_In, unsigned long* dwStreamSIze_InOut) { return true; }
virtual bool Dispatch() { return true; }
};
// <20><><EFBFBD><EFBFBD> <20><>Ŷ<EFBFBD><C5B6> <20>״<EFBFBD><D7B4><EFBFBD> <20>ٽ<EFBFBD> <20><><EFBFBD><EFBFBD> <20>ش<EFBFBD>.
class CEchoDispatch : public CPacketDispatch
{
public:
CEchoDispatch(CSession& Session) : CPacketDispatch(Session) { }
virtual ~CEchoDispatch() { }
virtual void Connected();
virtual void Disconnected();
virtual bool ParsePacket (char* const lpStream_In, unsigned long* dwStreamSIze_InOut);
virtual bool Dispatch() { return true; }
};
#endif

View File

@@ -0,0 +1,34 @@
#ifndef _GAMA_SERVER_NETWORK_POOL_DISPATCH_FACTORY_H_
#define _GAMA_SERVER_NETWORK_POOL_DISPATCH_FACTORY_H_
#include "Dispatch.h"
#include <boost/pool/pool.hpp>
template<typename DispatchType>
class CPoolDispatchFactory : public CDispatchFactory
{
public:
CPoolDispatchFactory() : m_DispatchPool(sizeof(DispatchType)) { }
virtual ~CPoolDispatchFactory() { }
virtual CPacketDispatch* CreateDispatch(CSession& Session)
{
void* ptr = m_DispatchPool.malloc();
return new (ptr) DispatchType(Session);
}
virtual void DeleteDispatch(CPacketDispatch* lpDispatch)
{
lpDispatch->~CPacketDispatch();
m_DispatchPool.free(lpDispatch);
}
protected:
typedef boost::pool<> DispatchPool;
DispatchPool m_DispatchPool;
};
#endif

View File

@@ -0,0 +1,272 @@
#include "stdafx.h"
#include "ServerRequest.h"
#include <Network/Session/Session.h>
#include <Network/Dispatch/Dispatch.h>
#include <Log/ServerLog.h>
#define REQUEST_LOG(x) x
enum RequestConst
{
CANNOT_ADD_REQUEST = (1 << 0)
};
CServerRequest& CServerRequest::GetInstance()
{
static CServerRequest serverRequest;
return serverRequest;
}
CServerRequest::Result::Result(unsigned long dwRequestKey, bool bRemove)
: m_bRemove(bRemove)
{
m_lpSrcDispatch = bRemove
// Request<73><74> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
? CServerRequest::GetInstance().PopRequest(dwRequestKey)
// Request<73><74> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ʴ´<CAB4>.
: CServerRequest::GetInstance().GetRequest(dwRequestKey);
}
CServerRequest::Result::~Result()
{
if(0 != m_lpSrcDispatch && m_bRemove)
{
m_lpSrcDispatch->GetSession().Release();
}
}
CSession* CServerRequest::Result::GetSession()
{
return (0 != m_lpSrcDispatch) ? &m_lpSrcDispatch->GetSession() : 0;
}
void CServerRequest::RequestInfo::ProcessRemove()
{
if(m_lpSrcDispatch)
{
if(m_lpTimeoutRequest)
{
m_lpTimeoutRequest(m_lpSrcDispatch);
}
m_lpSrcDispatch->GetSession().Release();
}
if(m_lpDstDispatch)
{
m_lpDstDispatch->GetSession().Release();
}
}
// return value : RequestKey
unsigned long CServerRequest::AddRequest(CPacketDispatch* lpSrcDispatch,
CPacketDispatch* lpDstDispatch,
unsigned long dwDurationSec,
TimeoutRequest lpTimeoutRequest)
{
if( 0 != lpSrcDispatch &&
0 != lpDstDispatch &&
0 != dwDurationSec)
{
LockType::Syncronize sync(m_RequestLock);
if(!(m_dwRequestFlags & CANNOT_ADD_REQUEST))
{
CSession& SrcSession = lpSrcDispatch->GetSession();
CSession& DstSession = lpDstDispatch->GetSession();
if(0 == m_dwRequestCounter)
{
++m_dwRequestCounter;
}
unsigned long dwRequestCounter = m_dwRequestCounter++;
if(m_RequestMap.insert(std::make_pair(dwRequestCounter,
RequestInfo(lpSrcDispatch, lpDstDispatch, dwDurationSec, lpTimeoutRequest))).second)
{
SrcSession.AddRef();
DstSession.AddRef();
REQUEST_LOG(DETLOG5(g_Log, "SS:0x%p/DP:0x%p/IP:%15s/Request:%d/DstDP:0x%p/Request Added",
&lpSrcDispatch->GetSession(), lpSrcDispatch,
lpSrcDispatch->GetSession().GetRemoteAddr().get_addr_string(),
dwRequestCounter, lpDstDispatch));
return dwRequestCounter;
}
}
}
return 0;
}
void CServerRequest::RemoveRequest(unsigned long dwRequestKey)
{
m_RequestLock.Lock();
RequestMap::iterator pos = m_RequestMap.find(dwRequestKey);
RequestMap::iterator end = m_RequestMap.end();
RequestInfo info;
if(pos != end)
{
info = pos->second;
REQUEST_LOG(DETLOG5(g_Log, "SS:0x%p/DP:0x%p/IP:%15s/Request:%d/DstDP:0x%p/Request Removed(By RequestKey)",
&info.m_lpSrcDispatch->GetSession(), info.m_lpSrcDispatch,
info.m_lpSrcDispatch->GetSession().GetRemoteAddr().get_addr_string(),
pos->first, info.m_lpDstDispatch));
pos = m_RequestMap.erase(pos);
}
m_RequestLock.Unlock();
info.ProcessRemove();
}
void CServerRequest::RemoveRequest(CPacketDispatch* lpDispatch)
{
LockType::Syncronize sync(m_RequestLock);
RequestMap::iterator pos = m_RequestMap.begin();
RequestMap::iterator end = m_RequestMap.end();
for(; pos != end;)
{
RequestInfo& info = pos->second;
if(lpDispatch == info.m_lpSrcDispatch ||
lpDispatch == info.m_lpDstDispatch)
{
REQUEST_LOG(DETLOG5(g_Log, "SS:0x%p/DP:0x%p/IP:%15s/Request:%d/DstDP:0x%p/Request Removed(By TargetPtr)",
&info.m_lpSrcDispatch->GetSession(), info.m_lpSrcDispatch,
info.m_lpSrcDispatch->GetSession().GetRemoteAddr().get_addr_string(),
pos->first, info.m_lpDstDispatch));
info.ProcessRemove();
pos = m_RequestMap.erase(pos);
}
else
{
++pos;
}
}
}
void CServerRequest::RemoveTimeoutRequest()
{
LockType::Syncronize sync(m_RequestLock);
RequestMap::iterator pos = m_RequestMap.begin();
RequestMap::iterator end = m_RequestMap.end();
for(; pos != end;)
{
RequestInfo& info = pos->second;
if(0 == --(info.m_dwDurationSec))
{
REQUEST_LOG(DETLOG5(g_Log, "SS:0x%p/DP:0x%p/IP:%15s/Request:%d/DstDP:0x%p/Request Removed(By Timeout)",
&info.m_lpSrcDispatch->GetSession(), info.m_lpSrcDispatch,
info.m_lpSrcDispatch->GetSession().GetRemoteAddr().get_addr_string(),
pos->first, info.m_lpDstDispatch));
info.ProcessRemove();
pos = m_RequestMap.erase(pos);
}
else
{
++pos;
}
}
}
void CServerRequest::RemoveAllRequest()
{
LockType::Syncronize sync(m_RequestLock);
RequestMap::iterator pos = m_RequestMap.begin();
RequestMap::iterator end = m_RequestMap.end();
for(; pos != end; ++pos)
{
pos->second.ProcessRemove();
}
m_RequestMap.clear();
}
void CServerRequest::RequestOn()
{
LockType::Syncronize sync(m_RequestLock);
m_dwRequestFlags &= ~CANNOT_ADD_REQUEST;
}
void CServerRequest::RequestOff()
{
LockType::Syncronize sync(m_RequestLock);
m_dwRequestFlags |= CANNOT_ADD_REQUEST;
}
CServerRequest::CServerRequest()
{
}
CServerRequest::~CServerRequest()
{
RequestOff();
RemoveAllRequest();
}
CPacketDispatch* CServerRequest::GetRequest(unsigned long dwRequestKey)
{
LockType::Syncronize sync(m_RequestLock);
RequestMap::iterator pos = m_RequestMap.find(dwRequestKey);
return (pos != m_RequestMap.end()) ? pos->second.m_lpSrcDispatch : 0;
}
CPacketDispatch* CServerRequest::PopRequest(unsigned long dwRequestKey)
{
LockType::Syncronize sync(m_RequestLock);
RequestMap::iterator pos = m_RequestMap.find(dwRequestKey);
if(pos != m_RequestMap.end())
{
RequestInfo info = pos->second;
REQUEST_LOG(DETLOG5(g_Log, "SS:0x%p/DP:0x%p/IP:%15s/Request:%d/DstDP:0x%p/Request Removed(By Pop Request)",
&info.m_lpSrcDispatch->GetSession(), info.m_lpSrcDispatch,
info.m_lpSrcDispatch->GetSession().GetRemoteAddr().get_addr_string(),
pos->first, info.m_lpDstDispatch));
m_RequestMap.erase(pos);
return info.m_lpSrcDispatch;
}
return 0;
}

View File

@@ -0,0 +1,103 @@
#ifndef _SERVER_REQUEST_H_
#define _SERVER_REQUEST_H_
#include <map>
#include <vector>
#include <utility>
#include <Thread/Lock.h>
class CSession;
class CPacketDispatch;
class CServerRequest
{
public:
typedef void (*TimeoutRequest)(CPacketDispatch* lpSrcDispatch);
static CServerRequest& GetInstance();
// return value : RequestKey
unsigned long AddRequest(CPacketDispatch* lpSrcDispatch, CPacketDispatch* lpDstDispatch,
unsigned long dwDurationSec, TimeoutRequest lpTimeoutRequest = 0);
void RemoveRequest(unsigned long dwRequestKey);
void RemoveRequest(CPacketDispatch* lpDispatch);
void RemoveTimeoutRequest();
void RemoveAllRequest();
void RequestOn();
void RequestOff();
class Result
{
public:
explicit Result(unsigned long dwRequestKey, bool bRemove = true);
~Result();
CPacketDispatch* GetDispatch() { return m_lpSrcDispatch; }
CSession* GetSession();
private:
// new <20><> delete<74><65> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><>.
void* operator new (size_t size);
void operator delete (void* ptr);
CPacketDispatch* m_lpSrcDispatch;
bool m_bRemove;
};
private:
CServerRequest();
~CServerRequest();
// return value : SrcRequest
CPacketDispatch* GetRequest(unsigned long dwRequestKey);
CPacketDispatch* PopRequest(unsigned long dwRequestKey);
struct RequestInfo
{
CPacketDispatch* m_lpSrcDispatch;
CPacketDispatch* m_lpDstDispatch;
unsigned long m_dwDurationSec;
TimeoutRequest m_lpTimeoutRequest;
RequestInfo()
: m_lpSrcDispatch(0),
m_lpDstDispatch(0),
m_dwDurationSec(0),
m_lpTimeoutRequest(0)
{
}
RequestInfo(CPacketDispatch* lpSrcDispatch, CPacketDispatch* lpDstDispatch,
unsigned long dwDurationSec, TimeoutRequest lpTimeoutRequest)
: m_lpSrcDispatch(lpSrcDispatch),
m_lpDstDispatch(lpDstDispatch),
m_dwDurationSec(dwDurationSec),
m_lpTimeoutRequest(lpTimeoutRequest)
{
}
void ProcessRemove();
};
typedef CCSLock LockType;
typedef std::map<unsigned long, RequestInfo> RequestMap;
LockType m_RequestLock;
CACHE_PAD(RequestLock, sizeof(LockType));
RequestMap m_RequestMap;
unsigned long m_dwRequestCounter;
unsigned long m_dwRequestFlags;
};
#endif

View File

@@ -0,0 +1,48 @@
#include "stdafx.h"
#include "CompletionHandler.h"
CCompletionHandler::CCompletionHandler()
: m_hIOCP(INVALID_HANDLE_VALUE), m_nThread(0), m_nTimeOutMS(0)
{
}
CCompletionHandler::~CCompletionHandler()
{
Destroy();
}
bool CCompletionHandler::Initialize(unsigned long nThread, unsigned long nTimeOutMS)
{
if(INVALID_HANDLE_VALUE != m_hIOCP)
{
return false;
}
m_hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, nThread);
if(0 == m_hIOCP)
{
return false;
}
m_nThread = nThread;
m_nTimeOutMS = nTimeOutMS;
return true;
}
bool CCompletionHandler::Destroy()
{
if(INVALID_HANDLE_VALUE != m_hIOCP)
{
if(!CloseHandle(m_hIOCP))
{
return false;
}
}
m_hIOCP = INVALID_HANDLE_VALUE;
return true;
}

View File

@@ -0,0 +1,59 @@
#ifndef _CCOMPLETIONHANDLER_H_
#define _CCOMPLETIONHANDLER_H_
#include <winsock2.h>
#include <windows.h>
//-----------------------------------------------------------------------------
// CCompletionHandler Class
//-----------------------------------------------------------------------------
class CCompletionHandler
{
private:
HANDLE m_hIOCP;
unsigned long m_nThread;
unsigned long m_nTimeOutMS;
public:
CCompletionHandler();
virtual ~CCompletionHandler();
bool Initialize(unsigned long nThread = 0, unsigned long nTimeOutMS = INFINITE); // Completion Handler<65><72> <20>ʱ<EFBFBD>ȭ<EFBFBD>Ѵ<EFBFBD>.
bool Destroy(); // Completion Hander<65><72> <20>Ҹ<EFBFBD><D2B8><EFBFBD>Ų<EFBFBD><C5B2>.
bool AttachToHander(HANDLE hAttach, ULONG_PTR pCompletionKey); // Completion Handler<65><72> <20><> <20>ڵ<EFBFBD><DAB5><EFBFBD> <20>߰<EFBFBD><DFB0>Ѵ<EFBFBD>.
BOOL GetHanderStatus(LPDWORD lpNumOfBytes,
PULONG_PTR lpCompletionKey, LPOVERLAPPED *lpOverlapped); // <20>۾<EFBFBD><DBBE><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ڵ<EFBFBD><DAB5><EFBFBD> <20><><EFBFBD><EFBFBD> <20>´<EFBFBD>. <20>׵<EFBFBD><D7B5><EFBFBD><EFBFBD><EFBFBD> block<63>ȴ<EFBFBD>.
BOOL PostToHandler(unsigned long dwNumOfBytesTransfered,
ULONG_PTR dwCompletionKey, LPOVERLAPPED lpOverlapped); // Handler<65><72> <20>۾<EFBFBD><DBBE><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>߰<EFBFBD><DFB0>Ѵ<EFBFBD>.
};
//-----------------------------------------------------------------------------
// Inline Implementation ------------------------------------------------------
inline bool CCompletionHandler::AttachToHander(HANDLE hAttach, ULONG_PTR pCompletionKey)
{
return (0 != CreateIoCompletionPort(hAttach, m_hIOCP, pCompletionKey, m_nThread));
}
inline BOOL CCompletionHandler::GetHanderStatus(LPDWORD lpNumOfBytes,
PULONG_PTR lpCompletionKey, LPOVERLAPPED *lpOverlapped)
{
return GetQueuedCompletionStatus(m_hIOCP, lpNumOfBytes, lpCompletionKey, lpOverlapped, m_nTimeOutMS);
}
inline BOOL CCompletionHandler::PostToHandler(unsigned long dwNumOfBytesTransfered,
ULONG_PTR dwCompletionKey, LPOVERLAPPED lpOverlapped)
{
return PostQueuedCompletionStatus(m_hIOCP, dwNumOfBytesTransfered, dwCompletionKey, lpOverlapped);
}
#endif

View File

@@ -0,0 +1,354 @@
#include "stdafx.h"
#include "IOCPNet.h"
#include "IOWorker.h"
#include "CompletionHandler.h"
#include "../../Thread/ThreadMgr.h"
#include "../../Stream/Buffer/BufferFactory.h"
#include "../Session/Session.h"
#include "../Session/SessionMgr.h"
#include "../Listener/Listener.h"
#include "../Dispatch/Dispatch.h"
#include "../Winsock/SocketFactory.h"
#include "../../Utility/Resource/EnsureCleanup.h"
#include "../../Utility/Debug/DebugUtils.h"
#include "../../Log/ServerLog.h"
#include <mmsystem.h>
enum IOCPInternalFlag
{
INITIALIZED_IOCP = (1 << 0),
DESTROYED_IOCP = (1 << 1)
};
unsigned long GetOptimalThreadNum()
{
unsigned long dwThreadCount;
SYSTEM_INFO systemInfo;
GetSystemInfo(&systemInfo);
dwThreadCount = systemInfo.dwNumberOfProcessors * 2;
return dwThreadCount;
}
CIOCPNet::CIOCPNet()
: m_dwFlags(0),
m_lpSocketHandler(new (std::nothrow) CCompletionHandler),
m_lpThreadMgr(new (std::nothrow) CThreadMgr),
m_lpSessionMgr(new (std::nothrow) CSessionMgr)
{
WSADATA wsaData;
WSAStartup(0x0202, &wsaData);
}
CIOCPNet::~CIOCPNet()
{
Destroy();
WSACleanup();
}
// Desc : <20>ʱ<EFBFBD>ȭ <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
bool CIOCPNet::Initialize()
{
{
SessionLock::Syncronize sync(m_IOCPLock);
// <20>ʱ<EFBFBD>ȭ<EFBFBD><C8AD> <20>ѹ<EFBFBD><D1B9><EFBFBD> <20><> <20><> <20><><EFBFBD><EFBFBD>.
if(INITIALIZED_IOCP & m_dwFlags)
{
return false;
}
m_dwFlags |= INITIALIZED_IOCP;
}
if(0 == m_lpSocketHandler ||
0 == m_lpThreadMgr ||
0 == m_lpSessionMgr ||
!m_lpSocketHandler->Initialize())
{
return false;
}
// IOCP <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
unsigned long dwThreadNum = GetOptimalThreadNum();
while(0 != dwThreadNum--)
{
if(!m_lpThreadMgr->RegisterAndRun(
new (std::nothrow) CIOWorker(*m_lpSocketHandler)))
{
return false;
}
}
return true;
}
// Desc : Listener<65><72> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
bool CIOCPNet::AddListener(CSessionPolicy* lpSessionPolicy,
const char* lpListenAddress, unsigned short usPort,
unsigned long dwMaxListenPeding,
CValidateConnection* lpValidateConnection)
{
if(0 == lpSessionPolicy || !lpSessionPolicy->IsValid() ||
0 == m_lpSocketHandler || 0 == m_lpSessionMgr)
{
return false;
}
CListener* lpListener = new (std::nothrow) CListener(*m_lpSocketHandler,
*lpSessionPolicy, *m_lpSessionMgr, lpValidateConnection);
if(0 == lpListener)
{
return false;
}
if(!lpListener->Initialize(lpListenAddress, usPort, dwMaxListenPeding))
{
delete lpListener;
return false;
}
lpSessionPolicy->AddRef();
SessionLock::Syncronize sync(m_IOCPLock);
m_ListenerList.push_back(lpListener);
++m_SessionPolicyMap[lpSessionPolicy];
return true;
}
// Desc : <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
bool CIOCPNet::Connect(CSessionPolicy* lpSessionPolicy,
const char* lpConnectAddress, unsigned short usPort)
{
if(0 == lpSessionPolicy || !lpSessionPolicy->IsValid() ||
0 == m_lpSocketHandler || 0 == m_lpSessionMgr)
{
return false;
}
SOCKET hConnectedSocket = lpSessionPolicy->GetSocketFactory().CreateConnectedSocket(lpConnectAddress, usPort);
if(INVALID_SOCKET == hConnectedSocket)
{
ERRLOG3(g_Log, "Connected socket creation error : %d, destination : %s:%d",
WSAGetLastError(), lpConnectAddress, usPort);
}
else
{
CSession* lpSession = m_lpSessionMgr->CreateSession(*lpSessionPolicy);
if(0 != lpSession)
{
if(m_lpSocketHandler->AttachToHander(
reinterpret_cast<HANDLE>(hConnectedSocket),
reinterpret_cast<ULONG_PTR>(lpSession)))
{
lpSession->Socket(hConnectedSocket);
lpSession->SetAddress(INET_Addr(lpConnectAddress, usPort), INET_Addr());
DETLOG3(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/ Connect Success.",
lpSession, lpSession->GetDispatch(), lpConnectAddress);
lpSession->InternalRecv();
m_lpSessionMgr->Add(lpSession);
lpSessionPolicy->AddRef();
SessionLock::Syncronize sync(m_IOCPLock);
++m_SessionPolicyMap[lpSessionPolicy];
return true;
}
m_lpSessionMgr->DeleteSession(lpSession);
}
closesocket(hConnectedSocket);
}
return false;
}
// Desc : Listener<65><72> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>ǵ<EFBFBD><C7B5><EFBFBD>, ConnectedSession<6F><6E> ó<><C3B3><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
void CIOCPNet::Process()
{
if(0 != m_lpSessionMgr)
{
m_lpSessionMgr->Process();
}
}
// Desc : <20><><EFBFBD><EFBFBD> Listener<65><72> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
bool CIOCPNet::Destroy()
{
m_IOCPLock.Lock();
if(!(m_dwFlags & DESTROYED_IOCP))
{
CThreadMgr* lpThreadMgr = 0;
CCompletionHandler* lpSocketHandler = 0;
CSessionMgr* lpSessionMgr = 0;
SessionPolicyMap tempMap(m_SessionPolicyMap);
m_SessionPolicyMap.clear();
std::swap(m_lpThreadMgr, lpThreadMgr);
std::swap(m_lpSocketHandler, lpSocketHandler);
std::swap(m_lpSessionMgr, lpSessionMgr);
m_dwFlags |= DESTROYED_IOCP;
m_IOCPLock.Unlock();
DestroyListener();
delete lpSessionMgr;
delete lpThreadMgr;
delete lpSocketHandler;
SessionPolicyMap::iterator pos = tempMap.begin();
SessionPolicyMap::iterator end = tempMap.end();
for(; pos != end; ++pos)
{
for(unsigned int nReleaseCount = pos->second;
0 != nReleaseCount; --nReleaseCount)
{
pos->first->Release();
}
}
return true;
}
m_IOCPLock.Unlock();
return false;
}
void CIOCPNet::DestroyListener()
{
ListenerList deleteList;
{
SessionLock::Syncronize sync(m_IOCPLock);
deleteList.splice(deleteList.end(), m_ListenerList);
}
ListenerList::iterator pos = deleteList.begin();
ListenerList::iterator end = deleteList.end();
for(; pos != end; ++pos)
{
delete (*pos);
}
}
// Desc : <20><><EFBFBD><EFBFBD> Accept<70><74> pending<6E>ϰ<EFBFBD> <20>ִ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
unsigned long CIOCPNet::GetAcceptPendingNum()
{
unsigned long dwPendingNum = 0;
SessionLock::Syncronize sync(m_IOCPLock);
for(ListenerList::iterator itr = m_ListenerList.begin();
itr != m_ListenerList.end(); ++itr)
{
dwPendingNum += (*itr)->GetPendingAcceptNum();
}
return dwPendingNum;
}
unsigned long CIOCPNet::GetSessionNum()
{
if(0 != m_lpSessionMgr)
{
return m_lpSessionMgr->GetSessionNum();
}
return 0;
}
/*
void CIOCPNet::LogListeners()
{
SessionLock::Syncronize sync(m_IOCPLock);
std::for_each(m_ListenerList.begin(), m_ListenerList.end(),
std::mem_fun(CListener::LogListenerStatus));
}
void CIOCPNet::LogConnected()
{
using namespace std;
unsigned int nStateNum[CSession::MAX_SESSION_STATE];
std::fill_n(nStateNum, unsigned int(CSession::MAX_SESSION_STATE), 0);
const char* szDelimiter = "// ------------------------------------------------------------------------------- ";
char szProgramName[MAX_PATH];
char szFileName[MAX_PATH];
char szTime[MAX_PATH];
SYSTEMTIME systemTime;
GetLocalTime(&systemTime);
DbgUtils::SetProgramName(szProgramName, MAX_PATH);
_snprintf(szTime, MAX_PATH, "%04d%02d%02d-%02d%02d%02d",
systemTime.wYear, systemTime.wMonth, systemTime.wDay,
systemTime.wHour, systemTime.wMinute, systemTime.wSecond);
_snprintf(szFileName, MAX_PATH, "%s/ConnectedLog-%s.txt", szProgramName, szTime);
fstream logfile(szFileName, ios::out | ios::app);
fstream::char_type endline = logfile.widen('\n');
logfile << szDelimiter << endline;
m_IOCPLock.Lock();
unsigned int nConnectedNum = 0;
ConnectedArray::iterator first = m_ConnectedArray.begin();
ConnectedArray::iterator last = m_ConnectedArray.end();
for(; first != last; ++first)
{
logfile << **first << endline;
++nStateNum[(*first)->m_cCurrentStatus];
++nConnectedNum;
}
m_IOCPLock.Unlock();
logfile << endline << szDelimiter << endline
<< "Time : " << szTime << endline << endline
<< "nUNINITIALIZED : " << nStateNum[CSession::UNINITIALIZED] << endline
<< "ACCEPT_PENDING : " << nStateNum[CSession::ACCEPT_PENDING] << endline
<< "CONNECTED : " << nStateNum[CSession::CONNECTED] << endline
<< "DISCONNECTED : " << nStateNum[CSession::DISCONNECTED] << endline
<< "Total : " << nConnectedNum << endl;
}
*/

View File

@@ -0,0 +1,61 @@
#ifndef _CIOCPMGR_H_
#define _CIOCPMGR_H_
#include <map>
#include <list>
#include "../../Thread/Lock.h"
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
class CListener;
class CSession;
class CSessionPolicy;
class CCompletionHandler;
class CThreadMgr;
class CSessionMgr;
class CValidateConnection;
class CIOCPNet
{
public:
CIOCPNet();
~CIOCPNet();
bool Initialize();
bool Destroy();
bool AddListener(CSessionPolicy* lpSessionPolicy,
const char* lpListenAddress, unsigned short usPort,
unsigned long dwMaxListenPeding = 10,
CValidateConnection* lpValidateConnection = 0);
bool Connect(CSessionPolicy* lpSessionPolicy,
const char* lpConnectAddress, unsigned short usPort);
void Process();
unsigned long GetAcceptPendingNum();
unsigned long GetSessionNum();
private:
void DestroyListener();
typedef std::list<CListener*> ListenerList;
typedef std::map<CSessionPolicy*, unsigned int> SessionPolicyMap;
typedef CCSLock SessionLock;
SessionLock m_IOCPLock;
CACHE_PAD(SessionLockPad, sizeof(SessionLock));
CCompletionHandler* m_lpSocketHandler;
CThreadMgr* m_lpThreadMgr;
CSessionMgr* m_lpSessionMgr;
ListenerList m_ListenerList;
SessionPolicyMap m_SessionPolicyMap;
unsigned long m_dwFlags;
};
#endif

View File

@@ -0,0 +1,64 @@
#include "stdafx.h"
#include "IOWorker.h"
#include "Overlapped.h"
#include "../IOCP/CompletionHandler.h"
#include "../Session/Session.h"
#include "../Listener/Listener.h"
#include <Log/ServerLog.h>
CIOWorker::CIOWorker(CCompletionHandler& SocketHandler)
: m_SocketHandler(SocketHandler)
{
}
CIOWorker::~CIOWorker()
{
}
unsigned int CIOWorker::Run()
{
COverlapped* lpOverlapped = 0;
while(true)
{
unsigned long dwProcessedBytes = 0;
ULONG_PTR lpSessionKey = 0;
OVERLAPPED* lpOverlappedStruct = 0;
BOOL bResult = m_SocketHandler.GetHanderStatus(&dwProcessedBytes,
&lpSessionKey, &lpOverlappedStruct);
if(0 == lpSessionKey)
{
DETLOG4(g_SessionLog, "SP:0x%p/lpOverlapped:0x%p/bResult:%s/Thread 0x%p Completed",
lpSessionKey, lpOverlappedStruct, bResult ? "T" : "F", GetCurrentThreadId());
break;
}
if(!bResult && 0 == lpOverlappedStruct)
{
// <20><> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>, Ȥ<><C8A4> Ÿ<>Ӿƿ<D3BE>.
DETLOG4(g_SessionLog, "SP:0x%p/lpOverlapped:0x%p/bResult:%s/GetQueuedCompletionStatus error : %u",
lpSessionKey, lpOverlappedStruct, bResult ? "T" : "F", WSAGetLastError());
}
else
{
// Recv, Send, Accept<70><74> <20><>.
lpOverlapped = static_cast<COverlapped*>(lpOverlappedStruct);
lpOverlapped->Dispatch(bResult, lpSessionKey, dwProcessedBytes);
}
}
return 0;
}
BOOL CIOWorker::End()
{
m_SocketHandler.PostToHandler(0, 0, 0);
return true;
}

View File

@@ -0,0 +1,27 @@
#ifndef _IO_WORKER_H_
#define _IO_WORKER_H_
#include "../../Thread/Thread.h"
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
class CCompletionHandler;
class CIOWorker : public CThread
{
public:
CIOWorker(CCompletionHandler& SocketHandler);
virtual ~CIOWorker();
private:
virtual unsigned int Run();
virtual BOOL End();
CCompletionHandler& m_SocketHandler;
};
#endif

View File

@@ -0,0 +1,284 @@
#include "stdafx.h"
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include "Overlapped.h"
#include "../Session/Session.h"
#include "../Listener/Listener.h"
#include "../../Stream/Buffer/Buffer.h"
#include "../../Stream/Buffer/BufferFactory.h"
#include <boost/pool/pool.hpp>
COverlapped::COverlapped(COverlappedFactory& ovlFactory, CBuffer* lpBuffer)
: m_lpBuffer(lpBuffer), m_ovlFactory(ovlFactory)
{
Internal = InternalHigh = Offset = OffsetHigh = 0;
hEvent = 0;
}
COverlapped::~COverlapped()
{
SAFE_RELEASE_BUFFER(m_lpBuffer);
}
void COverlapped::Release()
{
m_ovlFactory.DeleteOverlapped(this);
}
class CSendOverlapped : public COverlapped
{
public:
CSendOverlapped(COverlappedFactory& ovlFactory, CBuffer* lpSendBuffer)
: COverlapped(ovlFactory, lpSendBuffer) { }
virtual ~CSendOverlapped() { }
virtual void Dispatch(BOOL bResult, ULONG_PTR lpSessionKey, unsigned long dwProcessedBytes)
{
CSession& Session = *reinterpret_cast<CSession*>(lpSessionKey);
Session.SendCompleted(bResult, dwProcessedBytes);
m_ovlFactory.DeleteOverlapped(this);
}
};
class CStreamRecvOverlapped : public COverlapped
{
public:
CStreamRecvOverlapped(COverlappedFactory& ovlFactory) : COverlapped(ovlFactory, 0) { }
virtual ~CStreamRecvOverlapped() { }
virtual void Dispatch(BOOL bResult, ULONG_PTR lpSessionKey, unsigned long dwProcessedBytes)
{
CSession& Session = *reinterpret_cast<CSession*>(lpSessionKey);
if(Session.Dispatch(dwProcessedBytes))
{
Session.Recv();
}
m_ovlFactory.DeleteOverlapped(this);
}
};
class CDatagramRecvOverlapped : public COverlapped
{
public:
CDatagramRecvOverlapped(COverlappedFactory& ovlFactory) : COverlapped(ovlFactory, 0) { }
virtual ~CDatagramRecvOverlapped() { }
virtual void Dispatch(BOOL bResult, ULONG_PTR lpSessionKey, unsigned long dwProcessedBytes)
{
CSession& Session = *reinterpret_cast<CSession*>(lpSessionKey);
if(Session.Dispatch(dwProcessedBytes))
{
Session.RecvFrom();
}
m_ovlFactory.DeleteOverlapped(this);
}
};
class CAcceptOverlapped : public COverlapped
{
public:
CAcceptOverlapped(COverlappedFactory& ovlFactory, CListener& Listener, SOCKET hSocket, CBuffer* lpAddrBuffer)
: COverlapped(ovlFactory, lpAddrBuffer), m_Listener(Listener), m_hSocket(hSocket)
{
}
virtual ~CAcceptOverlapped() { }
virtual void Dispatch(BOOL bResult, ULONG_PTR lpSessionKey, unsigned long dwProcessedBytes)
{
CListener& Listener = *reinterpret_cast<CListener*>(lpSessionKey);
Listener.ProcessAccept(bResult, m_hSocket, m_lpBuffer, dwProcessedBytes);
m_ovlFactory.DeleteOverlapped(this);
}
private:
CListener& m_Listener;
SOCKET m_hSocket;
};
// ----------------------------------------------------------------------
// StreamOverlapped
CStreamOverlappedFactory::CStreamOverlappedFactory()
{
FactoryLock::Syncronize sync(m_Lock);
size_t nMaxPoolSize = std::max(sizeof(CAcceptOverlapped),
std::max(sizeof(CSendOverlapped), sizeof(CStreamRecvOverlapped)));
m_lpOverlappedPool = new (std::nothrow) boost::pool<>(nMaxPoolSize);
}
CStreamOverlappedFactory::~CStreamOverlappedFactory()
{
FactoryLock::Syncronize sync(m_Lock);
delete m_lpOverlappedPool;
m_lpOverlappedPool = 0;
}
COverlapped* CStreamOverlappedFactory::CreateSend(CSession* lpSession, CBuffer* lpMsgBlock)
{
COverlapped* lpOverlapped = 0;
FactoryLock::Syncronize sync(m_Lock);
if(0 != lpSession && 0 != lpMsgBlock && 0 != m_lpOverlappedPool)
{
void* lpBuffer = m_lpOverlappedPool->malloc();
if(0 != lpBuffer)
{
lpOverlapped = new (lpBuffer) CSendOverlapped(*this, lpMsgBlock);
}
}
return lpOverlapped;
}
COverlapped* CStreamOverlappedFactory::CreateRecv(CSession* lpSession, CBuffer* lpMsgBlock)
{
COverlapped* lpOverlapped = 0;
FactoryLock::Syncronize sync(m_Lock);
if(0 != lpSession && 0 != lpMsgBlock && 0 != m_lpOverlappedPool)
{
void* lpBuffer = m_lpOverlappedPool->malloc();
if(0 != lpBuffer)
{
lpOverlapped = new (lpBuffer) CStreamRecvOverlapped(*this);
}
}
return lpOverlapped;
}
COverlapped* CStreamOverlappedFactory::CreateAccept(CListener* lpListener, SOCKET hSocket, CBuffer* lpMsgBlock)
{
COverlapped* lpOverlapped = 0;
FactoryLock::Syncronize sync(m_Lock);
if(0 != lpListener && 0 != lpMsgBlock && 0 != m_lpOverlappedPool)
{
void* lpBuffer = m_lpOverlappedPool->malloc();
if(0 != lpBuffer)
{
lpOverlapped = new (lpBuffer) CAcceptOverlapped(*this, *lpListener, hSocket, lpMsgBlock);
}
}
return lpOverlapped;
}
void CStreamOverlappedFactory::DeleteOverlapped(COverlapped* lpOverlapped)
{
FactoryLock::Syncronize sync(m_Lock);
if(0 != lpOverlapped && 0 != m_lpOverlappedPool)
{
lpOverlapped->~COverlapped();
m_lpOverlappedPool->free(lpOverlapped);
}
}
// ----------------------------------------------------------------------
// DatagramOverlapped
CDatagramOverlappedFactory::CDatagramOverlappedFactory()
{
FactoryLock::Syncronize sync(m_Lock);
size_t nMaxPoolSize = std::max(sizeof(CAcceptOverlapped),
std::max(sizeof(CSendOverlapped), sizeof(CDatagramRecvOverlapped)));
m_lpOverlappedPool = new (std::nothrow) boost::pool<>(nMaxPoolSize);
}
CDatagramOverlappedFactory::~CDatagramOverlappedFactory()
{
FactoryLock::Syncronize sync(m_Lock);
delete m_lpOverlappedPool;
m_lpOverlappedPool = 0;
}
COverlapped* CDatagramOverlappedFactory::CreateSend(CSession* lpSession, CBuffer* lpMsgBlock)
{
COverlapped* lpOverlapped = 0;
FactoryLock::Syncronize sync(m_Lock);
if(0 != lpSession && 0 != lpMsgBlock && 0 != m_lpOverlappedPool)
{
void* lpBuffer = m_lpOverlappedPool->malloc();
if(0 != lpBuffer)
{
lpOverlapped = new (lpBuffer) CSendOverlapped(*this, lpMsgBlock);
}
}
return lpOverlapped;
}
COverlapped* CDatagramOverlappedFactory::CreateRecv(CSession* lpSession, CBuffer* lpMsgBlock)
{
COverlapped* lpOverlapped = 0;
FactoryLock::Syncronize sync(m_Lock);
if(0 != lpSession && 0 != lpMsgBlock && 0 != m_lpOverlappedPool)
{
void* lpBuffer = m_lpOverlappedPool->malloc();
if(0 != lpBuffer)
{
lpOverlapped = new (lpBuffer) CDatagramRecvOverlapped(*this);
}
}
return lpOverlapped;
}
void CDatagramOverlappedFactory::DeleteOverlapped(COverlapped* lpOverlapped)
{
FactoryLock::Syncronize sync(m_Lock);
if(0 != lpOverlapped && 0 != m_lpOverlappedPool)
{
lpOverlapped->~COverlapped();
m_lpOverlappedPool->free(lpOverlapped);
}
}

View File

@@ -0,0 +1,112 @@
#ifndef _COVERLAPPED_H_
#define _COVERLAPPED_H_
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include "../../Thread/Lock.h"
#include <winsock2.h>
#include <windows.h>
#include <boost/pool/poolfwd.hpp>
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
class CBuffer;
class CBufferFactory;
class CSession;
class CListener;
class COverlappedFactory;
class COverlapped : public OVERLAPPED
{
public:
COverlapped(COverlappedFactory& ovlFactory, CBuffer* lpBuffer);
virtual ~COverlapped();
virtual void Dispatch(BOOL bResult, ULONG_PTR lpSessionKey,
unsigned long dwProcessedBytes) = 0;
void SetBuffer(CBuffer* lpBuffer) { m_lpBuffer = lpBuffer; }
void Release();
protected:
COverlappedFactory& m_ovlFactory;
CBuffer* m_lpBuffer;
};
// ---------------------------------------------------------------------------
// COverlappedFactory : <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̽<EFBFBD> <20><><EFBFBD>
class COverlappedFactory
{
public:
virtual ~COverlappedFactory() { }
virtual COverlapped* CreateSend(CSession* lpSession, CBuffer* lpMsgBlock) = 0;
virtual COverlapped* CreateRecv(CSession* lpSession, CBuffer* lpMsgBlock) = 0;
virtual COverlapped* CreateAccept(CListener* lpListener, SOCKET hSocket, CBuffer* lpMsgBlock) = 0;
virtual void DeleteOverlapped(COverlapped* lpOverlapped) = 0;
};
// ---------------------------------------------------------------------------
// CStreamOverlappedFactory : TCP, SPX<50><58><EFBFBD>ſ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
class CStreamOverlappedFactory : public COverlappedFactory
{
public:
CStreamOverlappedFactory();
virtual ~CStreamOverlappedFactory();
virtual COverlapped* CreateSend(CSession* lpSession, CBuffer* lpMsgBlock);
virtual COverlapped* CreateRecv(CSession* lpSession, CBuffer* lpMsgBlock);
virtual COverlapped* CreateAccept(CListener* lpListener, SOCKET hSocket, CBuffer* lpMsgBlock);
virtual void DeleteOverlapped(COverlapped* lpOverlapped);
private:
typedef CCSLock FactoryLock;
FactoryLock m_Lock;
CACHE_PAD(FactoryLockPad, sizeof(FactoryLock));
boost::pool<>* m_lpOverlappedPool;
};
// ---------------------------------------------------------------------------
// CDatagramOverlappedFactory : UDP, IPX<50><58><EFBFBD>ſ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
class CDatagramOverlappedFactory : public COverlappedFactory
{
public:
CDatagramOverlappedFactory();
virtual ~CDatagramOverlappedFactory();
virtual COverlapped* CreateSend(CSession* lpSession, CBuffer* lpMsgBlock);
virtual COverlapped* CreateRecv(CSession* lpSession, CBuffer* lpMsgBlock);
virtual COverlapped* CreateAccept(CListener* lpListener, SOCKET hSocket, CBuffer* lpMsgBlock) { return 0; }
virtual void DeleteOverlapped(COverlapped* lpOverlapped);
private:
typedef CCSLock FactoryLock;
FactoryLock m_Lock;
CACHE_PAD(FactoryLockPad, sizeof(FactoryLock));
boost::pool<>* m_lpOverlappedPool;
};
#endif

View File

@@ -0,0 +1,395 @@
#include "stdafx.h"
#include "Listener.h"
#include "../Session/Session.h"
#include "../Session/SessionMgr.h"
#include "../Dispatch/Dispatch.h"
#include "../Winsock/SocketFactory.h"
#include "../IOCP/CompletionHandler.h"
#include "../IOCP/Overlapped.h"
#include "../../Stream/Buffer/Buffer.h"
#include "../../Stream/Buffer/BufferFactory.h"
#include "../../Utility/Debug/DebugUtils.h"
#include "../../Utility/Resource/EnsureCleanup.h"
#include "../../Log/ServerLog.h"
#include <mmsystem.h>
#include <iostream>
enum LISTENER_CONSTANT
{
DEFAULT_PENDING_NUM = 10
};
CListener::CListener(CCompletionHandler& SocketHandler,
CSessionPolicy& SessionPolicy,
CSessionMgr& SessionMgr,
CValidateConnection* lpValidateConnection)
: m_hListen(INVALID_SOCKET),
m_dwMaxPending(DEFAULT_PENDING_NUM),
m_dwCurrentPending(0),
m_dwTotalPendingCount(0),
m_dwTotalAcceptCompleteCount(0),
m_SocketHandler(SocketHandler),
m_SessionPolicy(SessionPolicy),
m_SessionMgr(SessionMgr),
m_lpValidateConnection(lpValidateConnection)
{
m_SessionPolicy.AddRef();
if(0 != m_lpValidateConnection)
{
m_lpValidateConnection->AddRef();
}
}
CListener::~CListener()
{
{
SessionLock::Syncronize sync(m_ListenerLock);
InternalCloseListen();
}
WaitForPendingComplete(5000);
m_SessionPolicy.Release();
if(0 != m_lpValidateConnection)
{
m_lpValidateConnection->Release();
}
}
bool CListener::Initialize(INET_Addr& addrListen, unsigned long dwMaxPending)
{
if(!m_SessionPolicy.IsValid())
{
ERRLOG0(g_SessionLog, "CListener initialized failed : Invalid SessionPolicy");
return false;
}
else
{
SessionLock::Syncronize sync(m_ListenerLock);
InternalCloseListen();
const sockaddr_in& addr_in = addrListen.get_addr_in();
m_hListen = m_SessionPolicy.GetSocketFactory().CreateListenSocket(
(0 != addr_in.sin_addr.S_un.S_addr) ? inet_ntoa(addr_in.sin_addr) : 0,
addrListen.get_port_in());
if(SOCKET_ERROR == m_hListen)
{
ERRLOG1(g_SessionLog, "CListener initialized failed : Create listen socket failed : %d",
WSAGetLastError());
return false;
}
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Handler<65><72> Attach<63>Ѵ<EFBFBD>.
if(!m_SocketHandler.AttachToHander(
reinterpret_cast<HANDLE>(m_hListen), reinterpret_cast<ULONG_PTR>(this)))
{
ERRLOG1(g_SessionLog, "CListener initialized failed : Attach to Handler failed : %d",
WSAGetLastError());
return false;
}
// Pending<6E><67> <20><20><> <20><><EFBFBD>´<EFBFBD>.
if(m_dwMaxPending < dwMaxPending)
{
m_dwMaxPending = dwMaxPending;
}
dwMaxPending = m_dwMaxPending;
}
for(unsigned long dwCount = 0; dwCount < dwMaxPending; ++dwCount)
{
PendingAccept();
}
return true;
}
void CListener::InternalCloseListen()
{
if(INVALID_SOCKET != m_hListen)
{
if(SOCKET_ERROR == closesocket(m_hListen))
{
ERRLOG1(g_SessionLog, "closesocket failed : %d", WSAGetLastError());
}
m_hListen = INVALID_SOCKET;
}
}
void CListener::WaitForPendingComplete(unsigned long dwTime)
{
unsigned long dwStartTime = timeGetTime();
for(;;)
{
long diffTime = timeGetTime() - dwStartTime;
if(dwTime < static_cast<unsigned long>(std::abs(diffTime)))
{
break;
}
{
SessionLock::Syncronize sync(m_ListenerLock);
if(0 == m_dwCurrentPending)
{
break;
}
}
Sleep(10);
}
}
bool CListener::PendingAccept()
{
SessionLock::Syncronize sync(m_ListenerLock);
if(INVALID_SOCKET == m_hListen)
{
return false;
}
unsigned long dwAddressLen = sizeof(SOCKADDR_IN) + 16;
unsigned long dwBytesReceived = 0;
SOCKET hSocket = m_SessionPolicy.GetSocketFactory().CreateSocket();
CBuffer* lpAddrBuffer = CREATE_BUFFER(m_SessionPolicy.GetBufferFactory(), dwAddressLen * 2);
COverlapped* lpOverlapped = m_SessionPolicy.GetOverlappedFactory().CreateAccept(this, hSocket, lpAddrBuffer);
if(SOCKET_ERROR == AcceptEx(m_hListen, hSocket, lpAddrBuffer->wr_ptr(),
0, dwAddressLen, dwAddressLen, &dwBytesReceived, lpOverlapped))
{
if(WSA_IO_PENDING != WSAGetLastError())
{
// <20><><EFBFBD>۴<EFBFBD> <20><><EFBFBD>ο<EFBFBD><CEBF><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
m_SessionPolicy.GetOverlappedFactory().DeleteOverlapped(lpOverlapped);
closesocket(hSocket);
return false;
}
}
++m_dwCurrentPending;
++m_dwTotalPendingCount;
return true;
}
void CListener::ProcessAccept(BOOL bResult, SOCKET hSocket,
CBuffer* lpBuffer, unsigned long dwProcessedBytes)
{
INET_Addr localAddr;
INET_Addr remoteAddr;
if(bResult)
{
// <20><><EFBFBD><EFBFBD> <20>ɼ<EFBFBD> <20><><EFBFBD><EFBFBD>.
if(SOCKET_ERROR == setsockopt(hSocket, SOL_SOCKET,
SO_UPDATE_ACCEPT_CONTEXT, (char*)&m_hListen, sizeof(m_hListen)))
{
bResult = FALSE;
}
else
{
SOCKADDR* lpLocalAddr = 0;
SOCKADDR* lpRemoteAddr = 0;
int nLocalSockAddrLen = 0;
int nRemoteSockAddrLen = 0;
unsigned long dwAddressLen = sizeof(SOCKADDR_IN) + 16;
// <20>ּ<EFBFBD> <20>м<EFBFBD> <20><> <20>ּ<EFBFBD> <20><>ü <20><><EFBFBD><EFBFBD>.
GetAcceptExSockaddrs(lpBuffer->rd_ptr(), 0, dwAddressLen, dwAddressLen,
&lpLocalAddr, &nLocalSockAddrLen, &lpRemoteAddr, &nRemoteSockAddrLen);
if(0 != lpLocalAddr)
{
localAddr.set_addr(*lpLocalAddr, nLocalSockAddrLen);
}
if(0 != lpRemoteAddr)
{
remoteAddr.set_addr(*lpRemoteAddr, nRemoteSockAddrLen);
}
}
}
if(bResult && 0 != m_lpValidateConnection
&& !(*m_lpValidateConnection)(localAddr, remoteAddr))
{
bResult = FALSE;
}
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
CSession* lpSession = 0;
if(bResult)
{
lpSession = m_SessionMgr.CreateSession(m_SessionPolicy);
if(0 == lpSession || !lpSession->isValid())
{
bResult = FALSE;
}
}
if(bResult && !m_SocketHandler.AttachToHander(
reinterpret_cast<HANDLE>(hSocket),
reinterpret_cast<ULONG_PTR>(lpSession)))
{
bResult = FALSE;
}
if(bResult)
{
lpSession->Socket(hSocket);
lpSession->SetAddress(remoteAddr, localAddr);
DETLOG3(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/ Accept Session Complete.",
lpSession, lpSession->GetDispatch(), remoteAddr.get_addr_string());
lpSession->InternalRecv();
m_SessionMgr.Add(lpSession);
}
else
{
m_SessionMgr.DeleteSession(lpSession);
lpSession = 0;
// pending failed
closesocket(hSocket);
}
{
SessionLock::Syncronize sync(m_ListenerLock);
--m_dwCurrentPending;
++m_dwTotalAcceptCompleteCount;
}
PendingAccept();
}
unsigned long CListener::GetPendingAcceptNum()
{
SessionLock::Syncronize sync(m_ListenerLock);
return m_dwCurrentPending;
}
std::ostream& CListener::PrintStatistics(std::ostream& strm)
{
SessionLock::Syncronize sync(m_ListenerLock);
const int MAX_BUFFER = 1024;
char szBuffer[MAX_BUFFER];
int nLen = InternalPrintStatistics(szBuffer, MAX_BUFFER);
if(0 < nLen)
{
strm << szBuffer;
}
return strm;
}
int CListener::InternalPrintStatistics(char* szBuffer, int nBufferLen)
{
return _snprintf(szBuffer, nBufferLen,
"[ListenSocket:0x%08x][MaxPending:%d][CurrentPending:%d]"
"[TotalPendingCount:%d][TotalAcceptCompleteCount:%d]",
m_hListen, m_dwMaxPending, m_dwCurrentPending,
m_dwTotalPendingCount, m_dwTotalAcceptCompleteCount);
}
/*
bool CListener::LogListenerStatus()
{
using namespace std;
unsigned int nStateNum[CSession::MAX_SESSION_STATE];
std::fill_n(nStateNum, unsigned int(CSession::MAX_SESSION_STATE), 0);
const char* szDelimiter = "// ------------------------------------------------------------------------------- ";
char szProgramName[MAX_PATH];
char szFileName[MAX_PATH];
char szTime[MAX_PATH];
SYSTEMTIME systemTime;
GetLocalTime(&systemTime);
DbgUtils::SetProgramName(szProgramName, MAX_PATH);
_snprintf(szTime, MAX_PATH, "%04d%02d%02d-%02d%02d%02d",
systemTime.wYear, systemTime.wMonth, systemTime.wDay,
systemTime.wHour, systemTime.wMinute, systemTime.wSecond);
_snprintf(szFileName, MAX_PATH, "%s/ListenerLog-%s.txt", szProgramName, szTime);
fstream logfile(szFileName, ios::out | ios::app);
fstream::char_type endline = logfile.widen('\n');
logfile << szDelimiter << endline;
SessionSet::iterator pos = m_SessionSet.begin();
SessionSet::iterator end = m_SessionSet.end();
for(; pos != end; ++pos)
{
CSession* lpSession = *pos;
logfile << lpSession << endline;
++nStateNum[lpSession->m_cCurrentStatus];
}
logfile << endline << szDelimiter << endline
<< "Time : " << szTime << endline << endline
<< "UNINITIALIZED : " << nStateNum[CSession::UNINITIALIZED] << endline
<< "ACCEPT_PENDING : " << nStateNum[CSession::ACCEPT_PENDING] << endline
<< "CONNECTED : " << nStateNum[CSession::CONNECTED] << endline
<< "DISCONNECTED : " << nStateNum[CSession::DISCONNECTED] << endline
<< "Total : " << m_dwMaxConnections << endl;
return true;
}
*/
LONG CValidateConnection::AddRef()
{
return InterlockedIncrement(&m_nRefCount);
}
LONG CValidateConnection::Release()
{
LONG nRefCount = InterlockedDecrement(&m_nRefCount);
if(0 == nRefCount)
{
delete this;
}
return nRefCount;
}

View File

@@ -0,0 +1,114 @@
#ifndef _CLISTENER_H_
#define _CLISTENER_H_
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <winsock2.h>
#include <windows.h>
#include <list>
#include <boost/pool/object_pool.hpp>
#include "../../Thread/Lock.h"
#include "../Address/INET_Addr.h"
#pragma comment(lib, "winmm")
#pragma comment(lib, "mswsock")
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
class CBuffer;
class CSession;
class CSessionMgr;
class CSessionPolicy;
class CSocketFactory;
class CCompletionHandler;
// IP<49><50>, <20><>Ÿ <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20><>ħ<EFBFBD><C4A7> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
class CValidateConnection
{
public:
LONG AddRef();
LONG Release();
virtual bool operator () (INET_Addr& localAddr, INET_Addr& remoteAddr) = 0;
protected:
CValidateConnection() : m_nRefCount(1) { }
virtual ~CValidateConnection() { }
private:
LONG m_nRefCount;
};
class CListener
{
public:
CListener(CCompletionHandler& SocketHandler,
CSessionPolicy& SessionPolicy,
CSessionMgr& SessionMgr,
CValidateConnection* lpValidateConnection);
virtual ~CListener();
bool Initialize(const char* lpListenAddress, unsigned short usPort,
unsigned long dwMaxPending = 0)
{
return Initialize(INET_Addr(lpListenAddress, usPort), dwMaxPending);
}
bool Initialize(INET_Addr& addrListen, unsigned long dwMaxPending = 0);
bool PendingAccept();
void ProcessAccept(BOOL bResult, SOCKET hSocket,
CBuffer* lpBuffer, unsigned long dwProcessedBytes);
unsigned long GetPendingAcceptNum();
CSessionPolicy& GetPolicy() { return m_SessionPolicy; }
friend std::ostream& Log(std::ostream& strm, CListener* lpListener) { return (0 != lpListener) ? lpListener->PrintStatistics(strm) : strm; }
friend std::ostream& Log(std::ostream& strm, CListener& Listener) { return Listener.PrintStatistics(strm); }
private:
void InternalProcess();
void InternalPending();
void InternalDestroy();
void InternalCloseListen();
void WaitForPendingComplete(unsigned long dwTime);
std::ostream& PrintStatistics(std::ostream& strm);
int InternalPrintStatistics(char* szBuffer, int nBufferLen);
//---------------------------------------------------
typedef CCSLock SessionLock;
SessionLock m_ListenerLock; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>ü <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ǵ帱 <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20><>.
CACHE_PAD(ListenerLockPad, sizeof(SessionLock));
SOCKET m_hListen;
INET_Addr m_ListenAddr;
CCompletionHandler& m_SocketHandler;
CSessionPolicy& m_SessionPolicy;
CSessionMgr& m_SessionMgr;
unsigned long m_dwMaxPending;
unsigned long m_dwCurrentPending;
unsigned long m_dwTotalPendingCount;
unsigned long m_dwTotalAcceptCompleteCount;
CValidateConnection* m_lpValidateConnection;
};
#endif

View File

@@ -0,0 +1,729 @@
#include "stdafx.h"
#include "Session.h"
#include "../IOCP/Overlapped.h"
#include "../IOCP/CompletionHandler.h"
#include "../Winsock/SocketFactory.h"
#include "../Address/INET_Addr.h"
#include "../Dispatch/Dispatch.h"
#include "../Dispatch/ServerRequest.h"
#include "../../Stream/Buffer/Buffer.h"
#include "../../Stream/Buffer/BufferFactory.h"
#include "../../Log/ServerLog.h"
#include <iostream>
// SP : SessionPointer
// DP : DispatchPointer
namespace SessionState
{
enum Type
{
CONNECTED, // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
DISCONNECTED, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ǿ<EFBFBD><C7BE><EFBFBD>.
MAX_SESSION_STATE
};
};
namespace SessionFlag
{
// 8bit SessionFlag
enum Type
{
CONNECT_CALLED = ( 1 << 0 ), // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
DISCONNECT_PROCESSED = ( 1 << 1 ), // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
SHUTDOWN_CALLED = ( 1 << 2 ), // Shutdown<77><6E> ȣ<><C8A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
SHUTDOWN_PROCESSED = ( 1 << 3 ), // Shutdown ó<><C3B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
SUSPEND_RECV = ( 1 << 4 ) // <20>÷<EFBFBD><C3B7>װ<EFBFBD> <20><><EFBFBD>õǾ<C3B5> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Recv<63><76> <20><><EFBFBD><EFBFBD>
};
};
namespace SessionConst
{
enum Data
{
MAX_RECV_BUFFER = 32768
};
}
CSession::CSession(CSessionPolicy& SessionPolicy)
: m_hSocket(INVALID_SOCKET),
m_nRefCount(0),
m_SessionPolicy(SessionPolicy),
m_dwRecvPending(0),
m_dwSendPending(0),
m_cCurrentStatus(SessionState::CONNECTED),
m_cFlags(0),
m_usPadding(0x4343)
{
m_SessionPolicy.AddRef();
m_lpRecvBuffer = CREATE_BUFFER(SessionPolicy.GetBufferFactory(), SessionConst::MAX_RECV_BUFFER);
m_lpDispatch = SessionPolicy.GetDispatchFactory().CreateDispatch(*this);
}
CSession::~CSession()
{
{
SessionLock::Syncronize sync(m_SessionLock);
InternalCloseSocket();
SAFE_RELEASE_BUFFER(m_lpRecvBuffer);
m_SessionPolicy.GetDispatchFactory().DeleteDispatch(m_lpDispatch);
m_usPadding = 0x4444;
}
m_SessionPolicy.Release();
}
// false <20><><EFBFBD>Ͻ<EFBFBD> Accept Pending<6E><67> <20><>.
bool CSession::Process()
{
if(!m_lpDispatch)
{
ERRLOG4(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/CloseSocket - Failed Dispatch Pointer",
this, m_lpDispatch, m_RemoteAddr.get_addr_string(), m_hSocket);
return false;
}
SessionState::Type eState = SessionState::MAX_SESSION_STATE;
unsigned char cFlags = 0;
bool bCloseSocket = false;
bool bCallConnected = false;
bool bCallDisconnected = false;
{
SessionLock::Syncronize sync(m_SessionLock);
eState = static_cast<SessionState::Type>(m_cCurrentStatus);
switch(m_cCurrentStatus)
{
case SessionState::CONNECTED:
if(SessionFlag::CONNECT_CALLED != (m_cFlags & SessionFlag::CONNECT_CALLED))
{
bCallConnected = true;
m_cFlags |= SessionFlag::CONNECT_CALLED;
}
if (!(m_cFlags & SessionFlag::SUSPEND_RECV) && 0 == m_dwRecvPending)
{
// <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>͸<EFBFBD> <20>޴´<DEB4>.
InternalRecv();
}
break;
case SessionState::DISCONNECTED:
if(SessionFlag::DISCONNECT_PROCESSED != (m_cFlags & SessionFlag::DISCONNECT_PROCESSED))
{
bCallDisconnected = true;
m_Statistics.m_DisconnectedTime = time(0);
m_cFlags |= SessionFlag::DISCONNECT_PROCESSED;
}
else if(INVALID_SOCKET == m_hSocket &&
0 == m_dwRecvPending &&
0 == m_dwSendPending &&
0 == m_nRefCount)
{
InternalCloseSocket();
DETLOG4(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/Eliminate Session",
this, m_lpDispatch, m_RemoteAddr.get_addr_string(), m_hSocket);
return false;
}
break;
}
cFlags = m_cFlags;
++m_nRefCount;
}
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20><>.
if(bCallConnected)
{
DETLOG4(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/Connection Open - Process connected",
this, m_lpDispatch, m_RemoteAddr.get_addr_string(), m_hSocket);
m_lpDispatch->Connected();
m_Statistics.m_ConnectedTime = time(0);
}
// <20><><EFBFBD><EFBFBD> <20><>Ŷ<EFBFBD><C5B6> Dispatch<63><68>.
if(SessionState::CONNECTED == eState && !m_lpDispatch->Dispatch())
{
DETLOG4(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/CloseSocket - Failed Dispatch",
this, m_lpDispatch, m_RemoteAddr.get_addr_string(), m_hSocket);
bCloseSocket = true;
}
// <20><><EFBFBD><EFBFBD> <20>ݱ<EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20><>.
if(bCallDisconnected)
{
DETLOG4(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ Connection Closed - Process disconnect",
this, m_lpDispatch, m_RemoteAddr.get_addr_string(), m_hSocket);
m_lpDispatch->Disconnected();
}
{
SessionLock::Syncronize sync(m_SessionLock);
// <20><><EFBFBD><EFBFBD> ó<><C3B3><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
InternalSend();
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Shutdown<77><6E> ȣ<><C8A3><EFBFBD>߾<EFBFBD><DFBE><EFBFBD><EFBFBD><EFBFBD> Shutdown ó<><C3B3><EFBFBD><EFBFBD> <20><>.
if((m_cFlags & SessionFlag::SHUTDOWN_CALLED) &&
m_SendQueue.empty() && INVALID_SOCKET != m_hSocket)
{
if(shutdown(m_hSocket, SD_SEND))
{
m_cFlags |= SessionFlag::SHUTDOWN_PROCESSED;
}
}
--m_nRefCount;
if(bCloseSocket)
{
InternalCloseSocket();
}
}
return true;
}
bool CSession::Dispatch(unsigned long dwReceivedBytes)
{
// <20><>Ŷ ó<><C3B3><EFBFBD><EFBFBD> <20>ϰ<EFBFBD>, ó<><C3B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>δ<EFBFBD>.
m_lpRecvBuffer->wr_ptr(dwReceivedBytes);
unsigned long dwDispatchSize = static_cast<unsigned long>(m_lpRecvBuffer->length());
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>Ʈ <20><><EFBFBD><EFBFBD> 0(<28><><EFBFBD><EFBFBD> <20>Ϸ<EFBFBD>) <20>̰ų<CCB0>, <20><>Ŷ ó<><C3B3><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD> Socket<65><74> Close<73>Ѵ<EFBFBD>.
bool bResult = (0 != dwReceivedBytes &&
m_lpDispatch->ParsePacket(m_lpRecvBuffer->rd_ptr(), &dwDispatchSize));
m_lpRecvBuffer->rd_ptr(dwDispatchSize);
m_lpRecvBuffer->pop_read_data();
SessionLock::Syncronize sync(m_SessionLock);
m_Statistics.m_dwTotalReceived += dwReceivedBytes;
--m_dwRecvPending;
if (!bResult)
{
DETLOG7(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/shutdown - %s : dwReceivedBytes:%d, ErrorCode:%d",
this, m_lpDispatch, m_RemoteAddr.get_addr_string(), m_hSocket,
(0 == dwReceivedBytes) ? "Disconnected" : "Failed To Dispatch Packet",
dwReceivedBytes, WSAGetLastError());
InternalCloseSocket();
}
return bResult;
}
void CSession::InternalCloseSocket()
{
if(INVALID_SOCKET != m_hSocket)
{
const char* szRemoteAddr = m_RemoteAddr.get_addr_string();
if(SOCKET_ERROR == shutdown(m_hSocket, SD_SEND))
{
DETLOG5(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ Shutdown failed - ErrorCode:%d",
this, m_lpDispatch, szRemoteAddr, m_hSocket, WSAGetLastError());
}
if(SOCKET_ERROR == closesocket(m_hSocket))
{
DETLOG5(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ InternalCloseSocket failed - ErrorCode:%d",
this, m_lpDispatch, szRemoteAddr, m_hSocket, WSAGetLastError());
}
const int MAX_BUFFER = 1024;
char szBuffer[MAX_BUFFER];
if(0 < InternalPrintStatistics(szBuffer, MAX_BUFFER))
{
DETLOG4(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/ InternalCloseSocket - Statistics : %s",
this, m_lpDispatch, szRemoteAddr, szBuffer);
}
m_cFlags |= SessionFlag::SHUTDOWN_PROCESSED;
m_hSocket = INVALID_SOCKET;
}
m_cCurrentStatus = SessionState::DISCONNECTED;
}
bool CSession::Shutdown()
{
SessionLock::Syncronize sync(m_SessionLock);
m_cFlags |= SessionFlag::SHUTDOWN_CALLED;
return false;
}
LONG CSession::AddRef()
{
SessionLock::Syncronize sync(m_SessionLock);
return ++m_nRefCount;
}
LONG CSession::Release()
{
SessionLock::Syncronize sync(m_SessionLock);
return --m_nRefCount;
}
void CSession::CloseSession()
{
SessionLock::Syncronize sync(m_SessionLock);
DETLOG4(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/ InternalCloseSocket - SessionClose Called : %d",
this, m_lpDispatch, m_RemoteAddr.get_addr_string(), WSAGetLastError());
InternalCloseSocket();
}
bool CSession::IsConnected()
{
SessionLock::Syncronize sync(m_SessionLock);
return (SessionState::CONNECTED == m_cCurrentStatus && m_hSocket != INVALID_SOCKET);
}
bool CSession::CalledConnected()
{
SessionLock::Syncronize sync(m_SessionLock);
return SessionFlag::CONNECT_CALLED == (m_cFlags & SessionFlag::CONNECT_CALLED);
}
bool CSession::CalledDisconnected()
{
SessionLock::Syncronize sync(m_SessionLock);
return SessionFlag::DISCONNECT_PROCESSED == (m_cFlags & SessionFlag::DISCONNECT_PROCESSED);
}
void CSession::SendCompleted(BOOL bResult, unsigned long dwSendedBytes)
{
SessionLock::Syncronize sync(m_SessionLock);
--m_dwSendPending;
m_Statistics.m_dwTotalSendCompleted += dwSendedBytes;
if(!bResult)
{
DETLOG4(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/ InternalCloseSocket - Send Completion Error : %d",
this, m_lpDispatch, m_RemoteAddr.get_addr_string(), WSAGetLastError());
InternalCloseSocket();
}
else
{
InternalSend();
}
}
void CSession::SetAddress(INET_Addr& remoteAddr, INET_Addr& localAddr)
{
m_RemoteAddr = remoteAddr;
m_LocalAddr = localAddr;
}
std::ostream& CSession::PrintStatistics(std::ostream& strm)
{
SessionLock::Syncronize sync(m_SessionLock);
const int MAX_BUFFER = 1024;
char szBuffer[MAX_BUFFER];
int nLen = InternalPrintStatistics(szBuffer, MAX_BUFFER);
if(0 < nLen)
{
strm << szBuffer;
}
return strm;
}
int CSession::InternalPrintStatistics(char* szBuffer, int nBufferLen)
{
const char* szMode = 0;
switch(m_cCurrentStatus)
{
case SessionState::CONNECTED: szMode = "CONNECTED"; break;
case SessionState::DISCONNECTED: szMode = "DISCONNECTED"; break;
default: szMode = "Unknown Mode"; break;
}
int nLen = _snprintf(szBuffer, nBufferLen - 1,
"[m_hSocket:0x%08x][%15s][DiffTime(Sec):%8f]"
"[m_dwTotalReceived:%5d][m_dwTotalSendPending:%5d][m_dwTotalSendCompleted:%5d]"
"[m_dwSendPending:%d][m_dwRecvPending:%d][m_nRefCount:%2d][flags:0x%02x]",
m_hSocket, szMode, difftime(time(0), m_Statistics.m_ConnectedTime),
m_Statistics.m_dwTotalReceived, m_Statistics.m_dwTotalSendPending,
m_Statistics.m_dwTotalSendCompleted,
m_dwSendPending, m_dwRecvPending,
m_nRefCount, m_cFlags);
szBuffer[nBufferLen - 1] = 0;
return nLen;
}
bool CSession::InternalRecv()
{
if (m_cFlags & SessionFlag::SUSPEND_RECV)
{
DETLOG4(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ Recv suspending now",
this, m_lpDispatch, m_RemoteAddr.get_addr_string(), m_hSocket);
return true;
}
else if (0 != m_dwRecvPending)
{
DETLOG4(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ Recv pending now",
this, m_lpDispatch, m_RemoteAddr.get_addr_string(), m_hSocket);
return true;
}
unsigned long dwReceived = 0;
unsigned long dwFlags = 0;
WSABUF wsaBuf;
wsaBuf.buf = m_lpRecvBuffer->wr_ptr();
wsaBuf.len = static_cast<u_long>(m_lpRecvBuffer->remain());
COverlapped* lpOverlapped = m_SessionPolicy.GetOverlappedFactory().CreateRecv(this, m_lpRecvBuffer);
const char* lpErrorFmtString = 0;
if(0 != lpOverlapped)
{
if(SOCKET_ERROR == WSARecv(m_hSocket, &wsaBuf, 1,
&dwReceived, &dwFlags, lpOverlapped, 0))
{
if(WSA_IO_PENDING != WSAGetLastError())
{
lpErrorFmtString = "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/InternalCloseSocket"
" - WSARecv Error - ErrorCode:%d";
}
}
}
else
{
lpErrorFmtString = "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/InternalCloseSocket"
" - WSARecv Error - Create RecvOverlapped Failed - ErrorCode:%d";
}
if(0 != lpErrorFmtString)
{
DETLOG5(g_SessionLog, lpErrorFmtString, this, m_lpDispatch,
m_RemoteAddr.get_addr_string(), m_hSocket, WSAGetLastError());
InternalCloseSocket();
m_SessionPolicy.GetOverlappedFactory().DeleteOverlapped(lpOverlapped);
return false;
}
++m_dwRecvPending;
return true;
}
bool CSession::InternalRecvFrom()
{
if(0 != m_dwRecvPending)
{
//DETLOG4(g_SessionLog, "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ RecvFrom pending now",
// this, m_lpDispatch, m_RemoteAddr.get_addr_string(), m_hSocket);
return true;
}
if(INVALID_SOCKET == m_hSocket)
{
return false;
}
unsigned long dwReceived = 0;
unsigned long dwFlags = 0;
WSABUF wsaBuf;
wsaBuf.buf = m_lpRecvBuffer->wr_ptr();
wsaBuf.len = static_cast<u_long>(m_lpRecvBuffer->remain());
COverlapped* lpOverlapped =
m_SessionPolicy.GetOverlappedFactory().CreateRecv(this, m_lpRecvBuffer);
const char* lpErrorFmtString = 0;
if(0 != lpOverlapped)
{
INET_Addr& addr = m_lpRecvBuffer->get_addr();
if(SOCKET_ERROR == WSARecvFrom(m_hSocket, &wsaBuf, 1, &dwReceived, &dwFlags,
&addr.get_addr(), addr.get_size_ptr(), lpOverlapped, 0))
{
if(WSA_IO_PENDING != WSAGetLastError())
{
lpErrorFmtString = "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ InternalCloseSocket"
" - WSARecvFrom Error - ErrorCode:%d";
}
}
}
else
{
lpErrorFmtString = "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/InternalCloseSocket"
" - WSARecvFrom Error - Create RecvOverlapped Failed - ErrorCode:%d";
}
if(0 != lpErrorFmtString)
{
DETLOG5(g_SessionLog, lpErrorFmtString, this, m_lpDispatch,
m_RemoteAddr.get_addr_string(), m_hSocket, WSAGetLastError());
InternalCloseSocket();
if(0 != lpOverlapped)
{
m_SessionPolicy.GetOverlappedFactory().DeleteOverlapped(lpOverlapped);
}
return false;
}
++m_dwRecvPending;
return true;
}
CSession::SendResult CSession::InternalSend(CBuffer* lpBuffer)
{
if(0 != m_dwSendPending)
{
return SEND_NEXT_TURN;
}
if(INVALID_SOCKET == m_hSocket)
{
return SEND_FAILED;
}
const char* lpErrorFmtString = 0;
COverlapped* lpOverlapped = 0;
if(0 != lpBuffer)
{
lpOverlapped = m_SessionPolicy.GetOverlappedFactory().CreateSend(this, lpBuffer);
if(0 != lpOverlapped)
{
unsigned long dwSentBytes = 0;
WSABUF wsaBuf;
wsaBuf.buf = lpBuffer->rd_ptr();
wsaBuf.len = static_cast<u_long>(lpBuffer->length());
m_Statistics.m_dwTotalSendPending += wsaBuf.len;
if(SOCKET_ERROR == WSASend(m_hSocket, &wsaBuf, 1,
&dwSentBytes, 0, lpOverlapped, 0))
{
if(WSA_IO_PENDING != WSAGetLastError())
{
lpErrorFmtString = "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ "
"InternalCloseSocket - WSASend Error - ErrorCode:%d";
}
}
}
else
{
lpErrorFmtString = "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ InternalCloseSocket"
" - WSASend Error - Cannot Create SendOverlapped - ErrorCode:%d";
}
}
else
{
lpErrorFmtString = "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ InternalCloseSocket"
" - WSASend Error - lpBuffer is 0 - ErrorCode:%d";
}
if(0 != lpErrorFmtString)
{
DETLOG5(g_SessionLog, lpErrorFmtString, this, m_lpDispatch,
m_RemoteAddr.get_addr_string(), m_hSocket, WSAGetLastError());
InternalCloseSocket();
if(0 != lpOverlapped)
{
lpOverlapped->SetBuffer(0);
m_SessionPolicy.GetOverlappedFactory().DeleteOverlapped(lpOverlapped);
}
return SEND_FAILED;
}
++m_dwSendPending;
return SEND_SUCCEEDED;
}
CSession::SendResult CSession::InternalSendTo(CBuffer* lpBuffer)
{
if(0 != m_dwSendPending)
{
return SEND_NEXT_TURN;
}
if(INVALID_SOCKET == m_hSocket)
{
return SEND_FAILED;
}
const char* lpErrorFmtString = 0;
COverlapped* lpOverlapped = 0;
if(0 != lpBuffer)
{
lpOverlapped = m_SessionPolicy.GetOverlappedFactory().CreateSend(this, lpBuffer);
if(0 != lpOverlapped)
{
unsigned long dwSentBytes = 0;
WSABUF wsaBuf;
wsaBuf.buf = lpBuffer->rd_ptr();
wsaBuf.len = static_cast<u_long>(lpBuffer->length());
m_Statistics.m_dwTotalSendPending += wsaBuf.len;
INET_Addr& addr = lpBuffer->get_addr();
if(SOCKET_ERROR == WSASendTo(m_hSocket, &wsaBuf, 1,
&dwSentBytes, 0, &addr.get_addr(), addr.get_size(), lpOverlapped, 0))
{
if(WSA_IO_PENDING != WSAGetLastError())
{
lpErrorFmtString = "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ "
"InternalCloseSocket - WSASendTo Error - ErrorCode:%d";
}
}
}
else
{
lpErrorFmtString = "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ InternalCloseSocket"
" - WSASendTo Error - Cannot Create SendOverlapped - ErrorCode:%d";
}
}
else
{
lpErrorFmtString = "SP:0x%p/DP:0x%p/IP:%15s/SOCKET:0x%p/ InternalCloseSocket"
" - WSASendTo Error - lpBuffer is 0 - ErrorCode:%d";
}
if(0 != lpErrorFmtString)
{
DETLOG5(g_SessionLog, lpErrorFmtString, this, m_lpDispatch,
m_RemoteAddr.get_addr_string(), m_hSocket, WSAGetLastError());
InternalCloseSocket();
if(0 != lpOverlapped)
{
lpOverlapped->SetBuffer(0);
m_SessionPolicy.GetOverlappedFactory().DeleteOverlapped(lpOverlapped);
}
return SEND_FAILED;
}
++m_dwSendPending;
return SEND_SUCCEEDED;
}
bool CSession::SendPending(CBuffer* lpBuffer)
{
SessionLock::Syncronize sync(m_SessionLock);
if(!(SessionFlag::SHUTDOWN_CALLED & m_cFlags) && INVALID_SOCKET != m_hSocket)
{
m_SendQueue.enqueue(lpBuffer);
return true;
}
return false;
}
bool CSession::InternalSend()
{
SendResult eSendResult = SEND_SUCCEEDED;
if(0 == m_dwSendPending)
{
CBuffer* lpBuffer = m_SendQueue.dequeue();
if(0 != lpBuffer)
{
eSendResult = (0 == lpBuffer->get_addr().get_size()) ?
InternalSend(lpBuffer) : InternalSendTo(lpBuffer);
if(SEND_SUCCEEDED != eSendResult)
{
m_SendQueue.enqueue(lpBuffer, true);
}
}
}
return (SEND_FAILED != eSendResult);
}
void CSession::SuspendRecv()
{
SessionLock::Syncronize sync(m_SessionLock);
m_cFlags |= SessionFlag::SUSPEND_RECV;
}
void CSession::ResumeRecv()
{
SessionLock::Syncronize sync(m_SessionLock);
m_cFlags &= ~SessionFlag::SUSPEND_RECV;
}

View File

@@ -0,0 +1,159 @@
#ifndef _CSESSION_H_
#define _CSESSION_H_
#include <winsock2.h>
#include <windows.h>
#include <mswsock.h>
#include <iosfwd>
#include "SessionPolicy.h"
#include "../Address/INET_Addr.h"
#include "../IOCP/Overlapped.h"
#include "../../Thread/Lock.h"
#include "../../Stream/Buffer/BufferQueue.h"
#pragma comment(lib, "ws2_32")
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
class CBuffer;
class CBufferFactory;
class CPacketDispatch;
class CDispatchFactory;
class CCompletionHandler;
class CSocketBaseFactory;
struct SessionStatistics
{
unsigned long m_dwTotalReceived; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><>.
unsigned long m_dwTotalSendPending; // <20><><EFBFBD>ǿ<EFBFBD><C7BF><EFBFBD> pending<6E><67> <20><>.
unsigned long m_dwTotalSendCompleted; // Send<6E>Ϸ<EFBFBD><CFB7><EFBFBD> <20><>.
time_t m_ConnectedTime; // Connect<63><74> <20>ð<EFBFBD>.
time_t m_DisconnectedTime; // Disconnected<65><64> <20>ð<EFBFBD>.
SessionStatistics::SessionStatistics()
: m_dwTotalReceived(0), m_dwTotalSendPending(0), m_dwTotalSendCompleted(0),
m_ConnectedTime(0), m_DisconnectedTime(0)
{
}
void Initialize()
{
m_dwTotalReceived = m_dwTotalSendPending = m_dwTotalSendCompleted = 0;
m_ConnectedTime = m_DisconnectedTime = 0;
}
};
class CSession
{
public:
CSession(CSessionPolicy& SessionPolicy);
~CSession();
enum SendResult
{
SEND_SUCCEEDED,
SEND_FAILED,
SEND_NEXT_TURN,
};
LONG AddRef();
LONG Release();
bool IsConnected();
void CloseSession();
bool CalledConnected();
bool CalledDisconnected();
void SetAddress(INET_Addr& remoteAddr, INET_Addr& localAddr);
INET_Addr& GetRemoteAddr() { return m_RemoteAddr; }
INET_Addr& GetLocalAddr() { return m_LocalAddr; }
CPacketDispatch* GetDispatch() { return m_lpDispatch; }
CSessionPolicy& GetPolicy() { return m_SessionPolicy; }
const SessionStatistics& GetStatistics() { return m_Statistics; }
bool SendPending(CBuffer* lpBuffer);
void SendCompleted(BOOL bResult, unsigned long dwSendedBytes);
bool Process();
bool Dispatch(unsigned long dwReceivedBytes);
bool Recv() { SessionLock::Syncronize sync(m_SessionLock); return InternalRecv(); }
bool RecvFrom() { SessionLock::Syncronize sync(m_SessionLock); return InternalRecvFrom(); }
bool Send() { SessionLock::Syncronize sync(m_SessionLock); return InternalSend(); }
bool Connect(CCompletionHandler& Handler, LPSTR lpConnectAddress, unsigned short usPort);
bool Shutdown();
void SuspendRecv();
void ResumeRecv();
friend std::ostream& Log(std::ostream& strm, CSession* lpSession) { return (0 != lpSession) ? lpSession->PrintStatistics(strm) : strm; }
friend std::ostream& Log(std::ostream& strm, CSession& Session) { return Session.PrintStatistics(strm); }
private:
bool isValid() const { return (0 != m_lpRecvBuffer && 0 != m_lpDispatch); }
void Socket(SOCKET hSocket) { m_hSocket = hSocket; }
SOCKET Socket() { return m_hSocket; }
bool InternalRecv();
bool InternalRecvFrom();
bool InternalSend();
SendResult InternalSend(CBuffer* lpBuffer);
SendResult InternalSendTo(CBuffer* lpBuffer);
void InternalCloseSocket();
// Desc : <20>α<EFBFBD> <20><><EFBFBD><EFBFBD>
std::ostream& PrintStatistics(std::ostream& strm);
int InternalPrintStatistics(char* szBuffer, int nBufferLen);
// -------------------------------------------------------------------------
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
typedef CCSLock SessionLock; // Critical Section Lock (24byte)
SessionLock m_SessionLock; // Multithreadȯ<64><C8AF><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Lock
CACHE_PAD(LockPadding, sizeof(SessionLock));// Cache-align<67><6E> <20><><EFBFBD><EFBFBD> Padding
// Shared class
CSessionPolicy& m_SessionPolicy; // Session Policy
// Per-session data
CPacketDispatch* m_lpDispatch; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> PacketDispatchŬ<68><C5AC><EFBFBD><EFBFBD>
SOCKET m_hSocket; // Socket Descriptor
INET_Addr m_RemoteAddr; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ּ<EFBFBD>
INET_Addr m_LocalAddr; // <20><><EFBFBD><EFBFBD> <20>ּ<EFBFBD>
CBuffer* m_lpRecvBuffer; // Recv Buffer
CBufferQueue m_SendQueue; // SendQueue
unsigned long m_dwRecvPending; // Recv PendingCount
unsigned long m_dwSendPending; // Send PendingCount
LONG m_nRefCount; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD>۷<EFBFBD><DBB7><EFBFBD> ī<><C4AB>Ʈ
SessionStatistics m_Statistics; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
unsigned char m_cCurrentStatus; // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
unsigned char m_cFlags; // <20><><EFBFBD><EFBFBD> flag
unsigned short m_usPadding; // <20>е<EFBFBD><D0B5><EFBFBD>
friend class CListener;
friend class CIOCPNet;
};
#endif

View File

@@ -0,0 +1,114 @@
#include "SessionMgr.h"
#include "Session.h"
#include <boost/pool/object_pool.hpp>
CSessionMgr::CSessionMgr()
: m_lpSessionPool(new boost::pool<>(sizeof(CSession)))
{
}
CSessionMgr::~CSessionMgr()
{
// <20><>Ÿ <20><><EFBFBD><EFBFBD><EFBFBD>۾<EFBFBD>.
Destroy(5000);
delete m_lpSessionPool;
}
void CSessionMgr::Add(CSession* lpSession)
{
if(0 != lpSession)
{
SessionLock::Syncronize sync(m_AddLock);
m_to_be_added.push_back(lpSession);
}
}
void CSessionMgr::InternalProcess()
{
{
SessionLock::Syncronize sync(m_AddLock);
m_current.splice(m_current.end(), m_to_be_added);
}
SessionSet::iterator pos = m_current.begin();
SessionSet::iterator end = m_current.end();
CSession* lpSession = 0;
for(;pos != end;)
{
lpSession = *pos;
if(!lpSession->Process())
{
pos = m_current.erase(pos);
DeleteSession(lpSession);
}
else
{
++pos;
}
}
}
void CSessionMgr::Destroy(unsigned long dwWaitTime)
{
SessionLock::Syncronize process_sync(m_ProcessLock);
{
SessionLock::Syncronize sync(m_AddLock);
m_current.splice(m_current.end(), m_to_be_added);
}
SessionSet::iterator pos = m_current.begin();
SessionSet::iterator end = m_current.end();
CSession* lpSession = 0;
for(;pos != end; ++pos)
{
lpSession = *pos;
lpSession->CloseSession();
}
pos = m_current.begin();
end = m_current.end();
unsigned long dwTime = timeGetTime();
while(!m_current.empty()
&& timeGetTime() < dwTime + dwWaitTime)
{
InternalProcess();
Sleep(10);
}
}
CSession* CSessionMgr::CreateSession(CSessionPolicy& SessionPolicy)
{
SessionLock::Syncronize sync(m_CreationLock);
void* ptr = m_lpSessionPool->malloc();
return ptr ? new (ptr) CSession(SessionPolicy) : 0;
}
void CSessionMgr::DeleteSession(CSession* lpSession)
{
SessionLock::Syncronize sync(m_CreationLock);
if(0 != m_lpSessionPool && 0 != lpSession)
{
lpSession->~CSession();
m_lpSessionPool->free(lpSession);
}
}

View File

@@ -0,0 +1,51 @@
#ifndef _NETWORK_SESSION_MGR_H_
#define _NETWORK_SESSION_MGR_H_
#include "../../Thread/Lock.h"
#include <list>
#include <boost/pool/poolfwd.hpp>
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
class CSession;
class CSessionPolicy;
class CSessionMgr
{
public:
CSessionMgr();
~CSessionMgr();
void Add(CSession* lpSession);
void Process() { SessionLock::Syncronize process_sync(m_ProcessLock); InternalProcess(); }
void Destroy(unsigned long dwWaitTime = INFINITE);
size_t GetSessionNum() { SessionLock::Syncronize process_sync(m_ProcessLock); return m_current.size(); }
CSession* CreateSession(CSessionPolicy& SessionPolicy);
void DeleteSession(CSession* lpSession);
private:
void InternalProcess();
typedef CCSLock SessionLock;
typedef std::list<CSession*> SessionSet;
SessionLock m_AddLock;
SessionSet m_to_be_added;
CACHE_PAD(AddLockPad, sizeof(SessionSet));
SessionLock m_ProcessLock;
SessionSet m_current;
CACHE_PAD(ProcessLockPad, sizeof(SessionSet));
SessionLock m_CreationLock;
boost::pool<>* m_lpSessionPool;
};
#endif

View File

@@ -0,0 +1,45 @@
#include "stdafx.h"
#include "SessionPolicy.h"
#include "../IOCP/Overlapped.h"
#include "../Dispatch/Dispatch.h"
#include "../Winsock/SocketFactory.h"
#include "../../Stream/Buffer/BufferFactory.h"
CSessionPolicy::CSessionPolicy(CSocketFactory* lpSocketFactory,
CBufferFactory* lpBufferFactory,
CDispatchFactory* lpDispatchFactory,
COverlappedFactory* lpOverlappedFactory)
: m_lpSocketFactory(lpSocketFactory),
m_lpBufferFactory(lpBufferFactory),
m_lpDispatchFactory(lpDispatchFactory),
m_lpOverlappedFactory(lpOverlappedFactory),
m_nRefCount(1)
{
}
CSessionPolicy::~CSessionPolicy()
{
delete m_lpSocketFactory;
delete m_lpBufferFactory;
delete m_lpDispatchFactory;
delete m_lpOverlappedFactory;
}
LONG CSessionPolicy::AddRef()
{
return InterlockedIncrement(&m_nRefCount);
}
LONG CSessionPolicy::Release()
{
LONG nRefCount = InterlockedDecrement(&m_nRefCount);
if(0 == nRefCount)
{
delete this;
}
return nRefCount;
}

View File

@@ -0,0 +1,66 @@
#ifndef _GAMA_NETWORK_LIBRARY_SESSION_POLICY_H_
#define _GAMA_NETWORK_LIBRARY_SESSION_POLICY_H_
// forward decl.
class CSocketFactory;
class CBufferFactory;
class CDispatchFactory;
class COverlappedFactory;
class CSessionPolicy
{
public:
LONG AddRef();
LONG Release();
bool IsValid()
{
return 0 != m_lpBufferFactory && 0 != m_lpSocketFactory &&
0 != m_lpDispatchFactory && 0 != m_lpOverlappedFactory;
}
CSocketFactory& GetSocketFactory() { return *m_lpSocketFactory; }
CBufferFactory& GetBufferFactory() { return *m_lpBufferFactory; }
CDispatchFactory& GetDispatchFactory() { return *m_lpDispatchFactory; }
COverlappedFactory& GetOverlappedFactory() { return *m_lpOverlappedFactory; }
// Creation Factory
template <class SocketFactory, class BufferFactory, class DispatchFactory, class OverlappedFactory>
static CSessionPolicy* Create()
{
CSessionPolicy* lpSessionPolicy = new (std::nothrow) CSessionPolicy(
new SocketFactory,
new BufferFactory,
new DispatchFactory,
new OverlappedFactory);
if(0 == lpSessionPolicy || !lpSessionPolicy->IsValid())
{
delete lpSessionPolicy;
lpSessionPolicy = 0;
}
return lpSessionPolicy;
}
// edith 2009.08.14 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>޸<EFBFBD><DEB8><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Private Ÿ<>Կ<EFBFBD><D4BF><EFBFBD> Public Ÿ<><C5B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
~CSessionPolicy();
private:
CSessionPolicy(
CSocketFactory* lpSocketFactory,
CBufferFactory* lpBufferFactory,
CDispatchFactory* lpDispatchFactory,
COverlappedFactory* lpOverlappedFactory);
CSocketFactory* m_lpSocketFactory;
CBufferFactory* m_lpBufferFactory;
CDispatchFactory* m_lpDispatchFactory;
COverlappedFactory* m_lpOverlappedFactory;
LONG m_nRefCount;
};
#endif

View File

@@ -0,0 +1,280 @@
#include "stdafx.h"
#include <winsock2.h>
#include <windows.h>
#include <wsipx.h>
#include <cassert>
#include "SocketFactory.h"
//#include "../../Utility/Math/Math.h"
CSocketFactory::CSocketFactory(int nSocketFamily, int nSocketType, int nSocketProtocol, int nAddressLen)
: m_nSockFamily(nSocketFamily), m_nSockType(nSocketType), m_nSockProtocol(nSocketProtocol),
m_nAddressLen(nAddressLen)
{
}
CINETFamilyFactory::CINETFamilyFactory(int nSocketType, int nSocketProtocol)
: CSocketFactory(AF_INET, nSocketType, nSocketProtocol, sizeof(SOCKADDR_IN))
{
}
CTCPFactory::CTCPFactory()
: CINETFamilyFactory(SOCK_STREAM, IPPROTO_TCP)
{
}
CUDPFactory::CUDPFactory()
: CINETFamilyFactory(SOCK_DGRAM, IPPROTO_UDP)
{
}
/*
CIPXFamilyFactory::CIPXFamilyFactory(int nSocketType, int nSocketProtocol)
: CSocketFactory(AF_IPX, nSocketType, nSocketProtocol, sizeof(SOCKADDR_IPX))
{
}
CSPXFactory::CSPXFactory()
: CIPXFamilyFactory(SOCK_STREAM, NSPROTO_SPX)
{
}
CIPXFactory::CIPXFactory()
: CIPXFamilyFactory(SOCK_DGRAM, NSPROTO_IPX)
{
}
*/
SOCKET CSocketFactory::CreateSocket()
{
SOCKET hSocket = WSASocket(m_nSockFamily, m_nSockType, m_nSockProtocol,
NULL, 0, WSA_FLAG_OVERLAPPED);
return hSocket;
}
SOCKET CSocketFactory::CreateConnectedSocket(const char* lpConnAddr, unsigned short usPort)
{
SOCKADDR sockAddr;
if (!SetAddr(&sockAddr, lpConnAddr, usPort))
{
return INVALID_SOCKET;
}
SOCKET connectedSocket = CreateSocket();
if (INVALID_SOCKET != connectedSocket)
{
if (SOCKET_ERROR == connect(connectedSocket, &sockAddr, m_nAddressLen))
{
closesocket(connectedSocket);
connectedSocket = INVALID_SOCKET;
}
}
return connectedSocket;
}
SOCKET CSocketFactory::CreateBindedSocket(const char* lpBindAddr, unsigned short usPort)
{
SOCKADDR sockAddr;
if (!SetAddr(&sockAddr, lpBindAddr, usPort))
{
return INVALID_SOCKET;
}
SOCKET bindedSocket = CreateSocket();
if(INVALID_SOCKET != bindedSocket)
{
BOOL bReuseAddr = TRUE;
if (SOCKET_ERROR == setsockopt(bindedSocket, SOL_SOCKET, SO_REUSEADDR,
(char *)&bReuseAddr, sizeof(bReuseAddr)))
{
closesocket(bindedSocket);
bindedSocket = INVALID_SOCKET;
}
else
{
if(SOCKET_ERROR == bind(bindedSocket, &sockAddr, m_nAddressLen))
{
closesocket(bindedSocket);
bindedSocket = INVALID_SOCKET;
}
}
}
return bindedSocket;
}
SOCKET CSocketFactory::CreateListenSocket(const char* lpListenAddr, unsigned short usPort, int nBackLog)
{
nBackLog = min(nBackLog, MAX_BACKLOG);
// bind server to Server address
SOCKET sdListen = CreateBindedSocket(lpListenAddr, usPort);
if (INVALID_SOCKET != sdListen)
{
// start listening
if (SOCKET_ERROR == listen(sdListen, nBackLog))
{
closesocket(sdListen);
sdListen = INVALID_SOCKET;
}
}
return sdListen;
}
bool CINETFamilyFactory::SetAddr(LPSOCKADDR lpSA, const char* szAddr, unsigned short usPort)
{
int nAddrLen = sizeof(SOCKADDR_IN);
memset(lpSA, 0, nAddrLen);
LPSOCKADDR_IN lpSA_in = reinterpret_cast<LPSOCKADDR_IN>(lpSA);
if (0 != szAddr)
{
lpSA_in->sin_family = m_nSockFamily;
lpSA_in->sin_addr.S_un.S_addr = inet_addr(szAddr);
lpSA_in->sin_port = htons(usPort);
if(0 == lpSA_in->sin_addr.S_un.S_addr)
{
return false;
}
}
else
{
lpSA_in->sin_addr.S_un.S_addr = htonl(INADDR_ANY);
}
lpSA_in->sin_family = m_nSockFamily;
lpSA_in->sin_port = htons(usPort);
return true;
}
bool CINETFamilyFactory::GetNetworkInfo(char *Address_Out, int nMaxBufferSize)
{
const int MAX_HOSTNAME_BUFFER = 256;
char szHostName[MAX_HOSTNAME_BUFFER];
if(!gethostname(szHostName, MAX_HOSTNAME_BUFFER - 1))
{
szHostName[MAX_HOSTNAME_BUFFER - 1] = '\0';
PHOSTENT pHost = gethostbyname(szHostName);
if(NULL == pHost)
{
return false;
}
IN_ADDR Addr = {0,};
int Count = 0;
for(Count = 0;pHost->h_addr_list[Count]; ++Count)
{
memcpy(&Addr, pHost->h_addr_list[Count], sizeof(IN_ADDR));
strncpy(Address_Out, inet_ntoa(Addr), nMaxBufferSize - 1);
Address_Out[nMaxBufferSize - 1] = '\0';
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ȯ<><C8AE>
// 10.0.0.0 ~ 10.255.255.255
// 172.16.0.0 ~ 172.31.255.255
// 192.168.0.0 ~ 192.168.255.255
if((unsigned char)10 == Addr.S_un.S_un_b.s_b1)
{
continue;
}
else if((unsigned char)172 == Addr.S_un.S_un_b.s_b1)
{
if(Addr.S_un.S_un_b.s_b2 >= (unsigned char)16 && Addr.S_un.S_un_b.s_b2 <= (unsigned char)31)
{
continue;
}
}
else if((unsigned char)192 == Addr.S_un.S_un_b.s_b1)
{
if((unsigned char)168 == Addr.S_un.S_un_b.s_b2)
{
continue;
}
}
return true;
}
if(0 != Count)
{
return true;
}
}
return false;
}
bool CTCPFactory::SetLinger(SOCKET hSocket, bool bOn, unsigned short usTimeOut)
{
linger socketLinger;
socketLinger.l_onoff = bOn ? 1 : 0;
socketLinger.l_linger = usTimeOut;
if(SOCKET_ERROR == setsockopt(hSocket, SOL_SOCKET, SO_LINGER,
(char *)&socketLinger, sizeof(linger)))
{
return false;
}
return true;
}
/*
bool CIPXFamilyFactory::SetAddr(LPSOCKADDR lpSA, char *szAddr, unsigned short usPort)
{
if(0 == szAddr) { return false; }
// get the offset for node number / network number separator
LPSTR lpszNodeNum = strchr(szAddr, '.');
if (0 == lpszNodeNum)
{
return false;
}
++lpszNodeNum;
LPSOCKADDR_IPX lpSA_ipx = reinterpret_cast<LPSOCKADDR_IPX>(lpSA);
lpSA_ipx->sa_family = m_nSockFamily;
Math::Convert::AcToHe(szAddr,(char*)&lpSA_ipx->sa_netnum, 4);
Math::Convert::AcToHe(lpszNodeNum,(char*)&lpSA_ipx->sa_nodenum, 6);
lpSA_ipx->sa_socket = htons(usPort);
return true;
}
bool CIPXFamilyFactory::GetNetworkInfo(char *Address_Out, int nMaxBufferSize)
{
return true;
}
*/

View File

@@ -0,0 +1,105 @@
#ifndef _SOCKET_FAMILY_H_
#define _SOCKET_FAMILY_H_
class CSocketFactory
{
public:
virtual ~CSocketFactory() { }
SOCKET CreateConnectedSocket(const char* lpConnAddr, unsigned short usPort);
SOCKET CreateBindedSocket(const char* lpBindAddr, unsigned short usPort);
SOCKET CreateListenSocket(const char* lpListenAddr, unsigned short usPort, int nBackLog = MAX_BACKLOG);
virtual SOCKET CreateSocket();
virtual bool GetNetworkInfo(char* Address_Out, int nMaxBufferSize) = 0;
virtual bool SetAddr(LPSOCKADDR lpSA, const char* szAddr, unsigned short usPort) = 0;
inline int GetAddressLen() const { return m_nAddressLen; }
protected:
CSocketFactory(int nSocketFamily, int nSocketType,
int nSocketProtocol, int nAddressLen);
enum { MAX_BACKLOG = 63 };
int m_nSockFamily;
int m_nSockType;
int m_nSockProtocol;
int m_nAddressLen;
};
class CINETFamilyFactory : public CSocketFactory
{
public:
virtual bool GetNetworkInfo(char* Address_Out, int nMaxBufferSize);
virtual bool SetAddr(LPSOCKADDR lpSA, const char* szAddr, unsigned short usPort);
protected:
CINETFamilyFactory(int nSocketType, int nSocketProtocol);
virtual ~CINETFamilyFactory() { }
};
class CTCPFactory : public CINETFamilyFactory
{
public:
CTCPFactory();
virtual ~CTCPFactory() { }
static bool SetLinger(SOCKET hSocket, bool bOn, unsigned short usTimeOut);
};
class CUDPFactory : public CINETFamilyFactory
{
public:
CUDPFactory();
virtual ~CUDPFactory() { }
};
/*
//-----------------------------------------------------------------------------------------
class CIPXFamilyFactory : public CSocketFactory
{
public:
virtual bool GetNetworkInfo(char* Address_Out, int nMaxBufferSize);
virtual bool SetAddr(LPSOCKADDR lpSA, char* szAddr, unsigned short usPort);
protected:
CIPXFamilyFactory(int nSocketType, int nSocketProtocol);
virtual ~CIPXFamilyFactory() { }
};
class CSPXFactory : public CIPXFamilyFactory
{
public:
CSPXFactory();
virtual ~CSPXFactory() { }
};
class CIPXFactory : public CIPXFamilyFactory
{
public:
CIPXFactory();
virtual ~CIPXFactory() { }
};
//-----------------------------------------------------------------------------------------
*/
#endif