Update ENetAddress to use 5 uint32_t to store IP
ENetAddress ea = {} will allow to listen to any IPv4 or IPv6 address when using system or bundled enet The last uint32_t is for IPv6 scope id (required for IPv6 only lan servers)
This commit is contained in:
parent
8995491eb6
commit
fa0da462fb
@ -81,7 +81,7 @@ The current server configuration xml looks like this:
|
||||
<!-- Disable it to turn off all stun related code in server, it allows for saving of server resources if your server is not behind a firewall. -->
|
||||
<firewalled-server value="true" />
|
||||
|
||||
<!-- Enable to allow IPv6 connection if you have a public IPv6 address. STK currently uses dual-stack mode which requires server to have both IPv4 and IPv6 and listen to same port. If STK detects your server has no public IPv6 address or port differs between IPv4 and IPv6 then it will use IPv4 only socket. -->
|
||||
<!-- Enable to allow IPv6 connection if you have a public IPv6 address. STK currently uses dual-stack mode which requires server to have both IPv4 and IPv6 and listen to same port. If STK detects your server has no public IPv6 address or port differs between IPv4 and IPv6 then it will use IPv4 only socket. For system which doesn't support dual-stack socket (like OpenBSD) you may fail to be connected by IPv4 clients. -->
|
||||
<ipv6-server value="true" />
|
||||
|
||||
<!-- No server owner in lobby which can control the starting of game or kick any players. -->
|
||||
|
@ -87,7 +87,7 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL
|
||||
host -> commandCount = 0;
|
||||
host -> bufferCount = 0;
|
||||
host -> checksum = NULL;
|
||||
host -> receivedAddress.host = ENET_HOST_ANY;
|
||||
host -> receivedAddress.host = (ENetIP) { 0 };
|
||||
host -> receivedAddress.port = 0;
|
||||
host -> receivedData = NULL;
|
||||
host -> receivedDataLength = 0;
|
||||
|
@ -76,6 +76,19 @@ typedef enum _ENetSocketShutdown
|
||||
#define ENET_HOST_BROADCAST 0xFFFFFFFFU
|
||||
#define ENET_PORT_ANY 0
|
||||
|
||||
typedef struct _ENetIP
|
||||
{
|
||||
enet_uint32 p0; // uint32_t here for IPv4, or 4 uint32_t IPv6 address
|
||||
enet_uint32 p1;
|
||||
enet_uint32 p2;
|
||||
enet_uint32 p3;
|
||||
enet_uint32 p4; // sockaddr_in6 sin6_scope_id (required for local link address)
|
||||
} ENetIP;
|
||||
|
||||
// We don't need to test sin6_scope_id as it only used for connection, and sin6_flowinfo is always zero
|
||||
#define enet_ip_equal(a, b) (a.p0 == b.p0 && a.p1 == b.p1 && a.p2 == b.p2 && a.p3 == b.p3)
|
||||
#define enet_ip_not_equal(a, b) (a.p0 != b.p0 || a.p1 != b.p1 || a.p2 != b.p2 || a.p3 != b.p3)
|
||||
|
||||
/**
|
||||
* Portable internet address structure.
|
||||
*
|
||||
@ -88,7 +101,7 @@ typedef enum _ENetSocketShutdown
|
||||
*/
|
||||
typedef struct _ENetAddress
|
||||
{
|
||||
enet_uint32 host;
|
||||
ENetIP host;
|
||||
enet_uint16 port;
|
||||
} ENetAddress;
|
||||
|
||||
|
@ -307,7 +307,7 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet
|
||||
}
|
||||
else
|
||||
if (currentPeer -> state != ENET_PEER_STATE_CONNECTING &&
|
||||
currentPeer -> address.host == host -> receivedAddress.host)
|
||||
enet_ip_equal(currentPeer -> address.host, host -> receivedAddress.host))
|
||||
{
|
||||
if (currentPeer -> address.port == host -> receivedAddress.port &&
|
||||
currentPeer -> connectID == command -> connect.connectID)
|
||||
@ -1019,9 +1019,9 @@ enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event)
|
||||
|
||||
if (peer -> state == ENET_PEER_STATE_DISCONNECTED ||
|
||||
peer -> state == ENET_PEER_STATE_ZOMBIE ||
|
||||
((host -> receivedAddress.host != peer -> address.host ||
|
||||
((enet_ip_not_equal(host -> receivedAddress.host, peer -> address.host) ||
|
||||
host -> receivedAddress.port != peer -> address.port) &&
|
||||
peer -> address.host != ENET_HOST_BROADCAST) ||
|
||||
peer -> address.host.p0 != ENET_HOST_BROADCAST) ||
|
||||
(peer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID &&
|
||||
sessionID != peer -> incomingSessionID))
|
||||
return 0;
|
||||
|
134
lib/enet/unix.c
134
lib/enet/unix.c
@ -63,6 +63,9 @@ typedef int socklen_t;
|
||||
|
||||
static enet_uint32 timeBase = 0;
|
||||
|
||||
// Global variable handled by STK
|
||||
extern int isIPv6Socket(void);
|
||||
|
||||
int
|
||||
enet_initialize (void)
|
||||
{
|
||||
@ -104,9 +107,9 @@ int
|
||||
enet_address_set_host_ip (ENetAddress * address, const char * name)
|
||||
{
|
||||
#ifdef HAS_INET_PTON
|
||||
if (! inet_pton (AF_INET, name, & address -> host))
|
||||
if (! inet_pton (AF_INET, name, & address -> host.p0))
|
||||
#else
|
||||
if (! inet_aton (name, (struct in_addr *) & address -> host))
|
||||
if (! inet_aton (name, (struct in_addr *) & address -> host.p0))
|
||||
#endif
|
||||
return -1;
|
||||
|
||||
@ -131,7 +134,7 @@ enet_address_set_host (ENetAddress * address, const char * name)
|
||||
{
|
||||
struct sockaddr_in * sin = (struct sockaddr_in *) result -> ai_addr;
|
||||
|
||||
address -> host = sin -> sin_addr.s_addr;
|
||||
address -> host.p0 = sin -> sin_addr.s_addr;
|
||||
|
||||
freeaddrinfo (resultList);
|
||||
|
||||
@ -159,7 +162,7 @@ enet_address_set_host (ENetAddress * address, const char * name)
|
||||
|
||||
if (hostEntry != NULL && hostEntry -> h_addrtype == AF_INET)
|
||||
{
|
||||
address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0];
|
||||
address -> host.p0 = * (enet_uint32 *) hostEntry -> h_addr_list [0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -172,9 +175,9 @@ int
|
||||
enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength)
|
||||
{
|
||||
#ifdef HAS_INET_NTOP
|
||||
if (inet_ntop (AF_INET, & address -> host, name, nameLength) == NULL)
|
||||
if (inet_ntop (AF_INET, & address -> host.p0, name, nameLength) == NULL)
|
||||
#else
|
||||
char * addr = inet_ntoa (* (struct in_addr *) & address -> host);
|
||||
char * addr = inet_ntoa (* (struct in_addr *) & address -> host.p0);
|
||||
if (addr != NULL)
|
||||
{
|
||||
size_t addrLen = strlen(addr);
|
||||
@ -199,7 +202,7 @@ enet_address_get_host (const ENetAddress * address, char * name, size_t nameLeng
|
||||
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
|
||||
sin.sin_addr.s_addr = address -> host;
|
||||
sin.sin_addr.s_addr = address -> host.p0;
|
||||
|
||||
err = getnameinfo ((struct sockaddr *) & sin, sizeof (sin), name, nameLength, NULL, 0, NI_NAMEREQD);
|
||||
if (! err)
|
||||
@ -218,7 +221,7 @@ enet_address_get_host (const ENetAddress * address, char * name, size_t nameLeng
|
||||
char buffer [2048];
|
||||
int errnum;
|
||||
|
||||
in.s_addr = address -> host;
|
||||
in.s_addr = address -> host.p0;
|
||||
|
||||
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
|
||||
gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum);
|
||||
@ -226,7 +229,7 @@ enet_address_get_host (const ENetAddress * address, char * name, size_t nameLeng
|
||||
hostEntry = gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & errnum);
|
||||
#endif
|
||||
#else
|
||||
in.s_addr = address -> host;
|
||||
in.s_addr = address -> host.p0;
|
||||
|
||||
hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET);
|
||||
#endif
|
||||
@ -246,6 +249,29 @@ enet_address_get_host (const ENetAddress * address, char * name, size_t nameLeng
|
||||
|
||||
int
|
||||
enet_socket_bind (ENetSocket socket, const ENetAddress * address)
|
||||
{
|
||||
if (isIPv6Socket() == 1)
|
||||
{
|
||||
struct sockaddr_in6 sin;
|
||||
memset (& sin, 0, sizeof (sin));
|
||||
sin.sin6_family = AF_INET6;
|
||||
|
||||
if (address != NULL)
|
||||
{
|
||||
sin.sin6_port = ENET_HOST_TO_NET_16 (address -> port);
|
||||
memcpy (sin.sin6_addr.s6_addr, & address -> host.p0, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
sin.sin6_port = 0;
|
||||
sin.sin6_addr = in6addr_any;
|
||||
}
|
||||
|
||||
return bind (socket,
|
||||
(struct sockaddr *) & sin,
|
||||
sizeof (struct sockaddr_in6));
|
||||
}
|
||||
else
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
|
||||
@ -256,7 +282,7 @@ enet_socket_bind (ENetSocket socket, const ENetAddress * address)
|
||||
if (address != NULL)
|
||||
{
|
||||
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
|
||||
sin.sin_addr.s_addr = address -> host;
|
||||
sin.sin_addr.s_addr = address -> host.p0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -268,9 +294,27 @@ enet_socket_bind (ENetSocket socket, const ENetAddress * address)
|
||||
(struct sockaddr *) & sin,
|
||||
sizeof (struct sockaddr_in));
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
enet_socket_get_address (ENetSocket socket, ENetAddress * address)
|
||||
{
|
||||
if (isIPv6Socket() == 1)
|
||||
{
|
||||
struct sockaddr_in6 sin;
|
||||
memset (& sin, 0, sizeof (sin));
|
||||
socklen_t sinLength = sizeof (struct sockaddr_in6);
|
||||
|
||||
if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1)
|
||||
return -1;
|
||||
|
||||
memcpy (& address -> host.p0, sin.sin6_addr.s6_addr, 16);
|
||||
address -> host.p4 = sin.sin6_scope_id;
|
||||
address -> port = ENET_NET_TO_HOST_16 (sin.sin6_port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
socklen_t sinLength = sizeof (struct sockaddr_in);
|
||||
@ -278,11 +322,12 @@ enet_socket_get_address (ENetSocket socket, ENetAddress * address)
|
||||
if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1)
|
||||
return -1;
|
||||
|
||||
address -> host = (enet_uint32) sin.sin_addr.s_addr;
|
||||
address -> host.p0 = (enet_uint32) sin.sin_addr.s_addr;
|
||||
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
enet_socket_listen (ENetSocket socket, int backlog)
|
||||
@ -293,7 +338,16 @@ 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);
|
||||
int pf_family = isIPv6Socket() == 1 ? PF_INET6 : PF_INET;
|
||||
int socket_fd = socket (pf_family, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
|
||||
if (isIPv6Socket() == 1 && socket_fd != -1)
|
||||
{
|
||||
int no = 0;
|
||||
// Allow IPv6 socket listen to IPv4 connection (as long as the host has IPv4 address)
|
||||
// We always use dual stack in STK
|
||||
setsockopt (socket_fd, IPPROTO_IPV6, IPV6_V6ONLY, (void *) & no, sizeof (no));
|
||||
}
|
||||
return socket_fd;
|
||||
}
|
||||
|
||||
int
|
||||
@ -382,7 +436,7 @@ enet_socket_connect (ENetSocket socket, const ENetAddress * address)
|
||||
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
|
||||
sin.sin_addr.s_addr = address -> host;
|
||||
sin.sin_addr.s_addr = address -> host.p0;
|
||||
|
||||
result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in));
|
||||
if (result == -1 && errno == EINPROGRESS)
|
||||
@ -407,7 +461,7 @@ enet_socket_accept (ENetSocket socket, ENetAddress * address)
|
||||
|
||||
if (address != NULL)
|
||||
{
|
||||
address -> host = (enet_uint32) sin.sin_addr.s_addr;
|
||||
address -> host.p0 = (enet_uint32) sin.sin_addr.s_addr;
|
||||
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
|
||||
}
|
||||
|
||||
@ -434,22 +488,36 @@ enet_socket_send (ENetSocket socket,
|
||||
size_t bufferCount)
|
||||
{
|
||||
struct msghdr msgHdr;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_storage sin;
|
||||
memset (& sin, 0, sizeof (sin));
|
||||
int sentLength;
|
||||
|
||||
memset (& msgHdr, 0, sizeof (struct msghdr));
|
||||
|
||||
if (address != NULL)
|
||||
{
|
||||
memset (& sin, 0, sizeof (struct sockaddr_in));
|
||||
if (isIPv6Socket() == 1)
|
||||
{
|
||||
struct sockaddr_in6 * v6 = (struct sockaddr_in6 *) & sin;
|
||||
v6 -> sin6_family = AF_INET6;
|
||||
v6 -> sin6_port = ENET_HOST_TO_NET_16 (address -> port);
|
||||
memcpy (v6 -> sin6_addr.s6_addr, & address -> host.p0, 16);
|
||||
v6 -> sin6_scope_id = address -> host.p4;
|
||||
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
|
||||
sin.sin_addr.s_addr = address -> host;
|
||||
msgHdr.msg_name = & sin;
|
||||
msgHdr.msg_namelen = sizeof (struct sockaddr_in6);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct sockaddr_in * v4 = (struct sockaddr_in *) & sin;
|
||||
v4 -> sin_family = AF_INET;
|
||||
v4 -> sin_port = ENET_HOST_TO_NET_16 (address -> port);
|
||||
v4 -> sin_addr.s_addr = address -> host.p0;
|
||||
|
||||
msgHdr.msg_name = & sin;
|
||||
msgHdr.msg_namelen = sizeof (struct sockaddr_in);
|
||||
}
|
||||
}
|
||||
|
||||
msgHdr.msg_iov = (struct iovec *) buffers;
|
||||
msgHdr.msg_iovlen = bufferCount;
|
||||
@ -474,7 +542,8 @@ enet_socket_receive (ENetSocket socket,
|
||||
size_t bufferCount)
|
||||
{
|
||||
struct msghdr msgHdr;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_storage sin;
|
||||
memset (& sin, 0, sizeof (sin));
|
||||
int recvLength;
|
||||
|
||||
memset (& msgHdr, 0, sizeof (struct msghdr));
|
||||
@ -482,7 +551,7 @@ enet_socket_receive (ENetSocket socket,
|
||||
if (address != NULL)
|
||||
{
|
||||
msgHdr.msg_name = & sin;
|
||||
msgHdr.msg_namelen = sizeof (struct sockaddr_in);
|
||||
msgHdr.msg_namelen = sizeof (sin);
|
||||
}
|
||||
|
||||
msgHdr.msg_iov = (struct iovec *) buffers;
|
||||
@ -505,8 +574,27 @@ 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);
|
||||
switch (sin.ss_family)
|
||||
{
|
||||
case AF_INET:
|
||||
// Should not happen if dual stack is working
|
||||
if (isIPv6Socket() == 1)
|
||||
return -1;
|
||||
struct sockaddr_in * v4 = (struct sockaddr_in *) & sin;
|
||||
address -> host.p0 = (enet_uint32) v4 -> sin_addr.s_addr;
|
||||
address -> port = ENET_NET_TO_HOST_16 (v4->sin_port);
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (isIPv6Socket() != 1)
|
||||
return -1;
|
||||
struct sockaddr_in6 * v6 = (struct sockaddr_in6 *) & sin;
|
||||
memcpy (& address -> host.p0, v6 -> sin6_addr.s6_addr, 16);
|
||||
address -> host.p4 = v6 -> sin6_scope_id;
|
||||
address -> port = ENET_NET_TO_HOST_16 (v6 -> sin6_port);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return recvLength;
|
||||
|
134
lib/enet/win32.c
134
lib/enet/win32.c
@ -6,11 +6,15 @@
|
||||
|
||||
#define ENET_BUILDING_LIB 1
|
||||
#include "enet/enet.h"
|
||||
#include <ws2tcpip.h>
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
static enet_uint32 timeBase = 0;
|
||||
|
||||
// Global variable handled by STK
|
||||
extern int isIPv6Socket(void);
|
||||
|
||||
int
|
||||
enet_initialize (void)
|
||||
{
|
||||
@ -81,7 +85,7 @@ enet_address_set_host_ip (ENetAddress * address, const char * name)
|
||||
name = next + 1;
|
||||
}
|
||||
|
||||
memcpy (& address -> host, vals, sizeof (enet_uint32));
|
||||
memcpy (& address -> host.p0, vals, sizeof (enet_uint32));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -95,7 +99,7 @@ enet_address_set_host (ENetAddress * address, const char * name)
|
||||
hostEntry -> h_addrtype != AF_INET)
|
||||
return enet_address_set_host_ip (address, name);
|
||||
|
||||
address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0];
|
||||
address -> host.p0 = * (enet_uint32 *) hostEntry -> h_addr_list [0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -103,7 +107,7 @@ enet_address_set_host (ENetAddress * address, const char * name)
|
||||
int
|
||||
enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength)
|
||||
{
|
||||
char * addr = inet_ntoa (* (struct in_addr *) & address -> host);
|
||||
char * addr = inet_ntoa (* (struct in_addr *) & address -> host.p0);
|
||||
if (addr == NULL)
|
||||
return -1;
|
||||
else
|
||||
@ -122,7 +126,7 @@ enet_address_get_host (const ENetAddress * address, char * name, size_t nameLeng
|
||||
struct in_addr in;
|
||||
struct hostent * hostEntry;
|
||||
|
||||
in.s_addr = address -> host;
|
||||
in.s_addr = address -> host.p0;
|
||||
|
||||
hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET);
|
||||
if (hostEntry == NULL)
|
||||
@ -140,6 +144,29 @@ enet_address_get_host (const ENetAddress * address, char * name, size_t nameLeng
|
||||
|
||||
int
|
||||
enet_socket_bind (ENetSocket socket, const ENetAddress * address)
|
||||
{
|
||||
if (isIPv6Socket() == 1)
|
||||
{
|
||||
struct sockaddr_in6 sin;
|
||||
memset (& sin, 0, sizeof (sin));
|
||||
sin.sin6_family = AF_INET6;
|
||||
|
||||
if (address != NULL)
|
||||
{
|
||||
sin.sin6_port = ENET_HOST_TO_NET_16 (address -> port);
|
||||
memcpy (sin.sin6_addr.s6_addr, &address->host.p0, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
sin.sin6_port = 0;
|
||||
sin.sin6_addr = in6addr_any;
|
||||
}
|
||||
|
||||
return bind (socket,
|
||||
(struct sockaddr *) & sin,
|
||||
sizeof (struct sockaddr_in6)) == SOCKET_ERROR ? -1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
|
||||
@ -150,7 +177,7 @@ enet_socket_bind (ENetSocket socket, const ENetAddress * address)
|
||||
if (address != NULL)
|
||||
{
|
||||
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
|
||||
sin.sin_addr.s_addr = address -> host;
|
||||
sin.sin_addr.s_addr = address -> host.p0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -162,21 +189,40 @@ enet_socket_bind (ENetSocket socket, const ENetAddress * address)
|
||||
(struct sockaddr *) & sin,
|
||||
sizeof (struct sockaddr_in)) == SOCKET_ERROR ? -1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
enet_socket_get_address (ENetSocket socket, ENetAddress * address)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
int sinLength = sizeof (struct sockaddr_in);
|
||||
if (isIPv6Socket() == 1)
|
||||
{
|
||||
struct sockaddr_in6 sin;
|
||||
memset (& sin, 0, sizeof (sin));
|
||||
socklen_t sinLength = sizeof (struct sockaddr_in6);
|
||||
|
||||
if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1)
|
||||
return -1;
|
||||
|
||||
address -> host = (enet_uint32) sin.sin_addr.s_addr;
|
||||
memcpy (& address->host.p0, sin.sin6_addr.s6_addr, 16);
|
||||
address -> host.p4 = sin.sin6_scope_id;
|
||||
address -> port = ENET_NET_TO_HOST_16 (sin.sin6_port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
socklen_t sinLength = sizeof (struct sockaddr_in);
|
||||
|
||||
if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1)
|
||||
return -1;
|
||||
|
||||
address -> host.p0 = (enet_uint32) sin.sin_addr.s_addr;
|
||||
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
enet_socket_listen (ENetSocket socket, int backlog)
|
||||
@ -187,7 +233,16 @@ 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);
|
||||
int pf_family = isIPv6Socket() == 1 ? PF_INET6 : PF_INET;
|
||||
SOCKET socket_fd = socket (pf_family, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
|
||||
if (isIPv6Socket() == 1 && socket_fd != INVALID_SOCKET)
|
||||
{
|
||||
int no = 0;
|
||||
// Allow IPv6 socket listen to IPv4 connection (as long as the host has IPv4 address)
|
||||
// We always use dual stack in STK
|
||||
setsockopt (socket_fd, IPPROTO_IPV6, IPV6_V6ONLY, (void *) & no, sizeof (no));
|
||||
}
|
||||
return socket_fd;
|
||||
}
|
||||
|
||||
int
|
||||
@ -264,7 +319,7 @@ enet_socket_connect (ENetSocket socket, const ENetAddress * address)
|
||||
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
|
||||
sin.sin_addr.s_addr = address -> host;
|
||||
sin.sin_addr.s_addr = address -> host.p0;
|
||||
|
||||
result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in));
|
||||
if (result == SOCKET_ERROR && WSAGetLastError () != WSAEWOULDBLOCK)
|
||||
@ -289,7 +344,7 @@ enet_socket_accept (ENetSocket socket, ENetAddress * address)
|
||||
|
||||
if (address != NULL)
|
||||
{
|
||||
address -> host = (enet_uint32) sin.sin_addr.s_addr;
|
||||
address -> host.p0 = (enet_uint32) sin.sin_addr.s_addr;
|
||||
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
|
||||
}
|
||||
|
||||
@ -315,16 +370,33 @@ enet_socket_send (ENetSocket socket,
|
||||
const ENetBuffer * buffers,
|
||||
size_t bufferCount)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_storage sin;
|
||||
memset (& sin, 0, sizeof (sin));
|
||||
size_t sin_size = 0;
|
||||
|
||||
DWORD sentLength;
|
||||
|
||||
if (address != NULL)
|
||||
{
|
||||
memset (& sin, 0, sizeof (struct sockaddr_in));
|
||||
if (isIPv6Socket() == 1)
|
||||
{
|
||||
struct sockaddr_in6 * v6 = (struct sockaddr_in6 *) & sin;
|
||||
v6 -> sin6_family = AF_INET6;
|
||||
v6 -> sin6_port = ENET_HOST_TO_NET_16 (address -> port);
|
||||
memcpy (v6 -> sin6_addr.s6_addr, & address -> host.p0, 16);
|
||||
v6 -> sin6_scope_id = address -> host.p4;
|
||||
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
|
||||
sin.sin_addr.s_addr = address -> host;
|
||||
sin_size = sizeof (struct sockaddr_in6);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct sockaddr_in * v4 = (struct sockaddr_in *) & sin;
|
||||
v4 -> sin_family = AF_INET;
|
||||
v4 -> sin_port = ENET_HOST_TO_NET_16 (address -> port);
|
||||
v4 -> sin_addr.s_addr = address -> host.p0;
|
||||
|
||||
sin_size = sizeof (struct sockaddr_in);
|
||||
}
|
||||
}
|
||||
|
||||
if (WSASendTo (socket,
|
||||
@ -333,7 +405,7 @@ enet_socket_send (ENetSocket socket,
|
||||
& sentLength,
|
||||
0,
|
||||
address != NULL ? (struct sockaddr *) & sin : NULL,
|
||||
address != NULL ? sizeof (struct sockaddr_in) : 0,
|
||||
address != NULL ? (int)sin_size : 0,
|
||||
NULL,
|
||||
NULL) == SOCKET_ERROR)
|
||||
{
|
||||
@ -352,10 +424,11 @@ enet_socket_receive (ENetSocket socket,
|
||||
ENetBuffer * buffers,
|
||||
size_t bufferCount)
|
||||
{
|
||||
INT sinLength = sizeof (struct sockaddr_in);
|
||||
INT sinLength = sizeof (struct sockaddr_storage);
|
||||
DWORD flags = 0,
|
||||
recvLength;
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_storage sin;
|
||||
memset (& sin, 0, sizeof (sin));
|
||||
|
||||
if (WSARecvFrom (socket,
|
||||
(LPWSABUF) buffers,
|
||||
@ -382,8 +455,27 @@ 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);
|
||||
switch (sin.ss_family)
|
||||
{
|
||||
case AF_INET:
|
||||
// Should not happen if dual stack is working
|
||||
if (isIPv6Socket() == 1)
|
||||
return -1;
|
||||
struct sockaddr_in * v4 = (struct sockaddr_in *) & sin;
|
||||
address -> host.p0 = (enet_uint32) v4 -> sin_addr.s_addr;
|
||||
address -> port = ENET_NET_TO_HOST_16 (v4->sin_port);
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (isIPv6Socket() != 1)
|
||||
return -1;
|
||||
struct sockaddr_in6 * v6 = (struct sockaddr_in6 *) & sin;
|
||||
memcpy (& address -> host.p0, v6 -> sin6_addr.s6_addr, 16);
|
||||
address -> host.p4 = v6 -> sin6_scope_id;
|
||||
address -> port = ENET_NET_TO_HOST_16 (v6 -> sin6_port);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return (int) recvLength;
|
||||
|
@ -69,7 +69,7 @@ Network::Network(int peer_count, int channel_limit,
|
||||
{
|
||||
Log::warn("Network", "%d port is in used, use another port",
|
||||
address->port);
|
||||
ENetAddress new_addr;
|
||||
ENetAddress new_addr = {};
|
||||
new_addr.host = address->host;
|
||||
// Any port
|
||||
new_addr.port = 0;
|
||||
|
@ -210,9 +210,7 @@ void NetworkConfig::detectIPType()
|
||||
return;
|
||||
}
|
||||
#ifdef ENABLE_IPV6
|
||||
ENetAddress eaddr;
|
||||
eaddr.host = STKHost::HOST_ANY;
|
||||
eaddr.port = STKHost::PORT_ANY;
|
||||
ENetAddress eaddr = {};
|
||||
// We don't need to result of stun, just to check if the socket can be
|
||||
// used in ipv4 or ipv6
|
||||
uint8_t stun_tansaction_id[16] = {};
|
||||
|
@ -69,8 +69,7 @@ ConnectToServer::ConnectToServer(std::shared_ptr<Server> server)
|
||||
: Protocol(PROTOCOL_CONNECTION)
|
||||
{
|
||||
m_quick_play_err_msg = _("No quick play server available.");
|
||||
m_server_address.host = 0;
|
||||
m_server_address.port = 0;
|
||||
m_server_address = {};
|
||||
if (server)
|
||||
m_server = server;
|
||||
} // ConnectToServer(server, host)
|
||||
@ -252,8 +251,7 @@ void ConnectToServer::asynchronousUpdate()
|
||||
// Free the bound socket first
|
||||
delete STKHost::get()->getNetwork();
|
||||
setIPv6Socket(1);
|
||||
ENetAddress addr;
|
||||
addr.host = STKHost::HOST_ANY;
|
||||
ENetAddress addr = {};
|
||||
addr.port = NetworkConfig::get()->getClientPort();
|
||||
auto new_network = new Network(/*peer_count*/1,
|
||||
/*channel_limit*/EVENT_CHANNEL_COUNT,
|
||||
@ -409,22 +407,16 @@ int ConnectToServer::interceptCallback(ENetHost* host, ENetEvent* event)
|
||||
host->receivedData[8] == '-' && host->receivedData[9] == 's' &&
|
||||
host->receivedData[10] == 't' && host->receivedData[11] == 'k')
|
||||
{
|
||||
#ifdef ENABLE_IPV6
|
||||
if (enet_ip_not_equal(host->receivedAddress.host, m_server_address.host) ||
|
||||
#else
|
||||
if (host->receivedAddress.host != m_server_address.host ||
|
||||
#endif
|
||||
host->receivedAddress.port != m_server_address.port)
|
||||
{
|
||||
std::string new_address =
|
||||
enetAddressToString(host->receivedAddress);
|
||||
if (isIPv6Socket())
|
||||
{
|
||||
// It was already mapped to real IPv6 before the intercept
|
||||
// callback
|
||||
new_address = "[";
|
||||
new_address += getIPV6ReadableFromMappedAddress
|
||||
(&host->receivedAddress) + "]:" +
|
||||
StringUtils::toString(host->receivedAddress.port);
|
||||
}
|
||||
SocketAddress new_address(host->receivedAddress);
|
||||
Log::info("ConnectToServer", "Using new server address %s",
|
||||
new_address.c_str());
|
||||
new_address.toString().c_str());
|
||||
m_retry_count = 15;
|
||||
m_server_address = host->receivedAddress;
|
||||
m_done_intecept = true;
|
||||
@ -441,9 +433,7 @@ bool ConnectToServer::tryConnect(int timeout, int retry, bool another_port,
|
||||
{
|
||||
m_retry_count = retry;
|
||||
ENetEvent event;
|
||||
ENetAddress ea;
|
||||
ea.host = STKHost::HOST_ANY;
|
||||
ea.port = STKHost::PORT_ANY;
|
||||
ENetAddress ea = {};
|
||||
Network* nw = another_port ? new Network(/*peer_count*/1,
|
||||
/*channel_limit*/EVENT_CHANNEL_COUNT,
|
||||
/*max_in_bandwidth*/0, /*max_out_bandwidth*/0, &ea,
|
||||
@ -453,31 +443,21 @@ bool ConnectToServer::tryConnect(int timeout, int retry, bool another_port,
|
||||
m_done_intecept = false;
|
||||
nw->getENetHost()->intercept = ConnectToServer::interceptCallback;
|
||||
|
||||
const SocketAddress* sa;
|
||||
if (ipv6)
|
||||
{
|
||||
SocketAddress* sa = m_server->getIPV6Address();
|
||||
sa = m_server->getIPV6Address();
|
||||
if (!sa)
|
||||
return false;
|
||||
struct sockaddr_in6* in6 = (struct sockaddr_in6*)sa->getSockaddr();
|
||||
addMappedAddress(&m_server_address, in6);
|
||||
}
|
||||
else
|
||||
{
|
||||
// IPv4 address
|
||||
m_server_address = toENetAddress(m_server->getAddress().getIP(),
|
||||
m_server->getAddress().getPort());
|
||||
}
|
||||
sa = &m_server->getAddress();
|
||||
m_server_address = sa->toENetAddress();
|
||||
|
||||
while (--m_retry_count >= 0 && !ProtocolManager::lock()->isExiting())
|
||||
{
|
||||
std::string connecting_address = enetAddressToString(m_server_address);
|
||||
if (ipv6)
|
||||
{
|
||||
connecting_address = "[";
|
||||
connecting_address += getIPV6ReadableFromMappedAddress
|
||||
(&m_server_address) + "]:" +
|
||||
StringUtils::toString(m_server->getIPV6Address()->getPort());
|
||||
}
|
||||
std::string connecting_address =
|
||||
SocketAddress(m_server_address).toString();
|
||||
ENetPeer* p = nw->connectTo(m_server_address);
|
||||
if (!p)
|
||||
break;
|
||||
@ -555,30 +535,6 @@ void ConnectToServer::registerWithSTKServer()
|
||||
}
|
||||
} // registerWithSTKServer
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
std::string ConnectToServer::enetAddressToString(const ENetAddress& addr)
|
||||
{
|
||||
uint32_t ip = htonl(addr.host);
|
||||
std::string s =
|
||||
StringUtils::insertValues("%d.%d.%d.%d",
|
||||
((ip >> 24) & 0xff), ((ip >> 16) & 0xff),
|
||||
((ip >> 8) & 0xff), ((ip >> 0) & 0xff));
|
||||
s += StringUtils::insertValues(":%d", addr.port);
|
||||
return s;
|
||||
} // enetAddressToString
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
ENetAddress ConnectToServer::toENetAddress(uint32_t ip, uint16_t port)
|
||||
{
|
||||
// because ENet wants little endian
|
||||
ENetAddress a;
|
||||
a.host = ((ip & 0xff000000) >> 24) +
|
||||
((ip & 0x00ff0000) >> 8) + ((ip & 0x0000ff00) << 8) +
|
||||
((ip & 0x000000ff) << 24);
|
||||
a.port = port;
|
||||
return a;
|
||||
} // toENetAddress
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool ConnectToServer::detectPort()
|
||||
{
|
||||
@ -663,9 +619,7 @@ bool ConnectToServer::detectPort()
|
||||
}
|
||||
#endif
|
||||
|
||||
ENetAddress ea;
|
||||
ea.host = STKHost::HOST_ANY;
|
||||
ea.port = STKHost::PORT_ANY;
|
||||
ENetAddress ea = {};
|
||||
std::unique_ptr<Network> nw(new Network(/*peer_count*/1,
|
||||
/*channel_limit*/EVENT_CHANNEL_COUNT,
|
||||
/*max_in_bandwidth*/0, /*max_out_bandwidth*/0, &ea,
|
||||
|
@ -68,8 +68,6 @@ public:
|
||||
virtual void setup() OVERRIDE;
|
||||
virtual void asynchronousUpdate() OVERRIDE;
|
||||
virtual void update(int ticks) OVERRIDE;
|
||||
static std::string enetAddressToString(const ENetAddress& addr);
|
||||
static ENetAddress toENetAddress(uint32_t ip, uint16_t port);
|
||||
}; // class ConnectToServer
|
||||
|
||||
#endif // CONNECT_TO_SERVER_HPP
|
||||
|
@ -189,7 +189,9 @@ namespace ServerConfig
|
||||
"STK currently uses dual-stack mode which requires server to have both "
|
||||
"IPv4 and IPv6 and listen to same port. If STK detects your server "
|
||||
"has no public IPv6 address or port differs between IPv4 and IPv6 "
|
||||
"then it will use IPv4 only socket."));
|
||||
"then it will use IPv4 only socket. For system which doesn't support "
|
||||
"dual-stack socket (like OpenBSD) you may fail to be connected by "
|
||||
"IPv4 clients."));
|
||||
|
||||
SERVER_CFG_PREFIX BoolServerConfigParam m_owner_less
|
||||
SERVER_CFG_DEFAULT(BoolServerConfigParam(false, "owner-less",
|
||||
|
@ -159,9 +159,7 @@ std::shared_ptr<Online::XMLRequest> ServersManager::getLANRefreshRequest() const
|
||||
// --------------------------------------------------------------------
|
||||
virtual void operation() OVERRIDE
|
||||
{
|
||||
ENetAddress addr;
|
||||
addr.host = STKHost::HOST_ANY;
|
||||
addr.port = STKHost::PORT_ANY;
|
||||
ENetAddress addr = {};
|
||||
setIPv6Socket(UserConfigParams::m_ipv6_lan ? 1 : 0);
|
||||
NetworkConfig::get()->setIPType(UserConfigParams::m_ipv6_lan ?
|
||||
NetworkConfig::IP_DUAL_STACK : NetworkConfig::IP_V4);
|
||||
|
@ -63,6 +63,33 @@ SocketAddress::SocketAddress(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4,
|
||||
{
|
||||
} // SocketAddress(uint8_t,...)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** ENetAddress constructor. */
|
||||
SocketAddress::SocketAddress(const ENetAddress& ea)
|
||||
{
|
||||
#ifdef ENABLE_IPV6
|
||||
if (isIPv6Socket())
|
||||
{
|
||||
m_family = AF_INET6;
|
||||
m_sockaddr = {};
|
||||
struct sockaddr_in6* in6 = (struct sockaddr_in6*)m_sockaddr.data();
|
||||
in6->sin6_family = AF_INET6;
|
||||
in6->sin6_port = htons(ea.port);
|
||||
// We modify host to use 5 uint32_t (see enet.h)
|
||||
memcpy(in6->sin6_addr.s6_addr, &ea.host.p0, 16);
|
||||
in6->sin6_scope_id = ea.host.p4;
|
||||
}
|
||||
else
|
||||
{
|
||||
setIP(htonl(ea.host.p0));
|
||||
setPort(ea.port);
|
||||
}
|
||||
#else
|
||||
setIP(htonl(ea.host));
|
||||
setPort(ea.port);
|
||||
#endif
|
||||
} // SocketAddress(const ENetAddress&)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** String initialization (Can be IPv4, IPv6 or domain).
|
||||
* \param str The address (can have a port with :)
|
||||
@ -680,3 +707,31 @@ void SocketAddress::unitTesting()
|
||||
assert(ipv6_port.getPort() == 1);
|
||||
|
||||
} // unitTesting
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
ENetAddress SocketAddress::toENetAddress() const
|
||||
{
|
||||
ENetAddress ea = {};
|
||||
uint32_t ip = getIP();
|
||||
#ifdef ENABLE_IPV6
|
||||
if (isIPv6Socket())
|
||||
{
|
||||
struct sockaddr_in6* in6 = (struct sockaddr_in6*)m_sockaddr.data();
|
||||
memcpy(&ea.host.p0, in6->sin6_addr.s6_addr, 16);
|
||||
ea.host.p4 = in6->sin6_scope_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
// because ENet wants little endian
|
||||
ea.host.p0 = ((ip & 0xff000000) >> 24) +
|
||||
((ip & 0x00ff0000) >> 8) + ((ip & 0x0000ff00) << 8) +
|
||||
((ip & 0x000000ff) << 24);
|
||||
}
|
||||
#else
|
||||
ea.host = ((ip & 0xff000000) >> 24) +
|
||||
((ip & 0x00ff0000) >> 8) + ((ip & 0x0000ff00) << 8) +
|
||||
((ip & 0x000000ff) << 24);
|
||||
#endif
|
||||
ea.port = getPort();
|
||||
return ea;
|
||||
} // toENetAddress
|
||||
|
@ -31,6 +31,7 @@
|
||||
# include <netinet/in.h>
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
#include <enet/enet.h>
|
||||
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
@ -69,6 +70,8 @@ public:
|
||||
init(str, port_number, family);
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
SocketAddress(const ENetAddress& ea);
|
||||
// ------------------------------------------------------------------------
|
||||
bool operator==(const SocketAddress& other) const;
|
||||
// ------------------------------------------------------------------------
|
||||
bool operator!=(const SocketAddress& other) const;
|
||||
@ -154,6 +157,8 @@ public:
|
||||
bool isLoopback() const;
|
||||
// ------------------------------------------------------------------------
|
||||
void convertForIPv6Socket(bool ipv6);
|
||||
// ------------------------------------------------------------------------
|
||||
ENetAddress toENetAddress() const;
|
||||
}; // SocketAddress
|
||||
|
||||
#endif // HEADER_SOCKET_ADDRESS_HPP
|
||||
|
@ -256,9 +256,7 @@ STKHost::STKHost(bool server)
|
||||
init();
|
||||
m_host_id = std::numeric_limits<uint32_t>::max();
|
||||
|
||||
ENetAddress addr;
|
||||
addr.host = STKHost::HOST_ANY;
|
||||
|
||||
ENetAddress addr = {};
|
||||
if (server)
|
||||
{
|
||||
setIPv6Socket(ServerConfig::m_ipv6_server ? 1 : 0);
|
||||
@ -758,8 +756,7 @@ void STKHost::mainLoop()
|
||||
if ((NetworkConfig::get()->isLAN() && is_server) ||
|
||||
NetworkConfig::get()->isPublicServer())
|
||||
{
|
||||
ENetAddress eaddr;
|
||||
eaddr.host = STKHost::HOST_ANY;
|
||||
ENetAddress eaddr = {};
|
||||
eaddr.port = stk_config->m_server_discovery_port;
|
||||
direct_socket = new Network(1, 1, 0, 0, &eaddr);
|
||||
if (direct_socket->getENetHost() == NULL)
|
||||
@ -774,7 +771,6 @@ void STKHost::mainLoop()
|
||||
uint64_t last_ping_time = StkTime::getMonoTimeMs();
|
||||
uint64_t last_update_speed_time = StkTime::getMonoTimeMs();
|
||||
uint64_t last_ping_time_update_for_client = StkTime::getMonoTimeMs();
|
||||
uint64_t last_disconnect_time_update = StkTime::getMonoTimeMs();
|
||||
std::map<std::string, uint64_t> ctp;
|
||||
while (m_exit_timeout.load() > StkTime::getMonoTimeMs())
|
||||
{
|
||||
@ -812,15 +808,6 @@ void STKHost::mainLoop()
|
||||
}
|
||||
} // if discovery host
|
||||
|
||||
if (isIPv6Socket() &&
|
||||
last_disconnect_time_update < StkTime::getMonoTimeMs())
|
||||
{
|
||||
// Check per 20 second, client needs to be handled too in case
|
||||
// the address changed in intercept callback
|
||||
// (see ConnectToServer::interceptCallback)
|
||||
last_disconnect_time_update = StkTime::getMonoTimeMs() + 20000;
|
||||
removeDisconnectedMappedAddress();
|
||||
}
|
||||
if (is_server)
|
||||
{
|
||||
std::unique_lock<std::mutex> peer_lock(m_peers_mutex);
|
||||
@ -969,7 +956,12 @@ void STKHost::mainLoop()
|
||||
// Enet will reuse a disconnected peer so we check here to avoid
|
||||
// sending to wrong peer
|
||||
if (peer->state != ENET_PEER_STATE_CONNECTED ||
|
||||
#ifdef ENABLE_IPV6
|
||||
(enet_ip_not_equal(ea_peer_now.host, ea.host) &&
|
||||
ea_peer_now.port != ea.port))
|
||||
#else
|
||||
(ea_peer_now.host != ea.host && ea_peer_now.port != ea.port))
|
||||
#endif
|
||||
{
|
||||
if (packet != NULL)
|
||||
enet_packet_destroy(packet);
|
||||
|
@ -69,17 +69,6 @@ enum ENetCommandType : unsigned int
|
||||
|
||||
class STKHost
|
||||
{
|
||||
public:
|
||||
/** \brief Defines three host types for the server.
|
||||
* These values tells the host where he will accept connections from.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
HOST_ANY = 0, //!< Any host.
|
||||
HOST_BROADCAST = 0xFFFFFFFF, //!< Defines the broadcast address.
|
||||
PORT_ANY = 0 //!< Any port.
|
||||
};
|
||||
|
||||
private:
|
||||
/** Singleton pointer to the instance. */
|
||||
static STKHost* m_stk_host;
|
||||
|
@ -334,188 +334,31 @@ extern "C" int insideIPv6CIDR(const char* ipv6_cidr, const char* ipv6_in)
|
||||
} // andIPv6
|
||||
|
||||
#ifndef ENABLE_IPV6
|
||||
#include "network/stk_ipv6.hpp"
|
||||
// ----------------------------------------------------------------------------
|
||||
int isIPv6Socket()
|
||||
extern "C" int isIPv6Socket()
|
||||
{
|
||||
return 0;
|
||||
} // isIPV6
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void setIPv6Socket(int val)
|
||||
extern "C" void setIPv6Socket(int val)
|
||||
{
|
||||
} // setIPV6
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
std::string getIPV6ReadableFromMappedAddress(const ENetAddress* ea)
|
||||
{
|
||||
return "";
|
||||
} // getIPV6ReadableFromMappedAddress
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void removeDisconnectedMappedAddress()
|
||||
{
|
||||
} // removeDisconnectedMappedAddress
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void addMappedAddress(const ENetAddress* ea, const struct sockaddr_in6* in6)
|
||||
{
|
||||
} // addMappedAddress
|
||||
|
||||
#else
|
||||
|
||||
#include "network/stk_ipv6.hpp"
|
||||
#include "network/protocols/connect_to_server.hpp"
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/time.hpp"
|
||||
#include "utils/types.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
// ============================================================================
|
||||
uint32_t g_mapped_ipv6_used;
|
||||
int g_ipv6;
|
||||
struct MappedAddress
|
||||
{
|
||||
ENetAddress m_addr;
|
||||
struct sockaddr_in6 m_in6;
|
||||
uint64_t m_last_activity;
|
||||
MappedAddress(const ENetAddress& addr, const struct sockaddr_in6& in6)
|
||||
{
|
||||
m_addr = addr;
|
||||
m_in6 = in6;
|
||||
m_last_activity = StkTime::getMonoTimeMs();
|
||||
}
|
||||
};
|
||||
std::vector<MappedAddress> g_mapped_ips;
|
||||
// ============================================================================
|
||||
int isIPv6Socket()
|
||||
extern "C" int isIPv6Socket()
|
||||
{
|
||||
return g_ipv6;
|
||||
} // isIPV6
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void setIPv6Socket(int val)
|
||||
extern "C" void setIPv6Socket(int val)
|
||||
{
|
||||
g_ipv6 = val;
|
||||
} // setIPV6
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
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();
|
||||
} // stkInitialize
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
std::string getIPV6ReadableFromMappedAddress(const ENetAddress* ea)
|
||||
{
|
||||
std::string result;
|
||||
auto it = std::find_if(g_mapped_ips.begin(), g_mapped_ips.end(),
|
||||
[ea](const MappedAddress& addr)
|
||||
{
|
||||
return ea->host == addr.m_addr.host &&
|
||||
ea->port == addr.m_addr.port;
|
||||
});
|
||||
if (it != g_mapped_ips.end())
|
||||
result = getIPV6ReadableFromIn6(&it->m_in6);
|
||||
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 MappedAddress& addr)
|
||||
{
|
||||
return ea->host == addr.m_addr.host &&
|
||||
ea->port == addr.m_addr.port;
|
||||
});
|
||||
if (it != g_mapped_ips.end())
|
||||
{
|
||||
it->m_last_activity = StkTime::getMonoTimeMs();
|
||||
memcpy(in6, &it->m_in6, sizeof(struct sockaddr_in6));
|
||||
}
|
||||
else
|
||||
memset(in6, 0, sizeof(struct sockaddr_in6));
|
||||
} // getIPV6FromMappedAddress
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/* 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 MappedAddress& addr)
|
||||
{
|
||||
return sameIPV6(in6, &addr.m_in6);
|
||||
});
|
||||
if (it != g_mapped_ips.end())
|
||||
{
|
||||
it->m_last_activity = StkTime::getMonoTimeMs();
|
||||
*ea = it->m_addr;
|
||||
return;
|
||||
}
|
||||
|
||||
if (isIPv4MappedAddress(in6))
|
||||
{
|
||||
ea->host = ((in_addr*)(in6->sin6_addr.s6_addr + 12))->s_addr;
|
||||
ea->port = ntohs(in6->sin6_port);
|
||||
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;
|
||||
*ea = ConnectToServer::toENetAddress(++g_mapped_ipv6_used,
|
||||
ntohs(in6->sin6_port));
|
||||
Log::debug("IPv6", "Fake IPv4 address %s mapped to %s",
|
||||
ConnectToServer::enetAddressToString(*ea).c_str(),
|
||||
getIPV6ReadableFromIn6(in6).c_str());
|
||||
addMappedAddress(ea, in6);
|
||||
}
|
||||
} // getMappedFromIPV6
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/* Called when a peer is expired (no activity for 20 seconds) and we remove its
|
||||
* reference to the IPv6.
|
||||
*/
|
||||
void removeDisconnectedMappedAddress()
|
||||
{
|
||||
for (auto it = g_mapped_ips.begin(); it != g_mapped_ips.end();)
|
||||
{
|
||||
if (it->m_last_activity + 20000 < StkTime::getMonoTimeMs())
|
||||
{
|
||||
Log::debug("IPv6", "Removing expired %s, IPv4 address %s.",
|
||||
getIPV6ReadableFromIn6(&it->m_in6).c_str(),
|
||||
ConnectToServer::enetAddressToString(it->m_addr).c_str());
|
||||
it = g_mapped_ips.erase(it);
|
||||
Log::debug("IPv6", "Mapped address size now: %d.",
|
||||
g_mapped_ips.size());
|
||||
}
|
||||
else
|
||||
it++;
|
||||
}
|
||||
} // removeDisconnectedMappedAddress
|
||||
|
||||
#endif
|
||||
|
@ -23,10 +23,6 @@ extern "C" {
|
||||
#endif
|
||||
int isIPv6Socket();
|
||||
void setIPv6Socket(int val);
|
||||
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);
|
||||
int getaddrinfo_compat(const char* hostname, const char* servname,
|
||||
const struct addrinfo* hints, struct addrinfo** res);
|
||||
int64_t upperIPv6(const char* ipv6);
|
||||
@ -34,9 +30,7 @@ int insideIPv6CIDR(const char* ipv6_cidr, const char* ipv6_in);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
std::string getIPV6ReadableFromMappedAddress(const ENetAddress* ea);
|
||||
std::string getIPV6ReadableFromIn6(const struct sockaddr_in6* in);
|
||||
bool sameIPV6(const struct sockaddr_in6* in_1,
|
||||
const struct sockaddr_in6* in_2);
|
||||
void removeDisconnectedMappedAddress();
|
||||
bool isIPv4MappedAddress(const struct sockaddr_in6* in6);
|
||||
|
@ -39,25 +39,7 @@ STKPeer::STKPeer(ENetPeer *enet_peer, STKHost* host, uint32_t host_id)
|
||||
: m_address(enet_peer->address), m_host(host)
|
||||
{
|
||||
m_addons_scores.fill(-1);
|
||||
uint32_t addr = htonl(enet_peer->address.host);
|
||||
#ifdef ENABLE_IPV6
|
||||
if (isIPv6Socket())
|
||||
{
|
||||
// This will return the mapped IPv4 address too for IPv6 socket
|
||||
// So we can sendto directly with it
|
||||
struct sockaddr_in6 in6 = {};
|
||||
getIPV6FromMappedAddress(&enet_peer->address, &in6);
|
||||
m_socket_address.reset(new SocketAddress());
|
||||
m_socket_address->setSockAddrIn(AF_INET6, (sockaddr*)&in6, sizeof(in6));
|
||||
if (m_socket_address->isIPv6())
|
||||
m_ipv6_address = m_socket_address->toString(false/*show_port*/);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
m_socket_address.reset(
|
||||
new SocketAddress(addr, enet_peer->address.port));
|
||||
}
|
||||
m_socket_address.reset(new SocketAddress(m_address));
|
||||
m_enet_peer = enet_peer;
|
||||
m_host_id = host_id;
|
||||
m_connected_time = StkTime::getMonoTimeMs();
|
||||
|
@ -117,8 +117,6 @@ 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;
|
||||
@ -140,8 +138,6 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
bool isConnected() const;
|
||||
// ------------------------------------------------------------------------
|
||||
const std::string& getIPV6Address() const { return m_ipv6_address; }
|
||||
// ------------------------------------------------------------------------
|
||||
bool isSamePeer(const STKPeer* peer) const;
|
||||
bool isSamePeer(const ENetPeer* peer) const;
|
||||
// ------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user