diff --git a/Net/include/Poco/Net/SocketImpl.h b/Net/include/Poco/Net/SocketImpl.h index cfc17ccbf..09b39fcad 100644 --- a/Net/include/Poco/Net/SocketImpl.h +++ b/Net/include/Poco/Net/SocketImpl.h @@ -421,11 +421,10 @@ private: SocketImpl& operator = (const SocketImpl&); poco_socket_t _sockfd; -#if defined(POCO_BROKEN_TIMEOUTS) Poco::Timespan _recvTimeout; Poco::Timespan _sndTimeout; -#endif bool _blocking; + bool _isbrokentimeout; friend class Socket; friend class SecureSocketImpl; diff --git a/Net/src/SocketImpl.cpp b/Net/src/SocketImpl.cpp index 74b26eb13..a8b6ea8f4 100644 --- a/Net/src/SocketImpl.cpp +++ b/Net/src/SocketImpl.cpp @@ -33,6 +33,11 @@ #endif +#ifdef POCO_OS_FAMILY_WINDOWS +#include +#endif + + using Poco::IOException; using Poco::TimeoutException; using Poco::InvalidArgumentException; @@ -44,16 +49,34 @@ namespace Poco { 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(): _sockfd(POCO_INVALID_SOCKET), - _blocking(true) + _blocking(true), + _isbrokentimeout(CheckIsBrokenTimeout()) { } SocketImpl::SocketImpl(poco_socket_t 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) { -#if defined(POCO_BROKEN_TIMEOUTS) - if (_sndTimeout.totalMicroseconds() != 0) + if (_isbrokentimeout) { - if (!poll(_sndTimeout, SELECT_WRITE)) - throw TimeoutException(); + if (_sndTimeout.totalMicroseconds() != 0) + { + if (!poll(_sndTimeout, SELECT_WRITE)) + throw TimeoutException(); + } } -#endif int rc; do @@ -284,13 +308,14 @@ int SocketImpl::sendBytes(const void* buffer, int length, int flags) int SocketImpl::receiveBytes(void* buffer, int length, int flags) { -#if defined(POCO_BROKEN_TIMEOUTS) - if (_recvTimeout.totalMicroseconds() != 0) + if (_isbrokentimeout) { - if (!poll(_recvTimeout, SELECT_READ)) - throw TimeoutException(); + if (_recvTimeout.totalMicroseconds() != 0) + { + if (!poll(_recvTimeout, SELECT_READ)) + throw TimeoutException(); + } } -#endif int rc; 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) { -#if defined(POCO_BROKEN_TIMEOUTS) - if (_recvTimeout.totalMicroseconds() != 0) + if (_isbrokentimeout) { - if (!poll(_recvTimeout, SELECT_READ)) - throw TimeoutException(); + if (_recvTimeout.totalMicroseconds() != 0) + { + if (!poll(_recvTimeout, SELECT_READ)) + throw TimeoutException(); + } } -#endif char abuffer[SocketAddress::MAX_ADDRESS_LENGTH]; struct sockaddr* pSA = reinterpret_cast(abuffer); @@ -561,11 +587,11 @@ void SocketImpl::setSendTimeout(const Poco::Timespan& timeout) #if defined(_WIN32) && !defined(POCO_BROKEN_TIMEOUTS) int value = (int) timeout.totalMilliseconds(); setOption(SOL_SOCKET, SO_SNDTIMEO, value); -#elif defined(POCO_BROKEN_TIMEOUTS) - _sndTimeout = timeout; -#else +#elif !defined(POCO_BROKEN_TIMEOUTS) setOption(SOL_SOCKET, SO_SNDTIMEO, timeout); #endif + if (_isbrokentimeout) + _sndTimeout = timeout; } @@ -576,11 +602,11 @@ Poco::Timespan SocketImpl::getSendTimeout() int value; getOption(SOL_SOCKET, SO_SNDTIMEO, value); result = Timespan::TimeDiff(value)*1000; -#elif defined(POCO_BROKEN_TIMEOUTS) - result = _sndTimeout; -#else +#elif !defined(POCO_BROKEN_TIMEOUTS) getOption(SOL_SOCKET, SO_SNDTIMEO, result); #endif + if (_isbrokentimeout) + result = _sndTimeout; return result; } @@ -594,9 +620,9 @@ void SocketImpl::setReceiveTimeout(const Poco::Timespan& timeout) #else setOption(SOL_SOCKET, SO_RCVTIMEO, timeout); #endif -#else - _recvTimeout = timeout; #endif + if (_isbrokentimeout) + _recvTimeout = timeout; } @@ -607,11 +633,11 @@ Poco::Timespan SocketImpl::getReceiveTimeout() int value; getOption(SOL_SOCKET, SO_RCVTIMEO, value); result = Timespan::TimeDiff(value)*1000; -#elif defined(POCO_BROKEN_TIMEOUTS) - result = _recvTimeout; -#else +#elif !defined(POCO_BROKEN_TIMEOUTS) getOption(SOL_SOCKET, SO_RCVTIMEO, result); #endif + if (_isbrokentimeout) + result = _recvTimeout; return result; }