OpenTTD
tcp_listen.h
Go to the documentation of this file.
1 /* $Id$ */
2 
3 /*
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/>.
8  */
9 
14 #ifndef NETWORK_CORE_TCP_LISTEN_H
15 #define NETWORK_CORE_TCP_LISTEN_H
16 
17 #include "tcp.h"
18 #include "../network.h"
19 #include "../../core/pool_type.hpp"
20 #include "../../debug.h"
21 #include "table/strings.h"
22 
29 template <class Tsocket, PacketType Tfull_packet, PacketType Tban_packet>
33 
34 public:
39  static void AcceptClient(SOCKET ls)
40  {
41  for (;;) {
42  struct sockaddr_storage sin;
43  memset(&sin, 0, sizeof(sin));
44  socklen_t sin_len = sizeof(sin);
45  SOCKET s = accept(ls, (struct sockaddr*)&sin, &sin_len);
46  if (s == INVALID_SOCKET) return;
47 
48  SetNonBlocking(s); // XXX error handling?
49 
50  NetworkAddress address(sin, sin_len);
51  DEBUG(net, 1, "[%s] Client connected from %s on frame %d", Tsocket::GetName(), address.GetHostname(), _frame_counter);
52 
53  SetNoDelay(s); // XXX error handling?
54 
55  /* Check if the client is banned */
56  bool banned = false;
57  for (const auto &entry : _network_ban_list) {
58  banned = address.IsInNetmask(entry.c_str());
59  if (banned) {
60  Packet p(Tban_packet);
61  p.PrepareToSend();
62 
63  DEBUG(net, 1, "[%s] Banned ip tried to join (%s), refused", Tsocket::GetName(), entry.c_str());
64 
65  if (send(s, (const char*)p.buffer, p.size, 0) < 0) {
66  DEBUG(net, 0, "send failed with error %d", GET_LAST_ERROR());
67  }
68  closesocket(s);
69  break;
70  }
71  }
72  /* If this client is banned, continue with next client */
73  if (banned) continue;
74 
75  /* Can we handle a new client? */
76  if (!Tsocket::AllowConnection()) {
77  /* no more clients allowed?
78  * Send to the client that we are full! */
79  Packet p(Tfull_packet);
80  p.PrepareToSend();
81 
82  if (send(s, (const char*)p.buffer, p.size, 0) < 0) {
83  DEBUG(net, 0, "send failed with error %d", GET_LAST_ERROR());
84  }
85  closesocket(s);
86 
87  continue;
88  }
89 
90  Tsocket::AcceptConnection(s, address);
91  }
92  }
93 
98  static bool Receive()
99  {
100  fd_set read_fd, write_fd;
101  struct timeval tv;
102 
103  FD_ZERO(&read_fd);
104  FD_ZERO(&write_fd);
105 
106 
107  Tsocket *cs;
108  FOR_ALL_ITEMS_FROM(Tsocket, idx, cs, 0) {
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_ALL_ITEMS_FROM(Tsocket, idx, cs, 0) {
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  NetworkError(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 */
bool _networking
are we in networking mode?
Definition: network.cpp:54
Internal entity of a packet.
Definition: packet.h:42
void GetBindAddresses(NetworkAddressList *addresses, uint16 port)
Get the addresses to bind to.
Definition: network.cpp:633
void PrepareToSend()
Writes the packet size from the raw packet from packet->size.
Definition: packet.cpp:63
Template for TCP listeners.
Definition: tcp_listen.h:30
Wrapper for (un)resolved network addresses; there&#39;s no reason to transform a numeric IP to a string a...
Definition: address.h:29
static SocketList sockets
List of sockets we listen on.
Definition: tcp_listen.h:32
std::vector< NetworkAddress > NetworkAddressList
Type for a list of addresses.
Definition: address.h:20
static void AcceptClient(SOCKET ls)
Accepts clients from the sockets.
Definition: tcp_listen.h:39
byte * buffer
The buffer of this packet, of basically variable length up to SEND_MTU.
Definition: packet.h:54
static bool Receive()
Handle the receiving of packets.
Definition: tcp_listen.h:98
const char * GetHostname()
Get the hostname; in case it wasn&#39;t given the IPv4 dotted representation is given.
Definition: address.cpp:24
PacketSize size
The size of the whole packet for received packets.
Definition: packet.h:50
bool IsInNetmask(const char *netmask)
Checks whether this IP address is contained by the given netmask.
Definition: address.cpp:159
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:37
uint32 _frame_counter
The current frame.
Definition: network.cpp:70
static bool SetNonBlocking(SOCKET d)
Try to set the socket into non-blocking mode.
StringList _network_ban_list
The banned clients.
Definition: network.cpp:67
static void CloseListeners()
Close the sockets we&#39;re listening on.
Definition: tcp_listen.h:162
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:141