From 3882b64b91251dea4d31ff2a9720864f04a8ba39 Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Sun, 16 Apr 2023 00:28:33 +0200 Subject: [PATCH] Fixed several bugs in socket creator class * Fixed 'connect' socket bug preventing connection to IPv4 addresses, by making the method used by the listen socket and connect socket configurator shared (dual stack was disabled on connect, but not on listen). * Removed extraneous member from the 'CSocketCreator' class, this member was a copy of the 'netadr_t' input, but nothing ever was done with it. --- r5dev/public/tier2/socketcreator.h | 7 +- r5dev/tier2/socketcreator.cpp | 101 +++++++++++++++-------------- 2 files changed, 53 insertions(+), 55 deletions(-) diff --git a/r5dev/public/tier2/socketcreator.h b/r5dev/public/tier2/socketcreator.h index 8a967612..f6cd2306 100644 --- a/r5dev/public/tier2/socketcreator.h +++ b/r5dev/public/tier2/socketcreator.h @@ -14,10 +14,8 @@ public: void RunFrame(void); void ProcessAccept(void); - bool ConfigureListenSocket(int iSocket); - bool ConfigureConnectSocket(SocketHandle_t hSocket); - - bool CreateListenSocket(const netadr_t& netAdr, bool bListenOnAllInterfaces = false); + bool ConfigureSocket(SocketHandle_t hSocket, bool bDualStack = true); + bool CreateListenSocket(const netadr_t& netAdr, bool bDualStack = true); void CloseListenSocket(void); int ConnectSocket(const netadr_t& netAdr, bool bSingleSocket); @@ -54,7 +52,6 @@ public: std::vector m_hAcceptedSockets; SocketHandle_t m_hListenSocket; // Used to accept connections. - netadr_t m_ListenAddress; // Address used to listen on. private: enum diff --git a/r5dev/tier2/socketcreator.cpp b/r5dev/tier2/socketcreator.cpp index 90bb6cc2..bf86e998 100644 --- a/r5dev/tier2/socketcreator.cpp +++ b/r5dev/tier2/socketcreator.cpp @@ -35,7 +35,7 @@ void CSocketCreator::RunFrame(void) { if (IsListening()) { - ProcessAccept(); // handle any new connection requests + ProcessAccept(); // handle any new connection requests. } } @@ -47,7 +47,7 @@ void CSocketCreator::ProcessAccept(void) sockaddr_storage inClient{}; int nLengthAddr = sizeof(inClient); SocketHandle_t newSocket = SocketHandle_t(::accept(SOCKET(m_hListenSocket), reinterpret_cast(&inClient), &nLengthAddr)); - if (newSocket == -1) + if (newSocket == SOCKET_ERROR) { if (!IsSocketBlocking()) { @@ -56,7 +56,7 @@ void CSocketCreator::ProcessAccept(void) return; } - if (!ConfigureListenSocket(newSocket)) + if (!ConfigureSocket(newSocket, false)) { ::closesocket(newSocket); return; @@ -69,51 +69,51 @@ void CSocketCreator::ProcessAccept(void) } //----------------------------------------------------------------------------- -// Purpose: Configures a listen socket for use +// Purpose: Configures a socket for use // Input : iSocket - +// bDualStack - // Output : true on success, false otherwise //----------------------------------------------------------------------------- -bool CSocketCreator::ConfigureListenSocket(int iSocket) +bool CSocketCreator::ConfigureSocket(SocketHandle_t hSocket, bool bDualStack /*= true*/) { // Disable NAGLE as RCON cmds are small in size. - int nodelay = 1; - int v6only = 0; - u_long opt = 1; - - ::setsockopt(iSocket, IPPROTO_TCP, TCP_NODELAY, (char*)&nodelay, sizeof(nodelay)); - ::setsockopt(iSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&nodelay, sizeof(nodelay)); - ::setsockopt(iSocket, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&v6only, sizeof(v6only)); - - int results = ::ioctlsocket(iSocket, FIONBIO, (u_long*)&opt); // Non-blocking. - if (results == -1) - { - Warning(eDLL_T::ENGINE, "Socket accept 'ioctl(%s)' failed (%s)\n", "FIONBIO", NET_ErrorString(WSAGetLastError())); - return false; - } - return true; -} - -//----------------------------------------------------------------------------- -// Purpose: Configures a accepted socket for use -// Input : hSocket - -// Output : true on success, false otherwise -//----------------------------------------------------------------------------- -bool CSocketCreator::ConfigureConnectSocket(SocketHandle_t hSocket) -{ int opt = 1; - int ret = 0; - - ret = ::ioctlsocket(hSocket, FIONBIO, reinterpret_cast(&opt)); // Non-blocking - if (ret == -1) + int ret = ::setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&opt), sizeof(opt)); + if (ret == SOCKET_ERROR) { - Warning(eDLL_T::ENGINE, "Socket ioctl(%s) failed (%s)\n", "FIONBIO", NET_ErrorString(WSAGetLastError())); - ::closesocket(hSocket); + Warning(eDLL_T::ENGINE, "Socket 'sockopt(%s)' failed (%s)\n", "TCP_NODELAY", NET_ErrorString(WSAGetLastError())); return false; } - // Disable NAGLE as RCON cmds are small in size. - int nodelay = 1; - ::setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (char*)&nodelay, sizeof(nodelay)); + // Mark socket as reusable. + opt = 1; + ret = ::setsockopt(hSocket, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&opt), sizeof(opt)); + if (ret == SOCKET_ERROR) + { + Warning(eDLL_T::ENGINE, "Socket 'sockopt(%s)' failed (%s)\n", "SO_REUSEADDR", NET_ErrorString(WSAGetLastError())); + return false; + } + + if (bDualStack) + { + // Disable IPv6 only mode to enable dual stack. + opt = 0; + ret = ::setsockopt(hSocket, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast(&opt), sizeof(opt)); + if (ret == SOCKET_ERROR) + { + Warning(eDLL_T::ENGINE, "Socket 'sockopt(%s)' failed (%s)\n", "IPV6_V6ONLY", NET_ErrorString(WSAGetLastError())); + return false; + } + } + + // Mark socket as non-blocking. + opt = 1; + ret = ::ioctlsocket(hSocket, FIONBIO, reinterpret_cast(&opt)); + if (ret == SOCKET_ERROR) + { + Warning(eDLL_T::ENGINE, "Socket 'ioctl(%s)' failed (%s)\n", "FIONBIO", NET_ErrorString(WSAGetLastError())); + return false; + } return true; } @@ -121,28 +121,27 @@ bool CSocketCreator::ConfigureConnectSocket(SocketHandle_t hSocket) //----------------------------------------------------------------------------- // Purpose: bind to a TCP port and accept incoming connections // Input : *netAdr - -// bListenOnAllInterfaces - +// bDualStack - // Output : true on success, failed otherwise //----------------------------------------------------------------------------- -bool CSocketCreator::CreateListenSocket(const netadr_t& netAdr, bool bListenOnAllInterfaces) +bool CSocketCreator::CreateListenSocket(const netadr_t& netAdr, bool bDualStack) { CloseListenSocket(); - m_ListenAddress = netAdr; m_hListenSocket = SocketHandle_t(::socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP)); if (m_hListenSocket != INVALID_SOCKET) { - if (!ConfigureListenSocket(m_hListenSocket)) + if (!ConfigureSocket(m_hListenSocket, bDualStack)) { CloseListenSocket(); return false; } sockaddr_storage sadr{}; - m_ListenAddress.ToSockadr(&sadr); + netAdr.ToSockadr(&sadr); int results = ::bind(m_hListenSocket, reinterpret_cast(&sadr), sizeof(sockaddr_in6)); - if (results == -1) + if (results == SOCKET_ERROR) { Warning(eDLL_T::ENGINE, "Socket bind failed (%s)\n", NET_ErrorString(WSAGetLastError())); CloseListenSocket(); @@ -151,7 +150,7 @@ bool CSocketCreator::CreateListenSocket(const netadr_t& netAdr, bool bListenOnAl } results = ::listen(m_hListenSocket, SOCKET_TCP_MAX_ACCEPTS); - if (results == -1) + if (results == SOCKET_ERROR) { Warning(eDLL_T::ENGINE, "Socket listen failed (%s)\n", NET_ErrorString(WSAGetLastError())); CloseListenSocket(); @@ -167,23 +166,23 @@ bool CSocketCreator::CreateListenSocket(const netadr_t& netAdr, bool bListenOnAl //----------------------------------------------------------------------------- void CSocketCreator::CloseListenSocket(void) { - if (m_hListenSocket != -1) + if (m_hListenSocket != SOCKET_ERROR) { ::closesocket(m_hListenSocket); - m_hListenSocket = -1; + m_hListenSocket = SOCKET_ERROR; } } //----------------------------------------------------------------------------- // Purpose: connect to the remote server // Input : *netAdr - -// bSingleSocker - +// bSingleSocket - // Output : accepted socket index, SOCKET_ERROR (-1) if failed //----------------------------------------------------------------------------- int CSocketCreator::ConnectSocket(const netadr_t& netAdr, bool bSingleSocket) { if (bSingleSocket) - { // NOTE: Closing an accepted socket will re-index all the sockets with higher indices + { // NOTE: Closing an accepted socket will re-index all the sockets with higher indices. CloseAllAcceptedSockets(); } @@ -194,8 +193,9 @@ int CSocketCreator::ConnectSocket(const netadr_t& netAdr, bool bSingleSocket) return SOCKET_ERROR; } - if (!ConfigureConnectSocket(hSocket)) + if (!ConfigureSocket(hSocket)) { + ::closesocket(hSocket); return SOCKET_ERROR; } @@ -224,6 +224,7 @@ int CSocketCreator::ConnectSocket(const netadr_t& netAdr, bool bSingleSocket) if (::select(hSocket + 1, NULL, &writefds, NULL, &tv) < 1) // block for at most 1 second. { + Warning(eDLL_T::ENGINE, "Socket connection timed out\n"); ::closesocket(hSocket); // took too long to connect to, give up. return SOCKET_ERROR; }