1 /* $Id: udp.cpp 26046 2013-11-22 21:41:19Z rubidium $ */
4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
11 * @file core/udp.cpp Basic functions to receive and send UDP packets.
16 #include "../../stdafx.h"
17 #include "../../date_func.h"
18 #include "../../debug.h"
22 #include "../../safeguards.h"
25 * Create an UDP socket but don't listen yet.
26 * @param bind the addresses to bind to.
28 NetworkUDPSocketHandler::NetworkUDPSocketHandler(NetworkAddressList
*bind
)
31 for (NetworkAddress
*addr
= bind
->Begin(); addr
!= bind
->End(); addr
++) {
32 *this->bind
.Append() = *addr
;
35 /* As hostname NULL and port 0/NULL don't go well when
36 * resolving it we need to add an address for each of
37 * the address families we support. */
38 *this->bind
.Append() = NetworkAddress(NULL
, 0, AF_INET
);
39 *this->bind
.Append() = NetworkAddress(NULL
, 0, AF_INET6
);
45 * Start listening on the given host and port.
46 * @return true if at least one port is listening
48 bool NetworkUDPSocketHandler::Listen()
50 /* Make sure socket is closed */
53 for (NetworkAddress
*addr
= this->bind
.Begin(); addr
!= this->bind
.End(); addr
++) {
54 addr
->Listen(SOCK_DGRAM
, &this->sockets
);
57 return this->sockets
.Length() != 0;
61 * Close the given UDP socket
63 void NetworkUDPSocketHandler::Close()
65 for (SocketList::iterator s
= this->sockets
.Begin(); s
!= this->sockets
.End(); s
++) {
66 closesocket(s
->second
);
68 this->sockets
.Clear();
71 NetworkRecvStatus
NetworkUDPSocketHandler::CloseConnection(bool error
)
73 NetworkSocketHandler::CloseConnection(error
);
74 return NETWORK_RECV_STATUS_OKAY
;
78 * Send a packet over UDP
79 * @param p the packet to send
80 * @param recv the receiver (target) of the packet
81 * @param all send the packet using all sockets that can send it
82 * @param broadcast whether to send a broadcast message
84 void NetworkUDPSocketHandler::SendPacket(Packet
*p
, NetworkAddress
*recv
, bool all
, bool broadcast
)
86 if (this->sockets
.Length() == 0) this->Listen();
88 for (SocketList::iterator s
= this->sockets
.Begin(); s
!= this->sockets
.End(); s
++) {
89 /* Make a local copy because if we resolve it we cannot
90 * easily unresolve it so we can resolve it later again. */
91 NetworkAddress
send(*recv
);
93 /* Not the same type */
94 if (!send
.IsFamily(s
->first
.GetAddress()->ss_family
)) continue;
98 #ifndef BEOS_NET_SERVER /* will work around this, some day; maybe. */
100 /* Enable broadcast */
101 unsigned long val
= 1;
102 if (setsockopt(s
->second
, SOL_SOCKET
, SO_BROADCAST
, (char *) &val
, sizeof(val
)) < 0) {
103 DEBUG(net
, 1, "[udp] setting broadcast failed with: %i", GET_LAST_ERROR());
108 /* Send the buffer */
109 int res
= sendto(s
->second
, (const char*)p
->buffer
, p
->size
, 0, (const struct sockaddr
*)send
.GetAddress(), send
.GetAddressLength());
110 DEBUG(net
, 7, "[udp] sendto(%s)", send
.GetAddressAsString());
112 /* Check for any errors, but ignore it otherwise */
113 if (res
== -1) DEBUG(net
, 1, "[udp] sendto(%s) failed with: %i", send
.GetAddressAsString(), GET_LAST_ERROR());
120 * Receive a packet at UDP level
122 void NetworkUDPSocketHandler::ReceivePackets()
124 for (SocketList::iterator s
= this->sockets
.Begin(); s
!= this->sockets
.End(); s
++) {
125 for (int i
= 0; i
< 1000; i
++) { // Do not infinitely loop when DoSing with UDP
126 struct sockaddr_storage client_addr
;
127 memset(&client_addr
, 0, sizeof(client_addr
));
130 socklen_t client_len
= sizeof(client_addr
);
132 /* Try to receive anything */
133 SetNonBlocking(s
->second
); // Some OSes seem to lose the non-blocking status of the socket
134 int nbytes
= recvfrom(s
->second
, (char*)p
.buffer
, SEND_MTU
, 0, (struct sockaddr
*)&client_addr
, &client_len
);
136 /* Did we get the bytes for the base header of the packet? */
137 if (nbytes
<= 0) break; // No data, i.e. no packet
138 if (nbytes
<= 2) continue; // Invalid data; try next packet
140 NetworkAddress
address(client_addr
, client_len
);
143 /* If the size does not match the packet must be corrupted.
144 * Otherwise it will be marked as corrupted later on. */
145 if (nbytes
!= p
.size
) {
146 DEBUG(net
, 1, "received a packet with mismatching size from %s", address
.GetAddressAsString());
150 /* Handle the packet */
151 this->HandleUDPPacket(&p
, &address
);
157 * Serializes the NewGRF information of the NetworkGameInfo struct to several packets
158 * @param p the packet type to write the data to
159 * @param info the NetworkGameInfo struct to serialize
160 * @return The ready to send packets.
162 std::list
<std::shared_ptr
<Packet
>> NetworkUDPSocketHandler::SendNetworkGameNewGrfInfo(PacketType packet_type
, const NetworkGameInfo
*info
)
164 /* Only send the GRF Identification (GRF_ID and MD5 checksum) of
165 * the GRFs that are needed, i.e. the ones that the server has
166 * selected in the NewGRF GUI and not the ones that are used due
167 * to the fact that they are in [newgrf-static] in openttd.cfg */
170 std::shared_ptr
<Packet
> packet
= std::make_shared
<Packet
>(PACKET_UDP_SERVER_NEWGRF_RESPONSE
);
171 std::list
<std::shared_ptr
<Packet
>> packets_to_send
;
172 std::list
<std::pair
<std::shared_ptr
<Packet
>, std::list
<GRFIdentifier
>>> packet_content_pairs
;
174 /* Collect GRF Identifications and split them into several packages */
175 for (auto config
= info
->grfconfig
; config
!= nullptr; config
= config
->next
) {
176 if (HasBit(config
->flags
, GCF_STATIC
)) continue;
178 if ((count
% NETWORK_MAX_GRF_COUNT
) == 0) {
179 auto new_pair
= std::make_pair(std::make_shared
<Packet
>(PACKET_UDP_SERVER_NEWGRF_RESPONSE
), std::list
<GRFIdentifier
>());
180 packet_content_pairs
.push_back(new_pair
);
183 assert(!packet_content_pairs
.empty());
185 packet_content_pairs
.back().second
.push_back(config
->ident
);
190 /* Send actual GRF Identifications */
191 for (auto pair
: packet_content_pairs
) {
192 auto packet
= pair
.first
;
194 packet
->Send_uint8(NETWORK_NEWGRF_INFO_VERSION
);
195 packet
->Send_uint8(packet_id
++); // The id of this packet
196 packet
->Send_uint8((uint8
)pair
.second
.size()); // Number of NewGRFs in this packet
198 for (auto grf_ident
: pair
.second
) {
199 this->SendGRFIdentifier(packet
.get(), &grf_ident
);
202 packets_to_send
.push_back(packet
);
205 return packets_to_send
;
210 * Serializes the NetworkGameInfo struct to the packet
211 * @param p the packet to write the data to
212 * @param info the NetworkGameInfo struct to serialize
214 void NetworkUDPSocketHandler::SendNetworkGameInfo(Packet
*p
, const NetworkGameInfo
*info
)
216 p
->Send_uint8 (NETWORK_GAME_INFO_VERSION
);
219 * Please observe the order.
220 * The parts must be read in the same order as they are sent!
223 /* Update the documentation in udp.h on changes
224 * to the NetworkGameInfo wire-protocol! */
226 /* NETWORK_GAME_INFO_VERSION = 128 */
228 /* Only send the GRF Identification (GRF_ID and MD5 checksum) of
229 * the GRFs that are needed, i.e. the ones that the server has
230 * selected in the NewGRF GUI and not the ones that are used due
231 * to the fact that they are in [newgrf-static] in openttd.cfg */
234 /* Count number of GRFs to send information about */
235 for (auto config
= info
->grfconfig
; config
!= nullptr; config
= config
->next
) {
236 if (!HasBit(config
->flags
, GCF_STATIC
)) ++count
;
239 uint8 num_grf_packets_to_expect
= std::ceil((float)count
/ NETWORK_MAX_GRF_COUNT
);
241 // Send number of GRF info packets that will be sent
242 p
->Send_uint8(num_grf_packets_to_expect
);
244 // Actual GRF Identifications will be send in multiple PACKET_UDP_SERVER_NEWGRF_RESPONSE packages.
245 // This package has not enough storage to send all that data depending on how many NewGRFs are active.
248 /* NETWORK_GAME_INFO_VERSION = 4 */
250 // This part is deprecated and is no longer sent. The version 128 part replaces it.
253 /* NETWORK_GAME_INFO_VERSION = 3 */
254 p
->Send_uint32(info
->game_date
);
255 p
->Send_uint32(info
->start_date
);
257 /* NETWORK_GAME_INFO_VERSION = 2 */
258 p
->Send_uint8 (info
->companies_max
);
259 p
->Send_uint8 (info
->companies_on
);
260 p
->Send_uint8 (info
->spectators_max
);
262 /* NETWORK_GAME_INFO_VERSION = 1 */
263 p
->Send_string(info
->server_name
);
264 p
->Send_string(info
->server_revision
);
265 p
->Send_uint8 (info
->server_lang
);
266 p
->Send_bool (info
->use_password
);
267 p
->Send_uint8 (info
->clients_max
);
268 p
->Send_uint8 (info
->clients_on
);
269 p
->Send_uint8 (info
->spectators_on
);
270 p
->Send_string(info
->map_name
);
271 p
->Send_uint16(info
->map_width
);
272 p
->Send_uint16(info
->map_height
);
273 p
->Send_uint8 (info
->map_set
);
274 p
->Send_bool (info
->dedicated
);
278 * Deserializes the NewGRF information of the NetworkGameInfo struct from one out of several sent packets
279 * @param p the packet to read the data from
280 * @param info the NetworkGameInfo to deserialize into
282 void NetworkUDPSocketHandler::ReceiveNetworkGameNewGrfInfo(Packet
*p
, NetworkGameInfo
*info
)
284 auto new_grf_info_packet_version
= p
->Recv_uint8();
286 // For now we only handle this specific version.
287 if (new_grf_info_packet_version
!= NETWORK_NEWGRF_INFO_VERSION
) return;
289 auto packet_id
= p
->Recv_uint8();
291 // Check if we already received this one. Bail if so. No need to process it again.
292 if (std::any_of(info
->received_grf_identifiers
.begin(), info
->received_grf_identifiers
.end(), [&](auto item
) {
293 return item
.first
== packet_id
;
296 auto num_grfs
= p
->Recv_uint8();
298 /* Broken/bad data. It cannot have that many NewGRFs. */
299 if (num_grfs
> NETWORK_MAX_GRF_COUNT
) return;
301 auto received_pair
= std::make_pair(packet_id
, std::list
<GRFIdentifier
>());
303 for (auto i
= 0; i
< num_grfs
; ++i
) {
305 this->ReceiveGRFIdentifier(p
, &ident
);
307 received_pair
.second
.push_back(ident
);
310 info
->received_grf_identifiers
.push_back(received_pair
);
314 * Deserializes the NetworkGameInfo struct minus NewGRF information from the packet
315 * @param p the packet to read the data from
316 * @param info the NetworkGameInfo to deserialize into
318 void NetworkUDPSocketHandler::ReceiveNetworkGameInfo(Packet
*p
, NetworkGameInfo
*info
)
320 static const Date MAX_DATE
= ConvertYMDToDate(MAX_YEAR
, 11, 31); // December is month 11
322 info
->game_info_version
= p
->Recv_uint8();
325 * Please observe the order.
326 * The parts must be read in the same order as they are sent!
329 /* Update the documentation in udp.h on changes
330 * to the NetworkGameInfo wire-protocol! */
332 switch (info
->game_info_version
) {
333 case 128: FALLTHROUGH
;
335 if (info
->game_info_version
== 4) {
336 GRFConfig
**dst
= &info
->grfconfig
;
338 uint num_grfs
= p
->Recv_uint8();
340 /* Broken/bad data. It cannot have that many NewGRFs. */
341 if (num_grfs
> NETWORK_MAX_GRF_COUNT
) return;
343 for (i
= 0; i
< num_grfs
; i
++) {
344 GRFConfig
*c
= new GRFConfig();
345 this->ReceiveGRFIdentifier(p
, &c
->ident
);
346 this->HandleIncomingNetworkGameInfoGRFConfig(c
);
348 /* Append GRFConfig to the list */
352 } else if (info
->game_info_version
== 128) {
353 // In NETWORK_GAME_INFO_VERSION 128 the actual newGRF information is sent via a different package type.
354 // Check ReceiveNetworkGameNewGrfInfo().
355 info
->new_grf_packages_to_expect
= p
->Recv_uint8();
361 info
->game_date
= Clamp(p
->Recv_uint32(), 0, MAX_DATE
);
362 info
->start_date
= Clamp(p
->Recv_uint32(), 0, MAX_DATE
);
366 info
->companies_max
= p
->Recv_uint8 ();
367 info
->companies_on
= p
->Recv_uint8 ();
368 info
->spectators_max
= p
->Recv_uint8 ();
372 p
->Recv_string(info
->server_name
, sizeof(info
->server_name
));
373 p
->Recv_string(info
->server_revision
, sizeof(info
->server_revision
));
374 info
->server_lang
= p
->Recv_uint8 ();
375 info
->use_password
= p
->Recv_bool ();
376 info
->clients_max
= p
->Recv_uint8 ();
377 info
->clients_on
= p
->Recv_uint8 ();
378 info
->spectators_on
= p
->Recv_uint8 ();
379 if (info
->game_info_version
< 3) { // 16 bits dates got scrapped and are read earlier
380 info
->game_date
= p
->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR
;
381 info
->start_date
= p
->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR
;
383 p
->Recv_string(info
->map_name
, sizeof(info
->map_name
));
384 info
->map_width
= p
->Recv_uint16();
385 info
->map_height
= p
->Recv_uint16();
386 info
->map_set
= p
->Recv_uint8 ();
387 info
->dedicated
= p
->Recv_bool ();
389 if (info
->server_lang
>= NETWORK_NUM_LANGUAGES
) info
->server_lang
= 0;
390 if (info
->map_set
>= NETWORK_NUM_LANDSCAPES
) info
->map_set
= 0;
395 * Handle an incoming packets by sending it to the correct function.
396 * @param p the received packet
397 * @param client_addr the sender of the packet
399 void NetworkUDPSocketHandler::HandleUDPPacket(Packet
*p
, NetworkAddress
*client_addr
)
403 /* New packet == new client, which has not quit yet */
406 type
= (PacketUDPType
)p
->Recv_uint8();
408 switch (this->HasClientQuit() ? PACKET_UDP_END
: type
) {
409 case PACKET_UDP_CLIENT_FIND_SERVER
: this->Receive_CLIENT_FIND_SERVER(p
, client_addr
); break;
410 case PACKET_UDP_SERVER_RESPONSE
: this->Receive_SERVER_RESPONSE(p
, client_addr
); break;
411 case PACKET_UDP_SERVER_NEWGRF_RESPONSE
: this->Receive_SERVER_NEWGRF_RESPONSE(p
, client_addr
); break;
412 case PACKET_UDP_CLIENT_DETAIL_INFO
: this->Receive_CLIENT_DETAIL_INFO(p
, client_addr
); break;
413 case PACKET_UDP_SERVER_DETAIL_INFO
: this->Receive_SERVER_DETAIL_INFO(p
, client_addr
); break;
414 case PACKET_UDP_SERVER_REGISTER
: this->Receive_SERVER_REGISTER(p
, client_addr
); break;
415 case PACKET_UDP_MASTER_ACK_REGISTER
: this->Receive_MASTER_ACK_REGISTER(p
, client_addr
); break;
416 case PACKET_UDP_CLIENT_GET_LIST
: this->Receive_CLIENT_GET_LIST(p
, client_addr
); break;
417 case PACKET_UDP_MASTER_RESPONSE_LIST
: this->Receive_MASTER_RESPONSE_LIST(p
, client_addr
); break;
418 case PACKET_UDP_SERVER_UNREGISTER
: this->Receive_SERVER_UNREGISTER(p
, client_addr
); break;
419 case PACKET_UDP_CLIENT_GET_NEWGRFS
: this->Receive_CLIENT_GET_NEWGRFS(p
, client_addr
); break;
420 case PACKET_UDP_SERVER_NEWGRFS
: this->Receive_SERVER_NEWGRFS(p
, client_addr
); break;
421 case PACKET_UDP_MASTER_SESSION_KEY
: this->Receive_MASTER_SESSION_KEY(p
, client_addr
); break;
424 if (this->HasClientQuit()) {
425 DEBUG(net
, 0, "[udp] received invalid packet type %d from %s", type
, client_addr
->GetAddressAsString());
427 DEBUG(net
, 0, "[udp] received illegal packet from %s", client_addr
->GetAddressAsString());
434 * Helper for logging receiving invalid packets.
435 * @param type The received packet type.
436 * @param client_addr The address we received the packet from.
438 void NetworkUDPSocketHandler::ReceiveInvalidPacket(PacketUDPType type
, NetworkAddress
*client_addr
)
440 DEBUG(net
, 0, "[udp] received packet type %d on wrong port from %s", type
, client_addr
->GetAddressAsString());
443 void NetworkUDPSocketHandler::Receive_CLIENT_FIND_SERVER(Packet
*p
, NetworkAddress
*client_addr
) { this->ReceiveInvalidPacket(PACKET_UDP_CLIENT_FIND_SERVER
, client_addr
); }
444 void NetworkUDPSocketHandler::Receive_SERVER_RESPONSE(Packet
*p
, NetworkAddress
*client_addr
) { this->ReceiveInvalidPacket(PACKET_UDP_SERVER_RESPONSE
, client_addr
); }
445 void NetworkUDPSocketHandler::Receive_SERVER_NEWGRF_RESPONSE(Packet
*p
, NetworkAddress
*client_addr
) { this->ReceiveInvalidPacket(PACKET_UDP_SERVER_NEWGRF_RESPONSE
, client_addr
); }
446 void NetworkUDPSocketHandler::Receive_CLIENT_DETAIL_INFO(Packet
*p
, NetworkAddress
*client_addr
) { this->ReceiveInvalidPacket(PACKET_UDP_CLIENT_DETAIL_INFO
, client_addr
); }
447 void NetworkUDPSocketHandler::Receive_SERVER_DETAIL_INFO(Packet
*p
, NetworkAddress
*client_addr
) { this->ReceiveInvalidPacket(PACKET_UDP_SERVER_DETAIL_INFO
, client_addr
); }
448 void NetworkUDPSocketHandler::Receive_SERVER_REGISTER(Packet
*p
, NetworkAddress
*client_addr
) { this->ReceiveInvalidPacket(PACKET_UDP_SERVER_REGISTER
, client_addr
); }
449 void NetworkUDPSocketHandler::Receive_MASTER_ACK_REGISTER(Packet
*p
, NetworkAddress
*client_addr
) { this->ReceiveInvalidPacket(PACKET_UDP_MASTER_ACK_REGISTER
, client_addr
); }
450 void NetworkUDPSocketHandler::Receive_CLIENT_GET_LIST(Packet
*p
, NetworkAddress
*client_addr
) { this->ReceiveInvalidPacket(PACKET_UDP_CLIENT_GET_LIST
, client_addr
); }
451 void NetworkUDPSocketHandler::Receive_MASTER_RESPONSE_LIST(Packet
*p
, NetworkAddress
*client_addr
) { this->ReceiveInvalidPacket(PACKET_UDP_MASTER_RESPONSE_LIST
, client_addr
); }
452 void NetworkUDPSocketHandler::Receive_SERVER_UNREGISTER(Packet
*p
, NetworkAddress
*client_addr
) { this->ReceiveInvalidPacket(PACKET_UDP_SERVER_UNREGISTER
, client_addr
); }
453 void NetworkUDPSocketHandler::Receive_CLIENT_GET_NEWGRFS(Packet
*p
, NetworkAddress
*client_addr
) { this->ReceiveInvalidPacket(PACKET_UDP_CLIENT_GET_NEWGRFS
, client_addr
); }
454 void NetworkUDPSocketHandler::Receive_SERVER_NEWGRFS(Packet
*p
, NetworkAddress
*client_addr
) { this->ReceiveInvalidPacket(PACKET_UDP_SERVER_NEWGRFS
, client_addr
); }
455 void NetworkUDPSocketHandler::Receive_MASTER_SESSION_KEY(Packet
*p
, NetworkAddress
*client_addr
) { this->ReceiveInvalidPacket(PACKET_UDP_MASTER_SESSION_KEY
, client_addr
); }
457 #endif /* ENABLE_NETWORK */