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