OpenTTD Source  1.11.2
udp.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * 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.
4  * 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.
5  * 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/>.
6  */
7 
12 #include "../../stdafx.h"
13 #include "../../date_func.h"
14 #include "../../debug.h"
15 #include "game_info.h"
16 #include "udp.h"
17 
18 #include "../../safeguards.h"
19 
25 {
26  if (bind != nullptr) {
27  for (NetworkAddress &addr : *bind) {
28  this->bind.push_back(addr);
29  }
30  } else {
31  /* As hostname nullptr and port 0/nullptr don't go well when
32  * resolving it we need to add an address for each of
33  * the address families we support. */
34  this->bind.emplace_back(nullptr, 0, AF_INET);
35  this->bind.emplace_back(nullptr, 0, AF_INET6);
36  }
37 }
38 
39 
45 {
46  /* Make sure socket is closed */
47  this->Close();
48 
49  for (NetworkAddress &addr : this->bind) {
50  addr.Listen(SOCK_DGRAM, &this->sockets);
51  }
52 
53  return this->sockets.size() != 0;
54 }
55 
60 {
61  for (auto &s : this->sockets) {
62  closesocket(s.second);
63  }
64  this->sockets.clear();
65 }
66 
68 {
71 }
72 
80 void NetworkUDPSocketHandler::SendPacket(Packet *p, NetworkAddress *recv, bool all, bool broadcast)
81 {
82  if (this->sockets.size() == 0) this->Listen();
83 
84  for (auto &s : this->sockets) {
85  /* Make a local copy because if we resolve it we cannot
86  * easily unresolve it so we can resolve it later again. */
87  NetworkAddress send(*recv);
88 
89  /* Not the same type */
90  if (!send.IsFamily(s.first.GetAddress()->ss_family)) continue;
91 
92  p->PrepareToSend();
93 
94  if (broadcast) {
95  /* Enable broadcast */
96  unsigned long val = 1;
97  if (setsockopt(s.second, SOL_SOCKET, SO_BROADCAST, (char *) &val, sizeof(val)) < 0) {
98  DEBUG(net, 1, "[udp] setting broadcast failed with: %s", NetworkError::GetLast().AsString());
99  }
100  }
101 
102  /* Send the buffer */
103  int res = sendto(s.second, (const char*)p->buffer, p->size, 0, (const struct sockaddr *)send.GetAddress(), send.GetAddressLength());
104  DEBUG(net, 7, "[udp] sendto(%s)", send.GetAddressAsString().c_str());
105 
106  /* Check for any errors, but ignore it otherwise */
107  if (res == -1) DEBUG(net, 1, "[udp] sendto(%s) failed with: %s", send.GetAddressAsString().c_str(), NetworkError::GetLast().AsString());
108 
109  if (!all) break;
110  }
111 }
112 
117 {
118  for (auto &s : this->sockets) {
119  for (int i = 0; i < 1000; i++) { // Do not infinitely loop when DoSing with UDP
120  struct sockaddr_storage client_addr;
121  memset(&client_addr, 0, sizeof(client_addr));
122 
123  Packet p(this);
124  socklen_t client_len = sizeof(client_addr);
125 
126  /* Try to receive anything */
127  SetNonBlocking(s.second); // Some OSes seem to lose the non-blocking status of the socket
128  int nbytes = recvfrom(s.second, (char*)p.buffer, SEND_MTU, 0, (struct sockaddr *)&client_addr, &client_len);
129 
130  /* Did we get the bytes for the base header of the packet? */
131  if (nbytes <= 0) break; // No data, i.e. no packet
132  if (nbytes <= 2) continue; // Invalid data; try next packet
133 #ifdef __EMSCRIPTEN__
134  client_len = FixAddrLenForEmscripten(client_addr);
135 #endif
136 
137  NetworkAddress address(client_addr, client_len);
138  p.PrepareToRead();
139 
140  /* If the size does not match the packet must be corrupted.
141  * Otherwise it will be marked as corrupted later on. */
142  if (nbytes != p.size) {
143  DEBUG(net, 1, "received a packet with mismatching size from %s", address.GetAddressAsString().c_str());
144  continue;
145  }
146 
147  /* Handle the packet */
148  this->HandleUDPPacket(&p, &address);
149  }
150  }
151 }
152 
159 {
160  PacketUDPType type;
161 
162  /* New packet == new client, which has not quit yet */
163  this->Reopen();
164 
165  type = (PacketUDPType)p->Recv_uint8();
166 
167  switch (this->HasClientQuit() ? PACKET_UDP_END : type) {
168  case PACKET_UDP_CLIENT_FIND_SERVER: this->Receive_CLIENT_FIND_SERVER(p, client_addr); break;
169  case PACKET_UDP_SERVER_RESPONSE: this->Receive_SERVER_RESPONSE(p, client_addr); break;
170  case PACKET_UDP_CLIENT_DETAIL_INFO: this->Receive_CLIENT_DETAIL_INFO(p, client_addr); break;
171  case PACKET_UDP_SERVER_DETAIL_INFO: this->Receive_SERVER_DETAIL_INFO(p, client_addr); break;
172  case PACKET_UDP_SERVER_REGISTER: this->Receive_SERVER_REGISTER(p, client_addr); break;
173  case PACKET_UDP_MASTER_ACK_REGISTER: this->Receive_MASTER_ACK_REGISTER(p, client_addr); break;
174  case PACKET_UDP_CLIENT_GET_LIST: this->Receive_CLIENT_GET_LIST(p, client_addr); break;
175  case PACKET_UDP_MASTER_RESPONSE_LIST: this->Receive_MASTER_RESPONSE_LIST(p, client_addr); break;
176  case PACKET_UDP_SERVER_UNREGISTER: this->Receive_SERVER_UNREGISTER(p, client_addr); break;
177  case PACKET_UDP_CLIENT_GET_NEWGRFS: this->Receive_CLIENT_GET_NEWGRFS(p, client_addr); break;
178  case PACKET_UDP_SERVER_NEWGRFS: this->Receive_SERVER_NEWGRFS(p, client_addr); break;
179  case PACKET_UDP_MASTER_SESSION_KEY: this->Receive_MASTER_SESSION_KEY(p, client_addr); break;
180 
181  default:
182  if (this->HasClientQuit()) {
183  DEBUG(net, 0, "[udp] received invalid packet type %d from %s", type, client_addr->GetAddressAsString().c_str());
184  } else {
185  DEBUG(net, 0, "[udp] received illegal packet from %s", client_addr->GetAddressAsString().c_str());
186  }
187  break;
188  }
189 }
190 
197 {
198  DEBUG(net, 0, "[udp] received packet type %d on wrong port from %s", type, client_addr->GetAddressAsString().c_str());
199 }
200 
PACKET_UDP_CLIENT_GET_LIST
@ PACKET_UDP_CLIENT_GET_LIST
Request for serverlist from master server.
Definition: udp.h:26
NetworkUDPSocketHandler::Receive_SERVER_UNREGISTER
virtual void Receive_SERVER_UNREGISTER(Packet *p, NetworkAddress *client_addr)
A server unregisters itself at the master server.
Definition: udp.cpp:209
Packet::PrepareToSend
void PrepareToSend()
Writes the packet size from the raw packet from packet->size.
Definition: packet.cpp:61
PACKET_UDP_CLIENT_DETAIL_INFO
@ PACKET_UDP_CLIENT_DETAIL_INFO
Queries a game server about details of the game, such as companies.
Definition: udp.h:22
NetworkUDPSocketHandler::Receive_MASTER_SESSION_KEY
virtual void Receive_MASTER_SESSION_KEY(Packet *p, NetworkAddress *client_addr)
The master server sends us a session key.
Definition: udp.cpp:212
NetworkAddress::GetAddress
const sockaddr_storage * GetAddress()
Get the address in its internal representation.
Definition: address.cpp:123
PACKET_UDP_CLIENT_GET_NEWGRFS
@ PACKET_UDP_CLIENT_GET_NEWGRFS
Requests the name for a list of GRFs (GRF_ID and MD5)
Definition: udp.h:29
NetworkUDPSocketHandler::Receive_MASTER_RESPONSE_LIST
virtual void Receive_MASTER_RESPONSE_LIST(Packet *p, NetworkAddress *client_addr)
The server sends a list of servers.
Definition: udp.cpp:208
Packet::buffer
byte * buffer
The buffer of this packet, of basically variable length up to SEND_MTU.
Definition: packet.h:52
NetworkAddress::GetAddressLength
int GetAddressLength()
Get the (valid) length of the address.
Definition: address.h:103
PACKET_UDP_CLIENT_FIND_SERVER
@ PACKET_UDP_CLIENT_FIND_SERVER
Queries a game server for game information.
Definition: udp.h:20
PACKET_UDP_SERVER_UNREGISTER
@ PACKET_UDP_SERVER_UNREGISTER
Request to be removed from the server-list.
Definition: udp.h:28
PACKET_UDP_SERVER_REGISTER
@ PACKET_UDP_SERVER_REGISTER
Packet to register itself to the master server.
Definition: udp.h:24
NetworkUDPSocketHandler::CloseConnection
NetworkRecvStatus CloseConnection(bool error=true) override
Close the current connection; for TCP this will be mostly equivalent to Close(), but for UDP it just ...
Definition: udp.cpp:67
NetworkUDPSocketHandler::Close
void Close() override
Close the given UDP socket.
Definition: udp.cpp:59
NetworkUDPSocketHandler::Receive_SERVER_NEWGRFS
virtual void Receive_SERVER_NEWGRFS(Packet *p, NetworkAddress *client_addr)
The server returns information about some NewGRFs.
Definition: udp.cpp:211
NetworkUDPSocketHandler::NetworkUDPSocketHandler
NetworkUDPSocketHandler(NetworkAddressList *bind=nullptr)
Create an UDP socket but don't listen yet.
Definition: udp.cpp:24
NetworkUDPSocketHandler::Receive_SERVER_REGISTER
virtual void Receive_SERVER_REGISTER(Packet *p, NetworkAddress *client_addr)
Registers the server to the master server.
Definition: udp.cpp:205
NetworkSocketHandler::CloseConnection
virtual NetworkRecvStatus CloseConnection(bool error=true)
Close the current connection; for TCP this will be mostly equivalent to Close(), but for UDP it just ...
Definition: core.h:59
NetworkUDPSocketHandler::Receive_CLIENT_FIND_SERVER
virtual void Receive_CLIENT_FIND_SERVER(Packet *p, NetworkAddress *client_addr)
Queries to the server for information about the game.
Definition: udp.cpp:201
PACKET_UDP_MASTER_SESSION_KEY
@ PACKET_UDP_MASTER_SESSION_KEY
Sends a fresh session key to the client.
Definition: udp.h:31
NetworkUDPSocketHandler::Receive_SERVER_DETAIL_INFO
virtual void Receive_SERVER_DETAIL_INFO(Packet *p, NetworkAddress *client_addr)
Reply with detailed company information.
Definition: udp.cpp:204
NetworkSocketHandler::Reopen
void Reopen()
Reopen the socket so we can send/receive stuff again.
Definition: core.h:72
NetworkAddressList
std::vector< NetworkAddress > NetworkAddressList
Type for a list of addresses.
Definition: address.h:20
DEBUG
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:35
NetworkUDPSocketHandler::Receive_CLIENT_GET_NEWGRFS
virtual void Receive_CLIENT_GET_NEWGRFS(Packet *p, NetworkAddress *client_addr)
The client requests information about some NewGRFs.
Definition: udp.cpp:210
Packet::PrepareToRead
void PrepareToRead()
Prepares the packet so it can be read.
Definition: packet.cpp:196
NetworkUDPSocketHandler::sockets
SocketList sockets
The opened sockets.
Definition: udp.h:50
Packet::size
PacketSize size
The size of the whole packet for received packets.
Definition: packet.h:48
NetworkError::GetLast
static NetworkError GetLast()
Get the last network error.
Definition: os_abstraction.cpp:116
PACKET_UDP_END
@ PACKET_UDP_END
Must ALWAYS be on the end of this list!! (period)
Definition: udp.h:32
SEND_MTU
static const uint16 SEND_MTU
Number of bytes we can pack in a single packet.
Definition: config.h:33
NetworkUDPSocketHandler::bind
NetworkAddressList bind
The address to bind to.
Definition: udp.h:48
PACKET_UDP_MASTER_ACK_REGISTER
@ PACKET_UDP_MASTER_ACK_REGISTER
Packet indicating registration has succeeded.
Definition: udp.h:25
PACKET_UDP_SERVER_DETAIL_INFO
@ PACKET_UDP_SERVER_DETAIL_INFO
Reply of the game server about details of the game, such as companies.
Definition: udp.h:23
Packet
Internal entity of a packet.
Definition: packet.h:40
NetworkUDPSocketHandler::ReceiveInvalidPacket
void ReceiveInvalidPacket(PacketUDPType, NetworkAddress *client_addr)
Helper for logging receiving invalid packets.
Definition: udp.cpp:196
PACKET_UDP_SERVER_NEWGRFS
@ PACKET_UDP_SERVER_NEWGRFS
Sends the list of NewGRF's requested.
Definition: udp.h:30
PACKET_UDP_SERVER_RESPONSE
@ PACKET_UDP_SERVER_RESPONSE
Reply of the game server with game information.
Definition: udp.h:21
NetworkSocketHandler::HasClientQuit
bool HasClientQuit() const
Whether the current client connected to the socket has quit.
Definition: core.h:67
NetworkAddress
Wrapper for (un)resolved network addresses; there's no reason to transform a numeric IP to a string a...
Definition: address.h:29
NetworkUDPSocketHandler::Receive_MASTER_ACK_REGISTER
virtual void Receive_MASTER_ACK_REGISTER(Packet *p, NetworkAddress *client_addr)
The master server acknowledges the registration.
Definition: udp.cpp:206
NetworkRecvStatus
NetworkRecvStatus
Status of a network client; reasons why a client has quit.
Definition: core.h:22
NetworkUDPSocketHandler::HandleUDPPacket
void HandleUDPPacket(Packet *p, NetworkAddress *client_addr)
Handle an incoming packets by sending it to the correct function.
Definition: udp.cpp:158
NetworkUDPSocketHandler::Listen
bool Listen()
Start listening on the given host and port.
Definition: udp.cpp:44
game_info.h
udp.h
Packet::Recv_uint8
uint8 Recv_uint8()
Read a 8 bits integer from the packet.
Definition: packet.cpp:217
error
void CDECL error(const char *s,...)
Error handling for fatal non-user errors.
Definition: openttd.cpp:132
NetworkUDPSocketHandler::Receive_CLIENT_GET_LIST
virtual void Receive_CLIENT_GET_LIST(Packet *p, NetworkAddress *client_addr)
The client requests a list of servers.
Definition: udp.cpp:207
SetNonBlocking
bool SetNonBlocking(SOCKET d)
Try to set the socket into non-blocking mode.
Definition: os_abstraction.cpp:133
PACKET_UDP_MASTER_RESPONSE_LIST
@ PACKET_UDP_MASTER_RESPONSE_LIST
Response from master server with server ip's + port's.
Definition: udp.h:27
NetworkAddress::IsFamily
bool IsFamily(int family)
Checks of this address is of the given family.
Definition: address.cpp:142
NetworkUDPSocketHandler::Receive_CLIENT_DETAIL_INFO
virtual void Receive_CLIENT_DETAIL_INFO(Packet *p, NetworkAddress *client_addr)
Query for detailed information about companies.
Definition: udp.cpp:203
NetworkUDPSocketHandler::ReceivePackets
void ReceivePackets()
Receive a packet at UDP level.
Definition: udp.cpp:116
NETWORK_RECV_STATUS_OKAY
@ NETWORK_RECV_STATUS_OKAY
Everything is okay.
Definition: core.h:23
NetworkUDPSocketHandler::Receive_SERVER_RESPONSE
virtual void Receive_SERVER_RESPONSE(Packet *p, NetworkAddress *client_addr)
Return of server information to the client.
Definition: udp.cpp:202
PacketUDPType
PacketUDPType
Enum with all types of UDP packets.
Definition: udp.h:19
NetworkError::AsString
const char * AsString() const
Get the string representation of the error message.
Definition: os_abstraction.cpp:79
NetworkAddress::GetAddressAsString
void GetAddressAsString(char *buffer, const char *last, bool with_family=true)
Get the address as a string, e.g.
Definition: address.cpp:77
NetworkUDPSocketHandler::SendPacket
void SendPacket(Packet *p, NetworkAddress *recv, bool all=false, bool broadcast=false)
Send a packet over UDP.
Definition: udp.cpp:80