OpenTTD Source  20241125-master-g5b02f51e17
tcp_listen.h
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 #ifndef NETWORK_CORE_TCP_LISTEN_H
13 #define NETWORK_CORE_TCP_LISTEN_H
14 
15 #include "tcp.h"
16 #include "../network.h"
17 #include "../../core/pool_type.hpp"
18 #include "../../debug.h"
19 #include "table/strings.h"
20 
27 template <class Tsocket, PacketType Tfull_packet, PacketType Tban_packet>
31 
32 public:
33  static bool ValidateClient(SOCKET s, NetworkAddress &address)
34  {
35  /* Check if the client is banned. */
36  for (const auto &entry : _network_ban_list) {
37  if (address.IsInNetmask(entry)) {
38  Packet p(nullptr, Tban_packet);
39  p.PrepareToSend();
40 
41  Debug(net, 2, "[{}] Banned ip tried to join ({}), refused", Tsocket::GetName(), entry);
42 
43  if (p.TransferOut<int>(send, s, 0) < 0) {
44  Debug(net, 0, "[{}] send failed: {}", Tsocket::GetName(), NetworkError::GetLast().AsString());
45  }
46  closesocket(s);
47  return false;
48  }
49  }
50 
51  /* Can we handle a new client? */
52  if (!Tsocket::AllowConnection()) {
53  /* No more clients allowed?
54  * Send to the client that we are full! */
55  Packet p(nullptr, Tfull_packet);
56  p.PrepareToSend();
57 
58  if (p.TransferOut<int>(send, s, 0) < 0) {
59  Debug(net, 0, "[{}] send failed: {}", Tsocket::GetName(), NetworkError::GetLast().AsString());
60  }
61  closesocket(s);
62 
63  return false;
64  }
65 
66  return true;
67  }
68 
73  static void AcceptClient(SOCKET ls)
74  {
75  for (;;) {
76  struct sockaddr_storage sin;
77  memset(&sin, 0, sizeof(sin));
78  socklen_t sin_len = sizeof(sin);
79  SOCKET s = accept(ls, (struct sockaddr*)&sin, &sin_len);
80  if (s == INVALID_SOCKET) return;
81 #ifdef __EMSCRIPTEN__
82  sin_len = FixAddrLenForEmscripten(sin);
83 #endif
84 
85  SetNonBlocking(s); // XXX error handling?
86 
87  NetworkAddress address(sin, sin_len);
88  Debug(net, 3, "[{}] Client connected from {} on frame {}", Tsocket::GetName(), address.GetHostname(), _frame_counter);
89 
90  SetNoDelay(s); // XXX error handling?
91 
92  if (!Tsocket::ValidateClient(s, address)) continue;
93  Tsocket::AcceptConnection(s, address);
94  }
95  }
96 
101  static bool Receive()
102  {
103  fd_set read_fd, write_fd;
104  struct timeval tv;
105 
106  FD_ZERO(&read_fd);
107  FD_ZERO(&write_fd);
108 
109 
110  for (Tsocket *cs : Tsocket::Iterate()) {
111  FD_SET(cs->sock, &read_fd);
112  FD_SET(cs->sock, &write_fd);
113  }
114 
115  /* take care of listener port */
116  for (auto &s : sockets) {
117  FD_SET(s.first, &read_fd);
118  }
119 
120  tv.tv_sec = tv.tv_usec = 0; // don't block at all.
121  if (select(FD_SETSIZE, &read_fd, &write_fd, nullptr, &tv) < 0) return false;
122 
123  /* accept clients.. */
124  for (auto &s : sockets) {
125  if (FD_ISSET(s.first, &read_fd)) AcceptClient(s.first);
126  }
127 
128  /* read stuff from clients */
129  for (Tsocket *cs : Tsocket::Iterate()) {
130  cs->writable = !!FD_ISSET(cs->sock, &write_fd);
131  if (FD_ISSET(cs->sock, &read_fd)) {
132  cs->ReceivePackets();
133  }
134  }
135  return _networking;
136  }
137 
143  static bool Listen(uint16_t port)
144  {
145  assert(sockets.empty());
146 
147  NetworkAddressList addresses;
148  GetBindAddresses(&addresses, port);
149 
150  for (NetworkAddress &address : addresses) {
151  address.Listen(SOCK_STREAM, &sockets);
152  }
153 
154  if (sockets.empty()) {
155  Debug(net, 0, "Could not start network: could not create listening socket");
156  ShowNetworkError(STR_NETWORK_ERROR_SERVER_START);
157  return false;
158  }
159 
160  return true;
161  }
162 
164  static void CloseListeners()
165  {
166  for (auto &s : sockets) {
167  closesocket(s.first);
168  }
169  sockets.clear();
170  Debug(net, 5, "[{}] Closed listeners", Tsocket::GetName());
171  }
172 };
173 
174 template <class Tsocket, PacketType Tfull_packet, PacketType Tban_packet> SocketList TCPListenHandler<Tsocket, Tfull_packet, Tban_packet>::sockets;
175 
176 #endif /* NETWORK_CORE_TCP_LISTEN_H */
std::vector< NetworkAddress > NetworkAddressList
Type for a list of addresses.
Definition: address.h:19
std::map< SOCKET, NetworkAddress > SocketList
Type for a mapping between address and socket.
Definition: address.h:21
Wrapper for (un)resolved network addresses; there's no reason to transform a numeric IP to a string a...
Definition: address.h:28
bool IsInNetmask(const std::string &netmask)
Checks whether this IP address is contained by the given netmask.
Definition: address.cpp:146
const std::string & GetHostname()
Get the hostname; in case it wasn't given the IPv4 dotted representation is given.
Definition: address.cpp:23
static NetworkError GetLast()
Get the last network error.
Template for TCP listeners.
Definition: tcp_listen.h:28
static bool Receive()
Handle the receiving of packets.
Definition: tcp_listen.h:101
static void AcceptClient(SOCKET ls)
Accepts clients from the sockets.
Definition: tcp_listen.h:73
static SocketList sockets
List of sockets we listen on.
Definition: tcp_listen.h:30
static bool Listen(uint16_t port)
Listen on a particular port.
Definition: tcp_listen.h:143
static void CloseListeners()
Close the sockets we're listening on.
Definition: tcp_listen.h:164
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
Definition: debug.h:37
uint32_t _frame_counter
The current frame.
Definition: network.cpp:78
bool _networking
are we in networking mode?
Definition: network.cpp:65
StringList _network_ban_list
The banned clients.
Definition: network.cpp:75
void GetBindAddresses(NetworkAddressList *addresses, uint16_t port)
Get the addresses to bind to.
Definition: network.cpp:718
bool SetNonBlocking([[maybe_unused]] SOCKET d)
Try to set the socket into non-blocking mode.
bool SetNoDelay([[maybe_unused]] SOCKET d)
Try to set the socket to not delay sending.
Internal entity of a packet.
Definition: packet.h:42
void PrepareToSend()
Writes the packet size from the raw packet from packet->size.
Definition: packet.cpp:66
ssize_t TransferOut(F transfer_function, D destination, Args &&... args)
Transfer data from the packet to the given function.
Definition: packet.h:139
Basic functions to receive and send TCP packets.