mirror of
https://github.com/pocoproject/poco.git
synced 2025-02-01 06:52:46 +01:00
* Windows 7 or lower have an undocumented minimum of 500ms for socket timeouts, detect at runtime and assume it as broken timeouts (https://social.msdn.microsoft.com/Forums/en-US/76620f6d-22b1-4872-aaf0-833204f3f867/minimum-timeout-value-for-sorcvtimeo)
This commit is contained in:
parent
51a8292649
commit
bd9b5b46d8
@ -421,11 +421,10 @@ private:
|
|||||||
SocketImpl& operator = (const SocketImpl&);
|
SocketImpl& operator = (const SocketImpl&);
|
||||||
|
|
||||||
poco_socket_t _sockfd;
|
poco_socket_t _sockfd;
|
||||||
#if defined(POCO_BROKEN_TIMEOUTS)
|
|
||||||
Poco::Timespan _recvTimeout;
|
Poco::Timespan _recvTimeout;
|
||||||
Poco::Timespan _sndTimeout;
|
Poco::Timespan _sndTimeout;
|
||||||
#endif
|
|
||||||
bool _blocking;
|
bool _blocking;
|
||||||
|
bool _isbrokentimeout;
|
||||||
|
|
||||||
friend class Socket;
|
friend class Socket;
|
||||||
friend class SecureSocketImpl;
|
friend class SecureSocketImpl;
|
||||||
|
@ -33,6 +33,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef POCO_OS_FAMILY_WINDOWS
|
||||||
|
#include <Windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
using Poco::IOException;
|
using Poco::IOException;
|
||||||
using Poco::TimeoutException;
|
using Poco::TimeoutException;
|
||||||
using Poco::InvalidArgumentException;
|
using Poco::InvalidArgumentException;
|
||||||
@ -44,16 +49,34 @@ namespace Poco {
|
|||||||
namespace Net {
|
namespace Net {
|
||||||
|
|
||||||
|
|
||||||
|
bool CheckIsBrokenTimeout()
|
||||||
|
{
|
||||||
|
#if defined(POCO_BROKEN_TIMEOUTS)
|
||||||
|
return true;
|
||||||
|
#elif defined(POCO_OS_FAMILY_WINDOWS)
|
||||||
|
// on Windows 7 and lower, socket timeouts have a minimum of 500ms, use poll for timeouts on this case
|
||||||
|
// https://social.msdn.microsoft.com/Forums/en-US/76620f6d-22b1-4872-aaf0-833204f3f867/minimum-timeout-value-for-sorcvtimeo
|
||||||
|
OSVERSIONINFO vi;
|
||||||
|
vi.dwOSVersionInfoSize = sizeof(vi);
|
||||||
|
if (GetVersionEx(&vi) == 0) return true; //throw SystemException("Cannot get OS version information");
|
||||||
|
return vi.dwMajorVersion < 6 || (vi.dwMajorVersion == 6 && vi.dwMinorVersion < 2);
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SocketImpl::SocketImpl():
|
SocketImpl::SocketImpl():
|
||||||
_sockfd(POCO_INVALID_SOCKET),
|
_sockfd(POCO_INVALID_SOCKET),
|
||||||
_blocking(true)
|
_blocking(true),
|
||||||
|
_isbrokentimeout(CheckIsBrokenTimeout())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SocketImpl::SocketImpl(poco_socket_t sockfd):
|
SocketImpl::SocketImpl(poco_socket_t sockfd):
|
||||||
_sockfd(sockfd),
|
_sockfd(sockfd),
|
||||||
_blocking(true)
|
_blocking(true),
|
||||||
|
_isbrokentimeout(CheckIsBrokenTimeout())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,13 +285,14 @@ void SocketImpl::shutdown()
|
|||||||
|
|
||||||
int SocketImpl::sendBytes(const void* buffer, int length, int flags)
|
int SocketImpl::sendBytes(const void* buffer, int length, int flags)
|
||||||
{
|
{
|
||||||
#if defined(POCO_BROKEN_TIMEOUTS)
|
if (_isbrokentimeout)
|
||||||
if (_sndTimeout.totalMicroseconds() != 0)
|
|
||||||
{
|
{
|
||||||
if (!poll(_sndTimeout, SELECT_WRITE))
|
if (_sndTimeout.totalMicroseconds() != 0)
|
||||||
throw TimeoutException();
|
{
|
||||||
|
if (!poll(_sndTimeout, SELECT_WRITE))
|
||||||
|
throw TimeoutException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
int rc;
|
int rc;
|
||||||
do
|
do
|
||||||
@ -284,13 +308,14 @@ int SocketImpl::sendBytes(const void* buffer, int length, int flags)
|
|||||||
|
|
||||||
int SocketImpl::receiveBytes(void* buffer, int length, int flags)
|
int SocketImpl::receiveBytes(void* buffer, int length, int flags)
|
||||||
{
|
{
|
||||||
#if defined(POCO_BROKEN_TIMEOUTS)
|
if (_isbrokentimeout)
|
||||||
if (_recvTimeout.totalMicroseconds() != 0)
|
|
||||||
{
|
{
|
||||||
if (!poll(_recvTimeout, SELECT_READ))
|
if (_recvTimeout.totalMicroseconds() != 0)
|
||||||
throw TimeoutException();
|
{
|
||||||
|
if (!poll(_recvTimeout, SELECT_READ))
|
||||||
|
throw TimeoutException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
int rc;
|
int rc;
|
||||||
do
|
do
|
||||||
@ -333,13 +358,14 @@ int SocketImpl::sendTo(const void* buffer, int length, const SocketAddress& addr
|
|||||||
|
|
||||||
int SocketImpl::receiveFrom(void* buffer, int length, SocketAddress& address, int flags)
|
int SocketImpl::receiveFrom(void* buffer, int length, SocketAddress& address, int flags)
|
||||||
{
|
{
|
||||||
#if defined(POCO_BROKEN_TIMEOUTS)
|
if (_isbrokentimeout)
|
||||||
if (_recvTimeout.totalMicroseconds() != 0)
|
|
||||||
{
|
{
|
||||||
if (!poll(_recvTimeout, SELECT_READ))
|
if (_recvTimeout.totalMicroseconds() != 0)
|
||||||
throw TimeoutException();
|
{
|
||||||
|
if (!poll(_recvTimeout, SELECT_READ))
|
||||||
|
throw TimeoutException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
char abuffer[SocketAddress::MAX_ADDRESS_LENGTH];
|
char abuffer[SocketAddress::MAX_ADDRESS_LENGTH];
|
||||||
struct sockaddr* pSA = reinterpret_cast<struct sockaddr*>(abuffer);
|
struct sockaddr* pSA = reinterpret_cast<struct sockaddr*>(abuffer);
|
||||||
@ -561,11 +587,11 @@ void SocketImpl::setSendTimeout(const Poco::Timespan& timeout)
|
|||||||
#if defined(_WIN32) && !defined(POCO_BROKEN_TIMEOUTS)
|
#if defined(_WIN32) && !defined(POCO_BROKEN_TIMEOUTS)
|
||||||
int value = (int) timeout.totalMilliseconds();
|
int value = (int) timeout.totalMilliseconds();
|
||||||
setOption(SOL_SOCKET, SO_SNDTIMEO, value);
|
setOption(SOL_SOCKET, SO_SNDTIMEO, value);
|
||||||
#elif defined(POCO_BROKEN_TIMEOUTS)
|
#elif !defined(POCO_BROKEN_TIMEOUTS)
|
||||||
_sndTimeout = timeout;
|
|
||||||
#else
|
|
||||||
setOption(SOL_SOCKET, SO_SNDTIMEO, timeout);
|
setOption(SOL_SOCKET, SO_SNDTIMEO, timeout);
|
||||||
#endif
|
#endif
|
||||||
|
if (_isbrokentimeout)
|
||||||
|
_sndTimeout = timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -576,11 +602,11 @@ Poco::Timespan SocketImpl::getSendTimeout()
|
|||||||
int value;
|
int value;
|
||||||
getOption(SOL_SOCKET, SO_SNDTIMEO, value);
|
getOption(SOL_SOCKET, SO_SNDTIMEO, value);
|
||||||
result = Timespan::TimeDiff(value)*1000;
|
result = Timespan::TimeDiff(value)*1000;
|
||||||
#elif defined(POCO_BROKEN_TIMEOUTS)
|
#elif !defined(POCO_BROKEN_TIMEOUTS)
|
||||||
result = _sndTimeout;
|
|
||||||
#else
|
|
||||||
getOption(SOL_SOCKET, SO_SNDTIMEO, result);
|
getOption(SOL_SOCKET, SO_SNDTIMEO, result);
|
||||||
#endif
|
#endif
|
||||||
|
if (_isbrokentimeout)
|
||||||
|
result = _sndTimeout;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,9 +620,9 @@ void SocketImpl::setReceiveTimeout(const Poco::Timespan& timeout)
|
|||||||
#else
|
#else
|
||||||
setOption(SOL_SOCKET, SO_RCVTIMEO, timeout);
|
setOption(SOL_SOCKET, SO_RCVTIMEO, timeout);
|
||||||
#endif
|
#endif
|
||||||
#else
|
|
||||||
_recvTimeout = timeout;
|
|
||||||
#endif
|
#endif
|
||||||
|
if (_isbrokentimeout)
|
||||||
|
_recvTimeout = timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -607,11 +633,11 @@ Poco::Timespan SocketImpl::getReceiveTimeout()
|
|||||||
int value;
|
int value;
|
||||||
getOption(SOL_SOCKET, SO_RCVTIMEO, value);
|
getOption(SOL_SOCKET, SO_RCVTIMEO, value);
|
||||||
result = Timespan::TimeDiff(value)*1000;
|
result = Timespan::TimeDiff(value)*1000;
|
||||||
#elif defined(POCO_BROKEN_TIMEOUTS)
|
#elif !defined(POCO_BROKEN_TIMEOUTS)
|
||||||
result = _recvTimeout;
|
|
||||||
#else
|
|
||||||
getOption(SOL_SOCKET, SO_RCVTIMEO, result);
|
getOption(SOL_SOCKET, SO_RCVTIMEO, result);
|
||||||
#endif
|
#endif
|
||||||
|
if (_isbrokentimeout)
|
||||||
|
result = _recvTimeout;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user