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.
This commit is contained in:
Kawe Mazidjatari 2023-04-16 00:28:33 +02:00
parent 2d3f2ba507
commit 3882b64b91
2 changed files with 53 additions and 55 deletions

View File

@ -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<AcceptedSocket_t> m_hAcceptedSockets;
SocketHandle_t m_hListenSocket; // Used to accept connections.
netadr_t m_ListenAddress; // Address used to listen on.
private:
enum

View File

@ -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<sockaddr*>(&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<u_long*>(&opt)); // Non-blocking
if (ret == -1)
int ret = ::setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&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<char*>(&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<char*>(&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<u_long*>(&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<sockaddr*>(&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;
}