Initial work on IPV6 game server
This commit is contained in:
parent
1551bdaaaa
commit
c2c5c20d92
@ -22,6 +22,7 @@ option(SERVER_ONLY "Create a server only (i.e. no graphics or sound)" OFF)
|
||||
option(CHECK_ASSETS "Check if assets are installed in ../stk-assets" ON)
|
||||
option(USE_SYSTEM_ANGELSCRIPT "Use system angelscript instead of built-in angelscript. If you enable this option, make sure to use a compatible version." OFF)
|
||||
option(USE_SYSTEM_ENET "Use system ENet instead of the built-in version, when available." ON)
|
||||
option(USE_IPV6 "Allow create or connect to game server with ipv6 address, system enet will not be used." OFF)
|
||||
option(USE_SYSTEM_GLEW "Use system GLEW instead of the built-in version, when available." ON)
|
||||
option(USE_SYSTEM_WIIUSE "Use system WiiUse instead of the built-in version, when available." OFF)
|
||||
option(USE_SQLITE3 "Use sqlite to manage server stats and ban list." ON)
|
||||
@ -160,11 +161,15 @@ add_subdirectory("${PROJECT_SOURCE_DIR}/lib/bullet")
|
||||
include_directories("${PROJECT_SOURCE_DIR}/lib/bullet/src")
|
||||
|
||||
# Find system ENet library or build it if missing
|
||||
if((UNIX AND NOT APPLE) AND USE_SYSTEM_ENET)
|
||||
if((UNIX AND NOT APPLE) AND USE_SYSTEM_ENET AND NOT USE_IPV6)
|
||||
pkg_check_modules(ENET libenet>=1.3.4)
|
||||
endif()
|
||||
|
||||
if(ENET_FOUND)
|
||||
if (USE_IPV6)
|
||||
add_definitions(-DENABLE_IPV6)
|
||||
endif()
|
||||
|
||||
if(ENET_FOUND AND NOT USE_IPV6)
|
||||
include_directories(${ENET_INCLUDE_DIRS})
|
||||
else()
|
||||
# Fallback to built-in version
|
||||
|
@ -9,6 +9,10 @@
|
||||
#include "enet/time.h"
|
||||
#include "enet/enet.h"
|
||||
|
||||
#ifdef ENABLE_IPV6
|
||||
extern void removeMappedAddress(const ENetAddress* ea);
|
||||
#endif
|
||||
|
||||
static size_t commandSizes [ENET_PROTOCOL_COMMAND_COUNT] =
|
||||
{
|
||||
0,
|
||||
@ -84,6 +88,10 @@ enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event)
|
||||
event -> peer = peer;
|
||||
event -> data = peer -> eventData;
|
||||
|
||||
#ifdef ENABLE_IPV6
|
||||
removeMappedAddress(&peer->address);
|
||||
#endif
|
||||
|
||||
enet_peer_reset (peer);
|
||||
|
||||
return 1;
|
||||
@ -148,6 +156,10 @@ enet_protocol_notify_disconnect (ENetHost * host, ENetPeer * peer, ENetEvent * e
|
||||
event -> peer = peer;
|
||||
event -> data = 0;
|
||||
|
||||
#ifdef ENABLE_IPV6
|
||||
removeMappedAddress(&peer->address);
|
||||
#endif
|
||||
|
||||
enet_peer_reset (peer);
|
||||
}
|
||||
else
|
||||
|
@ -58,18 +58,18 @@ typedef int socklen_t;
|
||||
|
||||
static enet_uint32 timeBase = 0;
|
||||
|
||||
#ifdef IOS_STK
|
||||
extern void iOSInitialize(void);
|
||||
extern int isIPV6Only(void);
|
||||
extern void getSynthesizedAddress(const ENetAddress* ea, struct sockaddr_in6* in6);
|
||||
extern void getIPV4FromSynthesized(const struct sockaddr_in6* in6, ENetAddress* ea);
|
||||
#ifdef ENABLE_IPV6
|
||||
extern void unixInitialize(void);
|
||||
extern int isIPV6(void);
|
||||
extern void getIPV6FromMappedAddress(const ENetAddress* ea, struct sockaddr_in6* in6);
|
||||
extern void getMappedFromIPV6(const struct sockaddr_in6* in6, ENetAddress* ea);
|
||||
#endif
|
||||
|
||||
int
|
||||
enet_initialize (void)
|
||||
{
|
||||
#ifdef IOS_STK
|
||||
iOSInitialize();
|
||||
#ifdef ENABLE_IPV6
|
||||
unixInitialize();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@ -199,9 +199,9 @@ enet_address_get_host (const ENetAddress * address, char * name, size_t nameLeng
|
||||
int
|
||||
enet_socket_bind (ENetSocket socket, const ENetAddress * address)
|
||||
{
|
||||
#ifdef IOS_STK
|
||||
#ifdef ENABLE_IPV6
|
||||
// In STK we only bind port and listen to any address
|
||||
if (isIPV6Only())
|
||||
if (isIPV6())
|
||||
{
|
||||
struct sockaddr_in6 sin;
|
||||
memset (&sin, 0, sizeof (struct sockaddr_in6));
|
||||
@ -261,12 +261,26 @@ enet_socket_listen (ENetSocket socket, int backlog)
|
||||
ENetSocket
|
||||
enet_socket_create (ENetSocketType type)
|
||||
{
|
||||
#ifdef IOS_STK
|
||||
int af_family = isIPV6Only() == 1 ? PF_INET6 : PF_INET;
|
||||
#ifdef ENABLE_IPV6
|
||||
int af_family = isIPV6() == 1 ? PF_INET6 : PF_INET;
|
||||
#else
|
||||
int af_family = PF_INET;
|
||||
#endif
|
||||
return socket (af_family, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
|
||||
int socket_fd = socket (af_family, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
|
||||
#ifdef ENABLE_IPV6
|
||||
if (isIPV6())
|
||||
{
|
||||
int no = 0;
|
||||
// Allow ipv6 socket listen to ipv4 connection (as long as the host has ipv4 address)
|
||||
int ret = setsockopt(socket_fd, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&no, sizeof(no));
|
||||
if (ret != 0)
|
||||
{
|
||||
close(socket_fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return socket_fd;
|
||||
}
|
||||
|
||||
int
|
||||
@ -408,7 +422,7 @@ enet_socket_send (ENetSocket socket,
|
||||
{
|
||||
struct msghdr msgHdr;
|
||||
struct sockaddr_in sin;
|
||||
#ifdef IOS_STK
|
||||
#ifdef ENABLE_IPV6
|
||||
struct sockaddr_in6 sin6;
|
||||
#endif
|
||||
int sentLength;
|
||||
@ -417,10 +431,10 @@ enet_socket_send (ENetSocket socket,
|
||||
|
||||
if (address != NULL)
|
||||
{
|
||||
#ifdef IOS_STK
|
||||
if (isIPV6Only())
|
||||
#ifdef ENABLE_IPV6
|
||||
if (isIPV6())
|
||||
{
|
||||
getSynthesizedAddress(address, &sin6);
|
||||
getIPV6FromMappedAddress(address, &sin6);
|
||||
msgHdr.msg_name = & sin6;
|
||||
msgHdr.msg_namelen = sizeof (struct sockaddr_in6);
|
||||
}
|
||||
@ -462,7 +476,7 @@ enet_socket_receive (ENetSocket socket,
|
||||
{
|
||||
struct msghdr msgHdr;
|
||||
struct sockaddr_in sin;
|
||||
#ifdef IOS_STK
|
||||
#ifdef ENABLE_IPV6
|
||||
struct sockaddr_in6 sin6;
|
||||
#endif
|
||||
int recvLength;
|
||||
@ -471,8 +485,8 @@ enet_socket_receive (ENetSocket socket,
|
||||
|
||||
if (address != NULL)
|
||||
{
|
||||
#ifdef IOS_STK
|
||||
if (isIPV6Only())
|
||||
#ifdef ENABLE_IPV6
|
||||
if (isIPV6())
|
||||
{
|
||||
msgHdr.msg_name = & sin6;
|
||||
msgHdr.msg_namelen = sizeof (struct sockaddr_in6);
|
||||
@ -505,10 +519,10 @@ enet_socket_receive (ENetSocket socket,
|
||||
|
||||
if (address != NULL)
|
||||
{
|
||||
#ifdef IOS_STK
|
||||
if (isIPV6Only())
|
||||
#ifdef ENABLE_IPV6
|
||||
if (isIPV6())
|
||||
{
|
||||
getIPV4FromSynthesized(&sin6, address);
|
||||
getMappedFromIPV6(&sin6, address);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Modify this file to change the last-modified date when you add/remove a file.
|
||||
# This will then trigger a new cmake run automatically.
|
||||
# This will then trigger a new cmake run automatically.
|
||||
file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp")
|
||||
file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp")
|
||||
file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*")
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include "io/file_manager.hpp"
|
||||
#include "network/event.hpp"
|
||||
#include "network/game_setup.hpp"
|
||||
#include "network/ios_ipv6.hpp"
|
||||
#include "network/unix_ipv6.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "network/network_console.hpp"
|
||||
#include "network/network_player_profile.hpp"
|
||||
@ -370,8 +370,7 @@ void STKHost::shutdown()
|
||||
*/
|
||||
void STKHost::setPublicAddress()
|
||||
{
|
||||
#ifdef IOS_STK
|
||||
if (isIPV6Only())
|
||||
if (isIPV6())
|
||||
{
|
||||
// IPV6 only in iOS doesn't support connection to firewalled server,
|
||||
// so no need to test STUN
|
||||
@ -379,7 +378,7 @@ void STKHost::setPublicAddress()
|
||||
m_public_address = TransportAddress("169.254.0.0:65535");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::vector<std::pair<std::string, uint32_t> > untried_server;
|
||||
for (auto& p : UserConfigParams::m_stun_servers)
|
||||
untried_server.push_back(p);
|
||||
@ -714,8 +713,8 @@ void STKHost::mainLoop()
|
||||
|
||||
// A separate network connection (socket) to handle LAN requests.
|
||||
Network* direct_socket = NULL;
|
||||
if ((NetworkConfig::get()->isLAN() && is_server) ||
|
||||
NetworkConfig::get()->isPublicServer())
|
||||
if (!isIPV6() && ((NetworkConfig::get()->isLAN() && is_server) ||
|
||||
NetworkConfig::get()->isPublicServer()))
|
||||
{
|
||||
TransportAddress address(0, stk_config->m_server_discovery_port);
|
||||
ENetAddress eaddr = address.toEnetAddress();
|
||||
@ -811,7 +810,7 @@ void STKHost::mainLoop()
|
||||
{
|
||||
Log::info("STKHost", "%s %s with ping %d is higher"
|
||||
" than %d ms when not in game, kick.",
|
||||
p.second->getAddress().toString().c_str(),
|
||||
p.second->getRealAddress().c_str(),
|
||||
player_name.c_str(), ap, max_ping);
|
||||
p.second->setWarnedForHighPing(true);
|
||||
p.second->setDisconnected(true);
|
||||
@ -824,7 +823,7 @@ void STKHost::mainLoop()
|
||||
{
|
||||
Log::info("STKHost", "%s %s with ping %d is higher"
|
||||
" than %d ms.",
|
||||
p.second->getAddress().toString().c_str(),
|
||||
p.second->getRealAddress().c_str(),
|
||||
player_name.c_str(), ap, max_ping);
|
||||
p.second->setWarnedForHighPing(true);
|
||||
NetworkString msg(PROTOCOL_LOBBY_ROOM);
|
||||
@ -889,7 +888,7 @@ void STKHost::mainLoop()
|
||||
{
|
||||
Log::info("STKHost", "%s has not been validated for more"
|
||||
" than %f seconds, disconnect it by force.",
|
||||
it->second->getAddress().toString().c_str(),
|
||||
it->second->getRealAddress().c_str(),
|
||||
timeout);
|
||||
enet_host_flush(host);
|
||||
enet_peer_reset(it->first);
|
||||
@ -976,7 +975,8 @@ void STKHost::mainLoop()
|
||||
stk_event = new Event(&event, stk_peer);
|
||||
TransportAddress addr(event.peer->address);
|
||||
Log::info("STKHost", "%s has just connected. There are "
|
||||
"now %u peers.", addr.toString().c_str(), getPeerCount());
|
||||
"now %u peers.", stk_peer->getRealAddress().c_str(),
|
||||
getPeerCount());
|
||||
// Client always trust the server
|
||||
if (!is_server)
|
||||
stk_peer->setValidated();
|
||||
@ -994,15 +994,17 @@ void STKHost::mainLoop()
|
||||
}
|
||||
// Use the previous stk peer so protocol can see the network
|
||||
// profile and handle it for disconnection
|
||||
std::string addr;
|
||||
if (m_peers.find(event.peer) != m_peers.end())
|
||||
{
|
||||
stk_event = new Event(&event, m_peers.at(event.peer));
|
||||
std::shared_ptr<STKPeer>& peer = m_peers.at(event.peer);
|
||||
addr = peer->getRealAddress();
|
||||
stk_event = new Event(&event, peer);
|
||||
std::lock_guard<std::mutex> lock(m_peers_mutex);
|
||||
m_peers.erase(event.peer);
|
||||
}
|
||||
TransportAddress addr(event.peer->address);
|
||||
Log::info("STKHost", "%s has just disconnected. There are "
|
||||
"now %u peers.", addr.toString().c_str(), getPeerCount());
|
||||
"now %u peers.", addr.c_str(), getPeerCount());
|
||||
} // ENET_EVENT_TYPE_DISCONNECT
|
||||
|
||||
if (!stk_event && m_peers.find(event.peer) != m_peers.end())
|
||||
|
@ -25,7 +25,9 @@
|
||||
#include "network/network_string.hpp"
|
||||
#include "network/stk_host.hpp"
|
||||
#include "network/transport_address.hpp"
|
||||
#include "network/unix_ipv6.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/time.hpp"
|
||||
|
||||
#include <string.h>
|
||||
@ -35,6 +37,7 @@
|
||||
STKPeer::STKPeer(ENetPeer *enet_peer, STKHost* host, uint32_t host_id)
|
||||
: m_peer_address(enet_peer->address), m_host(host)
|
||||
{
|
||||
m_ipv6_address = getIPV6ReadableFromMappedAddress(&enet_peer->address);
|
||||
m_enet_peer = enet_peer;
|
||||
m_host_id = host_id;
|
||||
m_connected_time = StkTime::getMonoTimeMs();
|
||||
@ -198,3 +201,13 @@ void STKPeer::setCrypto(std::unique_ptr<Crypto>&& c)
|
||||
{
|
||||
m_crypto = std::move(c);
|
||||
} // setCrypto
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/* Return an IPV6 or IPV4 address, used for debug printing.
|
||||
*/
|
||||
std::string STKPeer::getRealAddress() const
|
||||
{
|
||||
return m_ipv6_address.empty() ? m_peer_address.toString() :
|
||||
std::string("[") + m_ipv6_address + "]:" +
|
||||
StringUtils::toString(m_peer_address.getPort());
|
||||
} // getRealAddress
|
||||
|
@ -100,6 +100,8 @@ protected:
|
||||
|
||||
std::string m_user_version;
|
||||
|
||||
std::string m_ipv6_address;
|
||||
|
||||
/** List of client capabilities set when connecting it, to determine
|
||||
* features available in same version. */
|
||||
std::set<std::string> m_client_capabilities;
|
||||
@ -120,6 +122,11 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
bool isConnected() const;
|
||||
const TransportAddress& getAddress() const { return m_peer_address; }
|
||||
// ------------------------------------------------------------------------
|
||||
const std::string& getIPV6Address() const { return m_ipv6_address; }
|
||||
// ------------------------------------------------------------------------
|
||||
std::string getRealAddress() const;
|
||||
// ------------------------------------------------------------------------
|
||||
bool isSamePeer(const STKPeer* peer) const;
|
||||
bool isSamePeer(const ENetPeer* peer) const;
|
||||
// ------------------------------------------------------------------------
|
||||
|
210
src/network/unix_ipv6.cpp
Normal file
210
src/network/unix_ipv6.cpp
Normal file
@ -0,0 +1,210 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2019 SuperTuxKart-Team
|
||||
//
|
||||
// This program 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; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef ENABLE_IPV6
|
||||
#include "network/unix_ipv6.hpp"
|
||||
// ----------------------------------------------------------------------------
|
||||
int isIPV6()
|
||||
{
|
||||
return 0;
|
||||
} // isIPV6
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
std::string getIPV6ReadableFromMappedAddress(const ENetAddress* ea)
|
||||
{
|
||||
return "";
|
||||
} // getIPV6ReadableFromMappedAddress
|
||||
|
||||
#else
|
||||
|
||||
#include "network/unix_ipv6.hpp"
|
||||
#include "network/transport_address.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/types.hpp"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <err.h>
|
||||
#include <netdb.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
// ============================================================================
|
||||
uint32_t g_mapped_ipv6_used;
|
||||
int g_ipv6;
|
||||
std::vector<std::pair<ENetAddress, struct sockaddr_in6> > g_mapped_ips;
|
||||
// ============================================================================
|
||||
int isIPV6()
|
||||
{
|
||||
return g_ipv6;
|
||||
} // isIPV6
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void setIPV6(int val)
|
||||
{
|
||||
g_ipv6 = val;
|
||||
} // setIPV6
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void unixInitialize()
|
||||
{
|
||||
// Clear previous setting, in case user changed wifi or mobile data
|
||||
g_mapped_ipv6_used = 0;
|
||||
g_ipv6 = 1;
|
||||
g_mapped_ips.clear();
|
||||
} // unixInitialize
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
std::string getIPV6ReadableFromIn6(const struct sockaddr_in6* in)
|
||||
{
|
||||
std::string result;
|
||||
char ipv6[INET6_ADDRSTRLEN] = {};
|
||||
inet_ntop(AF_INET6, &(in->sin6_addr), ipv6, INET6_ADDRSTRLEN);
|
||||
result = ipv6;
|
||||
return result;
|
||||
} // getIPV6ReadableFromIn6
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/* Called when a peer is disconnected and we remove its reference to the ipv6.
|
||||
*/
|
||||
void removeMappedAddress(const ENetAddress* ea)
|
||||
{
|
||||
auto it = std::find_if(g_mapped_ips.begin(), g_mapped_ips.end(),
|
||||
[ea](const std::pair<ENetAddress, struct sockaddr_in6>& addr)
|
||||
{
|
||||
return ea->host == addr.first.host && ea->port == addr.first.port;
|
||||
});
|
||||
if (it != g_mapped_ips.end())
|
||||
{
|
||||
TransportAddress addr(it->first);
|
||||
Log::debug("IPV6", "Removing %s, ipv4 address %s.",
|
||||
getIPV6ReadableFromIn6(&it->second).c_str(),
|
||||
addr.toString().c_str());
|
||||
g_mapped_ips.erase(it);
|
||||
Log::debug("IPV6", "Mapped address size now: %d.",
|
||||
g_mapped_ips.size());
|
||||
}
|
||||
} // removeMappedAddress
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
std::string getIPV6ReadableFromMappedAddress(const ENetAddress* ea)
|
||||
{
|
||||
std::string result;
|
||||
auto it = std::find_if(g_mapped_ips.begin(), g_mapped_ips.end(),
|
||||
[ea](const std::pair<ENetAddress, struct sockaddr_in6>& addr)
|
||||
{
|
||||
return ea->host == addr.first.host && ea->port == addr.first.port;
|
||||
});
|
||||
if (it != g_mapped_ips.end())
|
||||
result = getIPV6ReadableFromIn6(&it->second);
|
||||
return result;
|
||||
} // getIPV6ReadableFromMappedAddress
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Add a (fake or synthesized by ios / osx) ipv4 address and map it to an ipv6
|
||||
* one, used in client to set the game server address or server to initialize
|
||||
* host.
|
||||
*/
|
||||
void addMappedAddress(const ENetAddress* ea, const struct sockaddr_in6* in6)
|
||||
{
|
||||
g_mapped_ips.emplace_back(*ea, *in6);
|
||||
} // addMappedAddress
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/* This is called when enet needs to sent to an mapped ipv4 address, we look up
|
||||
* the map here and get the real ipv6 address, so you need to call
|
||||
* addMappedAddress above first (for client mostly).
|
||||
*/
|
||||
void getIPV6FromMappedAddress(const ENetAddress* ea, struct sockaddr_in6* in6)
|
||||
{
|
||||
auto it = std::find_if(g_mapped_ips.begin(), g_mapped_ips.end(),
|
||||
[ea](const std::pair<ENetAddress, struct sockaddr_in6>& addr)
|
||||
{
|
||||
return ea->host == addr.first.host && ea->port == addr.first.port;
|
||||
});
|
||||
if (it != g_mapped_ips.end())
|
||||
memcpy(in6, &it->second, sizeof(struct sockaddr_in6));
|
||||
else
|
||||
memset(in6, 0, sizeof(struct sockaddr_in6));
|
||||
} // getIPV6FromMappedAddress
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool sameIPV6(const struct sockaddr_in6* in_1, const struct sockaddr_in6* in_2)
|
||||
{
|
||||
// Check port first, then address
|
||||
if (in_1->sin6_port != in_2->sin6_port)
|
||||
return false;
|
||||
|
||||
const struct in6_addr* a = &(in_1->sin6_addr);
|
||||
const struct in6_addr* b = &(in_2->sin6_addr);
|
||||
for (unsigned i = 0; i < sizeof(struct in6_addr); i++)
|
||||
{
|
||||
if (a->s6_addr[i] != b->s6_addr[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} // sameIPV6
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/* This is called when enet recieved a packet from its socket, we create an
|
||||
* real ipv4 address out of it or a fake one if it's from ipv6 connection.
|
||||
*/
|
||||
void getMappedFromIPV6(const struct sockaddr_in6* in6, ENetAddress* ea)
|
||||
{
|
||||
auto it = std::find_if(g_mapped_ips.begin(), g_mapped_ips.end(),
|
||||
[in6](const std::pair<ENetAddress, struct sockaddr_in6>& addr)
|
||||
{
|
||||
return sameIPV6(in6, &addr.second);
|
||||
});
|
||||
if (it != g_mapped_ips.end())
|
||||
{
|
||||
*ea = it->first;
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t w0 = in6->sin6_addr.s6_addr16[0];
|
||||
uint16_t w1 = in6->sin6_addr.s6_addr16[1];
|
||||
uint16_t w2 = in6->sin6_addr.s6_addr16[2];
|
||||
uint16_t w3 = in6->sin6_addr.s6_addr16[3];
|
||||
uint16_t w4 = in6->sin6_addr.s6_addr16[4];
|
||||
uint16_t w5 = in6->sin6_addr.s6_addr16[5];
|
||||
if (w0 == 0 && w1 == 0 && w2 == 0 && w3 == 0 && w4 == 0 && w5 == 0xFFFF)
|
||||
{
|
||||
ea->host = ((in_addr*)(in6->sin6_addr.s6_addr + 12))->s_addr;
|
||||
ea->port = ntohs(in6->sin6_port);
|
||||
TransportAddress addr(*ea);
|
||||
addMappedAddress(ea, in6);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a fake ipv4 address of 0.x.x.x if it's a real ipv6 connection
|
||||
if (g_mapped_ipv6_used >= 16777215)
|
||||
g_mapped_ipv6_used = 0;
|
||||
TransportAddress addr(++g_mapped_ipv6_used, ntohs(in6->sin6_port));
|
||||
*ea = addr.toEnetAddress();
|
||||
Log::debug("IPV6", "Fake IPV4 address %s mapped to %s",
|
||||
addr.toString().c_str(), getIPV6ReadableFromIn6(in6).c_str());
|
||||
addMappedAddress(ea, in6);
|
||||
}
|
||||
} // getMappedFromIPV6
|
||||
|
||||
#endif
|
33
src/network/unix_ipv6.hpp
Normal file
33
src/network/unix_ipv6.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2019 SuperTuxKart-Team
|
||||
//
|
||||
// This program 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; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program 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 this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include <enet/enet.h>
|
||||
#include <string>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
int isIPV6();
|
||||
void setIPV6(int val);
|
||||
void unixInitialize();
|
||||
void removeMappedAddress(const ENetAddress* ea);
|
||||
void getIPV6FromMappedAddress(const ENetAddress* ea, struct sockaddr_in6* in6);
|
||||
void getMappedFromIPV6(const struct sockaddr_in6* in6, ENetAddress* ea);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
std::string getIPV6ReadableFromMappedAddress(const ENetAddress* ea);
|
Loading…
Reference in New Issue
Block a user