summaryrefslogtreecommitdiffstats
path: root/src/Protocol/LengthenedProtocol.cpp
blob: 8e16b7db2e5ad61154bcaddd9096707841bec4c4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include "Globals.h"
#include "LengthenedProtocol.h"
#include "ClientAction.h"

cProtocol::cProtocolError cLengthenedProtocol::DataReceived(const char * a_Data, size_t a_Size, std::vector<std::unique_ptr<cClientAction>> & a_Actions)
{
	a_Actions.clear();
	if (m_IsEncrypted)
	{
		ASSERT((a_Size % 16) == 0); // AES requirement.
		Byte Decrypted[512];
		while (a_Size > 0)
		{
			size_t NumBytes = (a_Size > sizeof(Decrypted)) ? sizeof(Decrypted) : a_Size;
			m_Decryptor.ProcessData(Decrypted, reinterpret_cast<const Byte *>(a_Data), NumBytes);
			auto success = AddReceivedData(reinterpret_cast<const char *>(Decrypted), NumBytes, a_Actions);
			if (success != cProtocolError::Success)
			{
				return success;
			}
			a_Size -= NumBytes;
			a_Data += NumBytes;
		}
		return cProtocolError::Success;
	}
	else
	{
		return AddReceivedData(a_Data, a_Size, a_Actions);
	}
}

cProtocol::cProtocolError cLengthenedProtocol::AddReceivedData(const char * a_Data, size_t a_Size, std::vector<std::unique_ptr<cClientAction>> & a_Actions)
{
	// Write the incoming data into the comm log file:
	if (g_ShouldLogCommIn)
	{
		if (m_ReceivedData.GetReadableSpace() > 0)
		{
			AString AllData;
			size_t OldReadableSpace = m_ReceivedData.GetReadableSpace();
			m_ReceivedData.ReadAll(AllData);
			m_ReceivedData.ResetRead();
			m_ReceivedData.SkipRead(m_ReceivedData.GetReadableSpace() - OldReadableSpace);
			ASSERT(m_ReceivedData.GetReadableSpace() == OldReadableSpace);
			AString Hex;
			CreateHexDump(Hex, AllData.data(), AllData.size(), 16);
			m_CommLogFile.Printf("Incoming data, " SIZE_T_FMT " (0x" SIZE_T_FMT_HEX ") unparsed bytes already present in buffer:\n%s\n",
				AllData.size(), AllData.size(), Hex.c_str()
			);
		}
		AString Hex;
		CreateHexDump(Hex, a_Data, a_Size, 16);
		m_CommLogFile.Printf("Incoming data: %u (0x%x) bytes: \n%s\n",
			static_cast<unsigned>(a_Size), static_cast<unsigned>(a_Size), Hex.c_str()
		);
		m_CommLogFile.Flush();
	}

	if (!m_ReceivedData.Write(a_Data, a_Size))
	{
		return cProtocolError::BufferFull;
	}

	auto status = OnDataAddedToBuffer(m_ReceivedData, a_Actions);
	if (status != cProtocolError::Success)
	{
		return status;
	}

	
	// Log any leftover bytes into the logfile:
	if (g_ShouldLogCommIn && (m_ReceivedData.GetReadableSpace() > 0))
	{
		AString AllData;
		size_t OldReadableSpace = m_ReceivedData.GetReadableSpace();
		m_ReceivedData.ReadAll(AllData);
		m_ReceivedData.ResetRead();
		m_ReceivedData.SkipRead(m_ReceivedData.GetReadableSpace() - OldReadableSpace);
		ASSERT(m_ReceivedData.GetReadableSpace() == OldReadableSpace);
		AString Hex;
		CreateHexDump(Hex, AllData.data(), AllData.size(), 16);
		m_CommLogFile.Printf("There are " SIZE_T_FMT " (0x" SIZE_T_FMT_HEX ") bytes of non-parse-able data left in the buffer:\n%s",
			m_ReceivedData.GetReadableSpace(), m_ReceivedData.GetReadableSpace(), Hex.c_str()
		);
		m_CommLogFile.Flush();
	}
	return cProtocolError::Success;
}

#define ADD_SIMPLE_ACTION(Name) a_Action.push_back(cpp14::make_unique<cSimpleAction>(cClientAction::Type::Name));

cProtocol::cProtocolError cLengthenedProtocol::HandleHandshake(cByteBuffer & a_ByteBuffer, std::vector<std::unique_ptr<cClientAction>> & a_Action)
{
	// these need to replace the values provided to the constructor in the old version
        if (!a_ByteBuffer.ReadVarUTF8String(m_ServerAddress))
        {
        	return cProtocolError::PacketReadError;
        }
        if (!a_ByteBuffer.ReadBEUInt16(m_ServerPort))
        {
        	return cProtocolError::PacketReadError;
        }
        if (!a_ByteBuffer.ReadVarInt(m_State))
        {
        	return cProtocolError::PacketReadError;
        } 
        a_ByteBuffer.CommitRead();

	// BungeeCord handling:
	// If BC is setup with ip_forward == true, it sends additional data in the login packet's ServerAddress field:
	// hostname\00ip-address\00uuid\00profile-properties-as-json
	AStringVector Params;
	if (m_ShouldAllowBungeeCord && SplitZeroTerminatedStrings(m_ServerAddress, Params) && (Params.size() == 4))
	{
		LOGD("Player at %s connected via BungeeCord", Params[1].c_str());
		m_ServerAddress = Params[0];
		//a_Client->SetIPString(Params[1]);
		//a_Client->SetUUID(cMojangAPI::MakeUUIDShort(Params[2]));
		//a_Client->SetProperties(Params[3]);
		ADD_SIMPLE_ACTION(SetIPString);
		ADD_SIMPLE_ACTION(SetUUID);
		ADD_SIMPLE_ACTION(SetProperties);
	}
	return cProtocolError::Success;
}