Allow windows using IPV6

This commit is contained in:
Benau 2019-08-21 09:19:05 +08:00
parent 1053c582fa
commit 02f8f6fadd
8 changed files with 179 additions and 56 deletions

View File

@ -22,7 +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_IPV6 "Allow create or connect to game server with ipv6 address, system enet will not be used." ON)
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)

View File

@ -59,7 +59,7 @@ typedef int socklen_t;
static enet_uint32 timeBase = 0;
#ifdef ENABLE_IPV6
extern void unixInitialize(void);
extern void stkInitialize(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);
@ -69,7 +69,7 @@ int
enet_initialize (void)
{
#ifdef ENABLE_IPV6
unixInitialize();
stkInitialize();
#endif
return 0;
}
@ -268,7 +268,7 @@ enet_socket_create (ENetSocketType type)
#endif
int socket_fd = socket (af_family, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
#ifdef ENABLE_IPV6
if (isIPV6())
if (isIPV6() && socket_fd != -1)
{
int no = 0;
// Allow ipv6 socket listen to ipv4 connection (as long as the host has ipv4 address)

View File

@ -8,6 +8,14 @@
#define ENET_BUILDING_LIB 1
#include "enet/enet.h"
#ifdef ENABLE_IPV6
#include <ws2tcpip.h>
extern void stkInitialize(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
static enet_uint32 timeBase = 0;
int
@ -29,6 +37,10 @@ enet_initialize (void)
timeBeginPeriod (1);
#ifdef ENABLE_IPV6
stkInitialize();
#endif
return 0;
}
@ -120,26 +132,42 @@ enet_address_get_host (const ENetAddress * address, char * name, size_t nameLeng
int
enet_socket_bind (ENetSocket socket, const ENetAddress * address)
{
struct sockaddr_in sin;
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
if (address != NULL)
#ifdef ENABLE_IPV6
// In STK we only bind port and listen to any address
if (isIPV6())
{
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
struct sockaddr_in6 sin;
memset (&sin, 0, sizeof (struct sockaddr_in6));
sin.sin6_family = AF_INET6;
sin.sin6_addr = in6addr_any;
sin.sin6_port = ENET_HOST_TO_NET_16 (address -> port);
return bind (socket, (struct sockaddr *) & sin,
sizeof (struct sockaddr_in6)) == SOCKET_ERROR ? -1 : 0;
}
else
#endif
{
sin.sin_port = 0;
sin.sin_addr.s_addr = INADDR_ANY;
}
struct sockaddr_in sin;
return bind (socket,
(struct sockaddr *) & sin,
sizeof (struct sockaddr_in)) == SOCKET_ERROR ? -1 : 0;
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
if (address != NULL)
{
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
}
else
{
sin.sin_port = 0;
sin.sin_addr.s_addr = INADDR_ANY;
}
return bind (socket,
(struct sockaddr *) & sin,
sizeof (struct sockaddr_in)) == SOCKET_ERROR ? -1 : 0;
}
}
int
@ -166,7 +194,26 @@ enet_socket_listen (ENetSocket socket, int backlog)
ENetSocket
enet_socket_create (ENetSocketType type)
{
return socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
#ifdef ENABLE_IPV6
int af_family = isIPV6() == 1 ? PF_INET6 : PF_INET;
#else
int af_family = PF_INET;
#endif
SOCKET socket_fd = socket (af_family, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
#ifdef ENABLE_IPV6
if (isIPV6() && socket_fd != INVALID_SOCKET)
{
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)
{
closesocket(socket_fd);
return INVALID_SOCKET;
}
}
#endif
return socket_fd;
}
int
@ -294,9 +341,36 @@ enet_socket_send (ENetSocket socket,
const ENetBuffer * buffers,
size_t bufferCount)
{
struct sockaddr* sin_send = NULL;
INT sin_size = 0;
struct sockaddr_in sin;
#ifdef ENABLE_IPV6
struct sockaddr_in6 sin6;
#endif
DWORD sentLength;
if (address != NULL)
{
#ifdef ENABLE_IPV6
if (isIPV6())
{
getIPV6FromMappedAddress(address, &sin6);
sin_send = (struct sockaddr*)&sin6;
sin_size = sizeof(struct sockaddr_in6);
}
else
#endif
{
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
sin_send = (struct sockaddr*)&sin;
sin_size = sizeof(struct sockaddr_in);
}
}
if (address != NULL)
{
memset (& sin, 0, sizeof (struct sockaddr_in));
@ -311,8 +385,8 @@ enet_socket_send (ENetSocket socket,
(DWORD) bufferCount,
& sentLength,
0,
address != NULL ? (struct sockaddr *) & sin : NULL,
address != NULL ? sizeof (struct sockaddr_in) : 0,
sin_send,
sin_size,
NULL,
NULL) == SOCKET_ERROR)
{
@ -331,17 +405,37 @@ enet_socket_receive (ENetSocket socket,
ENetBuffer * buffers,
size_t bufferCount)
{
INT sinLength = sizeof (struct sockaddr_in);
struct sockaddr* sin_recv = NULL;
INT sinLength = 0;
DWORD flags = 0,
recvLength;
struct sockaddr_in sin;
#ifdef ENABLE_IPV6
struct sockaddr_in6 sin6;
#endif
#ifdef ENABLE_IPV6
if (address != NULL)
{
if (isIPV6())
{
sin_recv = (struct sockaddr*)&sin6;
sinLength = sizeof(struct sockaddr_in6);
}
else
{
sin_recv = (struct sockaddr*)&sin;
sinLength = sizeof(struct sockaddr_in);
}
}
#endif
if (WSARecvFrom (socket,
(LPWSABUF) buffers,
(DWORD) bufferCount,
& recvLength,
& flags,
address != NULL ? (struct sockaddr *) & sin : NULL,
sin_recv,
address != NULL ? & sinLength : NULL,
NULL,
NULL) == SOCKET_ERROR)
@ -361,8 +455,17 @@ enet_socket_receive (ENetSocket socket,
if (address != NULL)
{
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
#ifdef ENABLE_IPV6
if (isIPV6())
{
getMappedFromIPV6(&sin6, address);
}
else
#endif
{
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
}
}
return (int) recvLength;

View File

@ -29,9 +29,9 @@
#include "network/protocol_manager.hpp"
#include "network/servers_manager.hpp"
#include "network/server.hpp"
#include "network/stk_ipv6.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"

View File

@ -23,7 +23,6 @@
#include "io/file_manager.hpp"
#include "network/event.hpp"
#include "network/game_setup.hpp"
#include "network/unix_ipv6.hpp"
#include "network/network_config.hpp"
#include "network/network_console.hpp"
#include "network/network_player_profile.hpp"
@ -33,6 +32,7 @@
#include "network/protocols/server_lobby.hpp"
#include "network/protocol_manager.hpp"
#include "network/server_config.hpp"
#include "network/stk_ipv6.hpp"
#include "network/stk_peer.hpp"
#include "tracks/track.hpp"
#include "tracks/track_manager.hpp"
@ -726,7 +726,7 @@ void STKHost::setPublicAddress()
Log::debug("STKHost", "Using STUN server %s", server_name.c_str());
uint64_t ping = StkTime::getMonoTimeMs();
std::string ipv4_string = getIPFromStun(
m_network->getENetHost()->socket, server_name, true/*ipv4*/);
(int)m_network->getENetHost()->socket, server_name, true/*ipv4*/);
TransportAddress addr(ipv4_string);
if (!addr.isUnset())
{
@ -737,7 +737,7 @@ void STKHost::setPublicAddress()
if (isIPV6())
{
m_public_ipv6_address = getIPFromStun(
m_network->getENetHost()->socket, server_name,
(int)m_network->getENetHost()->socket, server_name,
false/*ipv4*/);
if (m_public_ipv6_address.empty())
{
@ -755,16 +755,32 @@ void STKHost::setPublicAddress()
//-----------------------------------------------------------------------------
void STKHost::setPrivatePort()
{
struct sockaddr_in sin;
socklen_t len = sizeof(sin);
ENetHost *host = m_network->getENetHost();
if (getsockname(host->socket, (struct sockaddr *)&sin, &len) == -1)
if (isIPV6())
{
Log::error("STKHost", "Error while using getsockname().");
m_private_port = 0;
struct sockaddr_in6 sin6;
socklen_t len = sizeof(sin6);
ENetHost *host = m_network->getENetHost();
if (getsockname(host->socket, (struct sockaddr *)&sin6, &len) == -1)
{
Log::error("STKHost", "Error while using getsockname().");
m_private_port = 0;
}
else
m_private_port = ntohs(sin6.sin6_port);
}
else
m_private_port = ntohs(sin.sin_port);
{
struct sockaddr_in sin;
socklen_t len = sizeof(sin);
ENetHost *host = m_network->getENetHost();
if (getsockname(host->socket, (struct sockaddr *)&sin, &len) == -1)
{
Log::error("STKHost", "Error while using getsockname().");
m_private_port = 0;
}
else
m_private_port = ntohs(sin.sin_port);
}
} // setPrivatePort
//-----------------------------------------------------------------------------

View File

@ -51,12 +51,8 @@ std::string getIPV6ReadableFromIn6(const struct sockaddr_in6* in)
{
std::string result;
char ipv6[INET6_ADDRSTRLEN] = {};
#ifdef WIN32
struct sockaddr_in6 copied = *in;
inet_ntop(AF_INET6, &copied, ipv6, INET6_ADDRSTRLEN);
#else
inet_ntop(AF_INET6, &(in->sin6_addr), ipv6, INET6_ADDRSTRLEN);
#endif
struct in6_addr ipv6_addr = in->sin6_addr;
inet_ntop(AF_INET6, &ipv6_addr, ipv6, INET6_ADDRSTRLEN);
result = ipv6;
return result;
} // getIPV6ReadableFromIn6
@ -134,7 +130,7 @@ extern "C" int getaddrinfo_compat(const char* hostname,
}
#ifndef ENABLE_IPV6
#include "network/unix_ipv6.hpp"
#include "network/stk_ipv6.hpp"
// ----------------------------------------------------------------------------
int isIPV6()
{
@ -164,7 +160,7 @@ void addMappedAddress(const ENetAddress* ea, const struct sockaddr_in6* in6)
#else
#include "network/unix_ipv6.hpp"
#include "network/stk_ipv6.hpp"
#include "network/transport_address.hpp"
#include "utils/string_utils.hpp"
#include "utils/log.hpp"
@ -203,13 +199,13 @@ void setIPV6(int val)
} // setIPV6
// ----------------------------------------------------------------------------
void unixInitialize()
void stkInitialize()
{
// Clear previous setting, in case user changed wifi or mobile data
g_mapped_ipv6_used = 0;
g_ipv6 = 0;
g_mapped_ips.clear();
} // unixInitialize
} // stkInitialize
// ----------------------------------------------------------------------------
std::string getIPV6ReadableFromMappedAddress(const ENetAddress* ea)
@ -276,13 +272,21 @@ void getMappedFromIPV6(const struct sockaddr_in6* in6, ENetAddress* ea)
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)
uint8_t w0 = in6->sin6_addr.s6_addr[0];
uint8_t w1 = in6->sin6_addr.s6_addr[1];
uint8_t w2 = in6->sin6_addr.s6_addr[2];
uint8_t w3 = in6->sin6_addr.s6_addr[3];
uint8_t w4 = in6->sin6_addr.s6_addr[4];
uint8_t w5 = in6->sin6_addr.s6_addr[5];
uint8_t w6 = in6->sin6_addr.s6_addr[6];
uint8_t w7 = in6->sin6_addr.s6_addr[7];
uint8_t w8 = in6->sin6_addr.s6_addr[8];
uint8_t w9 = in6->sin6_addr.s6_addr[9];
uint8_t w10 = in6->sin6_addr.s6_addr[10];
uint8_t w11 = in6->sin6_addr.s6_addr[11];
if (w0 == 0 && w1 == 0 && w2 == 0 && w3 == 0 && w4 == 0 &&
w5 == 0 && w6 == 0 && w7 == 0 && w8 == 0 && w9 == 0 &&
w10 == 0xff && w11 == 0xff)
{
ea->host = ((in_addr*)(in6->sin6_addr.s6_addr + 12))->s_addr;
ea->port = ntohs(in6->sin6_port);

View File

@ -23,7 +23,7 @@ extern "C" {
#endif
int isIPV6();
void setIPV6(int val);
void unixInitialize();
void stkInitialize();
void getIPV6FromMappedAddress(const ENetAddress* ea, struct sockaddr_in6* in6);
void getMappedFromIPV6(const struct sockaddr_in6* in6, ENetAddress* ea);
void addMappedAddress(const ENetAddress* ea, const struct sockaddr_in6* in6);

View File

@ -23,9 +23,9 @@
#include "network/event.hpp"
#include "network/network_config.hpp"
#include "network/network_string.hpp"
#include "network/stk_ipv6.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"