OpenTTD Source  12.0-beta2
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 
20 private:
21  ClientNetworkStunSocketHandler *stun_handler;
22  std::string token;
23  uint8 family;
24 
25 public:
31  NetworkStunConnecter(ClientNetworkStunSocketHandler *stun_handler, const std::string &connection_string, const std::string &token, uint8 family) :
33  stun_handler(stun_handler),
34  token(token),
35  family(family)
36  {
37  }
38 
39  void OnFailure() override
40  {
41  this->stun_handler->connecter = nullptr;
42 
43  /* Connection to STUN server failed. For example, the client doesn't
44  * support IPv6, which means it will fail that attempt. */
45 
46  _network_coordinator_client.StunResult(this->token, this->family, false);
47  }
48 
49  void OnConnect(SOCKET s) override
50  {
51  this->stun_handler->connecter = nullptr;
52 
53  assert(this->stun_handler->sock == INVALID_SOCKET);
54  this->stun_handler->sock = s;
55 
56  /* Store the local address; later connects will reuse it again.
57  * This is what makes STUN work for most NATs. */
58  this->stun_handler->local_addr = NetworkAddress::GetSockAddress(s);
59 
60  /* We leave the connection open till the real connection is setup later. */
61  }
62 };
63 
69 void ClientNetworkStunSocketHandler::Connect(const std::string &token, uint8 family)
70 {
71  this->token = token;
72  this->family = family;
73 
75 }
76 
83 std::unique_ptr<ClientNetworkStunSocketHandler> ClientNetworkStunSocketHandler::Stun(const std::string &token, uint8 family)
84 {
85  auto stun_handler = std::make_unique<ClientNetworkStunSocketHandler>();
86 
87  stun_handler->Connect(token, family);
88 
91  p->Send_string(token);
92  p->Send_uint8(family);
93 
94  stun_handler->SendPacket(p);
95 
96  return stun_handler;
97 }
98 
100 {
102 
103  /* If our connecter is still pending, shut it down too. Otherwise the
104  * callback of the connecter can call into us, and our object is most
105  * likely about to be destroyed. */
106  if (this->connecter != nullptr) {
107  this->connecter->Kill();
108  this->connecter = nullptr;
109  }
110 
112 }
113 
119 {
120  if (this->sock == INVALID_SOCKET) return;
121 
122  /* We never attempt to receive anything on a STUN socket. After
123  * connecting a STUN connection, the local address will be reused to
124  * to establish the connection with the real server. If we would be to
125  * read this socket, some OSes get confused and deliver us packets meant
126  * for the real connection. It appears most OSes play best when we simply
127  * never attempt to read it to start with (and the packets will remain
128  * available on the other socket).
129  * Protocol-wise, the STUN server will never send any packet back anyway. */
130 
131  this->CanSendReceive();
132  if (this->SendPackets() == SPS_ALL_SENT && !this->sent_result) {
133  /* We delay giving the GC the result this long, as to make sure we
134  * have sent the STUN packet first. This means the GC is more likely
135  * to have the result ready by the time our StunResult() packet
136  * arrives. */
137  this->sent_result = true;
139  }
140 }
ClientNetworkStunSocketHandler::connecter
TCPConnecter * connecter
Connecter instance.
Definition: network_stun.h:23
TCPConnecter::connection_string
std::string connection_string
Current address we are connecting to (before resolving).
Definition: tcp.h:100
TCPConnecter
"Helper" class for creating TCP connections in a non-blocking manner
Definition: tcp.h:71
ClientNetworkStunSocketHandler::family
uint8 family
Family of this STUN handler.
Definition: network_stun.h:19
network_stun.h
TCPConnecter::Kill
void Kill()
Kill this connecter.
Definition: tcp_connect.cpp:85
NetworkTCPSocketHandler::sock
SOCKET sock
The socket currently connected to.
Definition: tcp.h:39
NetworkStunConnectionString
const char * NetworkStunConnectionString()
Get the connection string for the STUN server from the environment variable OTTD_STUN_CS,...
Definition: config.cpp:46
Packet::Send_uint8
void Send_uint8(uint8 data)
Package a 8 bits integer in the packet.
Definition: packet.cpp:129
SPS_ALL_SENT
@ SPS_ALL_SENT
All packets in the queue are sent.
Definition: tcp.h:28
NetworkAddress::GetSockAddress
static NetworkAddress GetSockAddress(SOCKET sock)
Get the local address of a socket as NetworkAddress.
Definition: address.cpp:423
ClientNetworkStunSocketHandler::local_addr
NetworkAddress local_addr
Local addresses of the socket.
Definition: network_stun.h:24
NetworkStunConnecter::OnFailure
void OnFailure() override
Callback for when the connection attempt failed.
Definition: network_stun.cpp:39
network_coordinator.h
PACKET_STUN_SERCLI_STUN
@ PACKET_STUN_SERCLI_STUN
Send a STUN request to the STUN server.
Definition: tcp_stun.h:21
NETWORK_STUN_SERVER_PORT
static const uint16 NETWORK_STUN_SERVER_PORT
The default port of the STUN server (TCP)
Definition: config.h:24
NetworkTCPSocketHandler::CloseConnection
virtual NetworkRecvStatus CloseConnection(bool error=true)
This will put this socket handler in a close state.
Definition: tcp.cpp:65
ClientNetworkStunSocketHandler::Connect
void Connect(const std::string &token, uint8 family)
Connect to the STUN server over either IPv4 or IPv6.
Definition: network_stun.cpp:69
ClientNetworkCoordinatorSocketHandler::StunResult
void StunResult(const std::string &token, uint8 family, bool result)
Callback from the STUN connecter to inform the Game Coordinator about the result of the STUN.
Definition: network_coordinator.cpp:606
NetworkStunConnecter::OnConnect
void OnConnect(SOCKET s) override
Callback when the connection succeeded.
Definition: network_stun.cpp:49
Packet
Internal entity of a packet.
Definition: packet.h:44
ClientNetworkStunSocketHandler::token
std::string token
Token of this STUN handler.
Definition: network_stun.h:18
ClientNetworkStunSocketHandler::CloseConnection
NetworkRecvStatus CloseConnection(bool error=true) override
This will put this socket handler in a close state.
Definition: network_stun.cpp:99
NetworkTCPSocketHandler::SendPackets
SendPacketsState SendPackets(bool closing_down=false)
Sends all the buffered packets out for this client.
Definition: tcp.cpp:99
NetworkStunConnecter::NetworkStunConnecter
NetworkStunConnecter(ClientNetworkStunSocketHandler *stun_handler, const std::string &connection_string, const std::string &token, uint8 family)
Initiate the connecting.
Definition: network_stun.cpp:31
NetworkAddress
Wrapper for (un)resolved network addresses; there's no reason to transform a numeric IP to a string a...
Definition: address.h:30
NetworkTCPSocketHandler::CanSendReceive
bool CanSendReceive()
Check whether this socket can send or receive something.
Definition: tcp.cpp:218
ClientNetworkStunSocketHandler::SendReceive
void SendReceive()
Check whether we received/can send some data from/to the STUN server and when that's the case handle ...
Definition: network_stun.cpp:118
NetworkRecvStatus
NetworkRecvStatus
Status of a network client; reasons why a client has quit.
Definition: core.h:22
_network_coordinator_client
ClientNetworkCoordinatorSocketHandler _network_coordinator_client
The connection to the Game Coordinator.
Definition: network_coordinator.cpp:30
ClientNetworkStunSocketHandler::Stun
static std::unique_ptr< ClientNetworkStunSocketHandler > Stun(const std::string &token, uint8 family)
Send a STUN packet to the STUN server.
Definition: network_stun.cpp:83
error
void CDECL error(const char *s,...)
Error handling for fatal non-user errors.
Definition: openttd.cpp:132
network.h
Packet::Send_string
void Send_string(const std::string_view data)
Sends a string over the network.
Definition: packet.cpp:181
NETWORK_RECV_STATUS_OKAY
@ NETWORK_RECV_STATUS_OKAY
Everything is okay.
Definition: core.h:23
ClientNetworkStunSocketHandler::sent_result
bool sent_result
Did we sent the result of the STUN connection?
Definition: network_stun.h:20
NETWORK_COORDINATOR_VERSION
static const byte NETWORK_COORDINATOR_VERSION
What version of game-coordinator-protocol do we use?
Definition: config.h:53
ClientNetworkStunSocketHandler
Class for handling the client side of the STUN connection.
Definition: network_stun.h:16
NetworkStunConnecter
Connect to the STUN server.
Definition: network_stun.cpp:19