Add ipv6 info to game server

This commit is contained in:
Benau 2019-08-21 00:17:31 +08:00
parent a92b9abf54
commit ab56a4fa8b
5 changed files with 96 additions and 11 deletions

View File

@ -31,6 +31,7 @@
#include "network/server.hpp"
#include "network/stk_host.hpp"
#include "network/stk_peer.hpp"
#include "network/unix_ipv6.hpp"
#include "online/xml_request.hpp"
#include "states_screens/online/networking_lobby.hpp"
#include "utils/time.hpp"
@ -38,6 +39,12 @@
#include "utils/string_utils.hpp"
#include "utils/translation.hpp"
#ifdef WIN32
# include <ws2tcpip.h>
#else
# include <netdb.h>
#endif
#include <algorithm>
// ============================================================================
std::weak_ptr<bool> ConnectToServer::m_previous_unjoin;
@ -84,8 +91,14 @@ void ConnectToServer::setup()
Log::info("ConnectToServer", "SETUP");
// In case of LAN or client-server we already have the server's
// and our ip address, so we can immediately start requesting a connection.
m_state = NetworkConfig::get()->isLAN() ?
GOT_SERVER_ADDRESS : SET_PUBLIC_ADDRESS;
if (NetworkConfig::get()->isLAN())
{
m_state = GOT_SERVER_ADDRESS;
if (m_server->useIPV6Connection())
setIPV6(1);
}
else
m_state = SET_PUBLIC_ADDRESS;
} // setup
// ----------------------------------------------------------------------------
@ -211,6 +224,11 @@ void ConnectToServer::asynchronousUpdate()
}
servers.clear();
}
if (m_server->useIPV6Connection())
{
// Disable STUN if using ipv6 (check in setPublicAddress)
setIPV6(1);
}
if (m_server->supportsEncryption())
{
STKHost::get()->setPublicAddress();
@ -247,11 +265,19 @@ void ConnectToServer::asynchronousUpdate()
// direct connection to server first, if failed than use the one
// that has stun mapped, the first 8 seconds allow the server to
// start the connect to peer protocol first before the port is
// remapped
if (tryConnect(2000, 4, true/*another_port*/))
break;
if (!tryConnect(2000, 11))
m_state = DONE;
// remapped. IPV6 has no stun so try once with any port
if (isIPV6())
{
if (!tryConnect(2000, 15, true/*another_port*/, true/*ipv6*/))
m_state = DONE;
}
else
{
if (tryConnect(2000, 4, true/*another_port*/))
break;
if (!tryConnect(2000, 11))
m_state = DONE;
}
break;
}
case DONE:
@ -337,7 +363,8 @@ int ConnectToServer::interceptCallback(ENetHost* host, ENetEvent* event)
} // interceptCallback
// ----------------------------------------------------------------------------
bool ConnectToServer::tryConnect(int timeout, int retry, bool another_port)
bool ConnectToServer::tryConnect(int timeout, int retry, bool another_port,
bool ipv6)
{
m_retry_count = retry;
ENetEvent event;
@ -352,20 +379,51 @@ bool ConnectToServer::tryConnect(int timeout, int retry, bool another_port)
m_done_intecept = false;
nw->getENetHost()->intercept = ConnectToServer::interceptCallback;
std::string connecting_address = m_server_address.toString();
if (ipv6)
{
struct addrinfo hints;
struct addrinfo* res = NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_STREAM;
if (getaddrinfo(m_server->getIPV6Address().c_str(),
StringUtils::toString(m_server->getAddress().getPort()).c_str(),
&hints, &res) != 0 || res == NULL)
return false;
for (const struct addrinfo* addr = res; addr != NULL;
addr = addr->ai_next)
{
if (addr->ai_family == AF_INET6)
{
struct sockaddr_in6* ipv6 =
(struct sockaddr_in6*)addr->ai_addr;
ENetAddress addr = m_server_address.toEnetAddress();
connecting_address = std::string("[") +
m_server->getIPV6Address() + "]:" +
StringUtils::toString(addr.port);
addMappedAddress(&addr, ipv6);
break;
}
}
freeaddrinfo(res);
}
while (--m_retry_count >= 0 && !ProtocolManager::lock()->isExiting())
{
ENetPeer* p = nw->connectTo(m_server_address);
if (!p)
break;
Log::info("ConnectToServer", "Trying connecting to %s from port %d, "
"retry remain: %d", m_server_address.toString().c_str(),
"retry remain: %d", connecting_address.c_str(),
nw->getENetHost()->address.port, m_retry_count);
while (enet_host_service(nw->getENetHost(), &event, timeout) != 0)
{
if (event.type == ENET_EVENT_TYPE_CONNECT)
{
Log::info("ConnectToServer", "Connected to %s",
m_server_address.toString().c_str());
connecting_address.c_str());
nw->getENetHost()->intercept = NULL;
STKHost::get()->initClientNetwork(event, nw);
m_state = DONE;

View File

@ -49,7 +49,8 @@ private:
void getClientServerInfo();
void registerWithSTKServer();
bool tryConnect(int timeout, int retry, bool another_port = false);
bool tryConnect(int timeout, int retry, bool another_port = false,
bool ipv6 = false);
static TransportAddress m_server_address;
static int interceptCallback(ENetHost* host, ENetEvent* event);
static int m_retry_count;

View File

@ -36,6 +36,7 @@ Server::Server(const XMLNode& server_info) : m_supports_encrytion(true)
{
const XMLNode& xml = *server_info.getNode("server-info");
m_ipv6_connection = false;
m_name = "";
m_server_id = 0;
m_current_players = 0;
@ -57,6 +58,7 @@ Server::Server(const XMLNode& server_info) : m_supports_encrytion(true)
xml.get("max_players", &m_max_players);
xml.get("current_players", &m_current_players);
xml.get("current_track", &m_current_track);
xml.get("ipv6", &m_ipv6_address);
uint32_t ip;
xml.get("ip", &ip);
m_address.setIP(ip);
@ -170,6 +172,7 @@ Server::Server(unsigned server_id, const core::stringw &name, int max_players,
bool game_started, const std::string& current_track)
: m_supports_encrytion(false)
{
m_ipv6_connection = false;
m_name = name;
m_lower_case_name = StringUtils::toLowerCase(StringUtils::wideToUtf8(name));
m_server_id = server_id;

View File

@ -55,6 +55,8 @@ protected:
std::string m_lower_case_player_names;
std::string m_ipv6_address;
uint32_t m_server_id;
uint32_t m_server_owner;
@ -92,6 +94,8 @@ protected:
bool m_game_started;
bool m_ipv6_connection;
std::vector<std::tuple<
/*rank*/int, core::stringw, /*scores*/double, /*playing time*/float
> > m_players;
@ -166,5 +170,19 @@ public:
Track* getCurrentTrack() const;
// ------------------------------------------------------------------------
const std::string& getCountryCode() const { return m_country_code; }
// ------------------------------------------------------------------------
void setIPV6Connection(bool val)
{
if (m_ipv6_address.empty())
m_ipv6_connection = false;
else
m_ipv6_connection = val;
}
// ------------------------------------------------------------------------
bool useIPV6Connection() const { return m_ipv6_connection; }
// ------------------------------------------------------------------------
void setIPV6Address(const std::string& addr) { m_ipv6_address = addr; }
// ------------------------------------------------------------------------
const std::string& getIPV6Address() const { return m_ipv6_address; }
}; // Server
#endif // HEADER_SERVER_HPP

View File

@ -157,6 +157,11 @@ void removeDisconnectedMappedAddress()
{
} // removeDisconnectedMappedAddress
// ----------------------------------------------------------------------------
void addMappedAddress(const ENetAddress* ea, const struct sockaddr_in6* in6)
{
} // addMappedAddress
#else
#include "network/unix_ipv6.hpp"