2013-07-29 07:13:03 -04:00
// Connection.cpp
// Interfaces to the cConnection class representing a single pair of connected sockets
# include "Globals.h"
# include "Connection.h"
# include "Server.h"
# include <iostream>
2013-09-08 05:27:49 -04:00
# ifdef _WIN32
# include <direct.h> // For _mkdir()
# endif
2013-07-29 07:13:03 -04:00
# ifdef _DEBUG
# define DebugSleep Sleep
# else
# define DebugSleep(X)
# endif // else _DEBUG
# define HANDLE_CLIENT_PACKET_READ(Proc, Type, Var) \
Type Var ; \
{ \
if ( ! m_ClientBuffer . Proc ( Var ) ) \
{ \
return false ; \
} \
}
# define HANDLE_SERVER_PACKET_READ(Proc, Type, Var) \
Type Var ; \
{ \
if ( ! m_ServerBuffer . Proc ( Var ) ) \
{ \
return false ; \
} \
}
# define CLIENTSEND(...) SendData(m_ClientSocket, __VA_ARGS__, "Client")
# define SERVERSEND(...) SendData(m_ServerSocket, __VA_ARGS__, "Server")
# define CLIENTENCRYPTSEND(...) SendEncryptedData(m_ClientSocket, m_ClientEncryptor, __VA_ARGS__, "Client")
# define SERVERENCRYPTSEND(...) SendEncryptedData(m_ServerSocket, m_ServerEncryptor, __VA_ARGS__, "Server")
# define COPY_TO_SERVER() \
{ \
AString ToServer ; \
m_ClientBuffer . ReadAgain ( ToServer ) ; \
switch ( m_ServerState ) \
{ \
case csUnencrypted : \
{ \
SERVERSEND ( ToServer . data ( ) , ToServer . size ( ) ) ; \
break ; \
} \
case csEncryptedUnderstood : \
case csEncryptedUnknown : \
{ \
SERVERENCRYPTSEND ( ToServer . data ( ) , ToServer . size ( ) ) ; \
break ; \
} \
case csWaitingForEncryption : \
{ \
Log ( " Waiting for server encryption, queued %u bytes " , ToServer . size ( ) ) ; \
m_ServerEncryptionBuffer . append ( ToServer . data ( ) , ToServer . size ( ) ) ; \
break ; \
} \
} \
DebugSleep ( 50 ) ; \
}
# define COPY_TO_CLIENT() \
{ \
AString ToClient ; \
m_ServerBuffer . ReadAgain ( ToClient ) ; \
switch ( m_ClientState ) \
{ \
case csUnencrypted : \
{ \
CLIENTSEND ( ToClient . data ( ) , ToClient . size ( ) ) ; \
break ; \
} \
case csEncryptedUnderstood : \
case csEncryptedUnknown : \
{ \
CLIENTENCRYPTSEND ( ToClient . data ( ) , ToClient . size ( ) ) ; \
break ; \
} \
case csWaitingForEncryption : \
{ \
Log ( " Waiting for client encryption, queued %u bytes " , ToClient . size ( ) ) ; \
m_ClientEncryptionBuffer . append ( ToClient . data ( ) , ToClient . size ( ) ) ; \
break ; \
} \
} \
DebugSleep ( 50 ) ; \
}
# define HANDLE_CLIENT_READ(Proc) \
{ \
if ( ! Proc ( ) ) \
{ \
AString Leftover ; \
m_ClientBuffer . ReadAgain ( Leftover ) ; \
DataLog ( Leftover . data ( ) , Leftover . size ( ) , " Leftover data after client packet parsing, %d bytes: " , Leftover . size ( ) ) ; \
m_ClientBuffer . ResetRead ( ) ; \
return true ; \
} \
}
# define HANDLE_SERVER_READ(Proc) \
{ \
if ( ! Proc ( ) ) \
{ \
m_ServerBuffer . ResetRead ( ) ; \
return true ; \
} \
}
# define MAX_ENC_LEN 1024
typedef unsigned char Byte ;
enum
{
PACKET_KEEPALIVE = 0x00 ,
PACKET_LOGIN = 0x01 ,
PACKET_HANDSHAKE = 0x02 ,
PACKET_CHAT_MESSAGE = 0x03 ,
PACKET_TIME_UPDATE = 0x04 ,
PACKET_ENTITY_EQUIPMENT = 0x05 ,
PACKET_COMPASS = 0x06 ,
PACKET_USE_ENTITY = 0x07 ,
PACKET_UPDATE_HEALTH = 0x08 ,
PACKET_PLAYER_ON_GROUND = 0x0a ,
PACKET_PLAYER_POSITION = 0x0b ,
PACKET_PLAYER_LOOK = 0x0c ,
PACKET_PLAYER_POSITION_LOOK = 0x0d ,
PACKET_BLOCK_DIG = 0x0e ,
PACKET_BLOCK_PLACE = 0x0f ,
PACKET_SLOT_SELECT = 0x10 ,
PACKET_PLAYER_ANIMATION = 0x12 ,
PACKET_ENTITY_ACTION = 0x13 ,
PACKET_SPAWN_NAMED_ENTITY = 0x14 ,
PACKET_SPAWN_PICKUP = 0x15 ,
PACKET_COLLECT_PICKUP = 0x16 ,
PACKET_SPAWN_OBJECT_VEHICLE = 0x17 ,
PACKET_SPAWN_MOB = 0x18 ,
PACKET_SPAWN_PAINTING = 0x19 ,
PACKET_SPAWN_EXPERIENCE_ORB = 0x1a ,
PACKET_ENTITY_VELOCITY = 0x1c ,
PACKET_DESTROY_ENTITIES = 0x1d ,
PACKET_ENTITY = 0x1e ,
PACKET_ENTITY_RELATIVE_MOVE = 0x1f ,
PACKET_ENTITY_LOOK = 0x20 ,
PACKET_ENTITY_RELATIVE_MOVE_LOOK = 0x21 ,
PACKET_ENTITY_TELEPORT = 0x22 ,
PACKET_ENTITY_HEAD_LOOK = 0x23 ,
PACKET_ENTITY_STATUS = 0x26 ,
PACKET_ATTACH_ENTITY = 0x27 ,
PACKET_ENTITY_METADATA = 0x28 ,
PACKET_ENTITY_EFFECT = 0x29 ,
PACKET_ENTITY_EFFECT_REMOVE = 0x2a ,
PACKET_SET_EXPERIENCE = 0x2b ,
PACKET_ENTITY_PROPERTIES = 0x2c ,
PACKET_MAP_CHUNK = 0x33 ,
PACKET_MULTI_BLOCK_CHANGE = 0x34 ,
PACKET_BLOCK_CHANGE = 0x35 ,
PACKET_BLOCK_ACTION = 0x36 ,
PACKET_MAP_CHUNK_BULK = 0x38 ,
PACKET_SOUND_EFFECT = 0x3d ,
PACKET_NAMED_SOUND_EFFECT = 0x3e ,
PACKET_CHANGE_GAME_STATE = 0x46 ,
PACKET_WINDOW_OPEN = 0x64 ,
PACKET_WINDOW_CLOSE = 0x65 ,
PACKET_WINDOW_CLICK = 0x66 ,
PACKET_SET_SLOT = 0x67 ,
PACKET_WINDOW_CONTENTS = 0x68 ,
PACKET_CREATIVE_INVENTORY_ACTION = 0x6b ,
PACKET_UPDATE_SIGN = 0x82 ,
PACKET_UPDATE_TILE_ENTITY = 0x84 ,
PACKET_PLAYER_LIST_ITEM = 0xc9 ,
PACKET_PLAYER_ABILITIES = 0xca ,
PACKET_INCREMENT_STATISTIC = 0xc8 ,
2013-07-31 08:32:05 -04:00
PACKET_TAB_COMPLETION = 0xcb ,
2013-07-29 07:13:03 -04:00
PACKET_LOCALE_AND_VIEW = 0xcc ,
PACKET_CLIENT_STATUSES = 0xcd ,
PACKET_PLUGIN_MESSAGE = 0xfa ,
PACKET_ENCRYPTION_KEY_RESPONSE = 0xfc ,
PACKET_ENCRYPTION_KEY_REQUEST = 0xfd ,
PACKET_PING = 0xfe ,
PACKET_KICK = 0xff ,
2013-08-25 15:57:12 -04:00
// Synonyms:
PACKET_DISCONNECT = PACKET_KICK ,
2013-07-29 07:13:03 -04:00
} ;
enum
{
OBJECT_BOAT = 1 ,
OBJECT_MINECART = 10 ,
OBJECT_MINECART_STORAGE = 11 ,
OBJECT_MINECART_POWERED = 12 ,
2013-08-16 06:23:24 -04:00
OBJECT_MINECART_TNT = 13 ,
OBJECT_MINECART_HOPPER = 14 ,
2013-07-29 07:13:03 -04:00
OBJECT_TNT = 50 ,
OBJECT_ENDERCRYSTAL = 51 ,
OBJECT_ARROW = 60 ,
OBJECT_SNOWBALL = 61 ,
OBJECT_EGG = 62 ,
OBJECT_FALLING_BLOCK = 70 ,
OBJECT_EYE_OF_ENDER = 72 ,
OBJECT_DRAGON_EGG = 74 ,
OBJECT_FISHING_FLOAT = 90 ,
} ;
2013-09-04 14:42:37 -04:00
AString PrintableAbsIntTriplet ( int a_X , int a_Y , int a_Z , double a_Divisor = 32 )
{
return Printf ( " <%d, %d, %d> ~ {%.02f, %.02f, %.02f} " ,
a_X , a_Y , a_Z ,
( double ) a_X / a_Divisor , ( double ) a_Y / a_Divisor , ( double ) a_Z / a_Divisor
) ;
}
2013-07-29 07:13:03 -04:00
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cConnection:
cConnection : : cConnection ( SOCKET a_ClientSocket , cServer & a_Server ) :
m_ItemIdx ( 0 ) ,
m_LogFile ( NULL ) ,
m_Server ( a_Server ) ,
m_ClientSocket ( a_ClientSocket ) ,
m_ServerSocket ( - 1 ) ,
2013-08-30 04:10:56 -04:00
m_BeginTick ( m_Timer . GetNowTime ( ) ) ,
2013-07-29 07:13:03 -04:00
m_ClientState ( csUnencrypted ) ,
m_ServerState ( csUnencrypted ) ,
m_Nonce ( 0 ) ,
m_ClientBuffer ( 1024 KiB ) ,
m_ServerBuffer ( 1024 KiB ) ,
m_HasClientPinged ( false )
{
2013-09-08 05:27:49 -04:00
// Create the Logs subfolder, if not already created:
# if defined(_WIN32)
_mkdir ( " Logs " ) ;
# else
mkdir ( " Logs " , 0777 ) ;
# endif
Printf ( m_LogNameBase , " Logs/Log_%d " , ( int ) time ( NULL ) ) ;
2013-07-29 07:13:03 -04:00
AString fnam ( m_LogNameBase ) ;
fnam . append ( " .log " ) ;
m_LogFile = fopen ( fnam . c_str ( ) , " w " ) ;
Log ( " Log file created " ) ;
printf ( " Connection is logged to file \" %s \" \n " , fnam . c_str ( ) ) ;
}
cConnection : : ~ cConnection ( )
{
fclose ( m_LogFile ) ;
}
void cConnection : : Run ( void )
{
if ( ! ConnectToServer ( ) )
{
Log ( " Cannot connect to server; aborting " ) ;
return ;
}
while ( true )
{
fd_set ReadFDs ;
FD_ZERO ( & ReadFDs ) ;
FD_SET ( m_ServerSocket , & ReadFDs ) ;
FD_SET ( m_ClientSocket , & ReadFDs ) ;
int res = select ( 2 , & ReadFDs , NULL , NULL , NULL ) ;
if ( res < = 0 )
{
printf ( " select() failed: %d; aborting client " , WSAGetLastError ( ) ) ;
break ;
}
if ( FD_ISSET ( m_ServerSocket , & ReadFDs ) )
{
if ( ! RelayFromServer ( ) )
{
break ;
}
}
if ( FD_ISSET ( m_ClientSocket , & ReadFDs ) )
{
if ( ! RelayFromClient ( ) )
{
break ;
}
}
}
Log ( " Relaying ended, closing sockets " ) ;
closesocket ( m_ServerSocket ) ;
closesocket ( m_ClientSocket ) ;
}
void cConnection : : Log ( const char * a_Format , . . . )
{
va_list args ;
va_start ( args , a_Format ) ;
AString msg ;
AppendVPrintf ( msg , a_Format , args ) ;
va_end ( args ) ;
AString FullMsg ;
Printf ( FullMsg , " [%5.3f] %s \n " , GetRelativeTime ( ) , msg . c_str ( ) ) ;
// Log to file:
cCSLock Lock ( m_CSLog ) ;
fputs ( FullMsg . c_str ( ) , m_LogFile ) ;
// Log to screen:
// std::cout << FullMsg;
}
void cConnection : : DataLog ( const void * a_Data , int a_Size , const char * a_Format , . . . )
{
va_list args ;
va_start ( args , a_Format ) ;
AString msg ;
AppendVPrintf ( msg , a_Format , args ) ;
va_end ( args ) ;
AString FullMsg ;
AString Hex ;
Printf ( FullMsg , " [%5.3f] %s \n %s \n " , GetRelativeTime ( ) , msg . c_str ( ) , CreateHexDump ( Hex , a_Data , a_Size , 16 ) . c_str ( ) ) ;
// Log to file:
cCSLock Lock ( m_CSLog ) ;
fputs ( FullMsg . c_str ( ) , m_LogFile ) ;
/*
// Log to screen:
std : : cout < < FullMsg ;
//*/
}
void cConnection : : LogFlush ( void )
{
fflush ( m_LogFile ) ;
}
bool cConnection : : ConnectToServer ( void )
{
m_ServerSocket = socket ( AF_INET , SOCK_STREAM , IPPROTO_TCP ) ;
if ( m_ServerSocket = = INVALID_SOCKET )
{
return false ;
}
sockaddr_in localhost ;
localhost . sin_family = AF_INET ;
localhost . sin_port = htons ( m_Server . GetConnectPort ( ) ) ;
localhost . sin_addr . s_addr = htonl ( 0x7f000001 ) ; // localhost
if ( connect ( m_ServerSocket , ( sockaddr * ) & localhost , sizeof ( localhost ) ) ! = 0 )
{
printf ( " connection to server failed: %d \n " , WSAGetLastError ( ) ) ;
return false ;
}
Log ( " Connected to SERVER " ) ;
return true ;
}
bool cConnection : : RelayFromServer ( void )
{
char Buffer [ 64 KiB ] ;
int res = recv ( m_ServerSocket , Buffer , sizeof ( Buffer ) , 0 ) ;
if ( res < = 0 )
{
Log ( " Server closed the socket: %d; %d; aborting connection " , res , WSAGetLastError ( ) ) ;
return false ;
}
DataLog ( Buffer , res , " Received %d bytes from the SERVER " , res ) ;
switch ( m_ServerState )
{
case csUnencrypted :
case csWaitingForEncryption :
{
return DecodeServersPackets ( Buffer , res ) ;
}
case csEncryptedUnderstood :
{
m_ServerDecryptor . ProcessData ( ( byte * ) Buffer , ( byte * ) Buffer , res ) ;
DataLog ( Buffer , res , " Decrypted %d bytes from the SERVER " , res ) ;
return DecodeServersPackets ( Buffer , res ) ;
}
case csEncryptedUnknown :
{
m_ServerDecryptor . ProcessData ( ( byte * ) Buffer , ( byte * ) Buffer , res ) ;
DataLog ( Buffer , res , " Decrypted %d bytes from the SERVER " , res ) ;
m_ClientEncryptor . ProcessData ( ( byte * ) Buffer , ( byte * ) Buffer , res ) ;
return CLIENTSEND ( Buffer , res ) ;
}
}
return true ;
}
bool cConnection : : RelayFromClient ( void )
{
char Buffer [ 64 KiB ] ;
int res = recv ( m_ClientSocket , Buffer , sizeof ( Buffer ) , 0 ) ;
if ( res < = 0 )
{
Log ( " Client closed the socket: %d; %d; aborting connection " , res , WSAGetLastError ( ) ) ;
return false ;
}
DataLog ( Buffer , res , " Received %d bytes from the CLIENT " , res ) ;
switch ( m_ClientState )
{
case csUnencrypted :
case csWaitingForEncryption :
{
return DecodeClientsPackets ( Buffer , res ) ;
}
case csEncryptedUnderstood :
{
m_ClientDecryptor . ProcessData ( ( byte * ) Buffer , ( byte * ) Buffer , res ) ;
DataLog ( Buffer , res , " Decrypted %d bytes from the CLIENT " , res ) ;
return DecodeClientsPackets ( Buffer , res ) ;
}
case csEncryptedUnknown :
{
m_ClientDecryptor . ProcessData ( ( byte * ) Buffer , ( byte * ) Buffer , res ) ;
DataLog ( Buffer , res , " Decrypted %d bytes from the CLIENT " , res ) ;
m_ServerEncryptor . ProcessData ( ( byte * ) Buffer , ( byte * ) Buffer , res ) ;
return SERVERSEND ( Buffer , res ) ;
}
}
return true ;
}
double cConnection : : GetRelativeTime ( void )
{
2013-08-30 04:10:56 -04:00
return ( double ) ( m_Timer . GetNowTime ( ) - m_BeginTick ) / 1000 ;
2013-07-29 07:13:03 -04:00
}
bool cConnection : : SendData ( SOCKET a_Socket , const char * a_Data , int a_Size , const char * a_Peer )
{
DataLog ( a_Data , a_Size , " Sending data to %s " , a_Peer ) ;
int res = send ( a_Socket , a_Data , a_Size , 0 ) ;
if ( res < = 0 )
{
Log ( " %s closed the socket: %d, %d; aborting connection " , a_Peer , res , WSAGetLastError ( ) ) ;
return false ;
}
return true ;
}
bool cConnection : : SendData ( SOCKET a_Socket , cByteBuffer & a_Data , const char * a_Peer )
{
AString All ;
a_Data . ReadAll ( All ) ;
a_Data . CommitRead ( ) ;
return SendData ( a_Socket , All . data ( ) , All . size ( ) , a_Peer ) ;
}
bool cConnection : : SendEncryptedData ( SOCKET a_Socket , Encryptor & a_Encryptor , const char * a_Data , int a_Size , const char * a_Peer )
{
DataLog ( a_Data , a_Size , " Encrypting %d bytes to %s " , a_Size , a_Peer ) ;
const byte * Data = ( const byte * ) a_Data ;
while ( a_Size > 0 )
{
byte Buffer [ 64 KiB ] ;
int NumBytes = ( a_Size > sizeof ( Buffer ) ) ? sizeof ( Buffer ) : a_Size ;
a_Encryptor . ProcessData ( Buffer , Data , NumBytes ) ;
bool res = SendData ( a_Socket , ( const char * ) Buffer , NumBytes , a_Peer ) ;
if ( ! res )
{
return false ;
}
Data + = NumBytes ;
a_Size - = NumBytes ;
}
return true ;
}
bool cConnection : : SendEncryptedData ( SOCKET a_Socket , Encryptor & a_Encryptor , cByteBuffer & a_Data , const char * a_Peer )
{
AString All ;
a_Data . ReadAll ( All ) ;
a_Data . CommitRead ( ) ;
return SendEncryptedData ( a_Socket , a_Encryptor , All . data ( ) , All . size ( ) , a_Peer ) ;
}
bool cConnection : : DecodeClientsPackets ( const char * a_Data , int a_Size )
{
if ( ! m_ClientBuffer . Write ( a_Data , a_Size ) )
{
Log ( " Too much queued data for the server, aborting connection " ) ;
return false ;
}
while ( m_ClientBuffer . CanReadBytes ( 1 ) )
{
unsigned char PacketType ;
m_ClientBuffer . ReadByte ( PacketType ) ;
2013-08-30 04:15:54 -04:00
Log ( " Decoding client's packets, there are now %d bytes in the queue; next packet is 0x%02x " , m_ClientBuffer . GetReadableSpace ( ) , PacketType ) ;
2013-07-29 07:13:03 -04:00
switch ( PacketType )
{
case PACKET_BLOCK_DIG : HANDLE_CLIENT_READ ( HandleClientBlockDig ) ; break ;
case PACKET_BLOCK_PLACE : HANDLE_CLIENT_READ ( HandleClientBlockPlace ) ; break ;
case PACKET_CHAT_MESSAGE : HANDLE_CLIENT_READ ( HandleClientChatMessage ) ; break ;
case PACKET_CLIENT_STATUSES : HANDLE_CLIENT_READ ( HandleClientClientStatuses ) ; break ;
case PACKET_CREATIVE_INVENTORY_ACTION : HANDLE_CLIENT_READ ( HandleClientCreativeInventoryAction ) ; break ;
2013-08-25 15:57:12 -04:00
case PACKET_DISCONNECT : HANDLE_CLIENT_READ ( HandleClientDisconnect ) ; break ;
2013-07-29 07:13:03 -04:00
case PACKET_ENCRYPTION_KEY_RESPONSE : HANDLE_CLIENT_READ ( HandleClientEncryptionKeyResponse ) ; break ;
case PACKET_ENTITY_ACTION : HANDLE_CLIENT_READ ( HandleClientEntityAction ) ; break ;
case PACKET_HANDSHAKE : HANDLE_CLIENT_READ ( HandleClientHandshake ) ; break ;
case PACKET_KEEPALIVE : HANDLE_CLIENT_READ ( HandleClientKeepAlive ) ; break ;
case PACKET_LOCALE_AND_VIEW : HANDLE_CLIENT_READ ( HandleClientLocaleAndView ) ; break ;
case PACKET_PING : HANDLE_CLIENT_READ ( HandleClientPing ) ; break ;
case PACKET_PLAYER_ABILITIES : HANDLE_CLIENT_READ ( HandleClientPlayerAbilities ) ; break ;
case PACKET_PLAYER_ANIMATION : HANDLE_CLIENT_READ ( HandleClientAnimation ) ; break ;
case PACKET_PLAYER_LOOK : HANDLE_CLIENT_READ ( HandleClientPlayerLook ) ; break ;
case PACKET_PLAYER_ON_GROUND : HANDLE_CLIENT_READ ( HandleClientPlayerOnGround ) ; break ;
case PACKET_PLAYER_POSITION : HANDLE_CLIENT_READ ( HandleClientPlayerPosition ) ; break ;
case PACKET_PLAYER_POSITION_LOOK : HANDLE_CLIENT_READ ( HandleClientPlayerPositionLook ) ; break ;
case PACKET_PLUGIN_MESSAGE : HANDLE_CLIENT_READ ( HandleClientPluginMessage ) ; break ;
case PACKET_SLOT_SELECT : HANDLE_CLIENT_READ ( HandleClientSlotSelect ) ; break ;
2013-07-31 08:32:05 -04:00
case PACKET_TAB_COMPLETION : HANDLE_CLIENT_READ ( HandleClientTabCompletion ) ; break ;
2013-07-29 07:13:03 -04:00
case PACKET_UPDATE_SIGN : HANDLE_CLIENT_READ ( HandleClientUpdateSign ) ; break ;
case PACKET_USE_ENTITY : HANDLE_CLIENT_READ ( HandleClientUseEntity ) ; break ;
case PACKET_WINDOW_CLICK : HANDLE_CLIENT_READ ( HandleClientWindowClick ) ; break ;
case PACKET_WINDOW_CLOSE : HANDLE_CLIENT_READ ( HandleClientWindowClose ) ; break ;
default :
{
if ( m_ClientState = = csEncryptedUnderstood )
{
Log ( " ****************** Unknown packet 0x%02x from the client while encrypted; continuing to relay blind only " , PacketType ) ;
AString Data ;
m_ClientBuffer . ResetRead ( ) ;
m_ClientBuffer . ReadAll ( Data ) ;
DataLog ( Data . data ( ) , Data . size ( ) , " Current data in the client packet queue: %d bytes " , Data . size ( ) ) ;
m_ClientState = csEncryptedUnknown ;
m_ClientBuffer . ResetRead ( ) ;
if ( m_ServerState = = csUnencrypted )
{
SERVERSEND ( m_ClientBuffer ) ;
}
else
{
SERVERENCRYPTSEND ( m_ClientBuffer ) ;
}
return true ;
}
else
{
Log ( " Unknown packet 0x%02x from the client while unencrypted; aborting connection " , PacketType ) ;
return false ;
}
}
} // switch (PacketType)
m_ClientBuffer . CommitRead ( ) ;
} // while (CanReadBytes(1))
return true ;
}
bool cConnection : : DecodeServersPackets ( const char * a_Data , int a_Size )
{
if ( ! m_ServerBuffer . Write ( a_Data , a_Size ) )
{
Log ( " Too much queued data for the client, aborting connection " ) ;
return false ;
}
if (
( m_ServerState = = csEncryptedUnderstood ) & &
( m_ClientState = = csUnencrypted )
)
{
// Client hasn't finished encryption handshake yet, don't send them any data yet
}
while ( m_ServerBuffer . CanReadBytes ( 1 ) )
{
unsigned char PacketType ;
m_ServerBuffer . ReadByte ( PacketType ) ;
2013-08-30 04:15:54 -04:00
Log ( " Decoding server's packets, there are now %d bytes in the queue; next packet is 0x%02x " , m_ServerBuffer . GetReadableSpace ( ) , PacketType ) ;
2013-07-29 07:13:03 -04:00
LogFlush ( ) ;
switch ( PacketType )
{
case PACKET_ATTACH_ENTITY : HANDLE_SERVER_READ ( HandleServerAttachEntity ) ; break ;
case PACKET_BLOCK_ACTION : HANDLE_SERVER_READ ( HandleServerBlockAction ) ; break ;
case PACKET_BLOCK_CHANGE : HANDLE_SERVER_READ ( HandleServerBlockChange ) ; break ;
case PACKET_CHANGE_GAME_STATE : HANDLE_SERVER_READ ( HandleServerChangeGameState ) ; break ;
case PACKET_CHAT_MESSAGE : HANDLE_SERVER_READ ( HandleServerChatMessage ) ; break ;
case PACKET_COLLECT_PICKUP : HANDLE_SERVER_READ ( HandleServerCollectPickup ) ; break ;
case PACKET_COMPASS : HANDLE_SERVER_READ ( HandleServerCompass ) ; break ;
case PACKET_DESTROY_ENTITIES : HANDLE_SERVER_READ ( HandleServerDestroyEntities ) ; break ;
case PACKET_ENCRYPTION_KEY_REQUEST : HANDLE_SERVER_READ ( HandleServerEncryptionKeyRequest ) ; break ;
case PACKET_ENCRYPTION_KEY_RESPONSE : HANDLE_SERVER_READ ( HandleServerEncryptionKeyResponse ) ; break ;
case PACKET_ENTITY : HANDLE_SERVER_READ ( HandleServerEntity ) ; break ;
case PACKET_ENTITY_EQUIPMENT : HANDLE_SERVER_READ ( HandleServerEntityEquipment ) ; break ;
case PACKET_ENTITY_HEAD_LOOK : HANDLE_SERVER_READ ( HandleServerEntityHeadLook ) ; break ;
case PACKET_ENTITY_LOOK : HANDLE_SERVER_READ ( HandleServerEntityLook ) ; break ;
case PACKET_ENTITY_METADATA : HANDLE_SERVER_READ ( HandleServerEntityMetadata ) ; break ;
case PACKET_ENTITY_PROPERTIES : HANDLE_SERVER_READ ( HandleServerEntityProperties ) ; break ;
case PACKET_ENTITY_RELATIVE_MOVE : HANDLE_SERVER_READ ( HandleServerEntityRelativeMove ) ; break ;
case PACKET_ENTITY_RELATIVE_MOVE_LOOK : HANDLE_SERVER_READ ( HandleServerEntityRelativeMoveLook ) ; break ;
case PACKET_ENTITY_STATUS : HANDLE_SERVER_READ ( HandleServerEntityStatus ) ; break ;
case PACKET_ENTITY_TELEPORT : HANDLE_SERVER_READ ( HandleServerEntityTeleport ) ; break ;
case PACKET_ENTITY_VELOCITY : HANDLE_SERVER_READ ( HandleServerEntityVelocity ) ; break ;
case PACKET_INCREMENT_STATISTIC : HANDLE_SERVER_READ ( HandleServerIncrementStatistic ) ; break ;
case PACKET_KEEPALIVE : HANDLE_SERVER_READ ( HandleServerKeepAlive ) ; break ;
case PACKET_KICK : HANDLE_SERVER_READ ( HandleServerKick ) ; break ;
case PACKET_LOGIN : HANDLE_SERVER_READ ( HandleServerLogin ) ; break ;
case PACKET_MAP_CHUNK : HANDLE_SERVER_READ ( HandleServerMapChunk ) ; break ;
case PACKET_MAP_CHUNK_BULK : HANDLE_SERVER_READ ( HandleServerMapChunkBulk ) ; break ;
case PACKET_MULTI_BLOCK_CHANGE : HANDLE_SERVER_READ ( HandleServerMultiBlockChange ) ; break ;
case PACKET_NAMED_SOUND_EFFECT : HANDLE_SERVER_READ ( HandleServerNamedSoundEffect ) ; break ;
case PACKET_PLAYER_ABILITIES : HANDLE_SERVER_READ ( HandleServerPlayerAbilities ) ; break ;
case PACKET_PLAYER_ANIMATION : HANDLE_SERVER_READ ( HandleServerPlayerAnimation ) ; break ;
case PACKET_PLAYER_LIST_ITEM : HANDLE_SERVER_READ ( HandleServerPlayerListItem ) ; break ;
case PACKET_PLAYER_POSITION_LOOK : HANDLE_SERVER_READ ( HandleServerPlayerPositionLook ) ; break ;
case PACKET_PLUGIN_MESSAGE : HANDLE_SERVER_READ ( HandleServerPluginMessage ) ; break ;
case PACKET_SET_EXPERIENCE : HANDLE_SERVER_READ ( HandleServerSetExperience ) ; break ;
case PACKET_SET_SLOT : HANDLE_SERVER_READ ( HandleServerSetSlot ) ; break ;
case PACKET_SLOT_SELECT : HANDLE_SERVER_READ ( HandleServerSlotSelect ) ; break ;
case PACKET_SOUND_EFFECT : HANDLE_SERVER_READ ( HandleServerSoundEffect ) ; break ;
case PACKET_SPAWN_MOB : HANDLE_SERVER_READ ( HandleServerSpawnMob ) ; break ;
case PACKET_SPAWN_NAMED_ENTITY : HANDLE_SERVER_READ ( HandleServerSpawnNamedEntity ) ; break ;
case PACKET_SPAWN_OBJECT_VEHICLE : HANDLE_SERVER_READ ( HandleServerSpawnObjectVehicle ) ; break ;
case PACKET_SPAWN_PAINTING : HANDLE_SERVER_READ ( HandleServerSpawnPainting ) ; break ;
case PACKET_SPAWN_PICKUP : HANDLE_SERVER_READ ( HandleServerSpawnPickup ) ; break ;
2013-07-31 08:32:05 -04:00
case PACKET_TAB_COMPLETION : HANDLE_SERVER_READ ( HandleServerTabCompletion ) ; break ;
2013-07-29 07:13:03 -04:00
case PACKET_TIME_UPDATE : HANDLE_SERVER_READ ( HandleServerTimeUpdate ) ; break ;
case PACKET_UPDATE_HEALTH : HANDLE_SERVER_READ ( HandleServerUpdateHealth ) ; break ;
case PACKET_UPDATE_SIGN : HANDLE_SERVER_READ ( HandleServerUpdateSign ) ; break ;
case PACKET_UPDATE_TILE_ENTITY : HANDLE_SERVER_READ ( HandleServerUpdateTileEntity ) ; break ;
case PACKET_WINDOW_CLOSE : HANDLE_SERVER_READ ( HandleServerWindowClose ) ; break ;
case PACKET_WINDOW_CONTENTS : HANDLE_SERVER_READ ( HandleServerWindowContents ) ; break ;
case PACKET_WINDOW_OPEN : HANDLE_SERVER_READ ( HandleServerWindowOpen ) ; break ;
default :
{
if ( m_ServerState = = csEncryptedUnderstood )
{
Log ( " ********************** Unknown packet 0x%02x from the server while encrypted; continuing to relay blind only " , PacketType ) ;
AString Data ;
m_ServerBuffer . ResetRead ( ) ;
m_ServerBuffer . ReadAll ( Data ) ;
DataLog ( Data . data ( ) , Data . size ( ) , " Current data in the server packet queue: %d bytes " , Data . size ( ) ) ;
m_ServerState = csEncryptedUnknown ;
m_ServerBuffer . ResetRead ( ) ;
if ( m_ClientState = = csUnencrypted )
{
CLIENTSEND ( m_ServerBuffer ) ;
}
else
{
CLIENTENCRYPTSEND ( m_ServerBuffer ) ;
}
return true ;
}
else
{
Log ( " Unknown packet 0x%02x from the server while unencrypted; aborting connection " , PacketType ) ;
return false ;
}
}
} // switch (PacketType)
m_ServerBuffer . CommitRead ( ) ;
} // while (CanReadBytes(1))
return true ;
}
bool cConnection : : HandleClientAnimation ( void )
{
HANDLE_CLIENT_PACKET_READ ( ReadBEInt , int , EntityID ) ;
HANDLE_CLIENT_PACKET_READ ( ReadChar , char , Animation ) ;
Log ( " Received a PACKET_ANIMATION from the client: " ) ;
Log ( " EntityID: %d " , EntityID ) ;
Log ( " Animation: %d " , Animation ) ;
COPY_TO_SERVER ( ) ;
return true ;
}
bool cConnection : : HandleClientBlockDig ( void )
{
HANDLE_CLIENT_PACKET_READ ( ReadByte , Byte , Status ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEInt , int , BlockX ) ;
HANDLE_CLIENT_PACKET_READ ( ReadByte , Byte , BlockY ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEInt , int , BlockZ ) ;
HANDLE_CLIENT_PACKET_READ ( ReadByte , Byte , BlockFace ) ;
Log ( " Received a PACKET_BLOCK_DIG from the client: " ) ;
Log ( " Status = %d " , Status ) ;
Log ( " Pos = <%d, %d, %d> " , BlockX , BlockY , BlockZ ) ;
Log ( " BlockFace = %d " , BlockFace ) ;
COPY_TO_SERVER ( ) ;
return true ;
}
bool cConnection : : HandleClientBlockPlace ( void )
{
HANDLE_CLIENT_PACKET_READ ( ReadBEInt , int , BlockX ) ;
HANDLE_CLIENT_PACKET_READ ( ReadByte , Byte , BlockY ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEInt , int , BlockZ ) ;
HANDLE_CLIENT_PACKET_READ ( ReadChar , char , Face ) ;
AString Desc ;
if ( ! ParseSlot ( m_ClientBuffer , Desc ) )
{
return false ;
}
HANDLE_CLIENT_PACKET_READ ( ReadChar , char , CursorX ) ;
HANDLE_CLIENT_PACKET_READ ( ReadChar , char , CursorY ) ;
HANDLE_CLIENT_PACKET_READ ( ReadChar , char , CursorZ ) ;
Log ( " Received a PACKET_BLOCK_PLACE from the client: " ) ;
Log ( " Block = {%d, %d, %d} " , BlockX , BlockY , BlockZ ) ;
Log ( " Face = %d " , Face ) ;
Log ( " Item = %s " , Desc . c_str ( ) ) ;
Log ( " Cursor = <%d, %d, %d> " , CursorX , CursorY , CursorZ ) ;
COPY_TO_SERVER ( ) ;
return true ;
}
bool cConnection : : HandleClientChatMessage ( void )
{
HANDLE_CLIENT_PACKET_READ ( ReadBEUTF16String16 , AString , Message ) ;
Log ( " Received a PACKET_CHAT_MESSAGE from the client: " ) ;
Log ( " Message = \" %s \" " , Message . c_str ( ) ) ;
COPY_TO_SERVER ( ) ;
return true ;
}
bool cConnection : : HandleClientClientStatuses ( void )
{
HANDLE_CLIENT_PACKET_READ ( ReadChar , char , Statuses ) ;
Log ( " Received a PACKET_CLIENT_STATUSES from the CLIENT: " ) ;
Log ( " Statuses = %d " , Statuses ) ;
COPY_TO_SERVER ( ) ;
return true ;
}
bool cConnection : : HandleClientCreativeInventoryAction ( void )
{
HANDLE_CLIENT_PACKET_READ ( ReadBEShort , short , SlotNum ) ;
AString Item ;
if ( ! ParseSlot ( m_ClientBuffer , Item ) )
{
return false ;
}
Log ( " Received a PACKET_CREATIVE_INVENTORY_ACTION from the client: " ) ;
Log ( " SlotNum = %d " , SlotNum ) ;
Log ( " Item = %s " , Item . c_str ( ) ) ;
COPY_TO_SERVER ( ) ;
return true ;
}
2013-08-25 15:57:12 -04:00
bool cConnection : : HandleClientDisconnect ( void )
{
HANDLE_CLIENT_PACKET_READ ( ReadBEUTF16String16 , AString , Reason ) ;
Log ( " Received a PACKET_DISCONNECT from the client: " ) ;
Log ( " Reason = \" %s \" " , Reason . c_str ( ) ) ;
COPY_TO_SERVER ( ) ;
return true ;
}
2013-07-29 07:13:03 -04:00
bool cConnection : : HandleClientEncryptionKeyResponse ( void )
{
HANDLE_CLIENT_PACKET_READ ( ReadBEShort , short , EncKeyLength ) ;
AString EncKey ;
if ( ! m_ClientBuffer . ReadString ( EncKey , EncKeyLength ) )
{
return true ;
}
HANDLE_CLIENT_PACKET_READ ( ReadBEShort , short , EncNonceLength ) ;
AString EncNonce ;
if ( ! m_ClientBuffer . ReadString ( EncNonce , EncNonceLength ) )
{
return true ;
}
if ( ( EncKeyLength > MAX_ENC_LEN ) | | ( EncNonceLength > MAX_ENC_LEN ) )
{
Log ( " Client: Too long encryption params " ) ;
return true ;
}
StartClientEncryption ( EncKey , EncNonce ) ;
return true ;
}
bool cConnection : : HandleClientEntityAction ( void )
{
HANDLE_CLIENT_PACKET_READ ( ReadBEInt , int , PlayerID ) ;
HANDLE_CLIENT_PACKET_READ ( ReadByte , Byte , ActionType ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEInt , int , UnknownHorseVal ) ;
Log ( " Received a PACKET_ENTITY_ACTION from the client: " ) ;
Log ( " PlayerID = %d " , PlayerID ) ;
Log ( " ActionType = %d " , ActionType ) ;
Log ( " UnknownHorseVal = %d (0x%08x) " , UnknownHorseVal , UnknownHorseVal ) ;
COPY_TO_SERVER ( ) ;
return true ;
}
bool cConnection : : HandleClientHandshake ( void )
{
// Read the packet from the client:
HANDLE_CLIENT_PACKET_READ ( ReadByte , Byte , ProtocolVersion ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEUTF16String16 , AString , Username ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEUTF16String16 , AString , ServerHost ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEInt , int , ServerPort ) ;
m_ClientBuffer . CommitRead ( ) ;
Log ( " Received a PACKET_HANDSHAKE from the client: " ) ;
Log ( " ProtocolVersion = %d " , ProtocolVersion ) ;
Log ( " Username = \" %s \" " , Username . c_str ( ) ) ;
Log ( " ServerHost = \" %s \" " , ServerHost . c_str ( ) ) ;
Log ( " ServerPort = %d " , ServerPort ) ;
// Send the same packet to the server, but with our port:
cByteBuffer ToServer ( 512 ) ;
ToServer . WriteByte ( PACKET_HANDSHAKE ) ;
ToServer . WriteByte ( ProtocolVersion ) ;
ToServer . WriteBEUTF16String16 ( Username ) ;
ToServer . WriteBEUTF16String16 ( ServerHost ) ;
ToServer . WriteBEInt ( m_Server . GetConnectPort ( ) ) ;
SERVERSEND ( ToServer ) ;
return true ;
}
bool cConnection : : HandleClientKeepAlive ( void )
{
HANDLE_CLIENT_PACKET_READ ( ReadBEInt , int , ID ) ;
Log ( " Received a PACKET_KEEPALIVE from the client " ) ;
COPY_TO_SERVER ( ) ;
return true ;
}
bool cConnection : : HandleClientLocaleAndView ( void )
{
HANDLE_CLIENT_PACKET_READ ( ReadBEUTF16String16 , AString , Locale ) ;
HANDLE_CLIENT_PACKET_READ ( ReadChar , char , ViewDistance ) ;
HANDLE_CLIENT_PACKET_READ ( ReadChar , char , ChatFlags ) ;
HANDLE_CLIENT_PACKET_READ ( ReadChar , char , Difficulty ) ;
HANDLE_CLIENT_PACKET_READ ( ReadChar , char , ShowCape ) ;
Log ( " Received a PACKET_LOCALE_AND_VIEW from the client " ) ;
COPY_TO_SERVER ( ) ;
return true ;
}
bool cConnection : : HandleClientPing ( void )
{
m_HasClientPinged = true ;
Log ( " Received a PACKET_PING from the client " ) ;
m_ClientBuffer . ResetRead ( ) ;
SERVERSEND ( m_ClientBuffer ) ;
return true ;
}
bool cConnection : : HandleClientPlayerAbilities ( void )
{
HANDLE_CLIENT_PACKET_READ ( ReadChar , char , Flags ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEFloat , float , FlyingSpeed ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEFloat , float , WalkingSpeed ) ;
Log ( " Receives a PACKET_PLAYER_ABILITIES from the client: " ) ;
Log ( " Flags = %d (0x%02x) " , Flags , Flags ) ;
Log ( " FlyingSpeed = %f " , FlyingSpeed ) ;
Log ( " WalkingSpeed = %f " , WalkingSpeed ) ;
COPY_TO_SERVER ( ) ;
return true ;
}
bool cConnection : : HandleClientPlayerLook ( void )
{
HANDLE_CLIENT_PACKET_READ ( ReadBEFloat , float , Yaw ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEFloat , float , Pitch ) ;
HANDLE_CLIENT_PACKET_READ ( ReadChar , char , OnGround ) ;
Log ( " Received a PACKET_PLAYER_LOOK from the client " ) ;
COPY_TO_SERVER ( ) ;
return true ;
}
bool cConnection : : HandleClientPlayerOnGround ( void )
{
HANDLE_CLIENT_PACKET_READ ( ReadChar , char , OnGround ) ;
Log ( " Received a PACKET_PLAYER_ON_GROUND from the client " ) ;
COPY_TO_SERVER ( ) ;
return true ;
}
bool cConnection : : HandleClientPlayerPosition ( void )
{
HANDLE_CLIENT_PACKET_READ ( ReadBEDouble , double , PosX ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEDouble , double , Stance ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEDouble , double , PosY ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEDouble , double , PosZ ) ;
HANDLE_CLIENT_PACKET_READ ( ReadChar , char , IsOnGround ) ;
Log ( " Received a PACKET_PLAYER_POSITION from the client " ) ;
// TODO: list packet contents
COPY_TO_SERVER ( ) ;
return true ;
}
bool cConnection : : HandleClientPlayerPositionLook ( void )
{
HANDLE_CLIENT_PACKET_READ ( ReadBEDouble , double , PosX ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEDouble , double , Stance ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEDouble , double , PosY ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEDouble , double , PosZ ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEFloat , float , Yaw ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEFloat , float , Pitch ) ;
HANDLE_CLIENT_PACKET_READ ( ReadChar , char , IsOnGround ) ;
Log ( " Received a PACKET_PLAYER_POSITION_LOOK from the client " ) ;
Log ( " Pos = {%.03f, %.03f, %.03f} " , PosX , PosY , PosZ ) ;
Log ( " Stance = %.03f " , Stance ) ;
Log ( " Y, P = %.03f, %.03f " , Yaw , Pitch ) ;
Log ( " IsOnGround = %s " , IsOnGround ? " true " : " false " ) ;
COPY_TO_SERVER ( ) ;
return true ;
}
bool cConnection : : HandleClientPluginMessage ( void )
{
HANDLE_CLIENT_PACKET_READ ( ReadBEUTF16String16 , AString , ChannelName ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEShort , short , Length ) ;
AString Data ;
if ( ! m_ClientBuffer . ReadString ( Data , Length ) )
{
return false ;
}
Log ( " Received a PACKET_PLUGIN_MESSAGE from the client " ) ;
Log ( " ChannelName = \" %s \" " , ChannelName . c_str ( ) ) ;
DataLog ( Data . data ( ) , Length , " Data: %d bytes " , Length ) ;
COPY_TO_SERVER ( ) ;
return true ;
}
bool cConnection : : HandleClientSlotSelect ( void )
{
HANDLE_CLIENT_PACKET_READ ( ReadBEShort , short , SlotNum ) ;
Log ( " Received a PACKET_SLOT_SELECT from the client " ) ;
Log ( " SlotNum = %d " , SlotNum ) ;
COPY_TO_SERVER ( ) ;
return true ;
}
2013-07-31 08:32:05 -04:00
bool cConnection : : HandleClientTabCompletion ( void )
{
HANDLE_CLIENT_PACKET_READ ( ReadBEUTF16String16 , AString , Query ) ;
Log ( " Received a PACKET_TAB_COMPLETION query from the client " ) ;
Log ( " Query = \" %s \" " , Query . c_str ( ) ) ;
COPY_TO_SERVER ( ) ;
return true ;
}
2013-07-29 07:13:03 -04:00
bool cConnection : : HandleClientUpdateSign ( void )
{
HANDLE_CLIENT_PACKET_READ ( ReadBEInt , int , BlockX ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEShort , short , BlockY ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEInt , int , BlockZ ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEUTF16String16 , AString , Line1 ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEUTF16String16 , AString , Line2 ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEUTF16String16 , AString , Line3 ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEUTF16String16 , AString , Line4 ) ;
Log ( " Received a PACKET_UPDATE_SIGN from the client: " ) ;
Log ( " Block = {%d, %d, %d} " , BlockX , BlockY , BlockZ ) ;
Log ( " Lines = \" %s \" , \" %s \" , \" %s \" , \" %s \" " , Line1 . c_str ( ) , Line2 . c_str ( ) , Line3 . c_str ( ) , Line4 . c_str ( ) ) ;
COPY_TO_SERVER ( ) ;
return true ;
}
bool cConnection : : HandleClientUseEntity ( void )
{
HANDLE_CLIENT_PACKET_READ ( ReadBEInt , int , PlayerID ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEInt , int , EntityID ) ;
HANDLE_CLIENT_PACKET_READ ( ReadChar , char , MouseButton ) ;
Log ( " Received a PACKET_USE_ENTITY from the client: " ) ;
Log ( " PlayerID = %d " , PlayerID ) ;
Log ( " EntityID = %d " , EntityID ) ;
Log ( " MouseButton = %d " , MouseButton ) ;
COPY_TO_SERVER ( ) ;
return true ;
}
bool cConnection : : HandleClientWindowClick ( void )
{
HANDLE_CLIENT_PACKET_READ ( ReadChar , char , WindowID ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEShort , short , SlotNum ) ;
HANDLE_CLIENT_PACKET_READ ( ReadChar , char , IsRightClick ) ;
HANDLE_CLIENT_PACKET_READ ( ReadBEShort , short , TransactionID ) ;
HANDLE_CLIENT_PACKET_READ ( ReadChar , char , IsShiftClick ) ;
AString Item ;
if ( ! ParseSlot ( m_ClientBuffer , Item ) )
{
return false ;
}
Log ( " Received a PACKET_WINDOW_CLICK from the client " ) ;
Log ( " WindowID = %d " , WindowID ) ;
Log ( " SlotNum = %d " , SlotNum ) ;
Log ( " IsRclk = %d, IsShift = %d " , IsRightClick , IsShiftClick ) ;
Log ( " TransactionID = 0x%x " , TransactionID ) ;
Log ( " ClickedItem = %s " , Item . c_str ( ) ) ;
COPY_TO_SERVER ( ) ;
return true ;
}
bool cConnection : : HandleClientWindowClose ( void )
{
HANDLE_CLIENT_PACKET_READ ( ReadChar , char , WindowID ) ;
Log ( " Received a PACKET_WINDOW_CLOSE from the client: " ) ;
Log ( " WindowID = %d " , WindowID ) ;
COPY_TO_SERVER ( ) ;
return true ;
}
bool cConnection : : HandleServerAttachEntity ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , EntityID ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , VehicleID ) ;
HANDLE_SERVER_PACKET_READ ( ReadBool , bool , Leash ) ;
Log ( " Received a PACKET_ATTACH_ENTITY from the server: " ) ;
Log ( " EntityID = %d (0x%x) " , EntityID , EntityID ) ;
Log ( " VehicleID = %d (0x%x) " , VehicleID , VehicleID ) ;
Log ( " Leash = %s " , Leash ? " true " : " false " ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerBlockAction ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , BlockX ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , BlockY ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , BlockZ ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , Byte1 ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , Byte2 ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , BlockID ) ;
Log ( " Received a PACKET_BLOCK_ACTION from the server: " ) ;
Log ( " Pos = {%d, %d, %d} " , BlockX , BlockY , BlockZ ) ;
Log ( " Bytes = (%d, %d) == (0x%x, 0x%x) " , Byte1 , Byte2 , Byte1 , Byte2 ) ;
Log ( " BlockID = %d " , BlockID ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerBlockChange ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , BlockX ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , BlockY ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , BlockZ ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , BlockType ) ;
HANDLE_SERVER_PACKET_READ ( ReadChar , char , BlockMeta ) ;
Log ( " Received a PACKET_BLOCK_CHANGE from the server " ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerChangeGameState ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadChar , char , Reason ) ;
HANDLE_SERVER_PACKET_READ ( ReadChar , char , Data ) ;
Log ( " Received a PACKET_CHANGE_GAME_STATE from the server: " ) ;
Log ( " Reason = %d " , Reason ) ;
Log ( " Data = %d " , Data ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerChatMessage ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEUTF16String16 , AString , Message ) ;
Log ( " Received a PACKET_CHAT_MESSAGE from the server: " ) ;
Log ( " Message = \" %s \" " , Message . c_str ( ) ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerCollectPickup ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , CollectedID ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , CollectorID ) ;
Log ( " Received a PACKET_COLLECT_PICKUP from the server: " ) ;
Log ( " CollectedID = %d " , CollectedID ) ;
Log ( " CollectorID = %d " , CollectorID ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerCompass ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , SpawnX ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , SpawnY ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , SpawnZ ) ;
Log ( " Received PACKET_COMPASS from the server: " ) ;
Log ( " Spawn = {%d, %d, %d} " , SpawnX , SpawnY , SpawnZ ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerDestroyEntities ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , NumEntities ) ;
if ( ! m_ServerBuffer . SkipRead ( ( int ) NumEntities * 4 ) )
{
return false ;
}
Log ( " Received PACKET_DESTROY_ENTITIES from the server: " ) ;
Log ( " NumEntities = %d " , NumEntities ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerEncryptionKeyRequest ( void )
{
// Read the packet from the server:
HANDLE_SERVER_PACKET_READ ( ReadBEUTF16String16 , AString , ServerID ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , PublicKeyLength ) ;
AString PublicKey ;
if ( ! m_ServerBuffer . ReadString ( PublicKey , PublicKeyLength ) )
{
return false ;
}
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , NonceLength ) ;
AString Nonce ;
if ( ! m_ServerBuffer . ReadString ( Nonce , NonceLength ) )
{
return false ;
}
Log ( " Got PACKET_ENCRYPTION_KEY_REQUEST from the SERVER: " ) ;
Log ( " ServerID = %s " , ServerID . c_str ( ) ) ;
// Reply to the server:
SendEncryptionKeyResponse ( PublicKey , Nonce ) ;
// Send a 0xFD Encryption Key Request http://wiki.vg/Protocol#0xFD to the client, using our own key:
Log ( " Sending PACKET_ENCRYPTION_KEY_REQUEST to the CLIENT " ) ;
AString key ;
StringSink sink ( key ) ; // GCC won't allow inline instantiation in the following line, damned temporary refs
m_Server . GetPublicKey ( ) . Save ( sink ) ;
cByteBuffer ToClient ( 512 ) ;
ToClient . WriteByte ( PACKET_ENCRYPTION_KEY_REQUEST ) ;
ToClient . WriteBEUTF16String16 ( ServerID ) ;
ToClient . WriteBEShort ( ( short ) key . size ( ) ) ;
ToClient . WriteBuf ( key . data ( ) , key . size ( ) ) ;
ToClient . WriteBEShort ( 4 ) ;
ToClient . WriteBEInt ( m_Nonce ) ; // Using 'this' as the cryptographic nonce, so that we don't have to generate one each time :)
CLIENTSEND ( ToClient ) ;
return true ;
}
bool cConnection : : HandleServerEntity ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , EntityID ) ;
Log ( " Received a PACKET_ENTITY from the server: " ) ;
Log ( " EntityID = %d " , EntityID ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerEntityEquipment ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , EntityID ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , SlotNum ) ;
AString Item ;
if ( ! ParseSlot ( m_ServerBuffer , Item ) )
{
return false ;
}
Log ( " Received a PACKET_ENTITY_EQUIPMENT from the server: " ) ;
Log ( " EntityID = %d " , EntityID ) ;
Log ( " SlotNum = %d " , SlotNum ) ;
Log ( " Item = %s " , Item . c_str ( ) ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerEntityHeadLook ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , EntityID ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , HeadYaw ) ;
Log ( " Received a PACKET_ENTITY_HEAD_LOOK from the server: " ) ;
Log ( " EntityID = %d " , EntityID ) ;
Log ( " HeadYaw = %d " , HeadYaw ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerEntityLook ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , EntityID ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , Yaw ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , Pitch ) ;
Log ( " Received a PACKET_ENTITY_LOOK from the server: " ) ;
Log ( " EntityID = %d " , EntityID ) ;
Log ( " Yaw = %d " , Yaw ) ;
Log ( " Pitch = %d " , Pitch ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerEntityMetadata ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , EntityID ) ;
AString Metadata ;
if ( ! ParseMetadata ( m_ServerBuffer , Metadata ) )
{
return false ;
}
AString HexDump ;
CreateHexDump ( HexDump , Metadata . data ( ) , Metadata . size ( ) , 32 ) ;
Log ( " Received a PACKET_ENTITY_METADATA from the server: " ) ;
Log ( " EntityID = %d " , EntityID ) ;
Log ( " Metadata, length = %d (0x%x): \n %s " , Metadata . length ( ) , Metadata . length ( ) , HexDump . c_str ( ) ) ;
LogMetadata ( Metadata , 4 ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerEntityProperties ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , EntityID ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , Count ) ;
Log ( " Received a PACKET_ENTITY_PROPERTIES from the server: " ) ;
Log ( " EntityID = %d " , EntityID ) ;
Log ( " Count = %d " , Count ) ;
for ( int i = 0 ; i < Count ; i + + )
{
HANDLE_SERVER_PACKET_READ ( ReadBEUTF16String16 , AString , Key ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEDouble , double , Value ) ;
Log ( " \" %s \" = %f " , Key . c_str ( ) , Value ) ;
} // for i
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , ListLength ) ;
Log ( " ListLength = %d " , ListLength ) ;
for ( int i = 0 ; i < ListLength ; i + + )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt64 , Int64 , UUIDHi ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt64 , Int64 , UUIDLo ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEDouble , double , DblVal ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , ByteVal ) ;
Log ( " [%d] = {0x%08llx%08llx, %f, %i} " , i , UUIDHi , UUIDLo , DblVal , ByteVal ) ;
} // for i
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerEntityRelativeMove ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , EntityID ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , dx ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , dy ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , dz ) ;
Log ( " Received a PACKET_ENTITY_RELATIVE_MOVE from the server: " ) ;
Log ( " EntityID = %d " , EntityID ) ;
2013-09-04 14:42:37 -04:00
Log ( " RelMove = %s " , PrintableAbsIntTriplet ( dx , dy , dz ) . c_str ( ) ) ;
2013-07-29 07:13:03 -04:00
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerEntityRelativeMoveLook ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , EntityID ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , dx ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , dy ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , dz ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , Yaw ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , Pitch ) ;
Log ( " Received a PACKET_ENTITY_RELATIVE_MOVE_LOOK from the server: " ) ;
Log ( " EntityID = %d " , EntityID ) ;
2013-09-04 14:42:37 -04:00
Log ( " RelMove = %s " , PrintableAbsIntTriplet ( dx , dy , dz ) . c_str ( ) ) ;
2013-07-29 07:13:03 -04:00
Log ( " Yaw = %d " , Yaw ) ;
Log ( " Pitch = %d " , Pitch ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerEntityStatus ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , EntityID ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , Status ) ;
Log ( " Received a PACKET_ENTITY_STATUS from the server: " ) ;
Log ( " EntityID = %d " , EntityID ) ;
Log ( " Status = %d " , Status ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerEntityTeleport ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , EntityID ) ;
2013-09-04 14:42:37 -04:00
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , AbsX ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , AbsY ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , AbsZ ) ;
2013-07-29 07:13:03 -04:00
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , Yaw ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , Pitch ) ;
Log ( " Received a PACKET_ENTITY_TELEPORT from the server: " ) ;
Log ( " EntityID = %d " , EntityID ) ;
2013-09-04 14:42:37 -04:00
Log ( " Pos = (%d, %d, %d) ~ {%.02f, %.02f, %.02f} " , AbsX , AbsY , AbsZ , ( double ) AbsX / 32 , ( double ) AbsY / 32 , ( double ) AbsZ / 32 ) ;
2013-07-29 07:13:03 -04:00
Log ( " Yaw = %d " , Yaw ) ;
Log ( " Pitch = %d " , Pitch ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerEntityVelocity ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , EntityID ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , VelocityX ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , VelocityY ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , VelocityZ ) ;
Log ( " Received a PACKET_ENTITY_VELOCITY from the server: " ) ;
Log ( " EntityID = %d " , EntityID ) ;
2013-09-04 14:42:37 -04:00
Log ( " Velocity = %s " , PrintableAbsIntTriplet ( VelocityX , VelocityY , VelocityZ , 8000 ) . c_str ( ) ) ;
2013-07-29 07:13:03 -04:00
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerIncrementStatistic ( void )
{
// 0xc8
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , StatisticID ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , Amount ) ;
Log ( " Received a PACKET_INCREMENT_STATISTIC from the server: " ) ;
Log ( " StatisticID = %d (0x%x) " , StatisticID , StatisticID ) ;
Log ( " Amount = %d " , Amount ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerKeepAlive ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , PingID ) ;
Log ( " Received a PACKET_KEEP_ALIVE from the server: " ) ;
Log ( " ID = %d " , PingID ) ;
COPY_TO_CLIENT ( )
return true ;
}
bool cConnection : : HandleServerEncryptionKeyResponse ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , Lengths ) ;
if ( Lengths ! = 0 )
{
Log ( " Lengths are not zero! " ) ;
return true ;
}
Log ( " Server communication is now encrypted " ) ;
m_ServerState = csEncryptedUnderstood ;
DataLog ( m_ServerEncryptionBuffer . data ( ) , m_ServerEncryptionBuffer . size ( ) , " Sending the queued data to server (%u bytes): " , m_ServerEncryptionBuffer . size ( ) ) ;
SERVERENCRYPTSEND ( m_ServerEncryptionBuffer . data ( ) , m_ServerEncryptionBuffer . size ( ) ) ;
m_ServerEncryptionBuffer . clear ( ) ;
return true ;
}
bool cConnection : : HandleServerKick ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEUTF16String16 , AString , Reason ) ;
Log ( " Received PACKET_KICK from the SERVER: " ) ;
if ( m_HasClientPinged )
{
Log ( " This was a std reply to client's PING " ) ;
AStringVector Split ;
// Split by NULL chars (StringSplit() won't work here):
size_t Last = 0 ;
2013-09-08 05:12:34 -04:00
size_t Len = Reason . size ( ) ;
for ( size_t i = 0 ; i < Len ; i + + )
2013-07-29 07:13:03 -04:00
{
if ( Reason [ i ] = = 0 )
{
Split . push_back ( Reason . substr ( Last , i - Last ) ) ;
Last = i + 1 ;
}
}
2013-09-08 05:12:34 -04:00
if ( Last < Len )
{
Split . push_back ( Reason . substr ( Last ) ) ;
}
2013-07-29 07:13:03 -04:00
2013-09-08 05:12:34 -04:00
if ( Split . size ( ) = = 6 )
2013-07-29 07:13:03 -04:00
{
2013-09-08 05:12:34 -04:00
Log ( " Preamble: \" %s \" " , Split [ 0 ] . c_str ( ) ) ;
Log ( " Protocol version: \" %s \" " , Split [ 1 ] . c_str ( ) ) ;
Log ( " Server version: \" %s \" " , Split [ 2 ] . c_str ( ) ) ;
Log ( " MOTD: \" %s \" " , Split [ 3 ] . c_str ( ) ) ;
Log ( " Cur players: \" %s \" " , Split [ 4 ] . c_str ( ) ) ;
Log ( " Max players: \" %s \" " , Split [ 5 ] . c_str ( ) ) ;
// Modify the MOTD to show that it's being ProtoProxied:
Reason . assign ( Split [ 0 ] ) ;
Reason . push_back ( 0 ) ;
Reason . append ( Split [ 1 ] ) ;
Reason . push_back ( 0 ) ;
Reason . append ( Split [ 2 ] ) ;
Reason . push_back ( 0 ) ;
Reason . append ( Printf ( " ProtoProxy: %s " , Split [ 3 ] . c_str ( ) ) ) ;
Reason . push_back ( 0 ) ;
Reason . append ( Split [ 4 ] ) ;
Reason . push_back ( 0 ) ;
Reason . append ( Split [ 5 ] ) ;
AString ReasonBE16 ;
UTF8ToRawBEUTF16 ( Reason . data ( ) , Reason . size ( ) , ReasonBE16 ) ;
AString PacketStart ( " \xff " ) ;
PacketStart . push_back ( ( ReasonBE16 . size ( ) / 2 ) / 256 ) ;
PacketStart . push_back ( ( ReasonBE16 . size ( ) / 2 ) % 256 ) ;
CLIENTSEND ( PacketStart . data ( ) , PacketStart . size ( ) ) ;
CLIENTSEND ( ReasonBE16 . data ( ) , ReasonBE16 . size ( ) ) ;
return true ;
2013-07-29 07:13:03 -04:00
}
else
{
DataLog ( Reason . data ( ) , Reason . size ( ) , " Unknown reply format, dumping hex: " ) ;
}
}
else
{
Log ( " Reason = \" %s \" " , Reason . c_str ( ) ) ;
}
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerLogin ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , EntityID ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEUTF16String16 , AString , LevelType ) ;
HANDLE_SERVER_PACKET_READ ( ReadChar , char , GameMode ) ;
HANDLE_SERVER_PACKET_READ ( ReadChar , char , Dimension ) ;
HANDLE_SERVER_PACKET_READ ( ReadChar , char , Difficulty ) ;
HANDLE_SERVER_PACKET_READ ( ReadChar , char , Unused ) ;
HANDLE_SERVER_PACKET_READ ( ReadChar , char , MaxPlayers ) ;
Log ( " Received a PACKET_LOGIN from the server: " ) ;
Log ( " EntityID = %d " , EntityID ) ;
Log ( " LevelType = \" %s \" " , LevelType . c_str ( ) ) ;
Log ( " GameMode = %d " , GameMode ) ;
Log ( " Dimension = %d " , Dimension ) ;
Log ( " Difficulty = %d " , Difficulty ) ;
Log ( " Unused = %d " , Unused ) ;
Log ( " MaxPlayers = %d " , MaxPlayers ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerMapChunk ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , ChunkX ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , ChunkZ ) ;
HANDLE_SERVER_PACKET_READ ( ReadChar , char , IsContiguous ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , PrimaryBitmap ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , AdditionalBitmap ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , CompressedSize ) ;
AString CompressedData ;
if ( ! m_ServerBuffer . ReadString ( CompressedData , CompressedSize ) )
{
return false ;
}
Log ( " Received a PACKET_MAP_CHUNK from the server: " ) ;
Log ( " ChunkPos = [%d, %d] " , ChunkX , ChunkZ ) ;
Log ( " Compressed size = %d (0x%x) " , CompressedSize , CompressedSize ) ;
// TODO: Save the compressed data into a file for later analysis
COPY_TO_CLIENT ( )
return true ;
}
bool cConnection : : HandleServerMapChunkBulk ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , ChunkCount ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , CompressedSize ) ;
HANDLE_SERVER_PACKET_READ ( ReadBool , bool , IsSkyLightSent ) ;
AString CompressedData ;
if ( ! m_ServerBuffer . ReadString ( CompressedData , CompressedSize ) )
{
return false ;
}
2013-08-30 10:38:24 -04:00
// Read individual chunk metas.
// Need to read them first and only then start logging (in case we don't have the full packet yet)
struct sChunkMeta
2013-07-29 07:13:03 -04:00
{
2013-08-30 10:38:24 -04:00
int m_ChunkX , m_ChunkZ ;
short m_PrimaryBitmap ;
short m_AddBitmap ;
sChunkMeta ( int a_ChunkX , int a_ChunkZ , short a_PrimaryBitmap , short a_AddBitmap ) :
m_ChunkX ( a_ChunkX ) , m_ChunkZ ( a_ChunkZ ) , m_PrimaryBitmap ( a_PrimaryBitmap ) , m_AddBitmap ( a_AddBitmap )
{
}
} ;
typedef std : : vector < sChunkMeta > sChunkMetas ;
sChunkMetas ChunkMetas ;
ChunkMetas . reserve ( ChunkCount ) ;
for ( short i = 0 ; i < ChunkCount ; i + + )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , ChunkX ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , ChunkZ ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , PrimaryBitmap ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , AddBitmap ) ;
ChunkMetas . push_back ( sChunkMeta ( ChunkX , ChunkZ , PrimaryBitmap , AddBitmap ) ) ;
2013-07-29 07:13:03 -04:00
}
2013-08-30 10:38:24 -04:00
2013-07-29 07:13:03 -04:00
Log ( " Received a PACKET_MAP_CHUNK_BULK from the server: " ) ;
Log ( " ChunkCount = %d " , ChunkCount ) ;
Log ( " Compressed size = %d (0x%x) " , CompressedSize , CompressedSize ) ;
Log ( " IsSkyLightSent = %s " , IsSkyLightSent ? " true " : " false " ) ;
2013-08-30 10:38:24 -04:00
// Log individual chunk coords:
int idx = 0 ;
for ( sChunkMetas : : iterator itr = ChunkMetas . begin ( ) , end = ChunkMetas . end ( ) ; itr ! = end ; + + itr , + + idx )
{
Log ( " [%d]: [%d, %d], primary bitmap 0x%02x, add bitmap 0x%02x " ,
idx , itr - > m_ChunkX , itr - > m_ChunkZ , itr - > m_PrimaryBitmap , itr - > m_AddBitmap
) ;
} // for itr - ChunkMetas[]
2013-07-29 07:13:03 -04:00
// TODO: Save the compressed data into a file for later analysis
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerMultiBlockChange ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , ChunkX ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , ChunkZ ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , NumBlocks ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , DataSize ) ;
AString BlockChangeData ;
if ( ! m_ServerBuffer . ReadString ( BlockChangeData , DataSize ) )
{
return false ;
}
Log ( " Received a PACKET_MULTI_BLOCK_CHANGE packet from the server: " ) ;
Log ( " Chunk = [%d, %d] " , ChunkX , ChunkZ ) ;
Log ( " NumBlocks = %d " , NumBlocks ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerNamedSoundEffect ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEUTF16String16 , AString , SoundName ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , PosX ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , PosY ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , PosZ ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEFloat , float , Volume ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , Pitch ) ;
Log ( " Received a PACKET_NAMED_SOUND_EFFECT from the server: " ) ;
Log ( " SoundName = \" %s \" " , SoundName . c_str ( ) ) ;
Log ( " Pos = (%d, %d, %d) ~ {%d, %d, %d} " , PosX , PosY , PosZ , PosX / 8 , PosY / 8 , PosZ / 8 ) ;
Log ( " Volume = %f " , Volume ) ;
Log ( " Pitch = %d " , Pitch ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerPlayerAbilities ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadChar , char , Flags ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEFloat , float , FlyingSpeed ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEFloat , float , WalkingSpeed ) ;
Log ( " Received a PACKET_PLAYER_ABILITIES from the server: " ) ;
Log ( " Flags = %d (0x%02x) " , Flags , Flags ) ;
Log ( " FlyingSpeed = %f " , FlyingSpeed ) ;
Log ( " WalkingSpeed = %f " , WalkingSpeed ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerPlayerAnimation ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , PlayerID ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , AnimationID ) ;
Log ( " Received a PACKET_PLAYER_ANIMATION from the server: " ) ;
Log ( " PlayerID: %d (0x%x) " , PlayerID , PlayerID ) ;
Log ( " Animation: %d " , AnimationID ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerPlayerListItem ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEUTF16String16 , AString , PlayerName ) ;
HANDLE_SERVER_PACKET_READ ( ReadChar , char , IsOnline ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , Ping ) ;
Log ( " Received a PACKET_PLAYERLIST_ITEM from the server: " ) ;
Log ( " PlayerName = \" %s \" " , PlayerName . c_str ( ) ) ;
Log ( " Ping = %d " , Ping ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerPlayerPositionLook ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEDouble , double , PosX ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEDouble , double , Stance ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEDouble , double , PosY ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEDouble , double , PosZ ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEFloat , float , Yaw ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEFloat , float , Pitch ) ;
HANDLE_SERVER_PACKET_READ ( ReadChar , char , IsOnGround ) ;
Log ( " Received a PACKET_PLAYER_POSITION_LOOK from the server " ) ;
// TODO: list packet contents
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerPluginMessage ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEUTF16String16 , AString , ChannelName ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , Length ) ;
AString Data ;
if ( ! m_ServerBuffer . ReadString ( Data , Length ) )
{
return false ;
}
Log ( " Received a PACKET_PLUGIN_MESSAGE from the server " ) ;
Log ( " ChannelName = \" %s \" " , ChannelName . c_str ( ) ) ;
DataLog ( Data . data ( ) , Length , " Data: %d bytes " , Length ) ;
COPY_TO_SERVER ( ) ;
return true ;
}
bool cConnection : : HandleServerSetExperience ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEFloat , float , ExperienceBar ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , Level ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , TotalExperience ) ;
Log ( " Received a PACKET_SET_EXPERIENCE from the server: " ) ;
Log ( " ExperienceBar = %.05f " , ExperienceBar ) ;
Log ( " Level = %d " , Level ) ;
Log ( " TotalExperience = %d " , TotalExperience ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerSetSlot ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadChar , char , WindowID ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , SlotNum ) ;
AString Item ;
if ( ! ParseSlot ( m_ServerBuffer , Item ) )
{
return false ;
}
Log ( " Received a PACKET_SET_SLOT from the server: " ) ;
Log ( " WindowID = %d " , WindowID ) ;
Log ( " SlotNum = %d " , SlotNum ) ;
Log ( " Item = %s " , Item . c_str ( ) ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerSlotSelect ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , SlotNum ) ;
Log ( " Received a PACKET_SLOT_SELECT from the server: " ) ;
Log ( " SlotNum = %d " , SlotNum ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerSoundEffect ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , EffectID ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , PosX ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , PosY ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , PosZ ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , Data ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , NoVolumeDecrease ) ;
Log ( " Received a PACKET_SOUND_EFFECT from the server: " ) ;
Log ( " EffectID = %d " , EffectID ) ;
Log ( " Pos = {%d, %d, %d} " , PosX , PosY , PosZ ) ;
Log ( " Data = %d " , Data ) ;
Log ( " NoVolumeDecrease = %d " , NoVolumeDecrease ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerSpawnMob ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , EntityID ) ;
HANDLE_SERVER_PACKET_READ ( ReadChar , char , MobType ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , PosX ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , PosY ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , PosZ ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , Yaw ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , Pitch ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , HeadYaw ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , VelocityX ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , VelocityY ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , VelocityZ ) ;
AString Metadata ;
if ( ! ParseMetadata ( m_ServerBuffer , Metadata ) )
{
return false ;
}
AString HexDump ;
CreateHexDump ( HexDump , Metadata . data ( ) , Metadata . size ( ) , 32 ) ;
Log ( " Received a PACKET_SPAWN_MOB from the server: " ) ;
Log ( " EntityID = %d " , EntityID ) ;
Log ( " MobType = %d " , MobType ) ;
2013-09-04 14:42:37 -04:00
Log ( " Pos = %s " , PrintableAbsIntTriplet ( PosX , PosY , PosZ ) . c_str ( ) ) ;
2013-07-29 07:13:03 -04:00
Log ( " Angles = [%d, %d, %d] " , Yaw , Pitch , HeadYaw ) ;
2013-09-04 14:42:37 -04:00
Log ( " Velocity = %s " , PrintableAbsIntTriplet ( VelocityX , VelocityY , VelocityZ , 8000 ) . c_str ( ) ) ;
2013-07-29 07:13:03 -04:00
Log ( " Metadata, length = %d (0x%x): \n %s " , Metadata . length ( ) , Metadata . length ( ) , HexDump . c_str ( ) ) ;
LogMetadata ( Metadata , 4 ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerSpawnNamedEntity ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , EntityID ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEUTF16String16 , AString , EntityName ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , PosX ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , PosY ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , PosZ ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , Yaw ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , Pitch ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , CurrentItem ) ;
AString Metadata ;
if ( ! ParseMetadata ( m_ServerBuffer , Metadata ) )
{
return false ;
}
AString HexDump ;
CreateHexDump ( HexDump , Metadata . data ( ) , Metadata . size ( ) , 32 ) ;
Log ( " Received a PACKET_SPAWN_NAMED_ENTITY from the server: " ) ;
Log ( " EntityID = %d (0x%x) " , EntityID , EntityID ) ;
Log ( " Name = %s " , EntityName . c_str ( ) ) ;
2013-09-04 14:42:37 -04:00
Log ( " Pos = %s " , PrintableAbsIntTriplet ( PosX , PosY , PosZ ) . c_str ( ) ) ;
2013-07-29 07:13:03 -04:00
Log ( " Rotation = <yaw %d, pitch %d> " , Yaw , Pitch ) ;
Log ( " CurrentItem = %d " , CurrentItem ) ;
Log ( " Metadata, length = %d (0x%x): \n %s " , Metadata . length ( ) , Metadata . length ( ) , HexDump . c_str ( ) ) ;
LogMetadata ( Metadata , 4 ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerSpawnObjectVehicle ( void )
{
# ifdef _DEBUG
// DEBUG:
// This packet is still troublesome when DataIndicator != 0
AString Buffer ;
m_ServerBuffer . ResetRead ( ) ;
m_ServerBuffer . ReadAll ( Buffer ) ;
m_ServerBuffer . ResetRead ( ) ;
m_ServerBuffer . SkipRead ( 1 ) ;
if ( Buffer . size ( ) > 128 )
{
// Only log up to 128 bytes
Buffer . erase ( 128 , AString : : npos ) ;
}
DataLog ( Buffer . data ( ) , Buffer . size ( ) , " Buffer while parsing the PACKET_SPAWN_OBJECT_VEHICLE packet (%d bytes): " , Buffer . size ( ) ) ;
# endif // _DEBUG
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , EntityID ) ;
HANDLE_SERVER_PACKET_READ ( ReadChar , char , ObjType ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , PosX ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , PosY ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , PosZ ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , Yaw ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , Pitch ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , DataIndicator ) ;
AString ExtraData ;
short VelocityX , VelocityY , VelocityZ ;
if ( DataIndicator ! = 0 )
{
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , SpeedX ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , SpeedY ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , SpeedZ ) ;
VelocityX = SpeedX ; VelocityY = SpeedY ; VelocityZ = SpeedZ ; // Speed vars are local to this scope, but we need them available later
/*
// This doesn't seem to work - for a falling block I'm getting no extra data at all
int ExtraLen = 0 ;
switch ( ObjType )
{
case OBJECT_FALLING_BLOCK : ExtraLen = 4 ; break ; // int: BlockType | (BlockMeta << 12)
case OBJECT_ARROW :
case OBJECT_SNOWBALL :
case OBJECT_EGG :
case OBJECT_EYE_OF_ENDER :
case OBJECT_DRAGON_EGG :
case OBJECT_FISHING_FLOAT :
{
ExtraLen = 4 ; break ; // int: EntityID of the thrower
}
// TODO: Splash potions
}
if ( ( ExtraLen > 0 ) & & ! m_ServerBuffer . ReadString ( ExtraData , ExtraLen ) )
{
return false ;
}
*/
}
Log ( " Received a PACKET_SPAWN_OBJECT_VEHICLE from the server: " ) ;
Log ( " EntityID = %d (0x%x) " , EntityID , EntityID ) ;
Log ( " ObjType = %d (0x%x) " , ObjType , ObjType ) ;
2013-09-04 14:42:37 -04:00
Log ( " Pos = %s " , PrintableAbsIntTriplet ( PosX , PosY , PosZ ) . c_str ( ) ) ;
2013-07-29 07:13:03 -04:00
Log ( " Rotation = <yaw %d, pitch %d> " , Yaw , Pitch ) ;
Log ( " DataIndicator = %d (0x%x) " , DataIndicator , DataIndicator ) ;
if ( DataIndicator ! = 0 )
{
2013-09-04 14:42:37 -04:00
Log ( " Velocity = %s " , PrintableAbsIntTriplet ( VelocityX , VelocityY , VelocityZ , 8000 ) . c_str ( ) ) ;
2013-07-29 07:13:03 -04:00
DataLog ( ExtraData . data ( ) , ExtraData . size ( ) , " ExtraData size = %d: " , ExtraData . size ( ) ) ;
}
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerSpawnPainting ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , EntityID ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEUTF16String16 , AString , ImageName ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , PosX ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , PosY ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , PosZ ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , Direction ) ;
Log ( " Received a PACKET_SPAWN_PAINTING from the server: " ) ;
Log ( " EntityID = %d " , EntityID ) ;
Log ( " ImageName = \" %s \" " , ImageName . c_str ( ) ) ;
2013-09-04 14:42:37 -04:00
Log ( " Pos = %s " , PrintableAbsIntTriplet ( PosX , PosY , PosZ ) . c_str ( ) ) ;
2013-07-29 07:13:03 -04:00
Log ( " Direction = %d " , Direction ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerSpawnPickup ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , EntityID ) ;
AString ItemDesc ;
if ( ! ParseSlot ( m_ServerBuffer , ItemDesc ) )
{
return false ;
}
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , PosX ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , PosY ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , PosZ ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , Rotation ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , Pitch ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , Roll ) ;
Log ( " Received a PACKET_SPAWN_PICKUP from the server: " ) ;
Log ( " EntityID = %d " , EntityID ) ;
Log ( " Item = %s " , ItemDesc . c_str ( ) ) ;
2013-09-04 14:42:37 -04:00
Log ( " Pos = %s " , PrintableAbsIntTriplet ( PosX , PosY , PosZ ) . c_str ( ) ) ;
2013-07-29 07:13:03 -04:00
Log ( " Angles = [%d, %d, %d] " , Rotation , Pitch , Roll ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
2013-07-31 08:32:05 -04:00
bool cConnection : : HandleServerTabCompletion ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEUTF16String16 , AString , Results ) ;
Log ( " Received a PACKET_TAB_COMPLETION from the server, results given: " ) ;
// Parse the zero-terminated list of results:
size_t len = Results . size ( ) ;
size_t last = 0 ;
for ( size_t i = 0 ; i < len ; i + + )
{
if ( Results [ i ] = = 0 )
{
Log ( " \" %s \" " , Results . substr ( last , i - last ) . c_str ( ) ) ;
last = i + 1 ;
}
}
2013-07-31 08:35:48 -04:00
if ( last < len )
{
Log ( " \" %s \" " , Results . substr ( last , len - last ) . c_str ( ) ) ;
}
2013-07-31 08:32:05 -04:00
COPY_TO_CLIENT ( ) ;
return true ;
}
2013-07-29 07:13:03 -04:00
bool cConnection : : HandleServerTimeUpdate ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt64 , Int64 , WorldAge ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt64 , Int64 , TimeOfDay ) ;
Log ( " Received a PACKET_TIME_UPDATE from the server " ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerUpdateHealth ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEFloat , float , Health ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , Food ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEFloat , float , Saturation ) ;
Log ( " Received a PACKET_UPDATE_HEALTH from the server " ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerUpdateSign ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , BlockX ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , BlockY ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , BlockZ ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEUTF16String16 , AString , Line1 ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEUTF16String16 , AString , Line2 ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEUTF16String16 , AString , Line3 ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEUTF16String16 , AString , Line4 ) ;
Log ( " Received a PACKET_UPDATE_SIGN from the server: " ) ;
Log ( " Block = {%d, %d, %d} " , BlockX , BlockY , BlockZ ) ;
Log ( " Lines = \" %s \" , \" %s \" , \" %s \" , \" %s \" " , Line1 . c_str ( ) , Line2 . c_str ( ) , Line3 . c_str ( ) , Line4 . c_str ( ) ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerUpdateTileEntity ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , BlockX ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , BlockY ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , BlockZ ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , Action ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , DataLength ) ;
AString Data ;
if ( ( DataLength > 0 ) & & ! m_ServerBuffer . ReadString ( Data , DataLength ) )
{
return false ;
}
Log ( " Received a PACKET_UPDATE_TILE_ENTITY from the server: " ) ;
Log ( " Block = {%d, %d, %d} " , BlockX , BlockY , BlockZ ) ;
Log ( " Action = %d " , Action ) ;
DataLog ( Data . data ( ) , Data . size ( ) , " Data (%d bytes) " , Data . size ( ) ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerWindowClose ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadChar , char , WindowID ) ;
Log ( " Received a PACKET_WINDOW_CLOSE from the server: " ) ;
Log ( " WindowID = %d " , WindowID ) ;
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerWindowContents ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadChar , char , WindowID ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEShort , short , NumSlots ) ;
Log ( " Received a PACKET_WINDOW_CONTENTS from the server: " ) ;
Log ( " WindowID = %d " , WindowID ) ;
Log ( " NumSlots = %d " , NumSlots ) ;
AStringVector Items ;
for ( short i = 0 ; i < NumSlots ; i + + )
{
AString Item ;
if ( ! ParseSlot ( m_ServerBuffer , Item ) )
{
return false ;
}
Log ( " %d: %s " , i , Item . c_str ( ) ) ;
}
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : HandleServerWindowOpen ( void )
{
HANDLE_SERVER_PACKET_READ ( ReadChar , char , WindowID ) ;
HANDLE_SERVER_PACKET_READ ( ReadChar , char , WindowType ) ;
HANDLE_SERVER_PACKET_READ ( ReadBEUTF16String16 , AString , Title ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , NumSlots ) ;
HANDLE_SERVER_PACKET_READ ( ReadByte , Byte , UseProvidedTitle ) ;
int HorseInt = 0 ;
if ( WindowType = = 11 ) // Horse / Donkey / Mule
{
HANDLE_SERVER_PACKET_READ ( ReadBEInt , int , intHorseInt ) ;
HorseInt = intHorseInt ;
}
Log ( " Received a PACKET_WINDOW_OPEN from the server: " ) ;
Log ( " WindowID = %d " , WindowID ) ;
Log ( " WindowType = %d " , WindowType ) ;
Log ( " Title = \" %s \" , Use = %d " , Title . c_str ( ) , UseProvidedTitle ) ;
Log ( " NumSlots = %d " , NumSlots ) ;
if ( WindowType = = 11 )
{
Log ( " HorseInt = %d (0x%08x) " , HorseInt , HorseInt ) ;
}
COPY_TO_CLIENT ( ) ;
return true ;
}
bool cConnection : : ParseSlot ( cByteBuffer & a_Buffer , AString & a_ItemDesc )
{
short ItemType ;
if ( ! a_Buffer . ReadBEShort ( ItemType ) )
{
return false ;
}
if ( ItemType < = 0 )
{
a_ItemDesc = " <empty> " ;
return true ;
}
if ( ! a_Buffer . CanReadBytes ( 5 ) )
{
return false ;
}
char ItemCount ;
short ItemDamage ;
short MetadataLength ;
a_Buffer . ReadChar ( ItemCount ) ;
a_Buffer . ReadBEShort ( ItemDamage ) ;
a_Buffer . ReadBEShort ( MetadataLength ) ;
Printf ( a_ItemDesc , " %d:%d * %d " , ItemType , ItemDamage , ItemCount ) ;
if ( MetadataLength < = 0 )
{
return true ;
}
AString Metadata ;
Metadata . resize ( MetadataLength ) ;
if ( ! a_Buffer . ReadBuf ( ( void * ) Metadata . data ( ) , MetadataLength ) )
{
return false ;
}
AString MetaHex ;
CreateHexDump ( MetaHex , Metadata . data ( ) , Metadata . size ( ) , 16 ) ;
AppendPrintf ( a_ItemDesc , " ; %d bytes of meta: \n %s " , MetadataLength , MetaHex . c_str ( ) ) ;
// Save metadata to a file:
AString fnam ;
Printf ( fnam , " %s_item_%08x.nbt " , m_LogNameBase . c_str ( ) , m_ItemIdx + + ) ;
FILE * f = fopen ( fnam . c_str ( ) , " wb " ) ;
if ( f ! = NULL )
{
fwrite ( Metadata . data ( ) , 1 , Metadata . size ( ) , f ) ;
fclose ( f ) ;
AppendPrintf ( a_ItemDesc , " \n (saved to file \" %s \" ) " , fnam . c_str ( ) ) ;
}
return true ;
}
bool cConnection : : ParseMetadata ( cByteBuffer & a_Buffer , AString & a_Metadata )
{
char x ;
if ( ! a_Buffer . ReadChar ( x ) )
{
return false ;
}
a_Metadata . push_back ( x ) ;
while ( x ! = 0x7f )
{
int Index = ( ( unsigned ) ( ( unsigned char ) x ) ) & 0x1f ; // Lower 5 bits = index
int Type = ( ( unsigned ) ( ( unsigned char ) x ) ) > > 5 ; // Upper 3 bits = type
int Length = 0 ;
switch ( Type )
{
case 0 : Length = 1 ; break ; // byte
case 1 : Length = 2 ; break ; // short
case 2 : Length = 4 ; break ; // int
case 3 : Length = 4 ; break ; // float
case 4 : // string16
{
short Len = 0 ;
if ( ! a_Buffer . ReadBEShort ( Len ) )
{
return false ;
}
short NetLen = htons ( Len ) ;
a_Metadata . append ( ( char * ) & NetLen , 2 ) ;
Length = Len ;
break ;
}
case 5 :
{
int Before = a_Buffer . GetReadableSpace ( ) ;
AString ItemDesc ;
if ( ! ParseSlot ( a_Buffer , ItemDesc ) )
{
return false ;
}
int After = a_Buffer . GetReadableSpace ( ) ;
a_Buffer . ResetRead ( ) ;
a_Buffer . SkipRead ( a_Buffer . GetReadableSpace ( ) - Before ) ;
Length = Before - After ;
break ;
}
case 6 : Length = 12 ; break ; // 3 * int
default :
{
ASSERT ( ! " Unknown metadata type " ) ;
break ;
}
} // switch (Type)
AString data ;
if ( ! a_Buffer . ReadString ( data , Length ) )
{
return false ;
}
a_Metadata . append ( data ) ;
if ( ! a_Buffer . ReadChar ( x ) )
{
return false ;
}
a_Metadata . push_back ( x ) ;
} // while (x != 0x7f)
return true ;
}
void cConnection : : LogMetadata ( const AString & a_Metadata , size_t a_IndentCount )
{
AString Indent ( a_IndentCount , ' ' ) ;
int pos = 0 ;
while ( a_Metadata [ pos ] ! = 0x7f )
{
int Index = ( ( unsigned ) ( ( unsigned char ) a_Metadata [ pos ] ) ) & 0x1f ; // Lower 5 bits = index
int Type = ( ( unsigned ) ( ( unsigned char ) a_Metadata [ pos ] ) ) > > 5 ; // Upper 3 bits = type
int Length = 0 ;
switch ( Type )
{
case 0 :
{
Log ( " %sbyte[%d] = %d " , Indent . c_str ( ) , Index , a_Metadata [ pos + 1 ] ) ;
pos + = 1 ;
break ;
}
case 1 :
{
Log ( " %sshort[%d] = %d " , Indent . c_str ( ) , Index , ( a_Metadata [ pos + 1 ] < < 8 ) | a_Metadata [ pos + 2 ] ) ;
pos + = 2 ;
break ;
}
case 2 :
{
Log ( " %sint[%d] = %d " , Indent . c_str ( ) , Index , ( a_Metadata [ pos + 1 ] < < 24 ) | ( a_Metadata [ pos + 2 ] < < 16 ) | ( a_Metadata [ pos + 3 ] < < 8 ) | a_Metadata [ pos + 4 ] ) ;
pos + = 4 ;
break ;
}
case 3 :
{
Log ( " %sfloat[%d] = 0x%x " , Indent . c_str ( ) , Index , ( a_Metadata [ pos + 1 ] < < 24 ) | ( a_Metadata [ pos + 2 ] < < 16 ) | ( a_Metadata [ pos + 3 ] < < 8 ) | a_Metadata [ pos + 4 ] ) ;
pos + = 4 ;
break ;
}
case 4 : // string16
{
short Length = ( a_Metadata [ pos + 1 ] < < 8 ) | a_Metadata [ pos + 2 ] ;
Log ( " %sstring[%d] = \" %*s \" " , Indent . c_str ( ) , Index , Length , a_Metadata . c_str ( ) + pos + 3 ) ;
pos + = Length + 2 ;
break ;
}
case 5 :
{
int BytesLeft = a_Metadata . size ( ) - pos - 1 ;
cByteBuffer bb ( BytesLeft ) ;
bb . Write ( a_Metadata . data ( ) + pos + 1 , BytesLeft ) ;
AString ItemDesc ;
if ( ! ParseSlot ( bb , ItemDesc ) )
{
ASSERT ( ! " Cannot parse item description from metadata " ) ;
return ;
}
int After = bb . GetReadableSpace ( ) ;
int BytesConsumed = BytesLeft - bb . GetReadableSpace ( ) ;
Log ( " %sslot[%d] = %s (%d bytes) " , Indent . c_str ( ) , Index , ItemDesc . c_str ( ) , BytesConsumed ) ;
pos + = BytesConsumed ;
break ;
}
case 6 :
{
Log ( " %spos[%d] = <%d, %d, %d> " , Indent . c_str ( ) , Index ,
( a_Metadata [ pos + 1 ] < < 24 ) | ( a_Metadata [ pos + 2 ] < < 16 ) | ( a_Metadata [ pos + 3 ] < < 8 ) | a_Metadata [ pos + 4 ] ,
( a_Metadata [ pos + 5 ] < < 24 ) | ( a_Metadata [ pos + 6 ] < < 16 ) | ( a_Metadata [ pos + 7 ] < < 8 ) | a_Metadata [ pos + 8 ] ,
( a_Metadata [ pos + 9 ] < < 24 ) | ( a_Metadata [ pos + 10 ] < < 16 ) | ( a_Metadata [ pos + 11 ] < < 8 ) | a_Metadata [ pos + 12 ]
) ;
pos + = 12 ;
break ;
}
default :
{
ASSERT ( ! " Unknown metadata type " ) ;
break ;
}
} // switch (Type)
pos + = 1 ;
} // while (x != 0x7f)
}
void cConnection : : SendEncryptionKeyResponse ( const AString & a_ServerPublicKey , const AString & a_Nonce )
{
// Generate the shared secret and encrypt using the server's public key
byte SharedSecret [ 16 ] ;
byte EncryptedSecret [ 128 ] ;
memset ( SharedSecret , 0 , sizeof ( SharedSecret ) ) ; // Use all zeroes for the initial secret
RSA : : PublicKey pk ;
CryptoPP : : StringSource src ( a_ServerPublicKey , true ) ;
ByteQueue bq ;
src . TransferTo ( bq ) ;
bq . MessageEnd ( ) ;
pk . Load ( bq ) ;
RSAES < PKCS1v15 > : : Encryptor rsaEncryptor ( pk ) ;
RandomPool rng ;
time_t CurTime = time ( NULL ) ;
rng . Put ( ( const byte * ) & CurTime , sizeof ( CurTime ) ) ;
int EncryptedLength = rsaEncryptor . FixedCiphertextLength ( ) ;
ASSERT ( EncryptedLength < = sizeof ( EncryptedSecret ) ) ;
rsaEncryptor . Encrypt ( rng , SharedSecret , sizeof ( SharedSecret ) , EncryptedSecret ) ;
m_ServerEncryptor . SetKey ( SharedSecret , 16 , MakeParameters ( Name : : IV ( ) , ConstByteArrayParameter ( SharedSecret , 16 ) ) ( Name : : FeedbackSize ( ) , 1 ) ) ;
m_ServerDecryptor . SetKey ( SharedSecret , 16 , MakeParameters ( Name : : IV ( ) , ConstByteArrayParameter ( SharedSecret , 16 ) ) ( Name : : FeedbackSize ( ) , 1 ) ) ;
// Encrypt the nonce:
byte EncryptedNonce [ 128 ] ;
rsaEncryptor . Encrypt ( rng , ( const byte * ) ( a_Nonce . data ( ) ) , a_Nonce . size ( ) , EncryptedNonce ) ;
// Send the packet to the server:
Log ( " Sending PACKET_ENCRYPTION_KEY_RESPONSE to the SERVER " ) ;
cByteBuffer ToServer ( 1024 ) ;
ToServer . WriteByte ( PACKET_ENCRYPTION_KEY_RESPONSE ) ;
ToServer . WriteBEShort ( EncryptedLength ) ;
ToServer . WriteBuf ( EncryptedSecret , EncryptedLength ) ;
ToServer . WriteBEShort ( EncryptedLength ) ;
ToServer . WriteBuf ( EncryptedNonce , EncryptedLength ) ;
SERVERSEND ( ToServer ) ;
m_ServerState = csWaitingForEncryption ;
}
void cConnection : : StartClientEncryption ( const AString & a_EncKey , const AString & a_EncNonce )
{
// Decrypt EncNonce using privkey
RSAES < PKCS1v15 > : : Decryptor rsaDecryptor ( m_Server . GetPrivateKey ( ) ) ;
time_t CurTime = time ( NULL ) ;
RandomPool rng ;
rng . Put ( ( const byte * ) & CurTime , sizeof ( CurTime ) ) ;
byte DecryptedNonce [ MAX_ENC_LEN ] ;
DecodingResult res = rsaDecryptor . Decrypt ( rng , ( const byte * ) a_EncNonce . data ( ) , a_EncNonce . size ( ) , DecryptedNonce ) ;
if ( ! res . isValidCoding | | ( res . messageLength ! = 4 ) )
{
Log ( " Client: Bad nonce length " ) ;
return ;
}
if ( ntohl ( * ( ( int * ) DecryptedNonce ) ) ! = m_Nonce )
{
Log ( " Bad nonce value " ) ;
return ;
}
// Decrypt the symmetric encryption key using privkey:
byte SharedSecret [ MAX_ENC_LEN ] ;
res = rsaDecryptor . Decrypt ( rng , ( const byte * ) a_EncKey . data ( ) , a_EncKey . size ( ) , SharedSecret ) ;
if ( ! res . isValidCoding | | ( res . messageLength ! = 16 ) )
{
Log ( " Bad key length " ) ;
return ;
}
// Send encryption key response:
cByteBuffer ToClient ( 6 ) ;
ToClient . WriteByte ( ( char ) 0xfc ) ;
ToClient . WriteBEShort ( 0 ) ;
ToClient . WriteBEShort ( 0 ) ;
CLIENTSEND ( ToClient ) ;
// Start the encryption:
m_ClientEncryptor . SetKey ( SharedSecret , 16 , MakeParameters ( Name : : IV ( ) , ConstByteArrayParameter ( SharedSecret , 16 ) ) ( Name : : FeedbackSize ( ) , 1 ) ) ;
m_ClientDecryptor . SetKey ( SharedSecret , 16 , MakeParameters ( Name : : IV ( ) , ConstByteArrayParameter ( SharedSecret , 16 ) ) ( Name : : FeedbackSize ( ) , 1 ) ) ;
Log ( " Client connection is now encrypted " ) ;
m_ClientState = csEncryptedUnderstood ;
// Send the queued data:
DataLog ( m_ClientEncryptionBuffer . data ( ) , m_ClientEncryptionBuffer . size ( ) , " Sending the queued data to client (%u bytes): " , m_ClientEncryptionBuffer . size ( ) ) ;
CLIENTENCRYPTSEND ( m_ClientEncryptionBuffer . data ( ) , m_ClientEncryptionBuffer . size ( ) ) ;
m_ClientEncryptionBuffer . clear ( ) ;
// Handle all postponed server data
DecodeServersPackets ( NULL , 0 ) ;
}