From 24ae6a66ed77dc20ce2bc80d6bda8ad7a5da2382 Mon Sep 17 00:00:00 2001 From: lotodore Date: Mon, 8 Oct 2007 18:25:40 +0000 Subject: [PATCH] Always use IPv6 for the server if a "dual stack" is available. This means a server on vista (as well as most linux systems) will support IPv6 by default. IPv4 requests will be mapped by the OS. --- src/net/common/serveracceptthread.cpp | 10 ++++-- src/net/common/socket_startup_cmn.cpp | 44 ++++++++++++++++++--------- src/net/socket_helper.h | 4 +++ src/net/socket_startup.h | 1 + 4 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/net/common/serveracceptthread.cpp b/src/net/common/serveracceptthread.cpp index 4dbc4c47..6e15feba 100644 --- a/src/net/common/serveracceptthread.cpp +++ b/src/net/common/serveracceptthread.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #define ACCEPT_TIMEOUT_MSEC 50 #define NET_SERVER_LISTEN_BACKLOG 5 @@ -50,7 +51,9 @@ ServerAcceptThread::Init(unsigned serverPort, bool ipv6, bool sctp, const std::s ServerContext &context = GetContext(); context.SetProtocol(sctp ? SOCKET_IPPROTO_SCTP : 0); - context.SetAddrFamily(ipv6 ? AF_INET6 : AF_INET); + // If a "dual stack" is available, the pokerth server always uses ipv6. + // In this case, ipv4 requests will be mapped to ipv6. + context.SetAddrFamily(socket_has_dual_stack() ? AF_INET6 : (ipv6 ? AF_INET6 : AF_INET)); context.SetServerPort(serverPort); GetLobbyThread().Init(pwd); @@ -105,11 +108,14 @@ ServerAcceptThread::Listen() if (IOCTLSOCKET(context.GetSocket(), FIONBIO, &mode) == SOCKET_ERROR) throw ServerException(ERR_SOCK_CREATION_FAILED, SOCKET_ERRNO()); - // The following two calls are optional. If they fail, we don't care. + // The following three calls are optional. If they fail, we don't care. int reuse = 1; setsockopt(context.GetSocket(), SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)); int nodelay = 1; setsockopt(context.GetSocket(), SOL_SOCKET, TCP_NODELAY, (char *)&nodelay, sizeof(nodelay)); + // Enable dual-stack socket on Windows Vista. + int ipv6only = 0; + setsockopt(context.GetSocket(), IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, sizeof(ipv6only)); context.GetServerSockaddr()->ss_family = context.GetAddrFamily(); diff --git a/src/net/common/socket_startup_cmn.cpp b/src/net/common/socket_startup_cmn.cpp index 8027d8a7..28230967 100644 --- a/src/net/common/socket_startup_cmn.cpp +++ b/src/net/common/socket_startup_cmn.cpp @@ -21,20 +21,20 @@ #include -bool -socket_has_sctp() -{ -#ifdef IPPROTO_SCTP - SOCKET test = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP); - - if (test == INVALID_SOCKET) - return false; - CLOSESOCKET(test); - return true; -#else - return false; -#endif -} +bool +socket_has_sctp() +{ +#ifdef IPPROTO_SCTP + SOCKET test = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP); + + if (test == INVALID_SOCKET) + return false; + CLOSESOCKET(test); + return true; +#else + return false; +#endif +} bool socket_has_ipv6() @@ -47,3 +47,19 @@ socket_has_ipv6() return true; } +bool +socket_has_dual_stack() +{ + bool retVal = false; + SOCKET test = socket(AF_INET6, SOCK_STREAM, 0); + + if (test != INVALID_SOCKET) + { + int ipv6only = 0; + if (setsockopt(test, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&ipv6only, sizeof(ipv6only)) == 0) + retVal = true; + CLOSESOCKET(test); + } + return retVal; +} + diff --git a/src/net/socket_helper.h b/src/net/socket_helper.h index 87ae2a57..c0f1d951 100644 --- a/src/net/socket_helper.h +++ b/src/net/socket_helper.h @@ -35,6 +35,10 @@ #define SOCKET_ERR_NOTCONN WSAENOTCONN #define SOCKET_ERR_NOTSOCK WSAENOTSOCK +#ifndef IPV6_V6ONLY + #define IPV6_V6ONLY 27 +#endif + #ifdef __GNUC__ /* mingw provides stdint.h */ #include typedef uint16_t u_int16_t; diff --git a/src/net/socket_startup.h b/src/net/socket_startup.h index 5a0bd30c..057c1a31 100644 --- a/src/net/socket_startup.h +++ b/src/net/socket_startup.h @@ -25,6 +25,7 @@ void socket_cleanup(); bool socket_has_sctp(); bool socket_has_ipv6(); +bool socket_has_dual_stack(); #endif