Commit is being made to allow additions of GPL3+ code previously un-addable. With these changes, contributions back to cuberite are possible with the backporting exemtion, as well as adding stuff in minetest with minetest code properly being read through and implimented to upgrade it to GPL3 from GPL2. project still has Apache2.0 license and credits to all its contributers, but now has the freedom of GPL3+ and all the code that can be implimented and shared with it.
278 lines
9.9 KiB
C++
278 lines
9.9 KiB
C++
|
|
/*
|
|
* Copyright 2011-2022 Cuberite Contributors
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
// Connection.h
|
|
|
|
// Interfaces to the cConnection class representing a single pair of connected sockets
|
|
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
#include "ByteBuffer.h"
|
|
#include "mbedTLS++/AesCfb128Decryptor.h"
|
|
#include "mbedTLS++/AesCfb128Encryptor.h"
|
|
|
|
#ifndef _WIN32
|
|
typedef int SOCKET;
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
class cServer;
|
|
|
|
|
|
|
|
|
|
|
|
class cConnection
|
|
{
|
|
/** Base for the log filename and all files connected to this log */
|
|
AString m_LogNameBase;
|
|
|
|
/** Index for the next file into which item metadata should be written (ParseSlot() function) */
|
|
int m_ItemIdx;
|
|
|
|
cCriticalSection m_CSLog;
|
|
FILE * m_LogFile;
|
|
|
|
cServer & m_Server;
|
|
SOCKET m_ClientSocket;
|
|
SOCKET m_ServerSocket;
|
|
|
|
std::chrono::steady_clock::time_point m_BeginTick; // Tick when the relative time was first retrieved (used for GetRelativeTime())
|
|
|
|
enum eConnectionState
|
|
{
|
|
csUnencrypted, // The connection is not encrypted. Packets must be decoded in order to be able to start decryption.
|
|
csEncryptedUnderstood, // The communication is encrypted and so far all packets have been understood, so they can be still decoded
|
|
csEncryptedUnknown, // The communication is encrypted, but an unknown packet has been received, so packets cannot be decoded anymore
|
|
csWaitingForEncryption, // The communication is waiting for the other line to establish encryption
|
|
};
|
|
|
|
eConnectionState m_ClientState;
|
|
eConnectionState m_ServerState;
|
|
|
|
int m_Nonce;
|
|
|
|
public:
|
|
cConnection(SOCKET a_ClientSocket, cServer & a_Server);
|
|
~cConnection();
|
|
|
|
void Run(void);
|
|
|
|
void vLog(const char * a_Format, fmt::printf_args a_ArgList);
|
|
|
|
template <typename... Args>
|
|
void Log(const char * a_Format, const Args & ... a_Args)
|
|
{
|
|
vLog(a_Format, fmt::make_printf_args(a_Args...));
|
|
}
|
|
|
|
void vDataLog(const void * a_Data, size_t a_Size, const char * a_Format, fmt::printf_args a_ArgList);
|
|
|
|
template <typename... Args>
|
|
void DataLog(const void * a_Data, size_t a_Size, const char * a_Format, const Args & ... a_Args)
|
|
{
|
|
vDataLog(a_Data, a_Size, a_Format, fmt::make_printf_args(a_Args...));
|
|
}
|
|
|
|
void LogFlush(void);
|
|
|
|
protected:
|
|
|
|
cByteBuffer m_ClientBuffer;
|
|
cByteBuffer m_ServerBuffer;
|
|
|
|
cAesCfb128Decryptor m_ServerDecryptor;
|
|
cAesCfb128Encryptor m_ServerEncryptor;
|
|
|
|
ContiguousByteBuffer m_ServerEncryptionBuffer; // Buffer for the data to be sent to the server once encryption is established
|
|
|
|
/** Set to true when PACKET_PING is received from the client; will cause special parsing for server kick */
|
|
bool m_HasClientPinged;
|
|
|
|
/*
|
|
The protocol states can be one of:
|
|
-1: no initial handshake received yet
|
|
1: status
|
|
2: login
|
|
3: game
|
|
*/
|
|
/** State the to-server protocol is in (as defined by the initial handshake / login), -1 if no initial handshake received yet */
|
|
int m_ServerProtocolState;
|
|
|
|
/** State the to-client protocol is in (as defined by the initial handshake / login), -1 if no initial handshake received yet */
|
|
int m_ClientProtocolState;
|
|
|
|
/** True if the server connection has provided encryption keys */
|
|
bool m_IsServerEncrypted;
|
|
|
|
|
|
bool ConnectToServer(void);
|
|
|
|
/** Relays data from server to client; returns false if connection aborted */
|
|
bool RelayFromServer(void);
|
|
|
|
/** Relays data from client to server; returns false if connection aborted */
|
|
bool RelayFromClient(void);
|
|
|
|
/** Returns the time relative to the first call of this function, in the fractional seconds elapsed */
|
|
double GetRelativeTime(void);
|
|
|
|
/** Sends data to the specified socket. If sending fails, prints a fail message using a_Peer and returns false. */
|
|
bool SendData(SOCKET a_Socket, ContiguousByteBufferView a_Data, const char * a_Peer);
|
|
|
|
/** Sends data to the specified socket. If sending fails, prints a fail message using a_Peer and returns false. */
|
|
bool SendData(SOCKET a_Socket, cByteBuffer & a_Data, const char * a_Peer);
|
|
|
|
/** Sends data to the specfied socket, after encrypting it using a_Encryptor. If sending fails, prints a fail message using a_Peer and returns false */
|
|
bool SendEncryptedData(SOCKET a_Socket, cAesCfb128Encryptor & a_Encryptor, ContiguousByteBuffer & a_Data, const char * a_Peer);
|
|
|
|
/** Sends data to the specfied socket, after encrypting it using a_Encryptor. If sending fails, prints a fail message using a_Peer and returns false */
|
|
bool SendEncryptedData(SOCKET a_Socket, cAesCfb128Encryptor & a_Encryptor, cByteBuffer & a_Data, const char * a_Peer);
|
|
|
|
/** Decodes packets coming from the client, sends appropriate counterparts to the server; returns false if the connection is to be dropped */
|
|
bool DecodeClientsPackets(const char * a_Data, int a_Size);
|
|
|
|
/** Decodes packets coming from the server, sends appropriate counterparts to the client; returns false if the connection is to be dropped */
|
|
bool DecodeServersPackets(const char * a_Data, int a_Size);
|
|
|
|
// Packet handling, client-side, initial:
|
|
bool HandleClientHandshake(void);
|
|
|
|
// Packet handling, client-side, status:
|
|
bool HandleClientStatusPing(void);
|
|
bool HandleClientStatusRequest(void);
|
|
|
|
// Packet handling, client-side, login:
|
|
bool HandleClientLoginEncryptionKeyResponse(void);
|
|
bool HandleClientLoginStart(void);
|
|
|
|
// Packet handling, client-side, game:
|
|
bool HandleClientAnimation(void);
|
|
bool HandleClientBlockDig(void);
|
|
bool HandleClientBlockPlace(void);
|
|
bool HandleClientChatMessage(void);
|
|
bool HandleClientClientStatuses(void);
|
|
bool HandleClientCreativeInventoryAction(void);
|
|
bool HandleClientDisconnect(void);
|
|
bool HandleClientEntityAction(void);
|
|
bool HandleClientKeepAlive(void);
|
|
bool HandleClientLocaleAndView(void);
|
|
bool HandleClientPing(void);
|
|
bool HandleClientPlayerAbilities(void);
|
|
bool HandleClientPlayerLook(void);
|
|
bool HandleClientPlayerOnGround(void);
|
|
bool HandleClientPlayerPosition(void);
|
|
bool HandleClientPlayerPositionLook(void);
|
|
bool HandleClientPluginMessage(void);
|
|
bool HandleClientSlotSelect(void);
|
|
bool HandleClientTabCompletion(void);
|
|
bool HandleClientUpdateSign(void);
|
|
bool HandleClientUseEntity(void);
|
|
bool HandleClientWindowClick(void);
|
|
bool HandleClientWindowClose(void);
|
|
|
|
bool HandleClientUnknownPacket(UInt32 a_PacketType, UInt32 a_PacketLen, UInt32 a_PacketReadSoFar);
|
|
|
|
// Packet handling, server-side, login:
|
|
bool HandleServerLoginDisconnect(void);
|
|
bool HandleServerLoginEncryptionKeyRequest(void);
|
|
bool HandleServerLoginSuccess(void);
|
|
|
|
// Packet handling, server-side, game:
|
|
bool HandleServerAttachEntity(void);
|
|
bool HandleServerBlockAction(void);
|
|
bool HandleServerBlockChange(void);
|
|
bool HandleServerChangeGameState(void);
|
|
bool HandleServerChatMessage(void);
|
|
bool HandleServerCollectPickup(void);
|
|
bool HandleServerCompass(void);
|
|
bool HandleServerDestroyEntities(void);
|
|
bool HandleServerEntity(void);
|
|
bool HandleServerEntityEquipment(void);
|
|
bool HandleServerEntityHeadLook(void);
|
|
bool HandleServerEntityLook(void);
|
|
bool HandleServerEntityMetadata(void);
|
|
bool HandleServerEntityProperties(void);
|
|
bool HandleServerEntityRelativeMove(void);
|
|
bool HandleServerEntityRelativeMoveLook(void);
|
|
bool HandleServerEntityStatus(void);
|
|
bool HandleServerEntityTeleport(void);
|
|
bool HandleServerEntityVelocity(void);
|
|
bool HandleServerExplosion(void);
|
|
bool HandleServerIncrementStatistic(void);
|
|
bool HandleServerJoinGame(void);
|
|
bool HandleServerKeepAlive(void);
|
|
bool HandleServerKick(void);
|
|
bool HandleServerLogin(void);
|
|
bool HandleServerMapChunk(void);
|
|
bool HandleServerMapChunkBulk(void);
|
|
bool HandleServerMultiBlockChange(void);
|
|
bool HandleServerNamedSoundEffect(void);
|
|
bool HandleServerPlayerAbilities(void);
|
|
bool HandleServerPlayerAnimation(void);
|
|
bool HandleServerPlayerListItem(void);
|
|
bool HandleServerPlayerPositionLook(void);
|
|
bool HandleServerPluginMessage(void);
|
|
bool HandleServerRespawn(void);
|
|
bool HandleServerSetExperience(void);
|
|
bool HandleServerSetSlot(void);
|
|
bool HandleServerSlotSelect(void);
|
|
bool HandleServerSoundEffect(void);
|
|
bool HandleServerSpawnExperienceOrbs(void);
|
|
bool HandleServerSpawnMob(void);
|
|
bool HandleServerSpawnNamedEntity(void);
|
|
bool HandleServerSpawnObjectVehicle(void);
|
|
bool HandleServerSpawnPainting(void);
|
|
bool HandleServerSpawnPickup(void);
|
|
bool HandleServerStatistics(void);
|
|
bool HandleServerStatusPing(void);
|
|
bool HandleServerStatusResponse(void);
|
|
bool HandleServerTabCompletion(void);
|
|
bool HandleServerTimeUpdate(void);
|
|
bool HandleServerUpdateHealth(void);
|
|
bool HandleServerUpdateSign(void);
|
|
bool HandleServerUpdateTileEntity(void);
|
|
bool HandleServerUseBed(void);
|
|
bool HandleServerWindowClose(void);
|
|
bool HandleServerWindowContents(void);
|
|
bool HandleServerWindowOpen(void);
|
|
|
|
bool HandleServerUnknownPacket(UInt32 a_PacketType, UInt32 a_PacketLen, UInt32 a_PacketReadSoFar);
|
|
|
|
/** Parses the slot data in a_Buffer into item description; returns true if successful, false if not enough data */
|
|
bool ParseSlot(cByteBuffer & a_Buffer, AString & a_ItemDesc);
|
|
|
|
/** Parses the metadata in a_Buffer into raw metadata in an AString; returns true if successful, false if not enough data */
|
|
bool ParseMetadata(cByteBuffer & a_Buffer, AString & a_Metadata);
|
|
|
|
/** Logs the contents of the metadata in the AString, using Log(). Assumes a_Metadata is valid (parsed by ParseMetadata()). The log is indented by a_IndentCount spaces */
|
|
void LogMetadata(const AString & a_Metadata, size_t a_IndentCount);
|
|
|
|
/** Send EKResp to the server: */
|
|
void SendEncryptionKeyResponse(const AString & a_ServerPublicKey, const AString & a_Nonce);
|
|
|
|
/** Starts client encryption based on the parameters received */
|
|
void StartClientEncryption(const AString & a_EncryptedSecret, const AString & a_EncryptedNonce);
|
|
} ;
|