17 #include "../ClientHandle.h"
19 #include "../Server.h"
21 #include "../JsonUtils.h"
22 #include "../Bindings/PluginManager.h"
31 std::runtime_error(a_Message)
42 m_WaitingForData(true)
52 switch (a_ProtocolVersion)
75 ASSERT(!
"Unknown protocol version");
76 return fmt::format(FMT_STRING(
"Unknown protocol ({})"), a_ProtocolVersion);
165 if ((PacketID == 0x00) && (PacketLen == 1))
169 else if ((PacketID == 0x01) && (PacketLen == 9))
233 const auto PacketID =
GetPacketID(cProtocol::ePacketType::pktDisconnectDuringLogin);
252 if (RedirectUrl.empty())
262 const std::string_view Value(
reinterpret_cast<const char *
>(Buffer.data()), Buffer.size());
264 if (Value == u8
"GET / HTTP")
266 const auto Response = fmt::format(u8
"HTTP/1.0 303 See Other\r\nLocation: {}\r\n\r\n",
cRoot::Get()->GetServer()->GetCustomRedirectUrl());
267 a_Client.
SendData({
reinterpret_cast<const std::byte *
>(Response.data()), Response.size() });
290 LOGD(
"Client \"%s\" uses an unsupported protocol (lengthed, initial packet %u)",
309 const auto NextState = [NextStateValue]
311 switch (NextStateValue)
313 case 1:
return cProtocol::State::Status;
314 case 2:
return cProtocol::State::Login;
315 case 3:
return cProtocol::State::Game;
326 switch (ProtocolVersion)
350 LOGD(
"Client \"%s\" uses an unsupported protocol (lengthed, version %u (0x%x))",
351 a_Client.
GetIPString(), ProtocolVersion, ProtocolVersion
354 if (NextState != cProtocol::State::Status)
357 fmt::format(FMT_STRING(
"Unsupported protocol version {}.\nTry connecting with Minecraft {}"),
381 OutPacketLenBuffer.
ReadAll(LengthData);
386 a_OutPacketBuffer.
ReadAll(PacketData);
397 switch (a_PacketType)
399 case cProtocol::ePacketType::pktDisconnectDuringLogin:
return 0x00;
400 case cProtocol::ePacketType::pktStatusResponse:
return 0x00;
401 case cProtocol::ePacketType::pktPingResponse:
return 0x01;
404 ASSERT(!
"GetPacketID() called for an unhandled packet");
418 auto NumPlayers =
static_cast<signed>(Server->
GetNumPlayers());
419 auto MaxPlayers =
static_cast<signed>(Server->
GetMaxPlayers());
430 Players[
"online"] = NumPlayers;
431 Players[
"max"] = MaxPlayers;
435 Json::Value Description;
436 Description[
"text"] = ServerDescription.c_str();
439 Json::Value ResponseValue;
440 ResponseValue[
"version"] = Version;
441 ResponseValue[
"players"] = Players;
442 ResponseValue[
"description"] = Description;
443 if (!Favicon.empty())
445 ResponseValue[
"favicon"] =
"data:image/png;base64," + Favicon;
std::basic_string_view< std::byte > ContiguousByteBufferView
#define KiB
Allows arithmetic expressions like "32 KiB" (but consider using parenthesis around it,...
std::basic_string< std::byte > ContiguousByteBuffer
#define MCS_CLIENT_VERSIONS
#define MCS_LATEST_PROTOCOL_VERSION
AString SerializeSingleValueJsonObject(const AString &a_Key, const AString &a_Value)
Creates a Json string representing an object with the specified single value.
AString WriteFastString(const Json::Value &a_Root)
bool CallHookServerPing(cClientHandle &a_ClientHandle, AString &a_ServerDescription, int &a_OnlinePlayersCount, int &a_MaxPlayersCount, AString &a_Favicon)
An object that can store incoming bytes and lets its clients read the bytes sequentially The bytes ar...
bool ReadBEUInt16(UInt16 &a_Value)
size_t GetUsedSpace(void) const
Returns the number of bytes that are currently in the ringbuffer.
bool CanReadBytes(size_t a_Count) const
Returns true if the specified amount of bytes are available for reading.
void CommitRead(void)
Removes the bytes that have been read from the ringbuffer.
void ReadAll(ContiguousByteBuffer &a_Data)
Reads all available data into a_Data.
bool ReadBEInt64(Int64 &a_Value)
bool WriteBEInt64(Int64 a_Value)
bool ReadVarInt32(UInt32 &a_Value)
bool ReadVarInt(T &a_Value)
Reads VarInt, assigns it to anything that can be assigned from an UInt64 (unsigned short,...
bool WriteVarUTF8String(const AString &a_Value)
bool WriteVarInt32(UInt32 a_Value)
static size_t GetVarIntSize(UInt32 a_Value)
Gets the number of bytes that are needed to represent the given VarInt.
bool ReadVarUTF8String(AString &a_Value)
bool ReadSome(ContiguousByteBuffer &a_String, size_t a_Count)
Reads a_Count bytes into a_String; returns true if successful.
void ResetRead(void)
Restarts next reading operation at the start of the ringbuffer.
bool Write(const void *a_Bytes, size_t a_Count)
Writes the bytes specified to the ringbuffer.
void SetProtocolVersion(UInt32 a_ProtocolVersion)
Called by the protocol recognizer when the protocol version is known.
void PacketUnknown(UInt32 a_PacketType)
const AString & GetIPString(void) const
void PacketBufferFull(void)
void SendData(ContiguousByteBufferView a_Data)
ePacketType
Logical types of outgoing packets.
Version
The protocol version number, received from the client in the Handshake packet.
TriedToJoinWithUnsupportedProtocolException(const std::string &a_Message)
bool TryHandleHTTPRequest(cClientHandle &a_Client, ContiguousByteBuffer &a_Data)
cByteBuffer m_Buffer
Buffer for received protocol data.
void HandlePacketStatusPing(cClientHandle &a_Client)
void HandleOutgoingData(ContiguousByteBuffer &a_Data)
Allows the protocol (if any) to do a final pass on outgiong data, possibly modifying the provided buf...
void HandleIncomingData(cClientHandle &a_Client, ContiguousByteBuffer &a_Data)
Directs incoming protocol data along the correct pathway, depending on the state of the version recog...
bool m_WaitingForData
If we're still waiting for data required for version recognition to arrive.
void HandleIncomingDataInOldPingResponseStage(cClientHandle &a_Client, ContiguousByteBufferView a_Data)
Handles and responds to unsupported clients sending pings.
static UInt32 GetPacketID(cProtocol::ePacketType a_PacketType)
Returns the protocol-specific packet ID given the protocol-agnostic packet enum.
static void SendPacket(cClientHandle &a_Client, cByteBuffer &a_OutPacketBuffer)
Sends one packet inside a cByteBuffer.
void SendDisconnect(cClientHandle &a_Client, const AString &a_Reason)
Sends a disconnect to the client as a result of a recognition error.
void HandlePacketStatusRequest(cClientHandle &a_Client)
static AString GetVersionTextFromInt(cProtocol::Version a_ProtocolVersion)
Translates protocol version number into protocol version text: 49 -> "1.4.4".
std::unique_ptr< cProtocol > m_Protocol
The actual protocol implementation.
std::unique_ptr< cProtocol > TryRecognizeLengthedProtocol(cClientHandle &a_Client)
Tries to recognize a protocol in the lengthed family (1.7+), based on m_Buffer.
void HandleIncomingDataInRecognitionStage(cClientHandle &a_Client, ContiguousByteBuffer &a_Data)
Handles data reception in a newly-created client handle that doesn't yet have a known protocol.
cServer * GetServer(void)
cPluginManager * GetPluginManager(void)
size_t GetMaxPlayers(void) const
const AString & GetDescription(void) const
std::string_view GetCustomRedirectUrl(void)
size_t GetNumPlayers(void) const
const AString & GetFaviconData(void) const
Returns base64 encoded favicon data (obtained from favicon.png)