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 
8 /**
9  * @file tcp_listen.h Basic functions to listen for TCP connections.
10  */
11 
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 
21 /**
22  * Template for TCP listeners.
23  * @param Tsocket      The class we create sockets for.
24  * @param Tfull_packet The packet type to return when we don't allow more sockets.
25  * @param Tban_packet  The packet type to return when the client is banned.
26  */
27 template <class Tsocket, PacketType Tfull_packet, PacketType Tban_packet>
28 class TCPListenHandler {
29 	/** List of sockets we listen on. */
30 	static SocketList sockets;
31 
32 public:
ValidateClient(SOCKET s,NetworkAddress & address)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(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(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 
69 	/**
70 	 * Accepts clients from the sockets.
71 	 * @param ls Socket to accept clients from.
72 	 */
AcceptClient(SOCKET ls)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 
97 	/**
98 	 * Handle the receiving of packets.
99 	 * @return true if everything went okay.
100 	 */
Receive()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.second, &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.second, &read_fd)) AcceptClient(s.second);
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 
138 	/**
139 	 * Listen on a particular port.
140 	 * @param port The port to listen on.
141 	 * @return true if listening succeeded.
142 	 */
Listen(uint16 port)143 	static bool Listen(uint16 port)
144 	{
145 		assert(sockets.size() == 0);
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.size() == 0) {
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 
163 	/** Close the sockets we're listening on. */
CloseListeners()164 	static void CloseListeners()
165 	{
166 		for (auto &s : sockets) {
167 			closesocket(s.second);
168 		}
169 		sockets.clear();
170 		Debug(net, 5, "[{}] Closed listeners", Tsocket::GetName());
171 	}
172 };
173 
174 template <class Tsocket, PacketType Tfull_packet, PacketType Tban_packet> SocketList TCPListenHandler<Tsocket, Tfull_packet, Tban_packet>::sockets;
175 
176 #endif /* NETWORK_CORE_TCP_LISTEN_H */
177