Initial MSVC 2008 projects workspace
This commit is contained in:
188
L2C_Server/net/GameClient/GameClientThread.cpp
Normal file
188
L2C_Server/net/GameClient/GameClientThread.cpp
Normal 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;
|
||||
}
|
Reference in New Issue
Block a user