OpenTTD Source  1.11.2
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:
37  static void AcceptClient(SOCKET ls)
38  {
39  for (;;) {
40  struct sockaddr_storage sin;
41  memset(&sin, 0, sizeof(sin));
42  socklen_t sin_len = sizeof(sin);
43  SOCKET s = accept(ls, (struct sockaddr*)&sin, &sin_len);
44  if (s == INVALID_SOCKET) return;
45 #ifdef __EMSCRIPTEN__
46  sin_len = FixAddrLenForEmscripten(sin);
47 #endif
48 
49  SetNonBlocking(s); // XXX error handling?
50 
51  NetworkAddress address(sin, sin_len);
52  DEBUG(net, 1, "[%s] Client connected from %s on frame %d", Tsocket::GetName(), address.GetHostname(), _frame_counter);
53 
54  SetNoDelay(s); // XXX error handling?
55 
56  /* Check if the client is banned */
57  bool banned = false;
58  for (const auto &entry : _network_ban_list) {
59  banned = address.IsInNetmask(entry.c_str());
60  if (banned) {
61  Packet p(Tban_packet);
62  p.PrepareToSend();
63 
64  DEBUG(net, 1, "[%s] Banned ip tried to join (%s), refused", Tsocket::GetName(), entry.c_str());
65 
66  if (send(s, (const char*)p.buffer, p.size, 0) < 0) {
67  DEBUG(net, 0, "send failed with error %s", NetworkError::GetLast().AsString());
68  }
69  closesocket(s);
70  break;
71  }
72  }
73  /* If this client is banned, continue with next client */
74  if (banned) continue;
75 
76  /* Can we handle a new client? */
77  if (!Tsocket::AllowConnection()) {
78  /* no more clients allowed?
79  * Send to the client that we are full! */
80  Packet p(Tfull_packet);
81  p.PrepareToSend();
82 
83  if (send(s, (const char*)p.buffer, p.size, 0) < 0) {
84  DEBUG(net, 0, "send failed with error %s", NetworkError::GetLast().AsString());
85  }
86  closesocket(s);
87 
88  continue;
89  }
90 
91  Tsocket::AcceptConnection(s, address);
92  }
93  }
94 
99  static bool Receive()
100  {
101  fd_set read_fd, write_fd;
102  struct timeval tv;
103 
104  FD_ZERO(&read_fd);
105  FD_ZERO(&write_fd);
106 
107 
108  for (Tsocket *cs : Tsocket::Iterate()) {
109  FD_SET(cs->sock, &read_fd);
110  FD_SET(cs->sock, &write_fd);
111  }
112 
113  /* take care of listener port */
114  for (auto &s : sockets) {
115  FD_SET(s.second, &read_fd);
116  }
117 
118  tv.tv_sec = tv.tv_usec = 0; // don't block at all.
119  if (select(FD_SETSIZE, &read_fd, &write_fd, nullptr, &tv) < 0) return false;
120 
121  /* accept clients.. */
122  for (auto &s : sockets) {
123  if (FD_ISSET(s.second, &read_fd)) AcceptClient(s.second);
124  }
125 
126  /* read stuff from clients */
127  for (Tsocket *cs : Tsocket::Iterate()) {
128  cs->writable = !!FD_ISSET(cs->sock, &write_fd);
129  if (FD_ISSET(cs->sock, &read_fd)) {
130  cs->ReceivePackets();
131  }
132  }
133  return _networking;
134  }
135 
141  static bool Listen(uint16 port)
142  {
143  assert(sockets.size() == 0);
144 
145  NetworkAddressList addresses;
146  GetBindAddresses(&addresses, port);
147 
148  for (NetworkAddress &address : addresses) {
149  address.Listen(SOCK_STREAM, &sockets);
150  }
151 
152  if (sockets.size() == 0) {
153  DEBUG(net, 0, "[server] could not start network: could not create listening socket");
154  ShowNetworkError(STR_NETWORK_ERROR_SERVER_START);
155  return false;
156  }
157 
158  return true;
159  }
160 
162  static void CloseListeners()
163  {
164  for (auto &s : sockets) {
165  closesocket(s.second);
166  }
167  sockets.clear();
168  DEBUG(net, 1, "[%s] closed listeners", Tsocket::GetName());
169  }
170 };
171 
172 template <class Tsocket, PacketType Tfull_packet, PacketType Tban_packet> SocketList TCPListenHandler<Tsocket, Tfull_packet, Tban_packet>::sockets;
173 
174 #endif /* NETWORK_CORE_TCP_LISTEN_H */
_frame_counter
uint32 _frame_counter
The current frame.
Definition: network.cpp:67
Packet::PrepareToSend
void PrepareToSend()
Writes the packet size from the raw packet from packet->size.
Definition: packet.cpp:61
GetBindAddresses
void GetBindAddresses(NetworkAddressList *addresses, uint16 port)
Get the addresses to bind to.
Definition: network.cpp:619
Packet::buffer
byte * buffer
The buffer of this packet, of basically variable length up to SEND_MTU.
Definition: packet.h:52
NetworkAddress::IsInNetmask
bool IsInNetmask(const char *netmask)
Checks whether this IP address is contained by the given netmask.
Definition: address.cpp:156
SmallMap< NetworkAddress, SOCKET >
TCPListenHandler
Template for TCP listeners.
Definition: tcp_listen.h:28
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
TCPListenHandler::Receive
static bool Receive()
Handle the receiving of packets.
Definition: tcp_listen.h:99
NetworkAddress::GetHostname
const char * GetHostname()
Get the hostname; in case it wasn't given the IPv4 dotted representation is given.
Definition: address.cpp:22
TCPListenHandler::sockets
static SocketList sockets
List of sockets we listen on.
Definition: tcp_listen.h:30
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
_networking
bool _networking
are we in networking mode?
Definition: network.cpp:52
Packet
Internal entity of a packet.
Definition: packet.h:40
NetworkAddress
Wrapper for (un)resolved network addresses; there's no reason to transform a numeric IP to a string a...
Definition: address.h:29
TCPListenHandler::AcceptClient
static void AcceptClient(SOCKET ls)
Accepts clients from the sockets.
Definition: tcp_listen.h:37
tcp.h
SetNonBlocking
bool SetNonBlocking(SOCKET d)
Try to set the socket into non-blocking mode.
Definition: os_abstraction.cpp:133
_network_ban_list
StringList _network_ban_list
The banned clients.
Definition: network.cpp:64
TCPListenHandler::CloseListeners
static void CloseListeners()
Close the sockets we're listening on.
Definition: tcp_listen.h:162
SetNoDelay
bool SetNoDelay(SOCKET d)
Try to set the socket to not delay sending.
Definition: os_abstraction.cpp:151
TCPListenHandler::Listen
static bool Listen(uint16 port)
Listen on a particular port.
Definition: tcp_listen.h:141