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