Initial MSVC 2008 projects workspace
This commit is contained in:
341
l2detect/GameClient_full.cpp
Normal file
341
l2detect/GameClient_full.cpp
Normal file
@@ -0,0 +1,341 @@
|
||||
#include "stdafx.h"
|
||||
#include "ConfigIni.h"
|
||||
#include "Logger.h"
|
||||
#include "GameClient.h"
|
||||
#include "GameListener.h"
|
||||
#include "CharArray.h"
|
||||
#include "ClanList.h"
|
||||
#include "ProtocolConverter.h"
|
||||
//
|
||||
#include "RadarDllWnd.h"
|
||||
|
||||
extern class CConfig g_cfg;
|
||||
extern class GameListener *g_pgame;
|
||||
|
||||
bool GameClient::PC_full( SOCKET scl, unsigned char *sip, unsigned short int sport )
|
||||
{
|
||||
sock_client = INVALID_SOCKET;
|
||||
sock_server = INVALID_SOCKET;
|
||||
this->resetCounters( false );
|
||||
log_error( LOG_DEBUG, "GameClient::ProcessClient_full() started\n" );
|
||||
// assert
|
||||
if( (scl == INVALID_SOCKET) || (!sip) || (sport<1) )
|
||||
{
|
||||
log_error( LOG_ERROR, "GameClient::ProcessClient_full(): start assert failed\n" );
|
||||
return false;
|
||||
}
|
||||
// vars
|
||||
bool retVal = false;
|
||||
SOCKET sg = INVALID_SOCKET;
|
||||
char ssip[16] = {0};
|
||||
sprintf( ssip, "%d.%d.%d.%d", (int)sip[0], (int)sip[1], (int)sip[2], (int)sip[3] );
|
||||
|
||||
// first we should connect to real game server
|
||||
// create real GS socket
|
||||
sg = L2PNet_TCPsocket_create( true );
|
||||
if( sg == INVALID_SOCKET )
|
||||
{
|
||||
log_error( LOG_ERROR, "GameClient::ProcessClient_full(): real GS socket create\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// connect to real game server
|
||||
log_error( LOG_DEBUG, "GameClient::ProcessClient_full(): Connecting to real game server %s:%d ", ssip, (int)sport );
|
||||
L2PNet_connect( sg, ssip, sport );
|
||||
int nTries = 20;
|
||||
int r = 0;
|
||||
while( nTries > 0 )
|
||||
{
|
||||
log_error_np( LOG_DEBUG, "." );
|
||||
r = L2PNet_select( sg, L2PNET_SELECT_WRITE, 500, NULL, NULL );
|
||||
if( r == 1 ) break;
|
||||
nTries--;
|
||||
}
|
||||
|
||||
if( r == 1 )
|
||||
{
|
||||
log_error_np( LOG_DEBUG, " Connected. Tries left: %d\n", nTries );
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error_np( LOG_DEBUG, " Failed!\n", nTries );
|
||||
log_error( LOG_ERROR, "PC_full(): cannot connect to real game server!\n" );
|
||||
// close sockets
|
||||
L2PNet_shutdown( scl );
|
||||
L2PNet_closesocket( scl );
|
||||
L2PNet_shutdown( sg );
|
||||
L2PNet_closesocket( sg );
|
||||
log_error_np( LOG_DEBUG, " Not connected.\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// allocate receive buffer
|
||||
unsigned char *packbuffer = (unsigned char *)malloc( 65536 ); // 64 Kb :)
|
||||
if( !packbuffer )
|
||||
{
|
||||
log_error( LOG_ERROR, "PC_full(): cannot allocate 64 Kb packet receive buffer!\n" );
|
||||
// close sockets
|
||||
L2PNet_shutdown( scl );
|
||||
L2PNet_closesocket( scl );
|
||||
L2PNet_shutdown( sg );
|
||||
L2PNet_closesocket( sg );
|
||||
log_error_np( LOG_DEBUG, " Not connected.\n" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// open log file
|
||||
if( g_cfg.LogGamePackets )
|
||||
{
|
||||
char filename[256];
|
||||
time_t nowTime;
|
||||
time( &nowTime );
|
||||
sprintf( filename, "%s%u.txt", g_cfg.LogGameFileNamePrefix, (unsigned int)nowTime );
|
||||
this->logfile = fopen( filename, "wt" );
|
||||
if( !logfile )
|
||||
log_error( LOG_WARNING, "GameClient::PC_full(): Cannot open log file [%s] for writing!\n",
|
||||
filename );
|
||||
}
|
||||
|
||||
// set initial game client state
|
||||
this->state = GCST_CONNECTED;
|
||||
this->thisWasJustServerPing = false; // initial assign before any packet recieved
|
||||
bool bWasModified = false;
|
||||
this->sock_client = scl;
|
||||
this->sock_server = sg;
|
||||
|
||||
ProtoConv_Init();
|
||||
|
||||
this->postNotify( GCN_STATECHANGE, this->state );
|
||||
ai.notifyEvent( UAI_EVENT_START );
|
||||
this->counters.startTimer();
|
||||
|
||||
// infinite loop
|
||||
int recvTimeout = 120; // seconds
|
||||
long recvTimeoutMsec = recvTimeout * 1000;
|
||||
int selectTimeout = 1; // seconds
|
||||
struct timeval tv;
|
||||
fd_set fdReadSet;
|
||||
unsigned char *newBytes = NULL;
|
||||
unsigned int rcvdLen = 0;
|
||||
unsigned int sentLen = 0;
|
||||
unsigned int newLen = 0;
|
||||
int wsaerr = 0;
|
||||
unsigned int scode = 0;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
scode = g_pgame->getLastSignal();
|
||||
if( scode == FLGS_STOP )
|
||||
{
|
||||
log_error( LOG_DEBUG, "GameClient::PC_full(): exit signal\n" );
|
||||
break;
|
||||
}
|
||||
|
||||
tv.tv_sec = selectTimeout;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
// check readability on sockets
|
||||
FD_ZERO( &fdReadSet ); // zero set
|
||||
FD_SET( scl, &fdReadSet ); // add client socket to read set
|
||||
FD_SET( sg, &fdReadSet ); // add real GS socket to read set
|
||||
//
|
||||
r = L2PNet_select_wrapper_DUMB( 0, &fdReadSet, 0, 0, &tv );
|
||||
if( r == 0 ) /* timeout failed */
|
||||
{
|
||||
log_error_np( LOG_DEBUGDUMP, "." );
|
||||
}
|
||||
else if( r == -1 ) /* select error */
|
||||
{
|
||||
log_error_np( LOG_DEBUGDUMP, "\nselect() ERROR\n" );
|
||||
// TODO: what to do on select() error?
|
||||
wsaerr = L2PNet_WSAGetLastError();
|
||||
log_error( LOG_ERROR, "WinSock select() error %d: ", wsaerr );
|
||||
L2PNet_WSAPrintLastError( ErrorLogger_GetLogFile(), wsaerr );
|
||||
log_error_np( LOG_DEBUGDUMP, "\n" );
|
||||
//log_error( LOG_ERROR, "ProcessClient_full(): socket select() ERROR!\n" );
|
||||
//log_error( LOG_ERROR, "ProcessClient_full(): closing processing\n" );
|
||||
//goto netError;
|
||||
}
|
||||
else if( r > 0 )
|
||||
{
|
||||
log_error_np( LOG_DEBUGDUMP, "\nselect(): number of sockets ready: %d\n", r );
|
||||
// client sent something?
|
||||
if( L2PNet_FD_ISSET( scl, &fdReadSet ) )
|
||||
{
|
||||
//log_error( LOG_DEBUGDUMP, "C->S (reading...)\n" );
|
||||
// receive packet from client
|
||||
r = L2PacketReceive_buffer( scl, recvTimeoutMsec, &rcvdLen, packbuffer );
|
||||
//log_error( LOG_DEBUGDUMP, "Received %u bytes from client\n", rcvdLen );
|
||||
if( (r == 0) && (rcvdLen == 0) )
|
||||
{
|
||||
log_error( LOG_WARNING, "Connection closed by client?\n" );
|
||||
goto closeSocks;
|
||||
}
|
||||
if( r <= 0 )
|
||||
{
|
||||
log_error( LOG_ERROR, "L2PacketReceive() failed!\n" );
|
||||
wsaerr = L2PNet_WSAGetLastError();
|
||||
log_error( LOG_ERROR, "WinSock error %d: ", wsaerr );
|
||||
L2PNet_WSAPrintLastError( ErrorLogger_GetLogFile(), wsaerr );
|
||||
log_error_np( LOG_ERROR, "\n" );
|
||||
goto netError;
|
||||
}
|
||||
|
||||
// process it! :)
|
||||
bWasModified = PP_full_fromClient( packbuffer, rcvdLen, &newBytes, &newLen );
|
||||
if( newLen != -1 ) // -1 means - Drop packet
|
||||
{
|
||||
// resend packet to server after processing
|
||||
LockSend();
|
||||
r = L2PacketSend2( newBytes, sg, recvTimeoutMsec, &sentLen );
|
||||
UnlockSend();
|
||||
// if packet was not modified: newBytes points to the same memory as p points
|
||||
// if packet was modified: newBytes points to new memory
|
||||
// ... in this case we should free new memory separately
|
||||
if( newBytes != packbuffer ) free( newBytes ); // :)
|
||||
// in both cases newLen contains length to be sent
|
||||
|
||||
//log_error( LOG_DEBUGDUMP, "Sent %u bytes to server\n", sentLen );
|
||||
if( sentLen != newLen ) // we must send newLen
|
||||
{
|
||||
log_error( LOG_ERROR, "PC_full(): After L2PacketSend2() C->S sentLen != newLen!!! (%u != %u, bWasModified = %d)\n",
|
||||
sentLen, newLen, (int)bWasModified );
|
||||
goto netError;
|
||||
}
|
||||
// counters
|
||||
this->counters.addSentPacket( sentLen );
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// log_error( LOG_DEBUGDUMP, "PC_full(): dropped packet...\n" );
|
||||
//}
|
||||
}
|
||||
|
||||
// server sent something?
|
||||
if( L2PNet_FD_ISSET( sg, &fdReadSet ) )
|
||||
{
|
||||
//log_error( LOG_DEBUGDUMP, "S->C (reading...)\n" );
|
||||
// receive packet from server
|
||||
r = L2PacketReceive_buffer( sg, recvTimeoutMsec, &rcvdLen, packbuffer );
|
||||
//log_error( LOG_DEBUGDUMP, "Received %u bytes from server\n", rcvdLen );
|
||||
if( (r == 0) && (rcvdLen == 0) )
|
||||
{
|
||||
log_error( LOG_DEBUG, "Connection closed by server?\n" );
|
||||
goto closeSocks;
|
||||
}
|
||||
if( r <= 0 )
|
||||
{
|
||||
log_error( LOG_ERROR, "L2PacketReceive() failed!\n" );
|
||||
wsaerr = L2PNet_WSAGetLastError();
|
||||
log_error( LOG_ERROR, "WinSock error %d: ", wsaerr );
|
||||
L2PNet_WSAPrintLastError( ErrorLogger_GetLogFile(), wsaerr );
|
||||
log_error_np( LOG_ERROR, "\n" );
|
||||
goto netError;
|
||||
}
|
||||
|
||||
// counters
|
||||
this->counters.addRcvdPacket( rcvdLen );
|
||||
|
||||
// process it! :)
|
||||
bWasModified = PP_full_fromServer( packbuffer, rcvdLen, &newBytes, &newLen );
|
||||
if( newLen != -1 ) // -1 means - Drop packet
|
||||
{
|
||||
// resend packet to client
|
||||
LockSend();
|
||||
r = L2PacketSend2( newBytes, scl, recvTimeoutMsec, &sentLen );
|
||||
UnlockSend();
|
||||
// if packet was not modified: newBytes points to the same memory as p points
|
||||
// if packet was modified: newBytes points to new memory
|
||||
// ... in this case we should free new memory separately
|
||||
if( newBytes != packbuffer )
|
||||
{
|
||||
//log_error( LOG_OK, "Packet was modified, freeing newBytes buffer (newLen = %u)\n", newLen );
|
||||
free( newBytes ); // :)
|
||||
}
|
||||
// in both cases newLen contains length to be sent
|
||||
|
||||
//log_error( LOG_DEBUGDUMP, "Sent %u bytes to client\n", sentLen );
|
||||
if( sentLen != newLen )
|
||||
{
|
||||
log_error( LOG_ERROR, "PC_full(): After L2PacketrSend2() S->C sent != rcvd!!! (%u != %u, bWasModified = %d)\n",
|
||||
sentLen, newLen, (int)bWasModified );
|
||||
goto netError;
|
||||
}
|
||||
} // newLen != -1
|
||||
}
|
||||
} // (r>0) // select() OK
|
||||
}// while(1)
|
||||
|
||||
retVal = true;
|
||||
netError:
|
||||
retVal = true;
|
||||
if( wsaerr > 0 )
|
||||
{
|
||||
retVal = false;
|
||||
log_error( LOG_ERROR, "PC_full(): some error happened or network connection closed...\n" );
|
||||
}
|
||||
closeSocks:
|
||||
// save radar window size
|
||||
PostMessage( g_radardll_hwnd, WMMY_SAVE_WINDOW_SIZE, 0, 0 );
|
||||
// logfile
|
||||
if( this->logfile )
|
||||
{
|
||||
fclose( this->logfile );
|
||||
this->logfile = NULL;
|
||||
}
|
||||
// free packbuffer
|
||||
if( packbuffer ) free( packbuffer );
|
||||
packbuffer = NULL;
|
||||
// stop AI thread
|
||||
ai.notifyEvent( UAI_EVENT_STOP );
|
||||
// reset internal state
|
||||
this->resetConnectedState();
|
||||
// sockets
|
||||
L2PNet_shutdown( scl );
|
||||
L2PNet_closesocket( scl );
|
||||
L2PNet_shutdown( sg );
|
||||
L2PNet_closesocket( sg );
|
||||
// lists
|
||||
CharArray_DeleteAll();
|
||||
ClanList_DeleteAll();
|
||||
// switch state
|
||||
this->state = GCST_OFFLINE;
|
||||
this->postNotify( GCN_STATECHANGE, this->state );
|
||||
// log counters
|
||||
GameClient_NetStats netstats;
|
||||
counters.calcNowStats( &netstats );
|
||||
log_error_np( LOG_OK, "=============================================\n" );
|
||||
log_error_np( LOG_OK, "Network usage stats:\n" );
|
||||
log_error_np( LOG_OK, "Bytes, packets sent: %I64u, %I64u\n", counters.ullBytesSent, counters.ullPacketsSent );
|
||||
log_error_np( LOG_OK, "Bytes, packets rcvd: %I64u, %I64u\n", counters.ullBytesRcvd, counters.ullPacketsRcvd );
|
||||
log_error_np( LOG_OK, "Time connected: %0.2f seconds\n", netstats.timePassedSecs );
|
||||
log_error_np( LOG_OK, "Avg send speed: %0.2f bytes/sec\n", netstats.avgSendSpeed );
|
||||
log_error_np( LOG_OK, "Avg recv speed: %0.2f bytes/sec\n", netstats.avgRecvSpeed );
|
||||
log_error_np( LOG_OK, "Avg send L2 packets: %0.2f packets/sec\n", netstats.avgSendPacketsPerSec );
|
||||
log_error_np( LOG_OK, "Avg recv L2 packets: %0.2f packets/sec\n", netstats.avgRecvPacketsPerSec );
|
||||
log_error_np( LOG_OK, "Avg out packet size: %0.2f bytes\n", netstats.avgSendPacketSize );
|
||||
log_error_np( LOG_OK, "Avg in packet size: %0.2f bytes\n", netstats.avgRecvPacketSize );
|
||||
log_error_np( LOG_OK, "=============================================\n" );
|
||||
ErrorLogger_FlushLogFile();
|
||||
|
||||
//
|
||||
log_error( LOG_DEBUG, "GameClient::PC_full() ending, returning %d\n", (int)retVal );
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
// if packet was modified, it will be encoded again before resending
|
||||
bool GameClient::PP_full_reencode_packet( unsigned char *bytes, unsigned int len, unsigned char *key )
|
||||
{
|
||||
if( !this->xor_enabled ) return true; // no need to encrypt now - XOR keys not received yet
|
||||
//if( !bytes || (len<3) || !key ) return false; // asserts
|
||||
//L2GamePacket p;
|
||||
//if( !p.setBytes( bytes, len ) ) return false;
|
||||
//if( !p.encodeXOR( key ) ) return false;
|
||||
//memcpy( bytes, p.getBytesPtr(), len );
|
||||
// speed optimisation - remove constructor(), setBytes() calls and memcpy() call
|
||||
bool ret = L2GamePacket::encodeXOR_buffer( bytes, len, key ); // encode directly in buffer
|
||||
/*log_error( LOG_DEBUGDUMP, "PP_full_reencode_packet(): packet of len %u re-encode result: %d\n",
|
||||
len, (int)ret );*/
|
||||
return ret;
|
||||
}
|
Reference in New Issue
Block a user