Fix #10490: Allow ships to exit depots if another is not moving at the exit point...
[openttd-github.git] / src / network / network_udp.cpp
blob478e804eaf84871b572f697b5e92b8bf2d2f8bb9
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 */
8 /**
9 * @file network_udp.cpp This file handles the UDP related communication.
11 * This is the GameServer <-> GameClient
12 * communication before the game is being joined.
15 #include "../stdafx.h"
16 #include "../timer/timer_game_calendar.h"
17 #include "../map_func.h"
18 #include "../debug.h"
19 #include "core/network_game_info.h"
20 #include "network_gamelist.h"
21 #include "network_internal.h"
22 #include "network_udp.h"
23 #include "network.h"
24 #include "../core/endian_func.hpp"
25 #include "../company_base.h"
26 #include "../rev.h"
27 #include "../newgrf_text.h"
28 #include "../strings_func.h"
29 #include "table/strings.h"
31 #include "core/udp.h"
33 #include "../safeguards.h"
35 static bool _network_udp_server; ///< Is the UDP server started?
36 static uint16_t _network_udp_broadcast; ///< Timeout for the UDP broadcasts.
38 /** Some information about a socket, which exists before the actual socket has been created to provide locking and the likes. */
39 struct UDPSocket {
40 const std::string name; ///< The name of the socket.
41 NetworkUDPSocketHandler *socket; ///< The actual socket, which may be nullptr when not initialized yet.
43 UDPSocket(const std::string &name) : name(name), socket(nullptr) {}
45 void CloseSocket()
47 this->socket->CloseSocket();
48 delete this->socket;
49 this->socket = nullptr;
52 void ReceivePackets()
54 this->socket->ReceivePackets();
58 static UDPSocket _udp_client("Client"); ///< udp client socket
59 static UDPSocket _udp_server("Server"); ///< udp server socket
61 ///*** Communication with clients (we are server) ***/
63 /** Helper class for handling all server side communication. */
64 class ServerNetworkUDPSocketHandler : public NetworkUDPSocketHandler {
65 protected:
66 void Receive_CLIENT_FIND_SERVER(Packet &p, NetworkAddress &client_addr) override;
67 public:
68 /**
69 * Create the socket.
70 * @param addresses The addresses to bind on.
72 ServerNetworkUDPSocketHandler(NetworkAddressList *addresses) : NetworkUDPSocketHandler(addresses) {}
73 virtual ~ServerNetworkUDPSocketHandler() = default;
76 void ServerNetworkUDPSocketHandler::Receive_CLIENT_FIND_SERVER(Packet &, NetworkAddress &client_addr)
78 Packet packet(PACKET_UDP_SERVER_RESPONSE);
79 this->SendPacket(packet, client_addr);
81 Debug(net, 7, "Queried from {}", client_addr.GetHostname());
84 ///*** Communication with servers (we are client) ***/
86 /** Helper class for handling all client side communication. */
87 class ClientNetworkUDPSocketHandler : public NetworkUDPSocketHandler {
88 protected:
89 void Receive_SERVER_RESPONSE(Packet &p, NetworkAddress &client_addr) override;
90 public:
91 virtual ~ClientNetworkUDPSocketHandler() = default;
94 void ClientNetworkUDPSocketHandler::Receive_SERVER_RESPONSE(Packet &, NetworkAddress &client_addr)
96 Debug(net, 3, "Server response from {}", client_addr.GetAddressAsString());
98 NetworkAddServer(client_addr.GetAddressAsString(false), false, true);
101 /** Broadcast to all ips */
102 static void NetworkUDPBroadCast(NetworkUDPSocketHandler *socket)
104 for (NetworkAddress &addr : _broadcast_list) {
105 Debug(net, 5, "Broadcasting to {}", addr.GetHostname());
107 Packet p(PACKET_UDP_CLIENT_FIND_SERVER);
108 socket->SendPacket(p, addr, true, true);
112 /** Find all servers */
113 void NetworkUDPSearchGame()
115 /* We are still searching.. */
116 if (_network_udp_broadcast > 0) return;
118 Debug(net, 3, "Searching server");
120 NetworkUDPBroadCast(_udp_client.socket);
121 _network_udp_broadcast = 300; // Stay searching for 300 ticks
124 /** Initialize the whole UDP bit. */
125 void NetworkUDPInitialize()
127 /* If not closed, then do it. */
128 if (_udp_server.socket != nullptr) NetworkUDPClose();
130 Debug(net, 3, "Initializing UDP listeners");
131 assert(_udp_client.socket == nullptr && _udp_server.socket == nullptr);
133 _udp_client.socket = new ClientNetworkUDPSocketHandler();
135 NetworkAddressList server;
136 GetBindAddresses(&server, _settings_client.network.server_port);
137 _udp_server.socket = new ServerNetworkUDPSocketHandler(&server);
139 _network_udp_server = false;
140 _network_udp_broadcast = 0;
143 /** Start the listening of the UDP server component. */
144 void NetworkUDPServerListen()
146 _network_udp_server = _udp_server.socket->Listen();
149 /** Close all UDP related stuff. */
150 void NetworkUDPClose()
152 _udp_client.CloseSocket();
153 _udp_server.CloseSocket();
155 _network_udp_server = false;
156 _network_udp_broadcast = 0;
157 Debug(net, 5, "Closed UDP listeners");
160 /** Receive the UDP packets. */
161 void NetworkBackgroundUDPLoop()
163 if (_network_udp_server) {
164 _udp_server.ReceivePackets();
165 } else {
166 _udp_client.ReceivePackets();
167 if (_network_udp_broadcast > 0) _network_udp_broadcast--;