Skip to content

Commit c2c5c20

Browse files
committed
Initial work on IPV6 game server
1 parent 1551bda commit c2c5c20

File tree

9 files changed

+334
-38
lines changed

9 files changed

+334
-38
lines changed

CMakeLists.txt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ option(SERVER_ONLY "Create a server only (i.e. no graphics or sound)" OFF)
2222
option(CHECK_ASSETS "Check if assets are installed in ../stk-assets" ON)
2323
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)
2424
option(USE_SYSTEM_ENET "Use system ENet instead of the built-in version, when available." ON)
25+
option(USE_IPV6 "Allow create or connect to game server with ipv6 address, system enet will not be used." OFF)
2526
option(USE_SYSTEM_GLEW "Use system GLEW instead of the built-in version, when available." ON)
2627
option(USE_SYSTEM_WIIUSE "Use system WiiUse instead of the built-in version, when available." OFF)
2728
option(USE_SQLITE3 "Use sqlite to manage server stats and ban list." ON)
@@ -160,11 +161,15 @@ add_subdirectory("${PROJECT_SOURCE_DIR}/lib/bullet")
160161
include_directories("${PROJECT_SOURCE_DIR}/lib/bullet/src")
161162

162163
# Find system ENet library or build it if missing
163-
if((UNIX AND NOT APPLE) AND USE_SYSTEM_ENET)
164+
if((UNIX AND NOT APPLE) AND USE_SYSTEM_ENET AND NOT USE_IPV6)
164165
pkg_check_modules(ENET libenet>=1.3.4)
165166
endif()
166167

167-
if(ENET_FOUND)
168+
if (USE_IPV6)
169+
add_definitions(-DENABLE_IPV6)
170+
endif()
171+
172+
if(ENET_FOUND AND NOT USE_IPV6)
168173
include_directories(${ENET_INCLUDE_DIRS})
169174
else()
170175
# Fallback to built-in version

lib/enet/protocol.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
#include "enet/time.h"
1010
#include "enet/enet.h"
1111

12+
#ifdef ENABLE_IPV6
13+
extern void removeMappedAddress(const ENetAddress* ea);
14+
#endif
15+
1216
static size_t commandSizes [ENET_PROTOCOL_COMMAND_COUNT] =
1317
{
1418
0,
@@ -84,6 +88,10 @@ enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event)
8488
event -> peer = peer;
8589
event -> data = peer -> eventData;
8690

91+
#ifdef ENABLE_IPV6
92+
removeMappedAddress(&peer->address);
93+
#endif
94+
8795
enet_peer_reset (peer);
8896

8997
return 1;
@@ -148,6 +156,10 @@ enet_protocol_notify_disconnect (ENetHost * host, ENetPeer * peer, ENetEvent * e
148156
event -> peer = peer;
149157
event -> data = 0;
150158

159+
#ifdef ENABLE_IPV6
160+
removeMappedAddress(&peer->address);
161+
#endif
162+
151163
enet_peer_reset (peer);
152164
}
153165
else

lib/enet/unix.c

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,18 @@ typedef int socklen_t;
5858

5959
static enet_uint32 timeBase = 0;
6060

61-
#ifdef IOS_STK
62-
extern void iOSInitialize(void);
63-
extern int isIPV6Only(void);
64-
extern void getSynthesizedAddress(const ENetAddress* ea, struct sockaddr_in6* in6);
65-
extern void getIPV4FromSynthesized(const struct sockaddr_in6* in6, ENetAddress* ea);
61+
#ifdef ENABLE_IPV6
62+
extern void unixInitialize(void);
63+
extern int isIPV6(void);
64+
extern void getIPV6FromMappedAddress(const ENetAddress* ea, struct sockaddr_in6* in6);
65+
extern void getMappedFromIPV6(const struct sockaddr_in6* in6, ENetAddress* ea);
6666
#endif
6767

6868
int
6969
enet_initialize (void)
7070
{
71-
#ifdef IOS_STK
72-
iOSInitialize();
71+
#ifdef ENABLE_IPV6
72+
unixInitialize();
7373
#endif
7474
return 0;
7575
}
@@ -199,9 +199,9 @@ enet_address_get_host (const ENetAddress * address, char * name, size_t nameLeng
199199
int
200200
enet_socket_bind (ENetSocket socket, const ENetAddress * address)
201201
{
202-
#ifdef IOS_STK
202+
#ifdef ENABLE_IPV6
203203
// In STK we only bind port and listen to any address
204-
if (isIPV6Only())
204+
if (isIPV6())
205205
{
206206
struct sockaddr_in6 sin;
207207
memset (&sin, 0, sizeof (struct sockaddr_in6));
@@ -261,12 +261,26 @@ enet_socket_listen (ENetSocket socket, int backlog)
261261
ENetSocket
262262
enet_socket_create (ENetSocketType type)
263263
{
264-
#ifdef IOS_STK
265-
int af_family = isIPV6Only() == 1 ? PF_INET6 : PF_INET;
264+
#ifdef ENABLE_IPV6
265+
int af_family = isIPV6() == 1 ? PF_INET6 : PF_INET;
266266
#else
267267
int af_family = PF_INET;
268268
#endif
269-
return socket (af_family, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
269+
int socket_fd = socket (af_family, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
270+
#ifdef ENABLE_IPV6
271+
if (isIPV6())
272+
{
273+
int no = 0;
274+
// Allow ipv6 socket listen to ipv4 connection (as long as the host has ipv4 address)
275+
int ret = setsockopt(socket_fd, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&no, sizeof(no));
276+
if (ret != 0)
277+
{
278+
close(socket_fd);
279+
return -1;
280+
}
281+
}
282+
#endif
283+
return socket_fd;
270284
}
271285

272286
int
@@ -408,7 +422,7 @@ enet_socket_send (ENetSocket socket,
408422
{
409423
struct msghdr msgHdr;
410424
struct sockaddr_in sin;
411-
#ifdef IOS_STK
425+
#ifdef ENABLE_IPV6
412426
struct sockaddr_in6 sin6;
413427
#endif
414428
int sentLength;
@@ -417,10 +431,10 @@ enet_socket_send (ENetSocket socket,
417431

418432
if (address != NULL)
419433
{
420-
#ifdef IOS_STK
421-
if (isIPV6Only())
434+
#ifdef ENABLE_IPV6
435+
if (isIPV6())
422436
{
423-
getSynthesizedAddress(address, &sin6);
437+
getIPV6FromMappedAddress(address, &sin6);
424438
msgHdr.msg_name = & sin6;
425439
msgHdr.msg_namelen = sizeof (struct sockaddr_in6);
426440
}
@@ -462,7 +476,7 @@ enet_socket_receive (ENetSocket socket,
462476
{
463477
struct msghdr msgHdr;
464478
struct sockaddr_in sin;
465-
#ifdef IOS_STK
479+
#ifdef ENABLE_IPV6
466480
struct sockaddr_in6 sin6;
467481
#endif
468482
int recvLength;
@@ -471,8 +485,8 @@ enet_socket_receive (ENetSocket socket,
471485

472486
if (address != NULL)
473487
{
474-
#ifdef IOS_STK
475-
if (isIPV6Only())
488+
#ifdef ENABLE_IPV6
489+
if (isIPV6())
476490
{
477491
msgHdr.msg_name = & sin6;
478492
msgHdr.msg_namelen = sizeof (struct sockaddr_in6);
@@ -505,10 +519,10 @@ enet_socket_receive (ENetSocket socket,
505519

506520
if (address != NULL)
507521
{
508-
#ifdef IOS_STK
509-
if (isIPV6Only())
522+
#ifdef ENABLE_IPV6
523+
if (isIPV6())
510524
{
511-
getIPV4FromSynthesized(&sin6, address);
525+
getMappedFromIPV6(&sin6, address);
512526
}
513527
else
514528
#endif

sources.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Modify this file to change the last-modified date when you add/remove a file.
2-
# This will then trigger a new cmake run automatically.
2+
# This will then trigger a new cmake run automatically.
33
file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp")
44
file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp")
55
file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*")

src/network/stk_host.cpp

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#include "io/file_manager.hpp"
2424
#include "network/event.hpp"
2525
#include "network/game_setup.hpp"
26-
#include "network/ios_ipv6.hpp"
26+
#include "network/unix_ipv6.hpp"
2727
#include "network/network_config.hpp"
2828
#include "network/network_console.hpp"
2929
#include "network/network_player_profile.hpp"
@@ -370,16 +370,15 @@ void STKHost::shutdown()
370370
*/
371371
void STKHost::setPublicAddress()
372372
{
373-
#ifdef IOS_STK
374-
if (isIPV6Only())
373+
if (isIPV6())
375374
{
376375
// IPV6 only in iOS doesn't support connection to firewalled server,
377376
// so no need to test STUN
378377
Log::info("STKHost", "IPV6 only environment detected.");
379378
m_public_address = TransportAddress("169.254.0.0:65535");
380379
return;
381380
}
382-
#endif
381+
383382
std::vector<std::pair<std::string, uint32_t> > untried_server;
384383
for (auto& p : UserConfigParams::m_stun_servers)
385384
untried_server.push_back(p);
@@ -714,8 +713,8 @@ void STKHost::mainLoop()
714713

715714
// A separate network connection (socket) to handle LAN requests.
716715
Network* direct_socket = NULL;
717-
if ((NetworkConfig::get()->isLAN() && is_server) ||
718-
NetworkConfig::get()->isPublicServer())
716+
if (!isIPV6() && ((NetworkConfig::get()->isLAN() && is_server) ||
717+
NetworkConfig::get()->isPublicServer()))
719718
{
720719
TransportAddress address(0, stk_config->m_server_discovery_port);
721720
ENetAddress eaddr = address.toEnetAddress();
@@ -811,7 +810,7 @@ void STKHost::mainLoop()
811810
{
812811
Log::info("STKHost", "%s %s with ping %d is higher"
813812
" than %d ms when not in game, kick.",
814-
p.second->getAddress().toString().c_str(),
813+
p.second->getRealAddress().c_str(),
815814
player_name.c_str(), ap, max_ping);
816815
p.second->setWarnedForHighPing(true);
817816
p.second->setDisconnected(true);
@@ -824,7 +823,7 @@ void STKHost::mainLoop()
824823
{
825824
Log::info("STKHost", "%s %s with ping %d is higher"
826825
" than %d ms.",
827-
p.second->getAddress().toString().c_str(),
826+
p.second->getRealAddress().c_str(),
828827
player_name.c_str(), ap, max_ping);
829828
p.second->setWarnedForHighPing(true);
830829
NetworkString msg(PROTOCOL_LOBBY_ROOM);
@@ -889,7 +888,7 @@ void STKHost::mainLoop()
889888
{
890889
Log::info("STKHost", "%s has not been validated for more"
891890
" than %f seconds, disconnect it by force.",
892-
it->second->getAddress().toString().c_str(),
891+
it->second->getRealAddress().c_str(),
893892
timeout);
894893
enet_host_flush(host);
895894
enet_peer_reset(it->first);
@@ -976,7 +975,8 @@ void STKHost::mainLoop()
976975
stk_event = new Event(&event, stk_peer);
977976
TransportAddress addr(event.peer->address);
978977
Log::info("STKHost", "%s has just connected. There are "
979-
"now %u peers.", addr.toString().c_str(), getPeerCount());
978+
"now %u peers.", stk_peer->getRealAddress().c_str(),
979+
getPeerCount());
980980
// Client always trust the server
981981
if (!is_server)
982982
stk_peer->setValidated();
@@ -994,15 +994,17 @@ void STKHost::mainLoop()
994994
}
995995
// Use the previous stk peer so protocol can see the network
996996
// profile and handle it for disconnection
997+
std::string addr;
997998
if (m_peers.find(event.peer) != m_peers.end())
998999
{
999-
stk_event = new Event(&event, m_peers.at(event.peer));
1000+
std::shared_ptr<STKPeer>& peer = m_peers.at(event.peer);
1001+
addr = peer->getRealAddress();
1002+
stk_event = new Event(&event, peer);
10001003
std::lock_guard<std::mutex> lock(m_peers_mutex);
10011004
m_peers.erase(event.peer);
10021005
}
1003-
TransportAddress addr(event.peer->address);
10041006
Log::info("STKHost", "%s has just disconnected. There are "
1005-
"now %u peers.", addr.toString().c_str(), getPeerCount());
1007+
"now %u peers.", addr.c_str(), getPeerCount());
10061008
} // ENET_EVENT_TYPE_DISCONNECT
10071009

10081010
if (!stk_event && m_peers.find(event.peer) != m_peers.end())

src/network/stk_peer.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
#include "network/network_string.hpp"
2626
#include "network/stk_host.hpp"
2727
#include "network/transport_address.hpp"
28+
#include "network/unix_ipv6.hpp"
2829
#include "utils/log.hpp"
30+
#include "utils/string_utils.hpp"
2931
#include "utils/time.hpp"
3032

3133
#include <string.h>
@@ -35,6 +37,7 @@
3537
STKPeer::STKPeer(ENetPeer *enet_peer, STKHost* host, uint32_t host_id)
3638
: m_peer_address(enet_peer->address), m_host(host)
3739
{
40+
m_ipv6_address = getIPV6ReadableFromMappedAddress(&enet_peer->address);
3841
m_enet_peer = enet_peer;
3942
m_host_id = host_id;
4043
m_connected_time = StkTime::getMonoTimeMs();
@@ -198,3 +201,13 @@ void STKPeer::setCrypto(std::unique_ptr<Crypto>&& c)
198201
{
199202
m_crypto = std::move(c);
200203
} // setCrypto
204+
205+
//-----------------------------------------------------------------------------
206+
/* Return an IPV6 or IPV4 address, used for debug printing.
207+
*/
208+
std::string STKPeer::getRealAddress() const
209+
{
210+
return m_ipv6_address.empty() ? m_peer_address.toString() :
211+
std::string("[") + m_ipv6_address + "]:" +
212+
StringUtils::toString(m_peer_address.getPort());
213+
} // getRealAddress

src/network/stk_peer.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ class STKPeer : public NoCopy
100100

101101
std::string m_user_version;
102102

103+
std::string m_ipv6_address;
104+
103105
/** List of client capabilities set when connecting it, to determine
104106
* features available in same version. */
105107
std::set<std::string> m_client_capabilities;
@@ -120,6 +122,11 @@ class STKPeer : public NoCopy
120122
// ------------------------------------------------------------------------
121123
bool isConnected() const;
122124
const TransportAddress& getAddress() const { return m_peer_address; }
125+
// ------------------------------------------------------------------------
126+
const std::string& getIPV6Address() const { return m_ipv6_address; }
127+
// ------------------------------------------------------------------------
128+
std::string getRealAddress() const;
129+
// ------------------------------------------------------------------------
123130
bool isSamePeer(const STKPeer* peer) const;
124131
bool isSamePeer(const ENetPeer* peer) const;
125132
// ------------------------------------------------------------------------

0 commit comments

Comments
 (0)