OpenTTD Source 20241224-master-gee860a5c8e
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
27template <class Tsocket, PacketType Tfull_packet, PacketType Tban_packet>
31
32public:
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
174template <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:20
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 SetNoDelay(SOCKET d)
Try to set the socket to not delay sending.
bool SetNonBlocking(SOCKET d)
Try to set the socket into non-blocking mode.
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.