summaryrefslogtreecommitdiffstats
path: root/Tools/ProtoProxy/Connection.h
blob: 1fc9536de040a593795765d581553281018ed3b5 (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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247

// Connection.h

// Interfaces to the cConnection class representing a single pair of connected sockets





#pragma once

#include "ByteBuffer.h"
#include "OSSupport/Timer.h"
#include "PolarSSL++/AesCfb128Decryptor.h"
#include "PolarSSL++/AesCfb128Encryptor.h"





class cServer;





class cConnection
{
	AString m_LogNameBase;  ///< Base for the log filename and all files connected to this log
	
	int m_ItemIdx;  ///< Index for the next file into which item metadata should be written (ParseSlot() function)
	
	cCriticalSection m_CSLog;
	FILE * m_LogFile;
	
	cServer & m_Server;
	SOCKET m_ClientSocket;
	SOCKET m_ServerSocket;
	
	cTimer m_Timer;
	long long 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 Log(const char * a_Format, ...);
	void DataLog(const void * a_Data, int a_Size, const char * a_Format, ...);
	void LogFlush(void);
	
protected:

	cByteBuffer m_ClientBuffer;
	cByteBuffer m_ServerBuffer;
	
	cAesCfb128Decryptor m_ServerDecryptor;
	cAesCfb128Encryptor m_ServerEncryptor;

	AString 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, const char * a_Data, size_t a_Size, 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, const char * a_Data, size_t a_Size, 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);
} ;