OpenTTD Source 20251213-master-g1091fa6071
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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
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 "../../debug.h"
20
21#include "table/strings.h"
22
29template <class Tsocket, PacketType Tfull_packet, PacketType Tban_packet>
33
34public:
35 static bool ValidateClient(SOCKET s, NetworkAddress &address)
36 {
37 /* Check if the client is banned. */
38 for (const auto &entry : _network_ban_list) {
39 if (address.IsInNetmask(entry)) {
40 Packet p(nullptr, Tban_packet);
41 p.PrepareToSend();
42
43 Debug(net, 2, "[{}] Banned ip tried to join ({}), refused", Tsocket::GetName(), entry);
44
45 if (p.TransferOut(SocketSender{s}) < 0) {
46 Debug(net, 0, "[{}] send failed: {}", Tsocket::GetName(), NetworkError::GetLast().AsString());
47 }
48 closesocket(s);
49 return false;
50 }
51 }
52
53 /* Can we handle a new client? */
54 if (!Tsocket::AllowConnection()) {
55 /* No more clients allowed?
56 * Send to the client that we are full! */
57 Packet p(nullptr, Tfull_packet);
58 p.PrepareToSend();
59
60 if (p.TransferOut(SocketSender{s}) < 0) {
61 Debug(net, 0, "[{}] send failed: {}", Tsocket::GetName(), NetworkError::GetLast().AsString());
62 }
63 closesocket(s);
64
65 return false;
66 }
67
68 return true;
69 }
70
75 static void AcceptClient(SOCKET ls)
76 {
77 for (;;) {
78 struct sockaddr_storage sin{};
79 socklen_t sin_len = sizeof(sin);
80 SOCKET s = accept(ls, (struct sockaddr*)&sin, &sin_len);
81 if (s == INVALID_SOCKET) return;
82#ifdef __EMSCRIPTEN__
83 sin_len = FixAddrLenForEmscripten(sin);
84#endif
85
86 SetNonBlocking(s); // XXX error handling?
87
88 NetworkAddress address(sin, sin_len);
89 Debug(net, 3, "[{}] Client connected from {} on frame {}", Tsocket::GetName(), address.GetHostname(), _frame_counter);
90
91 SetNoDelay(s); // XXX error handling?
92
93 if (!Tsocket::ValidateClient(s, address)) continue;
94 Tsocket::AcceptConnection(s, address);
95 }
96 }
97
102 static bool Receive()
103 {
104 fd_set read_fd, write_fd;
105 struct timeval tv;
106
107 FD_ZERO(&read_fd);
108 FD_ZERO(&write_fd);
109
110
111 for (Tsocket *cs : Tsocket::Iterate()) {
112 FD_SET(cs->sock, &read_fd);
113 FD_SET(cs->sock, &write_fd);
114 }
115
116 /* take care of listener port */
117 for (auto &s : sockets) {
118 FD_SET(s.first, &read_fd);
119 }
120
121 tv.tv_sec = tv.tv_usec = 0; // don't block at all.
122 if (select(FD_SETSIZE, &read_fd, &write_fd, nullptr, &tv) < 0) return false;
123
124 /* accept clients.. */
125 for (auto &s : sockets) {
126 if (FD_ISSET(s.first, &read_fd)) AcceptClient(s.first);
127 }
128
129 /* read stuff from clients */
130 for (Tsocket *cs : Tsocket::Iterate()) {
131 cs->writable = !!FD_ISSET(cs->sock, &write_fd);
132 if (FD_ISSET(cs->sock, &read_fd)) {
133 cs->ReceivePackets();
134 }
135 }
136 return _networking;
137 }
138
144 static bool Listen(uint16_t port)
145 {
146 assert(sockets.empty());
147
148 NetworkAddressList addresses;
149 GetBindAddresses(&addresses, port);
150
151 for (NetworkAddress &address : addresses) {
152 address.Listen(SOCK_STREAM, &sockets);
153 }
154
155 if (sockets.empty()) {
156 Debug(net, 0, "Could not start network: could not create listening socket");
157 ShowNetworkError(STR_NETWORK_ERROR_SERVER_START);
158 return false;
159 }
160
161 return true;
162 }
163
165 static void CloseListeners()
166 {
167 for (auto &s : sockets) {
168 closesocket(s.first);
169 }
170 sockets.clear();
171 Debug(net, 5, "[{}] Closed listeners", Tsocket::GetName());
172 }
173};
174
175template <class Tsocket, PacketType Tfull_packet, PacketType Tban_packet> SocketList TCPListenHandler<Tsocket, Tfull_packet, Tban_packet>::sockets;
176
177#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:30
static bool Receive()
Handle the receiving of packets.
Definition tcp_listen.h:102
static void AcceptClient(SOCKET ls)
Accepts clients from the sockets.
Definition tcp_listen.h:75
static SocketList sockets
List of sockets we listen on.
Definition tcp_listen.h:32
static bool Listen(uint16_t port)
Listen on a particular port.
Definition tcp_listen.h:144
static void CloseListeners()
Close the sockets we're listening on.
Definition tcp_listen.h:165
#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:79
bool _networking
are we in networking mode?
Definition network.cpp:66
StringList _network_ban_list
The banned clients.
Definition network.cpp:76
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: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.