summaryrefslogtreecommitdiff
path: root/src/network/core/tcp_coordinator.h
blob: dea61cdec1dd914b2fb17fbf730a58191dc7ba64 (plain)
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
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
/*
 * This file is part of OpenTTD.
 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * @file tcp_coordinator.h Basic functions to receive and send TCP packets to/from the Game Coordinator server.
 */

#ifndef NETWORK_CORE_TCP_COORDINATOR_H
#define NETWORK_CORE_TCP_COORDINATOR_H

#include "os_abstraction.h"
#include "tcp.h"
#include "packet.h"
#include "game_info.h"

/**
 * Enum with all types of TCP Game Coordinator packets. The order MUST not be changed.
 *
 * GC     -> packets from Game Coordinator to either Client or Server.
 * SERVER -> packets from Server to Game Coordinator.
 * CLIENT -> packets from Client to Game Coordinator.
 * SERCLI -> packets from either the Server or Client to Game Coordinator.
 **/
enum PacketCoordinatorType {
	PACKET_COORDINATOR_GC_ERROR,              ///< Game Coordinator indicates there was an error.
	PACKET_COORDINATOR_SERVER_REGISTER,       ///< Server registration.
	PACKET_COORDINATOR_GC_REGISTER_ACK,       ///< Game Coordinator accepts the registration.
	PACKET_COORDINATOR_SERVER_UPDATE,         ///< Server sends an set intervals an update of the server.
	PACKET_COORDINATOR_CLIENT_LISTING,        ///< Client is requesting a listing of all public servers.
	PACKET_COORDINATOR_GC_LISTING,            ///< Game Coordinator returns a listing of all public servers.
	PACKET_COORDINATOR_CLIENT_CONNECT,        ///< Client wants to connect to a server based on an invite code.
	PACKET_COORDINATOR_GC_CONNECTING,         ///< Game Coordinator informs the client of the token assigned to the connection attempt.
	PACKET_COORDINATOR_SERCLI_CONNECT_FAILED, ///< Client/server tells the Game Coordinator the current connection attempt failed.
	PACKET_COORDINATOR_GC_CONNECT_FAILED,     ///< Game Coordinator informs client/server it has given up on the connection attempt.
	PACKET_COORDINATOR_CLIENT_CONNECTED,      ///< Client informs the Game Coordinator the connection with the server is established.
	PACKET_COORDINATOR_GC_DIRECT_CONNECT,     ///< Game Coordinator tells client to directly connect to the hostname:port of the server.
	PACKET_COORDINATOR_GC_STUN_REQUEST,       ///< Game Coordinator tells client/server to initiate a STUN request.
	PACKET_COORDINATOR_SERCLI_STUN_RESULT,    ///< Client/server informs the Game Coordinator of the result of the STUN request.
	PACKET_COORDINATOR_GC_STUN_CONNECT,       ///< Game Coordinator tells client/server to connect() reusing the STUN local address.
	PACKET_COORDINATOR_GC_NEWGRF_LOOKUP,      ///< Game Coordinator informs client about NewGRF lookup table updates needed for GC_LISTING.
	PACKET_COORDINATOR_GC_TURN_CONNECT,       ///< Game Coordinator tells client/server to connect to a specific TURN server.
	PACKET_COORDINATOR_END,                   ///< Must ALWAYS be on the end of this list!! (period)
};

/**
 * The type of connection the Game Coordinator can detect we have.
 */
enum ConnectionType {
	CONNECTION_TYPE_UNKNOWN,  ///< The Game Coordinator hasn't informed us yet what type of connection we have.
	CONNECTION_TYPE_ISOLATED, ///< The Game Coordinator failed to find a way to connect to your server. Nobody will be able to join.
	CONNECTION_TYPE_DIRECT,   ///< The Game Coordinator can directly connect to your server.
	CONNECTION_TYPE_STUN,     ///< The Game Coordinator can connect to your server via a STUN request.
	CONNECTION_TYPE_TURN,     ///< The Game Coordinator needs you to connect to a relay.
};

/**
 * The type of error from the Game Coordinator.
 */
enum NetworkCoordinatorErrorType {
	NETWORK_COORDINATOR_ERROR_UNKNOWN,             ///< There was an unknown error.
	NETWORK_COORDINATOR_ERROR_REGISTRATION_FAILED, ///< Your request for registration failed.
	NETWORK_COORDINATOR_ERROR_INVALID_INVITE_CODE, ///< The invite code given is invalid.
};

/** Base socket handler for all Game Coordinator TCP sockets. */
class NetworkCoordinatorSocketHandler : public NetworkTCPSocketHandler {
protected:
	bool ReceiveInvalidPacket(PacketCoordinatorType type);

	/**
	 * Game Coordinator indicates there was an error. This can either be a
	 * permanent error causing the connection to be dropped, or in response
	 * to a request that is invalid.
	 *
	 *  uint8   Type of error (see NetworkCoordinatorErrorType).
	 *  string  Details of the error.
	 *
	 * @param p The packet that was just received.
	 * @return True upon success, otherwise false.
	 */
	virtual bool Receive_GC_ERROR(Packet *p);

	/**
	 * Server is starting a multiplayer game and wants to let the
	 * Game Coordinator know.
	 *
	 *  uint8   Game Coordinator protocol version.
	 *  uint8   Type of game (see ServerGameType).
	 *  uint16  Local port of the server.
	 *  string  Invite code the server wants to use (can be empty; coordinator will assign a new invite code).
	 *  string  Secret that belongs to the invite code (empty if invite code is empty).
	 *
	 * @param p The packet that was just received.
	 * @return True upon success, otherwise false.
	 */
	virtual bool Receive_SERVER_REGISTER(Packet *p);

	/**
	 * Game Coordinator acknowledges the registration.
	 *
	 *  string  Invite code that can be used to join this server.
	 *  string  Secret that belongs to the invite code (only needed if reusing the invite code on next SERVER_REGISTER).
	 *  uint8   Type of connection was detected (see ConnectionType).
	 *
	 * @param p The packet that was just received.
	 * @return True upon success, otherwise false.
	 */
	virtual bool Receive_GC_REGISTER_ACK(Packet *p);

	/**
	 * Send an update of the current state of the server to the Game Coordinator.
	 *
	 *  uint8   Game Coordinator protocol version.
	 *  Serialized NetworkGameInfo. See game_info.hpp for details.
	 *
	 * @param p The packet that was just received.
	 * @return True upon success, otherwise false.
	 */
	virtual bool Receive_SERVER_UPDATE(Packet *p);

	/**
	 * Client requests a list of all public servers.
	 *
	 *  uint8   Game Coordinator protocol version.
	 *  uint8   Game-info version used by this client.
	 *  string  Revision of the client.
	 *  uint32  (Game Coordinator protocol >= 4) Cursor as received from GC_NEWGRF_LOOKUP, or zero.
	 *
	 * @param p The packet that was just received.
	 * @return True upon success, otherwise false.
	 */
	virtual bool Receive_CLIENT_LISTING(Packet *p);

	/**
	 * Game Coordinator replies with a list of all public servers. Multiple
	 * of these packets are received after a request till all servers are
	 * sent over. Last packet will have server count of 0.
	 *
	 *  uint16  Amount of public servers in this packet.
	 *  For each server:
	 *    string  Connection string for this server.
	 *    Serialized NetworkGameInfo. See game_info.hpp for details.
	 *
	 * @param p The packet that was just received.
	 * @return True upon success, otherwise false.
	 */
	virtual bool Receive_GC_LISTING(Packet *p);

	/**
	 * Client wants to connect to a Server.
	 *
	 *  uint8   Game Coordinator protocol version.
	 *  string  Invite code of the Server to join.
	 *
	 * @param p The packet that was just received.
	 * @return True upon success, otherwise false.
	 */
	virtual bool Receive_CLIENT_CONNECT(Packet *p);

	/**
	 * Game Coordinator informs the Client under what token it will start the
	 * attempt to connect the Server and Client together.
	 *
	 *  string  Token to track the current connect request.
	 *  string  Invite code of the Server to join.
	 *
	 * @param p The packet that was just received.
	 * @return True upon success, otherwise false.
	 */
	virtual bool Receive_GC_CONNECTING(Packet *p);

	/**
	 * Client or Server failed to connect to the remote side.
	 *
	 *  uint8   Game Coordinator protocol version.
	 *  string  Token to track the current connect request.
	 *  uint8   Tracking number to track current connect request.
	 *
	 * @param p The packet that was just received.
	 * @return True upon success, otherwise false.
	 */
	virtual bool Receive_SERCLI_CONNECT_FAILED(Packet *p);

	/**
	 * Game Coordinator informs the Client that it failed to find a way to
	 * connect the Client to the Server. Any open connections for this token
	 * should be closed now.
	 *
	 *  string  Token to track the current connect request.
	 *
	 * @param p The packet that was just received.
	 * @return True upon success, otherwise false.
	 */
	virtual bool Receive_GC_CONNECT_FAILED(Packet *p);

	/**
	 * Client informs the Game Coordinator the connection with the Server is
	 * established. The Client will disconnect from the Game Coordinator next.
	 *
	 *  uint8   Game Coordinator protocol version.
	 *  string  Token to track the current connect request.
	 *
	 * @param p The packet that was just received.
	 * @return True upon success, otherwise false.
	 */
	virtual bool Receive_CLIENT_CONNECTED(Packet *p);

	/**
	 * Game Coordinator requests that the Client makes a direct connection to
	 * the indicated peer, which is a Server.
	 *
	 *  string  Token to track the current connect request.
	 *  uint8   Tracking number to track current connect request.
	 *  string  Hostname of the peer.
	 *  uint16  Port of the peer.
	 *
	 * @param p The packet that was just received.
	 * @return True upon success, otherwise false.
	 */
	virtual bool Receive_GC_DIRECT_CONNECT(Packet *p);

	/**
	 * Game Coordinator requests the client/server to do a STUN request to the
	 * STUN server. Important is to remember the local port these STUN requests
	 * are sent from, as this will be needed for later conenctions too.
	 * The client/server should do multiple STUN requests for every available
	 * interface that connects to the Internet (e.g., once for IPv4 and once
	 * for IPv6).
	 *
	 *  string  Token to track the current connect request.
	 *
	 * @param p The packet that was just received.
	 * @return True upon success, otherwise false.
	 */
	virtual bool Receive_GC_STUN_REQUEST(Packet *p);

	/**
	 * Client/server informs the Game Coordinator the result of a STUN request.
	 *
	 *  uint8   Game Coordinator protocol version.
	 *  string  Token to track the current connect request.
	 *  uint8   Interface number, as given during STUN request.
	 *  bool    Whether the STUN connection was successful.
	 *
	 * @param p The packet that was just received.
	 * @return True upon success, otherwise false.
	 */
	virtual bool Receive_SERCLI_STUN_RESULT(Packet *p);

	/**
	 * Game Coordinator informs the client/server of its STUN peer (the host:ip
	 * of the other side). It should start a connect() to this peer ASAP with
	 * the local address as used with the STUN request.
	 *
	 *  string  Token to track the current connect request.
	 *  uint8   Tracking number to track current connect request.
	 *  uint8   Interface number, as given during STUN request.
	 *  string  Host of the peer.
	 *  uint16  Port of the peer.
	 *
	 * @param p The packet that was just received.
	 * @return True upon success, otherwise false.
	 */
	virtual bool Receive_GC_STUN_CONNECT(Packet *p);

	/**
	 * Game Coordinator informs the client of updates for the NewGRFs lookup table
	 * as used by the NewGRF deserialization in GC_LISTING.
	 * This packet is sent after a CLIENT_LISTING request, but before GC_LISTING.
	 *
	 *  uint32   Lookup table cursor.
	 *  uint16   Number of NewGRFs in the packet, with for each of the NewGRFs:
	 *      uint32   Lookup table index for the NewGRF.
	 *      uint32   Unique NewGRF ID.
	 *      byte[16] MD5 checksum of the NewGRF
	 *      string   Name of the NewGRF.
	 *
	 * The lookup table built using these packets are used by the deserialisation
	 * of the NewGRFs for servers in the GC_LISTING. These updates are additive,
	 * i.e. each update will add NewGRFs but never remove them. However, this
	 * lookup table is specific to the connection with the Game Coordinator, and
	 * should be considered invalid after disconnecting from the Game Coordinator.
	 *
	 * @param p The packet that was just received.
	 * @return True upon success, otherwise false.
	 */
	virtual bool Receive_GC_NEWGRF_LOOKUP(Packet *p);

	/**
	 * Game Coordinator requests that we make a connection to the indicated
	 * peer, which is a TURN server.
	 *
	 *  string  Token to track the current connect request.
	 *  uint8   Tracking number to track current connect request.
	 *  string  Ticket to hand over to the TURN server.
	 *  string  Connection string of the TURN server.
	 *
	 * @param p The packet that was just received.
	 * @return True upon success, otherwise false.
	 */
	virtual bool Receive_GC_TURN_CONNECT(Packet *p);

	bool HandlePacket(Packet *p);
public:
	/**
	 * Create a new cs socket handler for a given cs.
	 * @param s The socket we are connected with.
	 */
	NetworkCoordinatorSocketHandler(SOCKET s = INVALID_SOCKET) : NetworkTCPSocketHandler(s) {}

	bool ReceivePackets();
};

#endif /* NETWORK_CORE_TCP_COORDINATOR_H */