summaryrefslogtreecommitdiff
path: root/src/network/core
diff options
context:
space:
mode:
authorPatric Stout <truebrain@openttd.org>2021-05-05 10:47:01 +0200
committerPatric Stout <github@truebrain.nl>2021-07-20 19:57:23 +0200
commitfa1e27994dd1284f6fefbe08c47a5c4145ccf00d (patch)
treebbe8fab946192e5667ef176673590d2fae60e969 /src/network/core
parent8a361340037d6908c9a4df10aefdb58860a22b80 (diff)
downloadopenttd-fa1e27994dd1284f6fefbe08c47a5c4145ccf00d.tar.xz
Feature: allow the use of TURN to connect client and server together
TURN is a last resort, used only if all other methods failed. TURN is a relay approach to connect client and server together, where openttd.org (by default) is the middleman. It is very unlikely either the client or server cannot connect to the STUN server, as they are both already connected to the Game Coordinator. But in the odd case it does fail, estabilishing the connection fails without any further possibility to recover.
Diffstat (limited to 'src/network/core')
-rw-r--r--src/network/core/CMakeLists.txt2
-rw-r--r--src/network/core/config.h3
-rw-r--r--src/network/core/tcp_coordinator.cpp2
-rw-r--r--src/network/core/tcp_coordinator.h16
-rw-r--r--src/network/core/tcp_turn.cpp71
-rw-r--r--src/network/core/tcp_turn.h79
6 files changed, 172 insertions, 1 deletions
diff --git a/src/network/core/CMakeLists.txt b/src/network/core/CMakeLists.txt
index bcecad38c..756fa9e8f 100644
--- a/src/network/core/CMakeLists.txt
+++ b/src/network/core/CMakeLists.txt
@@ -30,6 +30,8 @@ add_files(
tcp_listen.h
tcp_stun.cpp
tcp_stun.h
+ tcp_turn.cpp
+ tcp_turn.h
udp.cpp
udp.h
)
diff --git a/src/network/core/config.h b/src/network/core/config.h
index 1b66c26cf..10ec070f0 100644
--- a/src/network/core/config.h
+++ b/src/network/core/config.h
@@ -22,6 +22,7 @@ static const char * const NETWORK_CONTENT_MIRROR_URL = "/bananas";
static const uint16 NETWORK_COORDINATOR_SERVER_PORT = 3976; ///< The default port of the Game Coordinator server (TCP)
static const uint16 NETWORK_STUN_SERVER_PORT = 3975; ///< The default port of the STUN server (TCP)
+static const uint16 NETWORK_TURN_SERVER_PORT = 3974; ///< The default port of the TURN server (TCP)
static const uint16 NETWORK_CONTENT_SERVER_PORT = 3978; ///< The default port of the content server (TCP)
static const uint16 NETWORK_CONTENT_MIRROR_PORT = 80; ///< The default port of the content mirror (TCP)
static const uint16 NETWORK_DEFAULT_PORT = 3979; ///< The default port of the game server (TCP & UDP)
@@ -49,7 +50,7 @@ static const uint16 COMPAT_MTU = 1460; ///< Numbe
static const byte NETWORK_GAME_ADMIN_VERSION = 1; ///< What version of the admin network do we use?
static const byte NETWORK_GAME_INFO_VERSION = 6; ///< What version of game-info do we use?
static const byte NETWORK_COMPANY_INFO_VERSION = 6; ///< What version of company info is this?
-static const byte NETWORK_COORDINATOR_VERSION = 4; ///< What version of game-coordinator-protocol do we use?
+static const byte NETWORK_COORDINATOR_VERSION = 5; ///< What version of game-coordinator-protocol do we use?
static const uint NETWORK_NAME_LENGTH = 80; ///< The maximum length of the server name and map name, in bytes including '\0'
static const uint NETWORK_COMPANY_NAME_LENGTH = 128; ///< The maximum length of the company name, in bytes including '\0'
diff --git a/src/network/core/tcp_coordinator.cpp b/src/network/core/tcp_coordinator.cpp
index 75f3f246f..44395a905 100644
--- a/src/network/core/tcp_coordinator.cpp
+++ b/src/network/core/tcp_coordinator.cpp
@@ -43,6 +43,7 @@ bool NetworkCoordinatorSocketHandler::HandlePacket(Packet *p)
case PACKET_COORDINATOR_SERCLI_STUN_RESULT: return this->Receive_SERCLI_STUN_RESULT(p);
case PACKET_COORDINATOR_GC_STUN_CONNECT: return this->Receive_GC_STUN_CONNECT(p);
case PACKET_COORDINATOR_GC_NEWGRF_LOOKUP: return this->Receive_GC_NEWGRF_LOOKUP(p);
+ case PACKET_COORDINATOR_GC_TURN_CONNECT: return this->Receive_GC_TURN_CONNECT(p);
default:
Debug(net, 0, "[tcp/coordinator] Received invalid packet type {}", type);
@@ -102,3 +103,4 @@ bool NetworkCoordinatorSocketHandler::Receive_GC_STUN_REQUEST(Packet *p) { retur
bool NetworkCoordinatorSocketHandler::Receive_SERCLI_STUN_RESULT(Packet *p) { return this->ReceiveInvalidPacket(PACKET_COORDINATOR_SERCLI_STUN_RESULT); }
bool NetworkCoordinatorSocketHandler::Receive_GC_STUN_CONNECT(Packet *p) { return this->ReceiveInvalidPacket(PACKET_COORDINATOR_GC_STUN_CONNECT); }
bool NetworkCoordinatorSocketHandler::Receive_GC_NEWGRF_LOOKUP(Packet *p) { return this->ReceiveInvalidPacket(PACKET_COORDINATOR_GC_NEWGRF_LOOKUP); }
+bool NetworkCoordinatorSocketHandler::Receive_GC_TURN_CONNECT(Packet *p) { return this->ReceiveInvalidPacket(PACKET_COORDINATOR_GC_TURN_CONNECT); }
diff --git a/src/network/core/tcp_coordinator.h b/src/network/core/tcp_coordinator.h
index b5395ad73..dea61cdec 100644
--- a/src/network/core/tcp_coordinator.h
+++ b/src/network/core/tcp_coordinator.h
@@ -42,6 +42,7 @@ enum PacketCoordinatorType {
PACKET_COORDINATOR_SERCLI_STUN_RESULT, ///< Client/server informs the Game Coordinator of the result of the STUN request.
PACKET_COORDINATOR_GC_STUN_CONNECT, ///< Game Coordinator tells client/server to connect() reusing the STUN local address.
PACKET_COORDINATOR_GC_NEWGRF_LOOKUP, ///< Game Coordinator informs client about NewGRF lookup table updates needed for GC_LISTING.
+ PACKET_COORDINATOR_GC_TURN_CONNECT, ///< Game Coordinator tells client/server to connect to a specific TURN server.
PACKET_COORDINATOR_END, ///< Must ALWAYS be on the end of this list!! (period)
};
@@ -53,6 +54,7 @@ enum ConnectionType {
CONNECTION_TYPE_ISOLATED, ///< The Game Coordinator failed to find a way to connect to your server. Nobody will be able to join.
CONNECTION_TYPE_DIRECT, ///< The Game Coordinator can directly connect to your server.
CONNECTION_TYPE_STUN, ///< The Game Coordinator can connect to your server via a STUN request.
+ CONNECTION_TYPE_TURN, ///< The Game Coordinator needs you to connect to a relay.
};
/**
@@ -288,6 +290,20 @@ protected:
*/
virtual bool Receive_GC_NEWGRF_LOOKUP(Packet *p);
+ /**
+ * Game Coordinator requests that we make a connection to the indicated
+ * peer, which is a TURN server.
+ *
+ * string Token to track the current connect request.
+ * uint8 Tracking number to track current connect request.
+ * string Ticket to hand over to the TURN server.
+ * string Connection string of the TURN server.
+ *
+ * @param p The packet that was just received.
+ * @return True upon success, otherwise false.
+ */
+ virtual bool Receive_GC_TURN_CONNECT(Packet *p);
+
bool HandlePacket(Packet *p);
public:
/**
diff --git a/src/network/core/tcp_turn.cpp b/src/network/core/tcp_turn.cpp
new file mode 100644
index 000000000..026b64194
--- /dev/null
+++ b/src/network/core/tcp_turn.cpp
@@ -0,0 +1,71 @@
+/*
+ * This file is part of OpenTTD.
+ * 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.
+ * 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.
+ * 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/>.
+ */
+
+/**
+ * @file tcp_turn.cpp Basic functions to receive and send TURN packets.
+ */
+
+#include "../../stdafx.h"
+#include "../../date_func.h"
+#include "../../debug.h"
+#include "tcp_turn.h"
+
+#include "../../safeguards.h"
+
+/**
+ * Handle the given packet, i.e. pass it to the right
+ * parser receive command.
+ * @param p the packet to handle
+ * @return true if we should immediately handle further packets, false otherwise
+ */
+bool NetworkTurnSocketHandler::HandlePacket(Packet *p)
+{
+ PacketTurnType type = (PacketTurnType)p->Recv_uint8();
+
+ switch (type) {
+ case PACKET_TURN_TURN_ERROR: return this->Receive_TURN_ERROR(p);
+ case PACKET_TURN_SERCLI_CONNECT: return this->Receive_SERCLI_CONNECT(p);
+ case PACKET_TURN_TURN_CONNECTED: return this->Receive_TURN_CONNECTED(p);
+
+ default:
+ Debug(net, 0, "[tcp/turn] Received invalid packet type {}", type);
+ return false;
+ }
+}
+
+/**
+ * Receive a packet at TCP level
+ * @return Whether at least one packet was received.
+ */
+bool NetworkTurnSocketHandler::ReceivePackets()
+{
+ Packet *p;
+ static const int MAX_PACKETS_TO_RECEIVE = 4;
+ int i = MAX_PACKETS_TO_RECEIVE;
+ while (--i != 0 && (p = this->ReceivePacket()) != nullptr) {
+ bool cont = this->HandlePacket(p);
+ delete p;
+ if (!cont) return true;
+ }
+
+ return i != MAX_PACKETS_TO_RECEIVE - 1;
+}
+
+/**
+ * Helper for logging receiving invalid packets.
+ * @param type The received packet type.
+ * @return Always false, as it's an error.
+ */
+bool NetworkTurnSocketHandler::ReceiveInvalidPacket(PacketTurnType type)
+{
+ Debug(net, 0, "[tcp/turn] Received illegal packet type {}", type);
+ return false;
+}
+
+bool NetworkTurnSocketHandler::Receive_TURN_ERROR(Packet *p) { return this->ReceiveInvalidPacket(PACKET_TURN_TURN_ERROR); }
+bool NetworkTurnSocketHandler::Receive_SERCLI_CONNECT(Packet *p) { return this->ReceiveInvalidPacket(PACKET_TURN_SERCLI_CONNECT); }
+bool NetworkTurnSocketHandler::Receive_TURN_CONNECTED(Packet *p) { return this->ReceiveInvalidPacket(PACKET_TURN_TURN_CONNECTED); }
diff --git a/src/network/core/tcp_turn.h b/src/network/core/tcp_turn.h
new file mode 100644
index 000000000..082373199
--- /dev/null
+++ b/src/network/core/tcp_turn.h
@@ -0,0 +1,79 @@
+/*
+ * This file is part of OpenTTD.
+ * 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.
+ * 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.
+ * 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/>.
+ */
+
+/**
+ * @file tcp_turn.h Basic functions to receive and send TCP packets to/from the TURN server.
+ */
+
+#ifndef NETWORK_CORE_TCP_TURN_H
+#define NETWORK_CORE_TCP_TURN_H
+
+#include "os_abstraction.h"
+#include "tcp.h"
+#include "packet.h"
+#include "game_info.h"
+
+/** Enum with all types of TCP TURN packets. The order MUST not be changed. **/
+enum PacketTurnType {
+ PACKET_TURN_TURN_ERROR, ///< TURN server is unable to relay.
+ PACKET_TURN_SERCLI_CONNECT, ///< Client or server is connecting to the TURN server.
+ PACKET_TURN_TURN_CONNECTED, ///< TURN server indicates the socket is now being relayed.
+ PACKET_TURN_END, ///< Must ALWAYS be on the end of this list!! (period)
+};
+
+/** Base socket handler for all TURN TCP sockets. */
+class NetworkTurnSocketHandler : public NetworkTCPSocketHandler {
+protected:
+ bool ReceiveInvalidPacket(PacketTurnType type);
+
+ /**
+ * TURN server was unable to connect the client or server based on the
+ * token. Most likely cause is an invalid token or the other side that
+ * hasn't connected in a reasonable amount of time.
+ *
+ * @param p The packet that was just received.
+ * @return True upon success, otherwise false.
+ */
+ virtual bool Receive_TURN_ERROR(Packet *p);
+
+ /**
+ * Client or servers wants to connect to the TURN server (on request by
+ * the Game Coordinator).
+ *
+ * uint8 Game Coordinator protocol version.
+ * string Token to track the current TURN request.
+ *
+ * @param p The packet that was just received.
+ * @return True upon success, otherwise false.
+ */
+ virtual bool Receive_SERCLI_CONNECT(Packet *p);
+
+ /**
+ * TURN server has connected client and server together and will now relay
+ * all packets to each other. No further TURN packets should be send over
+ * this socket, and the socket should be handed over to the game protocol.
+ *
+ * string Hostname of the peer. This can be used to check if a client is not banned etc.
+ *
+ * @param p The packet that was just received.
+ * @return True upon success, otherwise false.
+ */
+ virtual bool Receive_TURN_CONNECTED(Packet *p);
+
+ bool HandlePacket(Packet *p);
+public:
+ /**
+ * Create a new cs socket handler for a given cs.
+ * @param s the socket we are connected with.
+ * @param address IP etc. of the client.
+ */
+ NetworkTurnSocketHandler(SOCKET s = INVALID_SOCKET) : NetworkTCPSocketHandler(s) {}
+
+ bool ReceivePackets();
+};
+
+#endif /* NETWORK_CORE_TCP_TURN_H */