summaryrefslogblamecommitdiffstats
path: root/src/Protocol/ProtocolRecognizer.h
blob: 9aa31572e977a794bcd9b9a44e40e401531a866a (plain) (tree)
1
2
3
4
5
6
7
8
9


                     





                                                                    
                                          

                                                                                    




 

                                                                                  
                           
 
       
 

            





                                           
                                           
                                           
                                           
                                           
                                           
                                          
          
 
                                
 
                                                                                           
                                                                    
 




                                                                                                        
 











                                                                                                 
 





















                                                                                                                     
 
                                                                                               



                                                                                      
 

                                                                                   
 


                                                                                             
 

                                                 
 
   
#pragma once

#include "Protocol.h"





// Adjust these if a new protocol is added or an old one is removed:
#define MCS_CLIENT_VERSIONS "1.8.x-1.12.x"
#define MCS_PROTOCOL_VERSIONS "47, 107, 108, 109, 110, 210, 315, 316, 335, 338, 340"
#define MCS_LATEST_PROTOCOL_VERSION 340





/** Meta-protocol that recognizes multiple protocol versions, creates the specific
protocol version instance and redirects everything to it. */
class cMultiVersionProtocol
{
public:

	enum
	{
		PROTO_VERSION_1_8_0  = 47,
		PROTO_VERSION_1_9_0  = 107,
		PROTO_VERSION_1_9_1  = 108,
		PROTO_VERSION_1_9_2  = 109,
		PROTO_VERSION_1_9_4  = 110,
		PROTO_VERSION_1_10_0 = 210,
		PROTO_VERSION_1_11_0 = 315,
		PROTO_VERSION_1_11_1 = 316,
		PROTO_VERSION_1_12   = 335,
		PROTO_VERSION_1_12_1 = 338,
		PROTO_VERSION_1_12_2 = 340,
		PROTO_VERSION_1_13   = 393
	};

	cMultiVersionProtocol();

	/** Translates protocol version number into protocol version text: 49 -> "1.4.4" */
	static AString GetVersionTextFromInt(int a_ProtocolVersion);

	/** Returns if we contain a concrete protocol corresponding to the client's protocol version. */
	bool VersionRecognitionSuccessful()
	{
		return m_Protocol != nullptr;
	}

	/** Convenience overload to enable redirecting sends to the underlying implementation. */
	auto & operator->()
	{
		return m_Protocol;
	}

	/** The function that's responsible for processing incoming protocol data. */
	std::function<void(cClientHandle &, std::string_view)> HandleIncomingData;

	/** Sends a disconnect to the client as a result of a recognition error.
	This function can be used to disconnect before any protocol has been recognised. */
	void SendDisconnect(cClientHandle & a_Client, const AString & a_Reason);

private:

	/** Handles data reception in a newly-created client handle that doesn't yet have known protocol.
	a_Data contains a view of data that were just received.
	Calls TryRecognizeProtocol to populate m_Protocol, and transitions to another mode depending on success. */
	void HandleIncomingDataInRecognitionStage(cClientHandle & a_Client, std::string_view a_Data);

	/** Handles and responds to unsupported clients sending pings. */
	void HandleIncomingDataInOldPingResponseStage(cClientHandle & a_Client, const std::string_view a_Data);

	/* Tries to recognize a protocol based on a_Data and m_Buffer contents.
	a_Data is replaced with a sub-view, with handshake packet removed. */
	void TryRecognizeProtocol(cClientHandle & a_Client, std::string_view & a_Data);

	/** Tries to recognize a protocol in the lengthed family (1.7+), based on m_Buffer.
	The packet length and type have already been read, type is 0.
	Returns a cProtocol_XXX instance if recognized. */
	std::unique_ptr<cProtocol> TryRecognizeLengthedProtocol(cClientHandle & a_Client, std::string_view & a_Data);

	/** Sends one packet inside a cByteBuffer.
	This is used only when handling an outdated server ping. */
	static void SendPacket(cClientHandle & a_Client, cByteBuffer & a_OutPacketBuffer);

	/** Returns the protocol-specific packet ID given the protocol-agnostic packet enum. */
	static UInt32 GetPacketID(cProtocol::ePacketType a_PacketType);

	/* Status handler for unrecognised versions. */
	void HandlePacketStatusRequest(cClientHandle & a_Client, cByteBuffer & a_Out);

	/* Ping handler for unrecognised versions. */
	void HandlePacketStatusPing(cClientHandle & a_Client, cByteBuffer & a_Out);

	/** The actual protocol implementation.
	Created when recognition of the client version succeeds with a version we support. */
	std::unique_ptr<cProtocol> m_Protocol;

	/** Buffer for received protocol data. */
	cByteBuffer m_Buffer;

} ;