OpenTTD Source 20250613-master-ga1786fa1f4
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 "../network_func.h"
18#include "../network_internal.h"
19#include "../../core/pool_type.hpp"
20#include "../../debug.h"
21
22#include "table/strings.h"
23
30template <class Tsocket, PacketType Tfull_packet, PacketType Tban_packet>
34
35public:
36 static bool ValidateClient(SOCKET s, NetworkAddress &address)
37 {
38 /* Check if the client is banned. */
39 for (const auto &entry : _network_ban_list) {
40 if (address.IsInNetmask(entry)) {
41 Packet p(nullptr, Tban_packet);
42 p.PrepareToSend();
43
44 Debug(net, 2, "[{}] Banned ip tried to join ({}), refused", Tsocket::GetName(), entry);
45
46 if (p.TransferOut(SocketSender{s}) < 0) {
47 Debug(net, 0, "[{}] send failed: {}", Tsocket::GetName(), NetworkError::GetLast().AsString());
48 }
49 closesocket(s);
50 return false;
51 }
52 }
53
54 /* Can we handle a new client? */
55 if (!Tsocket::AllowConnection()) {
56 /* No more clients allowed?
57 * Send to the client that we are full! */
58 Packet p(nullptr, Tfull_packet);
59 p.PrepareToSend();
60
61 if (p.TransferOut(SocketSender{s}) < 0) {
62 Debug(net, 0, "[{}] send failed: {}", Tsocket::GetName(), NetworkError::GetLast().AsString());
63 }
64 closesocket(s);
65
66 return false;
67 }
68
69 return true;
70 }
71
76 static void AcceptClient(SOCKET ls)
77 {
78 for (;;) {
79 struct sockaddr_storage sin{};
80 socklen_t sin_len = sizeof(sin);
81 SOCKET s = accept(ls, (struct sockaddr*)&sin, &sin_len);
82 if (s == INVALID_SOCKET) return;
83#ifdef __EMSCRIPTEN__
84 sin_len = FixAddrLenForEmscripten(sin);
85#endif
86
87 SetNonBlocking(s); // XXX error handling?
88
89 NetworkAddress address(sin, sin_len);
90 Debug(net, 3, "[{}] Client connected from {} on frame {}", Tsocket::GetName(), address.GetHostname(), _frame_counter);
91
92 SetNoDelay(s); // XXX error handling?
93
94 if (!Tsocket::ValidateClient(s, address)) continue;
95 Tsocket::AcceptConnection(s, address);
96 }
97 }
98
103 static bool Receive()
104 {
105 fd_set read_fd, write_fd;
106 struct timeval tv;
107
108 FD_ZERO(&read_fd);
109 FD_ZERO(&write_fd);
110
111
112 for (Tsocket *cs : Tsocket::Iterate()) {
113 FD_SET(cs->sock, &read_fd);
114 FD_SET(cs->sock, &write_fd);
115 }
116
117 /* take care of listener port */
118 for (auto &s : sockets) {
119 FD_SET(s.first, &read_fd);
120 }
121
122 tv.tv_sec = tv.tv_usec = 0; // don't block at all.
123 if (select(FD_SETSIZE, &read_fd, &write_fd, nullptr, &tv) < 0) return false;
124
125 /* accept clients.. */
126 for (auto &s : sockets) {
127 if (FD_ISSET(s.first, &read_fd)) AcceptClient(s.first);
128 }
129
130 /* read stuff from clients */
131 for (Tsocket *cs : Tsocket::Iterate()) {
132 cs->writable = !!FD_ISSET(cs->sock, &write_fd);
133 if (FD_ISSET(cs->sock, &read_fd)) {
134 cs->ReceivePackets();
135 }
136 }
137 return _networking;
138 }
139
145 static bool Listen(uint16_t port)
146 {
147 assert(sockets.empty());
148
149 NetworkAddressList addresses;
150 GetBindAddresses(&addresses, port);
151
152 for (NetworkAddress &address : addresses) {
153 address.Listen(SOCK_STREAM, &sockets);
154 }
155
156 if (sockets.empty()) {
157 Debug(net, 0, "Could not start network: could not create listening socket");
158 ShowNetworkError(STR_NETWORK_ERROR_SERVER_START);
159 return false;
160 }
161
162 return true;
163 }
164
166 static void CloseListeners()
167 {
168 for (auto &s : sockets) {
169 closesocket(s.first);
170 }
171 sockets.clear();
172 Debug(net, 5, "[{}] Closed listeners", Tsocket::GetName());
173 }
174};
175
176template <class Tsocket, PacketType Tfull_packet, PacketType Tban_packet> SocketList TCPListenHandler<Tsocket, Tfull_packet, Tban_packet>::sockets;
177
178#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
const std::string & GetHostname()
Get the hostname; in case it wasn't given the IPv4 dotted representation is given.
Definition address.cpp:24
bool IsInNetmask(std::string_view netmask)
Checks whether this IP address is contained by the given netmask.
Definition address.cpp:147
static NetworkError GetLast()
Get the last network error.
Template for TCP listeners.
Definition tcp_listen.h:31
static bool Receive()
Handle the receiving of packets.
Definition tcp_listen.h:103
static void AcceptClient(SOCKET ls)
Accepts clients from the sockets.
Definition tcp_listen.h:76
static SocketList sockets
List of sockets we listen on.
Definition tcp_listen.h:33
static bool Listen(uint16_t port)
Listen on a particular port.
Definition tcp_listen.h:145
static void CloseListeners()
Close the sockets we're listening on.
Definition tcp_listen.h:166
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
uint32_t _frame_counter
The current frame.
Definition network.cpp:80
bool _networking
are we in networking mode?
Definition network.cpp:67
StringList _network_ban_list
The banned clients.
Definition network.cpp:77
void GetBindAddresses(NetworkAddressList *addresses, uint16_t port)
Get the addresses to bind to.
Definition network.cpp:719
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:43
void PrepareToSend()
Writes the packet size from the raw packet from packet->size.
Definition packet.cpp:66
ssize_t TransferOut(F transfer_function)
Transfer data from the packet to the given function.
Definition packet.h:128
IPv4 addresses should be 4 bytes.
Basic functions to receive and send TCP packets.