Initial MSVC 2008 projects workspace

This commit is contained in:
alexey.min
2012-02-01 05:25:08 +00:00
commit 03de3bdc95
1446 changed files with 476853 additions and 0 deletions

View File

@@ -0,0 +1,115 @@
#include "pch.h"
#include "l2c_utils.h"
#include "GameClient.h"
GameClient::GameClient( SOCKET s_cl, const char *ip, int port )
{
setUnused();
if( ip )
{
strncpy( m_ip, ip, 16 ); m_ip[16] = 0;
l2c_ansi_to_unicode( m_ip, m_wip, 16 );
}
m_port = port;
m_sock = s_cl;
m_was_force_disconnected = false;
m_flagStop = m_isRunning = false;
swprintf( m_tostring, 128, L"Client [IP: %s:%d]", m_wip, m_port );
m_ph = new ClientPacketHandler( this );
}
GameClient::~GameClient()
{
if( m_ph )
{
delete m_ph;
m_ph = NULL;
}
if( m_obf )
{
delete m_obf;
m_obf = NULL;
}
if( m_player )
{
delete m_player; // really? some notification?
m_player = NULL;
}
setUnused();
}
void GameClient::setUnused()
{
// zero our members
m_account[0] = 0;
memset( m_playKey, 0, sizeof(m_playKey) );
memset( m_loginKey, 0, sizeof(m_loginKey) );
m_ip[0] = 0;
m_wip[0] = 0;
m_port = 0;
m_sock = INVALID_SOCKET;
m_tostring[0] = 0;
m_state = CLIENT_STATE_OFFLINE;
m_xor_enabled = false;
memset( m_xor_key_recv, 0, sizeof(m_xor_key_recv) );
memset( m_xor_key_send, 0, sizeof(m_xor_key_send) );
m_protocolIsOk = false;
m_netStats.clear();
m_opcodeObfuscationSeed = 0;
m_obf = NULL;
m_player = NULL;
}
const wchar_t *GameClient::getAccount() const { return (const wchar_t *)m_account; }
void GameClient::getPlayKey( unsigned char *buffer ) const { memcpy( buffer, m_playKey, 8 ); }
void GameClient::getLoginKey( unsigned char *buffer ) const { memcpy( buffer, m_loginKey, 8 ); }
const char *GameClient::getIpA() const { return (const char *)m_ip; }
const wchar_t *GameClient::getIpW() const { return (const wchar_t *)m_wip; }
int GameClient::getPort() const { return m_port; }
const wchar_t *GameClient::toString() const { return (const wchar_t *)m_tostring; }
ClientState GameClient::getState() const { return m_state; }
bool GameClient::isProtocolOk() const { return m_protocolIsOk; }
const GameClientNetStats *GameClient::getNetStats() const { return &m_netStats; }
unsigned int GameClient::getOpcodeObfuscationSeed() const { return m_opcodeObfuscationSeed; }
L2PCodeObfuscator *GameClient::getOpcodeObfuscator() { return m_obf; }
GamePlayer *GameClient::getPlayer() { return m_player; }
void GameClient::setAccount( const wchar_t *acc )
{
if( acc )
{
wcsncpy( m_account, acc, sizeof(m_account)/sizeof(wchar_t) );
m_account[sizeof(m_account)/sizeof(wchar_t) - 1] = 0;
}
}
void GameClient::setSessionKeys( const unsigned char *playKey, const unsigned char *loginKey )
{
memcpy( m_playKey, playKey, 8 );
memcpy( m_loginKey, loginKey, 8 );
}
void GameClient::setProtocolOk( bool b ) { m_protocolIsOk = b; }
void GameClient::setOpcodeObfuscationSeed( unsigned int s )
{
m_opcodeObfuscationSeed = s;
if( m_obf )
{
delete m_obf;
m_obf = NULL;
}
if( s != 0 )
{
m_obf = new L2PCodeObfuscator();
m_obf->init_tables( m_opcodeObfuscationSeed );
}
}
void GameClient::setPlayer( GamePlayer *newPlayer, bool changeState, ClientState newState )
{
if( m_player ) delete m_player;
m_player = NULL;
if( newPlayer ) m_player = newPlayer;
if( changeState ) m_state = newState;
}

View File

@@ -0,0 +1,78 @@
#pragma once
#include "enums.h"
#include "net/ClientPacketHandler.h"
#include "GameClientNetStats.h"
#include "world/model/character/GamePlayer.h"
class GameClient
{
public:
GameClient( SOCKET s_cl, const char *ip, int port );
virtual ~GameClient();
virtual void setUnused();
public:
const wchar_t *getAccount() const;
void getPlayKey( unsigned char *buffer ) const;
void getLoginKey( unsigned char *buffer ) const;
const char *getIpA() const;
const wchar_t *getIpW() const;
int getPort() const;
const wchar_t *toString() const;
ClientState getState() const;
bool isProtocolOk() const;
const GameClientNetStats *getNetStats() const;
unsigned int getOpcodeObfuscationSeed() const;
L2PCodeObfuscator *getOpcodeObfuscator();
GamePlayer *getPlayer();
public:
void setAccount( const wchar_t *acc );
void setSessionKeys( const unsigned char *playKey, const unsigned char *loginKey );
void setProtocolOk( bool b ) ;
void setOpcodeObfuscationSeed( unsigned int s );
void setPlayer( GamePlayer *newPlayer, bool changeState = false, ClientState newState = CLIENT_STATE_OFFLINE );
public:
// begins client processing, starts thread
bool startThread();
// stops all client activity, disconnects socket, optionally sends packet before client close
void disconnectForceAndWaitThreadToStop( bool server_shutdown, bool reasonDualLogin );
// signal thread to stop (no wait to stop)
void signalThreadStop( bool setMarkToDeleteSelfAndCleanupClientPool );
bool sendPacket( L2GamePacket *pack, bool deleteAfterSend = false );
void enable_XOR_crypt( bool bEnable, unsigned char *initial_key );
void notifySessionKeysOK();
protected:
// signals to stop and waits for thread to stop
bool stopThread();
static DWORD WINAPI ClientThread( LPVOID lpvParam );
protected:
// informational stings
char m_ip[16];
wchar_t m_wip[16];
int m_port;
wchar_t m_account[128];
wchar_t m_tostring[128];
// network-related vars
SOCKET m_sock;
bool m_was_force_disconnected;
bool m_flagStop;
bool m_isRunning;
CriticalSection m_cs_send;
ClientState m_state;
bool m_xor_enabled;
unsigned char m_xor_key_send[16];
unsigned char m_xor_key_recv[16];
ClientPacketHandler *m_ph;
bool m_protocolIsOk;
GameClientNetStats m_netStats;
unsigned int m_opcodeObfuscationSeed;
L2PCodeObfuscator *m_obf;
unsigned char m_playKey[8];
unsigned char m_loginKey[8];
//
GamePlayer *m_player;
};

View File

@@ -0,0 +1,67 @@
#include "pch.h"
#include "Log.h"
#include "l2c_utils.h"
#include "GameClient.h"
#include "GS.h"
#include "../ServerPackets.h"
#include "utils/Exception.h"
bool GameClient::sendPacket( L2GamePacket *pack, bool deleteAfterSend /*= false*/ )
{
if( !pack ) return false;
if( m_sock == INVALID_SOCKET ) return false;
//
int r = 0;
unsigned int sentLen = 0;
unsigned int pack_size = pack->getPacketSize();
bool ret = true;
// encode xor if xor enabled
if( m_xor_enabled )
{
// KeyPacket is first packet sent to client by server.
// it is never encrypted
if( m_netStats.ullPacketsSent > 0 )
pack->encodeXOR( m_xor_key_send );
}
// send packet (lock before send, release lock after send)
m_cs_send.Lock();
r = L2PacketSend( m_sock, pack, 2000, &sentLen );
m_cs_send.Unlock();
// delete pack, if set to do so
if( deleteAfterSend ) delete pack;
// validate send OK
if( r<=0 || (sentLen != pack_size) ) // some error
{
ret = false;
throw Exception( "%S: send error: sent %u, retval %d", toString(), sentLen, r );
}
// count stats
m_netStats.addSentPacket( sentLen );
//
return ret;
}
void GameClient::enable_XOR_crypt( bool bEnable, unsigned char *initial_key )
{
m_xor_enabled = bEnable;
if( bEnable )
{
memcpy( m_xor_key_recv, initial_key, sizeof(m_xor_key_recv) );
memcpy( m_xor_key_send, initial_key, sizeof(m_xor_key_send) );
}
else
{
memset( m_xor_key_recv, 0, sizeof(m_xor_key_recv) );
memset( m_xor_key_send, 0, sizeof(m_xor_key_send) );
}
}
void GameClient::notifySessionKeysOK()
{
#ifdef _DEBUG
LogDebug( L"GameClient::notifySessionKeysOK()" );
#endif
m_state = CLIENT_STATE_AUTHED;
swprintf( m_tostring, 128, L"Client Acc: %s [IP %s:%d]", m_account, m_wip, m_port );
sendPacket( ServerPackets::CharacterSelectionInfo( this ), true );
}

View File

@@ -0,0 +1,25 @@
#include "pch.h"
#include "GameClientNetStats.h"
GameClientNetStats::GameClientNetStats()
{
clear();
}
void GameClientNetStats::clear()
{
ullPacketsSent = ullBytesSent = ullPacketsRcvd = ullBytesRcvd = 0;
}
void GameClientNetStats::addSentPacket( unsigned long long len )
{
ullPacketsSent++;
ullBytesSent += len;
}
void GameClientNetStats::addRcvdPacket( unsigned long long len )
{
ullPacketsRcvd++;
ullBytesRcvd += len;
}

View File

@@ -0,0 +1,15 @@
#pragma once
class GameClientNetStats
{
public:
GameClientNetStats();
void clear();
void addSentPacket( unsigned long long len );
void addRcvdPacket( unsigned long long len );
public:
unsigned long long ullPacketsSent;
unsigned long long ullBytesSent;
unsigned long long ullPacketsRcvd;
unsigned long long ullBytesRcvd;
};

View File

@@ -0,0 +1,188 @@
#include "pch.h"
#include "Log.h"
#include "l2c_utils.h"
#include "GameClient.h"
#include "GS.h"
#include "utils/Exception.h"
bool GameClient::startThread()
{
if( m_isRunning ) return false;
m_flagStop = false;
unsigned int tid = 0;
HANDLE hThread = (HANDLE)_beginthreadex( NULL, 0,
(unsigned int (__stdcall *)(void *))GameClient::ClientThread, (void *)this,
0, &tid );
bool ret = false;
if( hThread != NULL )
{
ret = true;
CloseHandle( hThread );
}
return ret;
}
bool GameClient::stopThread()
{
if( !m_isRunning ) return false;
m_flagStop = true;
while( m_isRunning ) Sleep(50);
m_flagStop = false;
return true;
}
void GameClient::disconnectForceAndWaitThreadToStop( bool server_shutdown, bool reasonDualLogin )
{
m_was_force_disconnected = true;
// TODO: send SystemMessage about account in use if dual login
if( reasonDualLogin )
{
}
// TODO: send ServerClose / ExRestartClient? if server shutdown
if( server_shutdown )
{
}
stopThread(); // stops thread; thread cleanups socket himself
}
void GameClient::signalThreadStop( bool setMarkToDeleteSelfAndCleanupClientPool )
{
m_flagStop = true;
m_was_force_disconnected = !setMarkToDeleteSelfAndCleanupClientPool;
}
DWORD WINAPI GameClient::ClientThread( LPVOID lpvParam )
{
GameClient *pl = (GameClient *)lpvParam;
pl->m_was_force_disconnected = false;
GameServer *gs = GameServer::getInstance();
pl->m_isRunning = true;
pl->m_state = CLIENT_STATE_CONNECTED;
pl->m_netStats.clear(); // reset nework statistics
int r, bReadyRead, bReadyWrite;
unsigned char *packbuffer = NULL;
unsigned int rcvdLen = 0;
L2GamePacket *pack = NULL;
try
{
// allocate packets recv buffer
packbuffer = (unsigned char *)malloc( 65536 );
if( !packbuffer ) throw std::bad_alloc( "allocate packbuffer (64 Kb) failed" );
// packets recv loop
while( !pl->m_flagStop )
{
// wait for socket ready to receive data
r = L2PNet_select( pl->m_sock, L2PNET_SELECT_READ, 100, &bReadyRead, &bReadyWrite );
if( r == 0 )
{
// select timout
// update world state? move moving objects?...
continue;
}
if( r == -1 ) // select error
{
LogError( L"%s: L2PNet_select() error!", pl->toString() );
throw Exception( "select error" );
}
// recv packet
r = L2PacketReceive_buffer( pl->m_sock, 1000, &rcvdLen, packbuffer );
if( r <= 0 )
{
if( r == 0 )
{
LogWarning( L"%s: closed connection? (received %u, retval %d)", pl->toString(), rcvdLen, r );
pl->m_flagStop = true;
break;
}
if( r < 0 )
{
LogError( L"%s: failed to receive packet (received %u, retval %d)", pl->toString(), rcvdLen, r );
throw Exception( "network packet receive error" );
}
}
// count stats
pl->m_netStats.addRcvdPacket( rcvdLen );
// create packet object
pack = new L2GamePacket( packbuffer, rcvdLen );
// decode XOR if enabled
if( pl->m_xor_enabled ) pack->decodeXOR( pl->m_xor_key_recv );
// deobfuscate opcode if enabled
if( pl->m_opcodeObfuscationSeed > 0 )
{
// HACK: here buffer that should be constant, is modified (but length is not changed thoug)
pl->m_obf->decodeIDs( (unsigned char *)pack->getBytesPtr() );
}
#ifdef _DEBUG
int opcode = pack->getByteAt(2);
LogDebug( L"%s: opcode %02X", pl->toString(), opcode );
#endif
// handle game client packet...
pl->m_ph->handlePacket( pack );
// free packet object
delete pack; pack = NULL;
}
}
catch( L2P_Exception& e )
{
LogError( L"ClientThread: %s: L2Packets exception: %S", pl->toString(), e.what() );
}
catch( std::bad_alloc& e )
{
LogError( L"ClientThread: %s: bad_alloc %S", pl->toString(), e.what() );
}
catch( std::exception& e )
{
LogError( L"ClientThread: %s: std::excpt %S", pl->toString(), e.what() );
}
catch( Exception& e )
{
LogError( L"ClientThread: Exception: %S", e.what() );
e.logStackTrace();
}
// player disconnected - remove player account from login server list of authed accounts
if( pl->m_account[0] ) // has authed??
gs->logoutAccountFromLoginServer( pl->m_account );
// cleanup socket
L2PNet_shutdown( pl->m_sock );
L2PNet_closesocket( pl->m_sock );
pl->m_sock = INVALID_SOCKET;
pl->m_state = CLIENT_STATE_OFFLINE;
// cleanup opcode obfuscator
if( pl->m_obf )
{
delete pl->m_obf;
pl->m_obf = NULL;
pl->m_opcodeObfuscationSeed = 0;
}
// free packets buffer
if( packbuffer ) free( packbuffer ); packbuffer = NULL;
// mark self as finished
pl->m_isRunning = false;
// notify GS ClientPool about client stop, if needed
if( !pl->m_was_force_disconnected )
{
#ifdef _DEBUG
LogDebug( L"ClientThread s: Calling ClientPool to cleanup & deleting self", pl->toString() );
#endif
gs->getClientPool()->notifyClientThreadEnded( pl );
delete pl;
}
return 0;
}