Network/TcpClient: Add PollForConnected
This commit is contained in:
parent
dad2dbae1c
commit
67c56b2aba
|
|
@ -149,6 +149,7 @@ Nazara Engine:
|
|||
- ⚠️ AbstractSocket::OnStateChange has been replaced by OnStateChanged, which is now called after state has been changed (with oldState and newState as parameters).
|
||||
- ⚠️ TcpClient::WaitForconnected now closes the socket on failure.
|
||||
- ⚠️ TcpClient::WaitForconnected now returns the new socket state.
|
||||
- Added TcpClient::PollForConnected
|
||||
|
||||
Nazara Development Kit:
|
||||
- Added ImageWidget (#139)
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ namespace Nz
|
|||
inline bool IsLowDelayEnabled() const;
|
||||
inline bool IsKeepAliveEnabled() const;
|
||||
|
||||
SocketState PollForConnected(UInt64 waitDuration = 0);
|
||||
|
||||
bool Receive(void* buffer, std::size_t size, std::size_t* received);
|
||||
bool ReceivePacket(NetPacket* packet);
|
||||
|
||||
|
|
|
|||
|
|
@ -138,59 +138,6 @@ namespace Nz
|
|||
return SocketState_Connected;
|
||||
}
|
||||
|
||||
SocketState SocketImpl::Connect(SocketHandle handle, const IpAddress& address, UInt64 msTimeout, SocketError* error)
|
||||
{
|
||||
SocketState state = Connect(handle, address, error);
|
||||
if (state == SocketState_Connecting)
|
||||
{
|
||||
// http://developerweb.net/viewtopic.php?id=3196
|
||||
fd_set localSet;
|
||||
FD_ZERO(&localSet);
|
||||
FD_SET(handle, &localSet);
|
||||
|
||||
timeval tv;
|
||||
tv.tv_sec = static_cast<long>(msTimeout / 1000ULL);
|
||||
tv.tv_usec = static_cast<long>((msTimeout % 1000ULL) * 1000ULL);
|
||||
|
||||
int ret = select(handle + 1, nullptr, &localSet, &localSet, (msTimeout > 0) ? &tv : nullptr);
|
||||
if (ret > 0)
|
||||
{
|
||||
int code = GetLastErrorCode(handle, error);
|
||||
if (code < 0) //< GetLastErrorCode() failed
|
||||
return SocketState_NotConnected;
|
||||
|
||||
if (code)
|
||||
{
|
||||
if (error)
|
||||
*error = TranslateErrnoToSocketError(code);
|
||||
|
||||
return SocketState_NotConnected;
|
||||
}
|
||||
}
|
||||
else if (ret == 0)
|
||||
{
|
||||
if (error)
|
||||
*error = SocketError_TimedOut;
|
||||
|
||||
return SocketState_NotConnected;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (error)
|
||||
*error = TranslateErrnoToSocketError(GetLastErrorCode());
|
||||
|
||||
return SocketState_NotConnected;
|
||||
}
|
||||
|
||||
if (error)
|
||||
*error = SocketError_NoError;
|
||||
|
||||
state = SocketState_Connected;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
bool SocketImpl::Initialize()
|
||||
{
|
||||
return true;
|
||||
|
|
@ -462,6 +409,58 @@ namespace Nz
|
|||
return static_cast<unsigned int>(result);
|
||||
}
|
||||
|
||||
SocketState SocketImpl::PollConnection(SocketHandle handle, const IpAddress& address, UInt64 msTimeout, SocketError* error)
|
||||
{
|
||||
// http://developerweb.net/viewtopic.php?id=3196
|
||||
fd_set localSet;
|
||||
FD_ZERO(&localSet);
|
||||
FD_SET(handle, &localSet);
|
||||
|
||||
timeval tv;
|
||||
tv.tv_sec = static_cast<long>(msTimeout / 1000ULL);
|
||||
tv.tv_usec = static_cast<long>((msTimeout % 1000ULL) * 1000ULL);
|
||||
|
||||
int ret = ::select(0, nullptr, &localSet, &localSet, (msTimeout >= 0 && msTimeout != std::numeric_limits<UInt64>::max()) ? &tv : nullptr);
|
||||
if (ret > 0)
|
||||
{
|
||||
int code = GetLastErrorCode(handle, error);
|
||||
if (code < 0) //< GetLastErrorCode() failed
|
||||
return SocketState_NotConnected;
|
||||
|
||||
if (code)
|
||||
{
|
||||
if (error)
|
||||
*error = TranslateWSAErrorToSocketError(code);
|
||||
|
||||
return SocketState_NotConnected;
|
||||
}
|
||||
}
|
||||
else if (ret == 0)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
if (msTimeout > 0)
|
||||
*error = SocketError_TimedOut;
|
||||
else
|
||||
*error = SocketError_NoError;
|
||||
}
|
||||
|
||||
return SocketState_Connecting;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (error)
|
||||
*error = TranslateWSAErrorToSocketError(WSAGetLastError());
|
||||
|
||||
return SocketState_NotConnected;
|
||||
}
|
||||
|
||||
if (error)
|
||||
*error = SocketError_NoError;
|
||||
|
||||
return SocketState_Connected;
|
||||
}
|
||||
|
||||
bool SocketImpl::Receive(SocketHandle handle, void* buffer, int length, int* read, SocketError* error)
|
||||
{
|
||||
NazaraAssert(handle != InvalidHandle, "Invalid handle");
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ namespace Nz
|
|||
static void Close(SocketHandle handle);
|
||||
|
||||
static SocketState Connect(SocketHandle handle, const IpAddress& address, SocketError* error);
|
||||
static SocketState Connect(SocketHandle handle, const IpAddress& address, UInt64 msTimeout, SocketError* error);
|
||||
|
||||
static bool Initialize();
|
||||
|
||||
|
|
@ -61,6 +60,7 @@ namespace Nz
|
|||
static std::size_t QuerySendBufferSize(SocketHandle handle, SocketError* error = nullptr);
|
||||
|
||||
static unsigned int Poll(PollSocket* fdarray, std::size_t nfds, int timeout, SocketError* error);
|
||||
static SocketState PollConnection(SocketHandle handle, const IpAddress& address, UInt64 msTimeout, SocketError* error);
|
||||
|
||||
static bool Receive(SocketHandle handle, void* buffer, int length, int* read, SocketError* error);
|
||||
static bool ReceiveFrom(SocketHandle handle, void* buffer, int length, IpAddress* from, int* read, SocketError* error);
|
||||
|
|
|
|||
|
|
@ -173,6 +173,50 @@ namespace Nz
|
|||
return QueryAvailableBytes();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Polls the connection status of the currently connecting socket
|
||||
* \return New socket state, which maybe unchanged (if connecting is still pending), SocketState_Connected if connection is successful or SocketState_NotConnected if connection failed
|
||||
*
|
||||
* This functions checks if the pending connection has either succeeded, failed or is still processing at the time of the call.
|
||||
*
|
||||
* \remark This function doesn't do anything if the socket is not currently connecting.
|
||||
*
|
||||
* \see WaitForConnected
|
||||
*/
|
||||
SocketState TcpClient::PollForConnected(UInt64 waitDuration)
|
||||
{
|
||||
switch (m_state)
|
||||
{
|
||||
case SocketState_Connecting:
|
||||
{
|
||||
NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Invalid handle");
|
||||
|
||||
SocketState newState = SocketImpl::PollConnection(m_handle, m_peerAddress, waitDuration, &m_lastError);
|
||||
|
||||
// Prevent valid peer address in non-connected state
|
||||
if (newState == SocketState_NotConnected)
|
||||
{
|
||||
m_openMode = OpenMode_NotOpen;
|
||||
m_peerAddress = IpAddress::Invalid;
|
||||
}
|
||||
|
||||
UpdateState(newState);
|
||||
return newState;
|
||||
}
|
||||
|
||||
case SocketState_Connected:
|
||||
case SocketState_NotConnected:
|
||||
return m_state;
|
||||
|
||||
case SocketState_Bound:
|
||||
case SocketState_Resolving:
|
||||
break;
|
||||
}
|
||||
|
||||
NazaraInternalError("Unexpected socket state (0x" + String::Number(m_state, 16) + ')');
|
||||
return m_state;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Receives the data available
|
||||
* \return true If data received
|
||||
|
|
@ -439,6 +483,8 @@ namespace Nz
|
|||
* \param msTimeout Time in milliseconds before time out (0 for system-specific duration, like a blocking connect would)
|
||||
*
|
||||
* \remark This function doesn't do anything if the socket is not currently connecting.
|
||||
*
|
||||
* \see PollForConnected
|
||||
*/
|
||||
SocketState TcpClient::WaitForConnected(UInt64 msTimeout)
|
||||
{
|
||||
|
|
@ -448,18 +494,11 @@ namespace Nz
|
|||
{
|
||||
NazaraAssert(m_handle != SocketImpl::InvalidHandle, "Invalid handle");
|
||||
|
||||
CallOnExit restoreBlocking;
|
||||
if (m_isBlockingEnabled)
|
||||
{
|
||||
SocketImpl::SetBlocking(m_handle, false);
|
||||
restoreBlocking.Reset([this] ()
|
||||
{
|
||||
SocketImpl::SetBlocking(m_handle, true);
|
||||
});
|
||||
}
|
||||
SocketState newState = SocketImpl::PollConnection(m_handle, m_peerAddress, (msTimeout > 0) ? msTimeout : std::numeric_limits<UInt64>::max(), &m_lastError);
|
||||
|
||||
SocketState newState = SocketImpl::Connect(m_handle, m_peerAddress, msTimeout, &m_lastError);
|
||||
NazaraAssert(newState != SocketState_Connecting, "Invalid internal return"); //< Connect cannot return Connecting is a timeout was specified
|
||||
// If connection is still pending after waiting, cancel it
|
||||
if (newState == SocketState_Connecting)
|
||||
newState = SocketState_NotConnected;
|
||||
|
||||
// Prevent valid stats in non-connected state
|
||||
if (newState == SocketState_NotConnected)
|
||||
|
|
|
|||
|
|
@ -154,59 +154,6 @@ namespace Nz
|
|||
return SocketState_Connected;
|
||||
}
|
||||
|
||||
SocketState SocketImpl::Connect(SocketHandle handle, const IpAddress& address, UInt64 msTimeout, SocketError* error)
|
||||
{
|
||||
SocketState state = Connect(handle, address, error);
|
||||
if (state == SocketState_Connecting)
|
||||
{
|
||||
// http://developerweb.net/viewtopic.php?id=3196
|
||||
fd_set localSet;
|
||||
FD_ZERO(&localSet);
|
||||
FD_SET(handle, &localSet);
|
||||
|
||||
timeval tv;
|
||||
tv.tv_sec = static_cast<long>(msTimeout / 1000ULL);
|
||||
tv.tv_usec = static_cast<long>((msTimeout % 1000ULL) * 1000ULL);
|
||||
|
||||
int ret = select(0, nullptr, &localSet, &localSet, (msTimeout > 0) ? &tv : nullptr);
|
||||
if (ret > 0)
|
||||
{
|
||||
int code = GetLastErrorCode(handle, error);
|
||||
if (code < 0) //< GetLastErrorCode() failed
|
||||
return SocketState_NotConnected;
|
||||
|
||||
if (code)
|
||||
{
|
||||
if (error)
|
||||
*error = TranslateWSAErrorToSocketError(code);
|
||||
|
||||
return SocketState_NotConnected;
|
||||
}
|
||||
}
|
||||
else if (ret == 0)
|
||||
{
|
||||
if (error)
|
||||
*error = SocketError_TimedOut;
|
||||
|
||||
return SocketState_NotConnected;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (error)
|
||||
*error = TranslateWSAErrorToSocketError(WSAGetLastError());
|
||||
|
||||
return SocketState_NotConnected;
|
||||
}
|
||||
|
||||
if (error)
|
||||
*error = SocketError_NoError;
|
||||
|
||||
state = SocketState_Connected;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
bool SocketImpl::Initialize()
|
||||
{
|
||||
int errorCode = WSAStartup(MAKEWORD(2, 2), &s_WSA);
|
||||
|
|
@ -502,6 +449,58 @@ namespace Nz
|
|||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
SocketState SocketImpl::PollConnection(SocketHandle handle, const IpAddress& address, UInt64 msTimeout, SocketError* error)
|
||||
{
|
||||
// http://developerweb.net/viewtopic.php?id=3196
|
||||
fd_set localSet;
|
||||
FD_ZERO(&localSet);
|
||||
FD_SET(handle, &localSet);
|
||||
|
||||
timeval tv;
|
||||
tv.tv_sec = static_cast<long>(msTimeout / 1000ULL);
|
||||
tv.tv_usec = static_cast<long>((msTimeout % 1000ULL) * 1000ULL);
|
||||
|
||||
int ret = ::select(0, nullptr, &localSet, &localSet, (msTimeout != std::numeric_limits<UInt64>::max()) ? &tv : nullptr);
|
||||
if (ret > 0)
|
||||
{
|
||||
int code = GetLastErrorCode(handle, error);
|
||||
if (code < 0) //< GetLastErrorCode() failed
|
||||
return SocketState_NotConnected;
|
||||
|
||||
if (code)
|
||||
{
|
||||
if (error)
|
||||
*error = TranslateWSAErrorToSocketError(code);
|
||||
|
||||
return SocketState_NotConnected;
|
||||
}
|
||||
}
|
||||
else if (ret == 0)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
if (msTimeout > 0)
|
||||
*error = SocketError_TimedOut;
|
||||
else
|
||||
*error = SocketError_NoError;
|
||||
}
|
||||
|
||||
return SocketState_Connecting;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (error)
|
||||
*error = TranslateWSAErrorToSocketError(WSAGetLastError());
|
||||
|
||||
return SocketState_NotConnected;
|
||||
}
|
||||
|
||||
if (error)
|
||||
*error = SocketError_NoError;
|
||||
|
||||
return SocketState_Connected;
|
||||
}
|
||||
|
||||
bool SocketImpl::Receive(SocketHandle handle, void* buffer, int length, int* read, SocketError* error)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ namespace Nz
|
|||
static void Close(SocketHandle handle);
|
||||
|
||||
static SocketState Connect(SocketHandle handle, const IpAddress& address, SocketError* error);
|
||||
static SocketState Connect(SocketHandle handle, const IpAddress& address, UInt64 msTimeout, SocketError* error);
|
||||
|
||||
static bool Initialize();
|
||||
|
||||
|
|
@ -61,6 +60,7 @@ namespace Nz
|
|||
static std::size_t QuerySendBufferSize(SocketHandle handle, SocketError* error = nullptr);
|
||||
|
||||
static unsigned int Poll(PollSocket* fdarray, std::size_t nfds, int timeout, SocketError* error);
|
||||
static SocketState PollConnection(SocketHandle handle, const IpAddress& address, UInt64 msTimeout, SocketError* error);
|
||||
|
||||
static bool Receive(SocketHandle handle, void* buffer, int length, int* read, SocketError* error);
|
||||
static bool ReceiveFrom(SocketHandle handle, void* buffer, int length, IpAddress* from, int* read, SocketError* error);
|
||||
|
|
|
|||
Loading…
Reference in New Issue