summaryrefslogtreecommitdiffstats
path: root/Tools/ProtoProxy/Connection.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/ProtoProxy/Connection.cpp')
-rw-r--r--Tools/ProtoProxy/Connection.cpp5102
1 files changed, 2551 insertions, 2551 deletions
diff --git a/Tools/ProtoProxy/Connection.cpp b/Tools/ProtoProxy/Connection.cpp
index 32dfe321e..7c808f2c1 100644
--- a/Tools/ProtoProxy/Connection.cpp
+++ b/Tools/ProtoProxy/Connection.cpp
@@ -1,2551 +1,2551 @@
-
-// 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>
-
-
-
-
-
-#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,
- 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,
-} ;
-
-
-
-
-enum
-{
- OBJECT_BOAT = 1,
- OBJECT_MINECART = 10,
- OBJECT_MINECART_STORAGE = 11,
- OBJECT_MINECART_POWERED = 12,
- 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,
-} ;
-
-
-
-
-
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-// 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),
- m_BeginTick(clock()),
- m_ClientState(csUnencrypted),
- m_ServerState(csUnencrypted),
- m_Nonce(0),
- m_ClientBuffer(1024 KiB),
- m_ServerBuffer(1024 KiB),
- m_HasClientPinged(false)
-{
- Printf(m_LogNameBase, "Log_%d", (int)time(NULL));
- 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)
-{
- return (double)(clock() - m_BeginTick) / CLOCKS_PER_SEC;
-
-}
-
-
-
-
-
-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))
- {
- Log("Decoding client's packets, there are now %d bytes in the queue", m_ClientBuffer.GetReadableSpace());
- unsigned char PacketType;
- m_ClientBuffer.ReadByte(PacketType);
- 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;
- 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;
- 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);
- Log("Decoding server's packets, there are now %d bytes in the queue; next packet is 0x%x", m_ServerBuffer.GetReadableSpace(), PacketType);
- 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;
- 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;
-}
-
-
-
-
-
-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;
-}
-
-
-
-
-
-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);
- Log(" RelMove = <%d, %d, %d>", dx, dy, dz);
- 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);
- Log(" RelMove = <%d, %d, %d>", dx, dy, dz);
- 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);
- HANDLE_SERVER_PACKET_READ(ReadBEInt, int, BlockX);
- HANDLE_SERVER_PACKET_READ(ReadBEInt, int, BlockY);
- HANDLE_SERVER_PACKET_READ(ReadBEInt, int, BlockZ);
- 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);
- Log(" Pos = {%d, %d, %d}", BlockX, BlockY, BlockZ);
- 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);
- Log(" Velocity = <%d, %d, %d>", VelocityX, VelocityY, VelocityZ);
- 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;
- for (size_t i = 0; i < Reason.size(); i++)
- {
- if (Reason[i] == 0)
- {
- Split.push_back(Reason.substr(Last, i - Last));
- Last = i + 1;
- }
- }
-
- if (Split.size() == 5)
- {
- Log(" Protocol version: \"%s\"", Split[0].c_str());
- Log(" Server version: \"%s\"", Split[1].c_str());
- Log(" MOTD: \"%s\"", Split[2].c_str());
- Log(" Cur players: \"%s\"", Split[3].c_str());
- Log(" Max players: \"%s\"", Split[4].c_str());
- }
- 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;
- }
- AString Meta;
- if (!m_ServerBuffer.ReadString(Meta, ChunkCount * 12))
- {
- return false;
- }
- 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");
-
- // 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);
- Log(" Pos = <%d, %d, %d> ~ {%d, %d, %d}", PosX, PosY, PosZ, PosX / 32, PosY / 32, PosZ / 32);
- Log(" Angles = [%d, %d, %d]", Yaw, Pitch, HeadYaw);
- Log(" Velocity = <%d, %d, %d>", VelocityX, VelocityY, VelocityZ);
- 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());
- Log(" Pos = <%d, %d, %d> ~ {%d, %d, %d}", PosX, PosY, PosZ, PosX / 32, PosY / 32, PosZ / 32);
- 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);
- Log(" Pos = <%d, %d, %d> ~ {%d, %d, %d}", PosX, PosY, PosZ, PosX / 32, PosY / 32, PosZ / 32);
- Log(" Rotation = <yaw %d, pitch %d>", Yaw, Pitch);
- Log(" DataIndicator = %d (0x%x)", DataIndicator, DataIndicator);
- if (DataIndicator != 0)
- {
- Log(" Velocity = <%d, %d, %d>", VelocityX, VelocityY, VelocityZ);
- 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());
- Log(" Pos = <%d, %d, %d> ~ {%d, %d, %d}", PosX, PosY, PosZ, PosX / 32, PosY / 32, PosZ / 32);
- 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());
- Log(" Pos = <%d, %d, %d> ~ {%d, %d, %d}", PosX, PosY, PosZ, PosX / 32, PosY / 32, PosZ / 32);
- Log(" Angles = [%d, %d, %d]", Rotation, Pitch, Roll);
- COPY_TO_CLIENT();
- return true;
-}
-
-
-
-
-
-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);
-}
-
-
-
-
+
+// 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>
+
+
+
+
+
+#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,
+ 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,
+} ;
+
+
+
+
+enum
+{
+ OBJECT_BOAT = 1,
+ OBJECT_MINECART = 10,
+ OBJECT_MINECART_STORAGE = 11,
+ OBJECT_MINECART_POWERED = 12,
+ 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,
+} ;
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 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),
+ m_BeginTick(clock()),
+ m_ClientState(csUnencrypted),
+ m_ServerState(csUnencrypted),
+ m_Nonce(0),
+ m_ClientBuffer(1024 KiB),
+ m_ServerBuffer(1024 KiB),
+ m_HasClientPinged(false)
+{
+ Printf(m_LogNameBase, "Log_%d", (int)time(NULL));
+ 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)
+{
+ return (double)(clock() - m_BeginTick) / CLOCKS_PER_SEC;
+
+}
+
+
+
+
+
+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))
+ {
+ Log("Decoding client's packets, there are now %d bytes in the queue", m_ClientBuffer.GetReadableSpace());
+ unsigned char PacketType;
+ m_ClientBuffer.ReadByte(PacketType);
+ 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;
+ 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;
+ 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);
+ Log("Decoding server's packets, there are now %d bytes in the queue; next packet is 0x%x", m_ServerBuffer.GetReadableSpace(), PacketType);
+ 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;
+ 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;
+}
+
+
+
+
+
+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;
+}
+
+
+
+
+
+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);
+ Log(" RelMove = <%d, %d, %d>", dx, dy, dz);
+ 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);
+ Log(" RelMove = <%d, %d, %d>", dx, dy, dz);
+ 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);
+ HANDLE_SERVER_PACKET_READ(ReadBEInt, int, BlockX);
+ HANDLE_SERVER_PACKET_READ(ReadBEInt, int, BlockY);
+ HANDLE_SERVER_PACKET_READ(ReadBEInt, int, BlockZ);
+ 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);
+ Log(" Pos = {%d, %d, %d}", BlockX, BlockY, BlockZ);
+ 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);
+ Log(" Velocity = <%d, %d, %d>", VelocityX, VelocityY, VelocityZ);
+ 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;
+ for (size_t i = 0; i < Reason.size(); i++)
+ {
+ if (Reason[i] == 0)
+ {
+ Split.push_back(Reason.substr(Last, i - Last));
+ Last = i + 1;
+ }
+ }
+
+ if (Split.size() == 5)
+ {
+ Log(" Protocol version: \"%s\"", Split[0].c_str());
+ Log(" Server version: \"%s\"", Split[1].c_str());
+ Log(" MOTD: \"%s\"", Split[2].c_str());
+ Log(" Cur players: \"%s\"", Split[3].c_str());
+ Log(" Max players: \"%s\"", Split[4].c_str());
+ }
+ 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;
+ }
+ AString Meta;
+ if (!m_ServerBuffer.ReadString(Meta, ChunkCount * 12))
+ {
+ return false;
+ }
+ 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");
+
+ // 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);
+ Log(" Pos = <%d, %d, %d> ~ {%d, %d, %d}", PosX, PosY, PosZ, PosX / 32, PosY / 32, PosZ / 32);
+ Log(" Angles = [%d, %d, %d]", Yaw, Pitch, HeadYaw);
+ Log(" Velocity = <%d, %d, %d>", VelocityX, VelocityY, VelocityZ);
+ 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());
+ Log(" Pos = <%d, %d, %d> ~ {%d, %d, %d}", PosX, PosY, PosZ, PosX / 32, PosY / 32, PosZ / 32);
+ 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);
+ Log(" Pos = <%d, %d, %d> ~ {%d, %d, %d}", PosX, PosY, PosZ, PosX / 32, PosY / 32, PosZ / 32);
+ Log(" Rotation = <yaw %d, pitch %d>", Yaw, Pitch);
+ Log(" DataIndicator = %d (0x%x)", DataIndicator, DataIndicator);
+ if (DataIndicator != 0)
+ {
+ Log(" Velocity = <%d, %d, %d>", VelocityX, VelocityY, VelocityZ);
+ 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());
+ Log(" Pos = <%d, %d, %d> ~ {%d, %d, %d}", PosX, PosY, PosZ, PosX / 32, PosY / 32, PosZ / 32);
+ 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());
+ Log(" Pos = <%d, %d, %d> ~ {%d, %d, %d}", PosX, PosY, PosZ, PosX / 32, PosY / 32, PosZ / 32);
+ Log(" Angles = [%d, %d, %d]", Rotation, Pitch, Roll);
+ COPY_TO_CLIENT();
+ return true;
+}
+
+
+
+
+
+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);
+}
+
+
+
+