Fix: server menu tooltip shouldn't show language info (#12955)
[openttd-github.git] / src / network / network_stun.cpp
blob2acd438e5636c4c9bba338a2bfd61aaae49e893e
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 /** @file network_stun.cpp STUN sending/receiving part of the network protocol. */
10 #include "../stdafx.h"
11 #include "../debug.h"
12 #include "network.h"
13 #include "network_coordinator.h"
14 #include "network_stun.h"
16 #include "../safeguards.h"
18 /** Connect to the STUN server. */
19 class NetworkStunConnecter : public TCPConnecter {
20 private:
21 ClientNetworkStunSocketHandler *stun_handler;
22 std::string token;
23 uint8_t family;
25 public:
26 /**
27 * Initiate the connecting.
28 * @param stun_handler The handler for this request.
29 * @param connection_string The address of the server.
31 NetworkStunConnecter(ClientNetworkStunSocketHandler *stun_handler, const std::string &connection_string, const std::string &token, uint8_t family) :
32 TCPConnecter(connection_string, NETWORK_STUN_SERVER_PORT, NetworkAddress(), family),
33 stun_handler(stun_handler),
34 token(token),
35 family(family)
39 void OnFailure() override
41 Debug(net, 9, "Stun::OnFailure(): family={}", this->family);
43 this->stun_handler->connecter = nullptr;
45 /* Connection to STUN server failed. For example, the client doesn't
46 * support IPv6, which means it will fail that attempt. */
48 _network_coordinator_client.StunResult(this->token, this->family, false);
51 void OnConnect(SOCKET s) override
53 Debug(net, 9, "Stun::OnConnect(): family={}", this->family);
55 this->stun_handler->connecter = nullptr;
57 assert(this->stun_handler->sock == INVALID_SOCKET);
58 this->stun_handler->sock = s;
60 /* Store the local address; later connects will reuse it again.
61 * This is what makes STUN work for most NATs. */
62 this->stun_handler->local_addr = NetworkAddress::GetSockAddress(s);
64 /* We leave the connection open till the real connection is setup later. */
68 /**
69 * Connect to the STUN server over either IPv4 or IPv6.
70 * @param token The token as received from the Game Coordinator.
71 * @param family What IP family to use.
73 void ClientNetworkStunSocketHandler::Connect(const std::string &token, uint8_t family)
75 this->token = token;
76 this->family = family;
78 Debug(net, 9, "Stun::Connect(): family={}", this->family);
80 this->connecter = TCPConnecter::Create<NetworkStunConnecter>(this, NetworkStunConnectionString(), token, family);
83 /**
84 * Send a STUN packet to the STUN server.
85 * @param token The token as received from the Game Coordinator.
86 * @param family What IP family this STUN request is for.
87 * @return The handler for this STUN request.
89 std::unique_ptr<ClientNetworkStunSocketHandler> ClientNetworkStunSocketHandler::Stun(const std::string &token, uint8_t family)
91 auto stun_handler = std::make_unique<ClientNetworkStunSocketHandler>();
93 stun_handler->Connect(token, family);
95 auto p = std::make_unique<Packet>(stun_handler.get(), PACKET_STUN_SERCLI_STUN);
96 p->Send_uint8(NETWORK_COORDINATOR_VERSION);
97 p->Send_string(token);
98 p->Send_uint8(family);
100 stun_handler->SendPacket(std::move(p));
102 return stun_handler;
105 NetworkRecvStatus ClientNetworkStunSocketHandler::CloseConnection(bool error)
107 NetworkStunSocketHandler::CloseConnection(error);
109 /* Also make sure any pending connecter is killed ASAP. */
110 if (this->connecter != nullptr) {
111 this->connecter->Kill();
112 this->connecter = nullptr;
115 return NETWORK_RECV_STATUS_OKAY;
118 ClientNetworkStunSocketHandler::~ClientNetworkStunSocketHandler()
120 if (this->connecter != nullptr) {
121 this->connecter->Kill();
122 this->connecter = nullptr;
127 * Check whether we received/can send some data from/to the STUN server and
128 * when that's the case handle it appropriately.
130 void ClientNetworkStunSocketHandler::SendReceive()
132 if (this->sock == INVALID_SOCKET) return;
134 /* We never attempt to receive anything on a STUN socket. After
135 * connecting a STUN connection, the local address will be reused to
136 * to establish the connection with the real server. If we would be to
137 * read this socket, some OSes get confused and deliver us packets meant
138 * for the real connection. It appears most OSes play best when we simply
139 * never attempt to read it to start with (and the packets will remain
140 * available on the other socket).
141 * Protocol-wise, the STUN server will never send any packet back anyway. */
143 this->CanSendReceive();
144 if (this->SendPackets() == SPS_ALL_SENT && !this->sent_result) {
145 /* We delay giving the GC the result this long, as to make sure we
146 * have sent the STUN packet first. This means the GC is more likely
147 * to have the result ready by the time our StunResult() packet
148 * arrives. */
149 this->sent_result = true;
150 _network_coordinator_client.StunResult(this->token, this->family, true);