OpenTTD Source: src/network/core/tcp_listen.h Source File

OpenTTD Source 1.11.0-RC1

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>
28 class TCPListenHandler {
30 static SocketList sockets;
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 %d", GET_LAST_ERROR());
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 %d", GET_LAST_ERROR());
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 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 */
_frame_counter
uint32 _frame_counter
The current frame.
Definition: network.cpp:68
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:623
Packet::buffer
byte * buffer
The buffer of this packet, of basically variable length up to SEND_MTU.
Definition: packet.h:52
SetNoDelay
static bool SetNoDelay(SOCKET d)
Try to set the socket to not delay sending.
Definition: os_abstraction.h:200
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 >
SetNonBlocking
static bool SetNonBlocking(SOCKET d)
Try to set the socket into non-blocking mode.
Definition: os_abstraction.h:181
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
_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
_network_ban_list
StringList _network_ban_list
The banned clients.
Definition: network.cpp:65
TCPListenHandler::CloseListeners
static void CloseListeners()
Close the sockets we're listening on.
Definition: tcp_listen.h:162
TCPListenHandler::Listen
static bool Listen(uint16 port)
Listen on a particular port.
Definition: tcp_listen.h:141