diff --git a/src/network/C4NetIO.cpp b/src/network/C4NetIO.cpp index d2e046cc3..88976cd4b 100644 --- a/src/network/C4NetIO.cpp +++ b/src/network/C4NetIO.cpp @@ -674,6 +674,17 @@ C4NetIO::~C4NetIO() } +bool C4NetIO::EnableDualStack(SOCKET socket) +{ + int opt = 0; + if (setsockopt(socket, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast(&opt), sizeof(opt)) == SOCKET_ERROR) + { + SetError("could not enable dual-stack socket", true); + return false; + } + return true; +} + void C4NetIO::SetError(const char *strnError, bool fSockErr) { fSockErr &= HaveSocketError(); @@ -1097,6 +1108,9 @@ bool C4NetIOTCP::Connect(const C4NetIO::addr_t &addr) // (mt-safe) return false; } + if (!EnableDualStack(nsock)) + return false; + #ifdef STDSCHEDULER_USE_EVENTS // set event if (::WSAEventSelect(nsock, Event, FD_CONNECT) == SOCKET_ERROR) @@ -1424,6 +1438,8 @@ bool C4NetIOTCP::Listen(uint16_t inListenPort) SetError("socket creation failed", true); return false; } + if (!EnableDualStack(lsock)) + return false; // To be able to reuse the port after close #if !defined(_DEBUG) && !defined(_WIN32) int reuseaddr = 1; @@ -1796,6 +1812,9 @@ bool C4NetIOSimpleUDP::Init(uint16_t inPort) return false; } + if (!EnableDualStack(sock)) + return false; + // set reuse socket option if (::setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&fAllowReUse), sizeof fAllowReUse) == SOCKET_ERROR) { diff --git a/src/network/C4NetIO.h b/src/network/C4NetIO.h index aa8063832..177b123f3 100644 --- a/src/network/C4NetIO.h +++ b/src/network/C4NetIO.h @@ -273,6 +273,9 @@ public: protected: // virtual SOCKET CreateSocket() = 0; + // Makes IPv4 connections from an IPv6 socket work. + bool EnableDualStack(SOCKET socket); + // *** errors protected: StdCopyStrBuf Error;