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:
@@ -0,0 +1,42 @@
|
||||
// ClientSock.cpp : 구현 파일입니다.
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include <Network/AsyncSock/ClientSock.h>
|
||||
#include <Network/SingleSession/ClientSingleSession.h>
|
||||
#include ".\clientsock.h"
|
||||
|
||||
// CClientSock
|
||||
|
||||
CClientSock::CClientSock( CSingleSession* Instance ) : m_SingleSession( Instance )
|
||||
{
|
||||
m_SingleSession = Instance;
|
||||
}
|
||||
|
||||
CClientSock::~CClientSock()
|
||||
{
|
||||
}
|
||||
|
||||
// CClientSock 멤버 함수입니다.
|
||||
|
||||
void CClientSock::OnReceive(int nErrorCode)
|
||||
{
|
||||
// TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다.
|
||||
m_SingleSession->Recv( );
|
||||
CAsyncSocket::OnReceive(nErrorCode);
|
||||
}
|
||||
|
||||
void CClientSock::OnClose(int nErrorCode)
|
||||
{
|
||||
// TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다.
|
||||
//MessageBox( NULL, "서버와 연결이 끊어졌습니다.", "알림", MB_OK );
|
||||
m_SingleSession->Disconnected( );
|
||||
CAsyncSocket::OnClose(nErrorCode);
|
||||
}
|
||||
|
||||
void CClientSock::OnConnect(int nErrorCode)
|
||||
{
|
||||
// TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다.
|
||||
CSocket::OnConnect(nErrorCode);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
|
||||
// CClientSock 명령 대상입니다.
|
||||
class CSingleSession;
|
||||
|
||||
class CClientSock : public CSocket
|
||||
{
|
||||
public:
|
||||
CClientSock( CSingleSession* Instance );
|
||||
virtual ~CClientSock();
|
||||
|
||||
private:
|
||||
CSingleSession* m_SingleSession;
|
||||
public:
|
||||
virtual void OnReceive(int nErrorCode);
|
||||
virtual void OnClose(int nErrorCode);
|
||||
virtual void OnConnect(int nErrorCode);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "AdminToolDispatch.h"
|
||||
|
||||
#include < Network/Packet/PacketBase.h >
|
||||
#include < Network/Packet/WrapPacket.h >
|
||||
#include < Network/XORCrypt/XORCrypt.h >
|
||||
|
||||
#include < Utility/Compress/MiniLZO/miniLZOWrapper.h >
|
||||
#include < Log/ServerLog.h >
|
||||
|
||||
bool CClientMultiThreadDispatch::ParsePacket( char* const lpStream_In, unsigned long* dwStreamSize_InOut )
|
||||
{
|
||||
CXORCrypt& Crypt = CXORCrypt::GetInstance();
|
||||
|
||||
PktBase* lpPktBase = NULL;
|
||||
char* lpBufferPos = lpStream_In;
|
||||
|
||||
unsigned long dwStreamSize = *dwStreamSize_InOut;
|
||||
unsigned long dwDecompressedSize = 0;
|
||||
char szDecompressedPacket[PktMaxLen] = "";
|
||||
|
||||
while(dwStreamSize >= sizeof(PktBase))
|
||||
{
|
||||
lpPktBase = reinterpret_cast<PktBase*>(lpBufferPos);
|
||||
|
||||
// 패킷 헤더가 vaild한지 확인한다. invalid한 경우는 그냥 끊어버린다.
|
||||
if(StartBit != lpPktBase->GetStartBit())
|
||||
{
|
||||
PktBase::CMDType cCmd = lpPktBase->GetCmd();
|
||||
Crypt.DecodeHeader(reinterpret_cast<char*>(&cCmd), 1, 0, 0);
|
||||
//LogErrorPacket("패킷 헤더의 시작 비트가 잘못되었습니다.", cCmd);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 패킷 헤더 디코딩
|
||||
Crypt.DecodeHeader(lpBufferPos + 1, sizeof(PktBase) - 1, 0, 0);
|
||||
|
||||
// 헤더 길이 얻어 오기.
|
||||
const PktBase::CMDType nPacketCMD = lpPktBase->GetCmd();
|
||||
const PktBase::LengthType nPacketLength = lpPktBase->GetLen();
|
||||
|
||||
if(dwStreamSize < nPacketLength)
|
||||
{
|
||||
// 전체 스트림 사이즈가 파싱을 하기에는 모자람. 다시 인코딩 한 후 다음 턴을 기다림
|
||||
Crypt.EncodeHeader(lpBufferPos + 1, sizeof(PktBase) - 1, 0, 0);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 패킷 디코딩.
|
||||
if(lpPktBase->IsCrypt())
|
||||
{
|
||||
Crypt.DecodePacket(lpBufferPos + sizeof(PktBase),
|
||||
nPacketLength - sizeof(PktBase), lpPktBase->GetCodePage());
|
||||
}
|
||||
|
||||
// 패킷 압축 해제.
|
||||
if(lpPktBase->IsCompress())
|
||||
{
|
||||
// 압축 지원하지 않음..
|
||||
// return false;
|
||||
dwDecompressedSize = PktMaxLen - sizeof(PktBase);
|
||||
memcpy(szDecompressedPacket, lpPktBase, sizeof(PktBase));
|
||||
|
||||
// 로컬 버퍼에서 압축 해제.
|
||||
if(!CMiniLZO::Decompress(lpBufferPos + sizeof(PktBase), nPacketLength - sizeof(PktBase),
|
||||
szDecompressedPacket + sizeof(PktBase), &dwDecompressedSize))
|
||||
{
|
||||
//LogErrorPacket("패킷 압축 해제에 실패했습니다.", nPacketCMD);
|
||||
return false;
|
||||
}
|
||||
|
||||
// lpPktBase를 로컬 버퍼로 세팅.
|
||||
lpPktBase = reinterpret_cast<PktBase*>(szDecompressedPacket);
|
||||
lpPktBase->SetLen(static_cast<PktBase::LengthType>(dwDecompressedSize + sizeof(PktBase)));
|
||||
}
|
||||
|
||||
if(!DispatchPacket(lpPktBase))
|
||||
{
|
||||
// 패킷 파싱에 실패. 세션을 종료한다.
|
||||
return false;
|
||||
}
|
||||
|
||||
dwStreamSize -= nPacketLength;
|
||||
lpBufferPos += nPacketLength;
|
||||
}
|
||||
}
|
||||
|
||||
*dwStreamSize_InOut -= dwStreamSize;
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#ifndef _ADMIN_TOOL_DISPATCH_H_
|
||||
#define _ADMIN_TOOL_DISPATCH_H_
|
||||
|
||||
struct PktBase;
|
||||
|
||||
class CSingleSession;
|
||||
class CWnd;
|
||||
class CPacketToolDispatch
|
||||
{
|
||||
public:
|
||||
|
||||
// Desc: 세션에서 받은 데이터로 패킷을 생성한다.
|
||||
// Input: const char* lpStream_In : 세션에서 받은 데이터.
|
||||
// size_t* nStreamSize_InOut : 받은 데이터의 크기.
|
||||
// Output: size_t* nStreamSize_InOut : 처리된 데이터의 크기.
|
||||
// 리턴값 : false 리턴 시 접속을 해제한다. (잘못된 패킷 존재 가능성 있음)
|
||||
virtual bool ParsePacket(char* const lpStream_In, unsigned long* dwStreamSize_InOut) = 0;
|
||||
|
||||
// Desc: 생성한 패킷을 단일 스레드에서 처리한다.
|
||||
// (CSession::Process 에서 매 펄스마다 호출한다.)
|
||||
virtual bool SingleThreadDispatch(unsigned long dwCurrentTime) = 0;
|
||||
|
||||
// Desc: 자기 자신을 생성한다.
|
||||
// Output: 리턴값 : 생성 실패시 NULL 리턴
|
||||
virtual CPacketToolDispatch* Clone() = 0;
|
||||
|
||||
// Desc: 자기 자신을 소멸시킨다.
|
||||
virtual void Destroy() = 0;
|
||||
|
||||
// Desc: 연결 종료시 처리할 내용을 넣는다.
|
||||
virtual void Disconnected() = 0;
|
||||
|
||||
// Desc: 세션과의 상호참조를 위한 함수들.
|
||||
inline void SetSession(CSingleSession* lpSession) { m_lpSession = lpSession; }
|
||||
inline CSingleSession* GetSession() { return m_lpSession; }
|
||||
|
||||
virtual ~CPacketToolDispatch() { }
|
||||
|
||||
protected:
|
||||
|
||||
// Dispatcher의 생성자는 항상 Protected이어야 한다.
|
||||
CPacketToolDispatch() : m_lpSession(0) { }
|
||||
CSingleSession* m_lpSession;
|
||||
};
|
||||
|
||||
class CClientMultiThreadDispatch : public CPacketToolDispatch
|
||||
{
|
||||
public:
|
||||
CClientMultiThreadDispatch( ) { m_pDispatchWindow = NULL; }
|
||||
|
||||
virtual bool ParsePacket(char* const lpStream_In, unsigned long* dwStreamSize_InOut);
|
||||
virtual bool SingleThreadDispatch(unsigned long dwCurrentTime) { return true; }
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool DispatchPacket(PktBase* lpPktBase) = 0;
|
||||
|
||||
virtual ~CClientMultiThreadDispatch() { }
|
||||
|
||||
CWnd* m_pDispatchWindow;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,213 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include <Stream/Buffer/Buffer.h>
|
||||
#include <Stream/Buffer/BufferFactory.h>
|
||||
#include <Network/Dispatch/AdminToolDispatch.h>
|
||||
|
||||
#include <Network/AsyncSock/ClientSock.h>
|
||||
#include <Network/SingleSession/ClientSingleSession.h>
|
||||
|
||||
|
||||
CSingleSession::CSingleSession( )
|
||||
: m_hSock( INVALID_SOCKET ), m_lpClientAsync( NULL ), m_pPacketDispatch( NULL ), m_bIsConnected( FALSE )
|
||||
//m_pRecvBuffer( CREATE_BUFFER( static_cast< unsigned long >( CBufferFactory::GetOptimizedBufferSize( 32768 ) ) ) )
|
||||
{
|
||||
m_pRecvBuffer = m_DefaultBufferFactory.Create( 32768 );
|
||||
}
|
||||
|
||||
CSingleSession::~CSingleSession( )
|
||||
{
|
||||
Destroy( );
|
||||
|
||||
if( m_pRecvBuffer )
|
||||
{
|
||||
m_DefaultBufferFactory.Release( m_pRecvBuffer );
|
||||
//RELEASE_BUFFER( m_pRecvBuffer );
|
||||
}
|
||||
}
|
||||
|
||||
bool CSingleSession::Initialize( CPacketToolDispatch* pPacketDispatch )
|
||||
{
|
||||
if( pPacketDispatch == NULL ) return false;
|
||||
|
||||
m_lpClientAsync = new CClientSock( this );
|
||||
|
||||
if( !SetDispatch( pPacketDispatch ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( !m_lpClientAsync->Create( ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CSingleSession::Disconnected( )
|
||||
{
|
||||
MessageBox( NULL, _T("서버와 연결이 끊어졌습니다."), _T("알림"), MB_OK );
|
||||
m_bIsConnected = false;
|
||||
}
|
||||
|
||||
bool CSingleSession::Connect( TCHAR* Address, int nPort )
|
||||
{
|
||||
if( m_lpClientAsync )
|
||||
{
|
||||
if( InitializeInternal( m_pPacketDispatch ) )
|
||||
{
|
||||
if( m_lpClientAsync->Connect(Address, nPort ) )
|
||||
{
|
||||
m_hSock = m_lpClientAsync->m_hSocket;
|
||||
m_bIsConnected = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CSingleSession::GetConnected( )
|
||||
{
|
||||
return m_bIsConnected;
|
||||
}
|
||||
|
||||
bool CSingleSession::InitializeInternal( CPacketToolDispatch* lpPacketDispatch )
|
||||
{
|
||||
m_bIsConnected = FALSE;
|
||||
|
||||
CloseSocket( );
|
||||
|
||||
//m_pRecvBuffer->ClearBuffer( );
|
||||
|
||||
if( m_pRecvBuffer == NULL )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if( m_pPacketDispatch == NULL )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSingleSession::Send( CBuffer* lpBuffer )
|
||||
{
|
||||
unsigned long dwSendBytes = 0;
|
||||
unsigned long nSendByte = lpBuffer->length( );
|
||||
|
||||
if( m_hSock != INVALID_SOCKET )
|
||||
{
|
||||
while( nSendByte )
|
||||
{
|
||||
dwSendBytes = m_lpClientAsync->Send( lpBuffer->begin( ), lpBuffer->length( ) ); // 전부보낼때까지 버텨~
|
||||
|
||||
if( dwSendBytes )
|
||||
{
|
||||
nSendByte -= dwSendBytes;
|
||||
}
|
||||
else //뭔가 삑싸리
|
||||
{
|
||||
CloseSocket( );
|
||||
//RELEASE_BUFFER( lpBuffer );
|
||||
m_DefaultBufferFactory.Release( lpBuffer );
|
||||
|
||||
AfxMessageBox( _T("패킷보내기 실패 접속 끊어~~"), MB_OK );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//RELEASE_BUFFER( lpBuffer );
|
||||
m_DefaultBufferFactory.Release( lpBuffer );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CSingleSession::Recv( )
|
||||
{
|
||||
unsigned long dwReceived = 0; //리쌔에에에에엣~
|
||||
unsigned long dwBufferLength = m_pRecvBuffer->remain( ); //현제 버퍼의 남은공간을 가져오자
|
||||
|
||||
if( m_hSock != INVALID_SOCKET ) // 유효한 소켓?
|
||||
{
|
||||
dwReceived = m_lpClientAsync->Receive( m_pRecvBuffer->wr_ptr( ), m_pRecvBuffer->remain( ) ); // 전부 받아버려주자~
|
||||
|
||||
if( dwReceived ) // 뭔가 받았다.
|
||||
{
|
||||
return Dispatch( dwReceived ); // 패킷 디스패치~ 이
|
||||
}
|
||||
else // 헉~
|
||||
{
|
||||
CloseSocket( );
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CSingleSession::Dispatch( unsigned long dwReceivedBytes )
|
||||
{
|
||||
// 패킷 처리를 하고, 처리하지 못한 양을 앞으로 갖다 붙인다.
|
||||
//m_pRecvBuffer->UseBuffer(dwReceivedBytes);
|
||||
m_pRecvBuffer->wr_ptr( dwReceivedBytes );
|
||||
unsigned long dwDispatchSize = m_pRecvBuffer->length( );
|
||||
|
||||
// 받은 바이트 수가 0(접속 완료) 이거나, 패킷 처리에 실패하면 Socket을 Close한다.
|
||||
bool bResult = ( ( 0 != dwReceivedBytes ) && ( NULL != m_pPacketDispatch ) &&
|
||||
m_pPacketDispatch->ParsePacket( m_pRecvBuffer->begin( ), &dwDispatchSize ) );
|
||||
|
||||
m_pRecvBuffer->rd_ptr( dwDispatchSize ); // 처리한 패킷길이만큼 밀어주고
|
||||
m_pRecvBuffer->pop_read_data( ); // 처리한 패킷은 버퍼에서 지워버리고...
|
||||
|
||||
if( !bResult )
|
||||
{
|
||||
AfxMessageBox( _T("Dispatch 실패 접속 종료~~"), MB_OK );
|
||||
CloseSocket();
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
void CSingleSession::Close( )
|
||||
{
|
||||
if( m_lpClientAsync ) delete m_lpClientAsync;
|
||||
m_hSock = INVALID_SOCKET;
|
||||
m_bIsConnected = FALSE;
|
||||
}
|
||||
|
||||
bool CSingleSession::SetDispatch( CPacketToolDispatch* pPacketDispatch )
|
||||
{
|
||||
if( m_pPacketDispatch ) return false;
|
||||
|
||||
m_pPacketDispatch = pPacketDispatch;
|
||||
m_pPacketDispatch->SetSession(this);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CSingleSession::Destroy( )
|
||||
{
|
||||
Close( );
|
||||
|
||||
CloseSocket( );
|
||||
|
||||
if( m_pPacketDispatch )
|
||||
{
|
||||
m_pPacketDispatch->Destroy();
|
||||
m_pPacketDispatch = NULL;
|
||||
}
|
||||
|
||||
// m_pRecvBuffer->ClearBuffer();
|
||||
}
|
||||
|
||||
void CSingleSession::CloseSocket( )
|
||||
{
|
||||
if(INVALID_SOCKET != m_hSock)
|
||||
{
|
||||
shutdown(m_hSock, SD_BOTH);
|
||||
closesocket(m_hSock);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef _CLIENT_SINGLE_SESSION_H_
|
||||
#define _CLIENT_SINGLE_SESSION_H_
|
||||
|
||||
#include <Stream/Buffer/BufferFactory.h>
|
||||
#include <tchar.h>
|
||||
|
||||
// forward decl.
|
||||
class CClientSock;
|
||||
class CBuffer;
|
||||
class CPacketToolDispatch;
|
||||
class CWnd;
|
||||
|
||||
class CSingleSession
|
||||
{
|
||||
public:
|
||||
CSingleSession( );
|
||||
~CSingleSession( );
|
||||
|
||||
bool Send( CBuffer* lpBuffer );
|
||||
bool Recv( );
|
||||
void Close( );
|
||||
void Destroy( );
|
||||
bool Initialize( CPacketToolDispatch* CPacketToolDispatch );
|
||||
bool Connect( TCHAR* Address, int nPort );
|
||||
void Disconnected( );
|
||||
bool GetConnected( );
|
||||
bool SetCurrentWindow( CWnd* pMainFrame );
|
||||
CWnd* GetCurrentWindow( );
|
||||
|
||||
private:
|
||||
SOCKET m_hSock; // Socket정의
|
||||
CClientSock* m_lpClientAsync; // Mfc클레스 CAsyncSocket
|
||||
|
||||
CBuffer* m_pRecvBuffer; // 받은데이터를 보관해두자.
|
||||
CPacketToolDispatch* m_pPacketDispatch; // 받았으면 가지고 놀자..
|
||||
|
||||
bool m_bIsConnected;
|
||||
|
||||
void CloseSocket( );
|
||||
bool InitializeInternal( CPacketToolDispatch* pPacketDispatch );
|
||||
bool Dispatch( unsigned long dwReceivedBytes );
|
||||
bool SetDispatch( CPacketToolDispatch* pPacketDispatch );
|
||||
CDefaultBufferFactory m_DefaultBufferFactory;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user