OpenTTD Source 20241224-master-gee860a5c8e
network_stun.cpp
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 <http://www.gnu.org/licenses/>.
6 */
7
10#include "../stdafx.h"
11#include "../debug.h"
12#include "network.h"
13#include "network_coordinator.h"
14#include "network_stun.h"
15
16#include "../safeguards.h"
17
20private:
22 std::string token;
23 uint8_t family;
24
25public:
31 NetworkStunConnecter(ClientNetworkStunSocketHandler *stun_handler, const std::string &connection_string, const std::string &token, uint8_t family) :
33 stun_handler(stun_handler),
34 token(token),
35 family(family)
36 {
37 }
38
39 void OnFailure() override
40 {
41 Debug(net, 9, "Stun::OnFailure(): family={}", this->family);
42
43 this->stun_handler->connecter = nullptr;
44
45 /* Connection to STUN server failed. For example, the client doesn't
46 * support IPv6, which means it will fail that attempt. */
47
48 _network_coordinator_client.StunResult(this->token, this->family, false);
49 }
50
51 void OnConnect(SOCKET s) override
52 {
53 Debug(net, 9, "Stun::OnConnect(): family={}", this->family);
54
55 this->stun_handler->connecter = nullptr;
56
57 assert(this->stun_handler->sock == INVALID_SOCKET);
58 this->stun_handler->sock = s;
59
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);
63
64 /* We leave the connection open till the real connection is setup later. */
65 }
66};
67
73void ClientNetworkStunSocketHandler::Connect(const std::string &token, uint8_t family)
74{
75 this->token = token;
76 this->family = family;
77
78 Debug(net, 9, "Stun::Connect(): family={}", this->family);
79
80 this->connecter = TCPConnecter::Create<NetworkStunConnecter>(this, NetworkStunConnectionString(), token, family);
81}
82
89std::unique_ptr<ClientNetworkStunSocketHandler> ClientNetworkStunSocketHandler::Stun(const std::string &token, uint8_t family)
90{
91 auto stun_handler = std::make_unique<ClientNetworkStunSocketHandler>();
92
93 stun_handler->Connect(token, family);
94
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);
99
100 stun_handler->SendPacket(std::move(p));
101
102 return stun_handler;
103}
104
106{
108
109 /* Also make sure any pending connecter is killed ASAP. */
110 if (this->connecter != nullptr) {
111 this->connecter->Kill();
112 this->connecter = nullptr;
113 }
114
116}
117
118ClientNetworkStunSocketHandler::~ClientNetworkStunSocketHandler()
119{
120 if (this->connecter != nullptr) {
121 this->connecter->Kill();
122 this->connecter = nullptr;
123 }
124}
125
131{
132 if (this->sock == INVALID_SOCKET) return;
133
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. */
142
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;
151 }
152}
void StunResult(const std::string &token, uint8_t family, bool result)
Callback from the STUN connecter to inform the Game Coordinator about the result of the STUN.
Class for handling the client side of the STUN connection.
void Connect(const std::string &token, uint8_t family)
Connect to the STUN server over either IPv4 or IPv6.
std::string token
Token of this STUN handler.
void SendReceive()
Check whether we received/can send some data from/to the STUN server and when that's the case handle ...
uint8_t family
Family of this STUN handler.
static std::unique_ptr< ClientNetworkStunSocketHandler > Stun(const std::string &token, uint8_t family)
Send a STUN packet to the STUN server.
std::shared_ptr< TCPConnecter > connecter
Connecter instance.
NetworkAddress local_addr
Local addresses of the socket.
NetworkRecvStatus CloseConnection(bool error=true) override
This will put this socket handler in a close state.
bool sent_result
Did we sent the result of the STUN connection?
Wrapper for (un)resolved network addresses; there's no reason to transform a numeric IP to a string a...
Definition address.h:28
static NetworkAddress GetSockAddress(SOCKET sock)
Get the local address of a socket as NetworkAddress.
Definition address.cpp:419
Connect to the STUN server.
void OnConnect(SOCKET s) override
Callback when the connection succeeded.
NetworkStunConnecter(ClientNetworkStunSocketHandler *stun_handler, const std::string &connection_string, const std::string &token, uint8_t family)
Initiate the connecting.
void OnFailure() override
Callback for when the connection attempt failed.
virtual NetworkRecvStatus CloseConnection(bool error=true)
This will put this socket handler in a close state.
Definition tcp.cpp:51
SOCKET sock
The socket currently connected to.
Definition tcp.h:38
SendPacketsState SendPackets(bool closing_down=false)
Sends all the buffered packets out for this client.
Definition tcp.cpp:86
bool CanSendReceive()
Check whether this socket can send or receive something.
Definition tcp.cpp:204
"Helper" class for creating TCP connections in a non-blocking manner
Definition tcp.h:70
std::string connection_string
Current address we are connecting to (before resolving).
Definition tcp.h:99
const char * NetworkStunConnectionString()
Get the connection string for the STUN server from the environment variable OTTD_STUN_CS,...
Definition config.cpp:45
static const uint16_t NETWORK_STUN_SERVER_PORT
The default port of the STUN server (TCP)
Definition config.h:22
static const uint8_t NETWORK_COORDINATOR_VERSION
What version of game-coordinator-protocol do we use?
Definition config.h:50
NetworkRecvStatus
Status of a network client; reasons why a client has quit.
Definition core.h:23
@ NETWORK_RECV_STATUS_OKAY
Everything is okay.
Definition core.h:24
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
Definition debug.h:37
Basic functions/variables used all over the place.
ClientNetworkCoordinatorSocketHandler _network_coordinator_client
The connection to the Game Coordinator.
Part of the network protocol handling Game Coordinator requests.
Part of the network protocol handling STUN requests.
@ SPS_ALL_SENT
All packets in the queue are sent.
Definition tcp.h:27
@ PACKET_STUN_SERCLI_STUN
Send a STUN request to the STUN server.
Definition tcp_stun.h:21