diff --git a/contrib/CMakeLists.txt b/contrib/CMakeLists.txt index a2f496d9..41c7015b 100644 --- a/contrib/CMakeLists.txt +++ b/contrib/CMakeLists.txt @@ -8,66 +8,6 @@ unset (_current_dir_name) set_property(DIRECTORY PROPERTY EXCLUDE_FROM_ALL 1) - -#if (CH_ODBC_PREFER_BUNDLED_POCO OR NOT Poco_FOUND) -# if (NOT Poco_FOUND AND NOT CH_ODBC_PREFER_BUNDLED_POCO) -# message (WARNING "Poco: unable to find system Poco, falling back to using the bundled variant of the library") -# endif () -# -# if (CH_ODBC_ENABLE_SSL AND MSVC) -# set (ENABLE_NETSSL_WIN ON CACHE INTERNAL "") -# endif () -# -# if (CH_ODBC_THIRD_PARTY_LINK_STATIC) -# set (POCO_STATIC ON CACHE INTERNAL "") -# endif () -# -# if (CH_ODBC_RUNTIME_LINK_STATIC) -# set (POCO_MT ON CACHE INTERNAL "") -# endif () -# -# set (CMAKE_MODULE_PATH_bak ${CMAKE_MODULE_PATH}) -# set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH_orig}) -# -# add_subdirectory (poco) -# -# set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH_bak}) -# unset (CMAKE_MODULE_PATH_bak) -# -# if (TARGET NetSSL) -# add_library(Poco::NetSSL ALIAS NetSSL) -# endif () -# -# if (TARGET NetSSLWin) -# add_library(Poco::NetSSLWin ALIAS NetSSLWin) -# endif () -# -# add_library(Poco::Net ALIAS Net) -# add_library(Poco::Foundation ALIAS Foundation) -# add_library(Poco::Util ALIAS Util) -# -# # Remove pthread from linking poco's Net -# set_property (TARGET Net PROPERTY INTERFACE_LINK_LIBRARIES "") -# set_property (TARGET Foundation PROPERTY INTERFACE_LINK_LIBRARIES "") -#endif () -# -## Bug in poco https://github.com/pocoproject/poco/pull/2100 found on macos -#if (OPENSSL_FOUND) -# if (TARGET Crypto) -# target_include_directories (Crypto INTERFACE $) -# elseif (TARGET Poco::Crypto) -# target_include_directories (Poco::Crypto INTERFACE $) -# endif () -#endif() -# -#if (MSVC) -# if (TARGET Foundation) -# set_property(TARGET Foundation APPEND PROPERTY INTERFACE_LINK_LIBRARIES Iphlpapi) -# elseif (TARGET Poco::Foundation) -# set_property(TARGET Poco::Foundation APPEND PROPERTY INTERFACE_LINK_LIBRARIES Iphlpapi) -# endif () -#endif () - # add_contrib cmake_folder[ base_folder1[, ...base_folderN]] function(add_contrib cmake_folder) if (ARGN) @@ -101,20 +41,14 @@ add_contrib (unixodbc-cmake unixodbc) add_contrib (nanodbc-cmake nanodbc) add_contrib (lz4-cmake lz4) add_contrib (double-conversion-cmake double-conversion) + if (OS_DARWIN OR OS_LINUX) add_contrib (openssl-cmake openssl) endif() + add_contrib (zlib-ng-cmake zlib-ng) set (FOLLY_INLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/folly" CACHE INTERNAL "") -# if (CH_ODBC_PREFER_BUNDLED_FOLLY OR NOT Folly_FOUND) -# if (NOT Folly_FOUND AND NOT CH_ODBC_PREFER_BUNDLED_FOLLY) -# message (WARNING "Folly: unable to find system Folly, falling back to using the bundled variant of the library") -# endif () -# -# add_subdirectory (folly) -# endif () - if (CH_ODBC_ENABLE_TESTING) if (CH_ODBC_PREFER_BUNDLED_GOOGLETEST OR NOT GTEST_FOUND) if (NOT GTEST_FOUND AND NOT CH_ODBC_PREFER_BUNDLED_GOOGLETEST) diff --git a/contrib/nanodbc-cmake/CMakeLists.txt b/contrib/nanodbc-cmake/CMakeLists.txt index c0612ecf..feaecd51 100644 --- a/contrib/nanodbc-cmake/CMakeLists.txt +++ b/contrib/nanodbc-cmake/CMakeLists.txt @@ -1,5 +1,4 @@ - -if (OS_DARWIN OR OS_LINIX) +if (OS_DARWIN OR OS_LINUX) if (NOT TARGET ch_contrib::unixodbc) message(FATAL_ERROR "Configuration error: unixodbc is not a target") endif() @@ -14,6 +13,7 @@ if (OS_DARWIN OR OS_LINIX) target_link_libraries(_nanodbc PUBLIC ch_contrib::unixodbc) target_include_directories(_nanodbc SYSTEM PUBLIC "${LIBRARY_DIR}/") add_library(ch_contrib::nanodbc ALIAS _nanodbc) + elseif (OS_WINDOWS) set (LIBRARY_DIR "${CMAKE_SOURCE_DIR}/contrib/nanodbc") set (SRCS @@ -24,5 +24,4 @@ elseif (OS_WINDOWS) target_link_libraries(_nanodbc PUBLIC ODBC::Driver) target_include_directories(_nanodbc SYSTEM PUBLIC "${LIBRARY_DIR}/") add_library(ch_contrib::nanodbc ALIAS _nanodbc) - endif() diff --git a/contrib/poco/Foundation/CMakeLists.txt b/contrib/poco/Foundation/CMakeLists.txt index addec6e3..7f27f865 100644 --- a/contrib/poco/Foundation/CMakeLists.txt +++ b/contrib/poco/Foundation/CMakeLists.txt @@ -128,6 +128,7 @@ set(SRCS src/SimpleFileChannel.cpp src/SortedDirectoryIterator.cpp src/SplitterChannel.cpp + src/SyslogChannel.cpp src/Stopwatch.cpp src/StreamChannel.cpp src/StreamConverter.cpp @@ -179,7 +180,7 @@ set(SRCS ) if(WIN32) - set(SYSLIBS ${SYSLIBS} iphlpapi) + set(SYSLIBS ${SYSLIBS} iphlpapi) endif(WIN32) add_library(_poco_foundation ${SRCS}) diff --git a/contrib/poco/Foundation/include/Poco/EventLogChannel.h b/contrib/poco/Foundation/include/Poco/EventLogChannel.h index bcaf3a42..2fecead4 100644 --- a/contrib/poco/Foundation/include/Poco/EventLogChannel.h +++ b/contrib/poco/Foundation/include/Poco/EventLogChannel.h @@ -17,6 +17,7 @@ #ifndef Foundation_EventLogChannel_INCLUDED #define Foundation_EventLogChannel_INCLUDED +#if defined(POCO_OS_FAMILY_WINDOWS) #include "Poco/Foundation.h" #include "Poco/Channel.h" @@ -101,5 +102,6 @@ class Foundation_API EventLogChannel: public Channel } // namespace Poco +#endif #endif // Foundation_EventLogChannel_INCLUDED diff --git a/contrib/poco/Foundation/include/Poco/WindowsConsoleChannel.h b/contrib/poco/Foundation/include/Poco/WindowsConsoleChannel.h index b395c26d..5059e3e2 100644 --- a/contrib/poco/Foundation/include/Poco/WindowsConsoleChannel.h +++ b/contrib/poco/Foundation/include/Poco/WindowsConsoleChannel.h @@ -17,6 +17,7 @@ #ifndef Foundation_WindowsConsoleChannel_INCLUDED #define Foundation_WindowsConsoleChannel_INCLUDED +#if defined(POCO_OS_FAMILY_WINDOWS) #include "Poco/Foundation.h" #include "Poco/Channel.h" @@ -179,5 +180,6 @@ class Foundation_API WindowsColorConsoleChannel: public Channel } // namespace Poco +#endif #endif // Foundation_WindowsConsoleChannel_INCLUDED diff --git a/contrib/poco/Foundation/src/EventLogChannel.cpp b/contrib/poco/Foundation/src/EventLogChannel.cpp index de6f8a9b..94199d89 100644 --- a/contrib/poco/Foundation/src/EventLogChannel.cpp +++ b/contrib/poco/Foundation/src/EventLogChannel.cpp @@ -12,6 +12,8 @@ // +#if defined(POCO_OS_FAMILY_WINDOWS) + #include "Poco/EventLogChannel.h" #include "Poco/Message.h" #include "Poco/String.h" @@ -316,3 +318,5 @@ std::string EventLogChannel::findLibrary(const char* name) } // namespace Poco + +#endif diff --git a/contrib/poco/Foundation/src/WindowsConsoleChannel.cpp b/contrib/poco/Foundation/src/WindowsConsoleChannel.cpp index 07e35293..1d08c9c6 100644 --- a/contrib/poco/Foundation/src/WindowsConsoleChannel.cpp +++ b/contrib/poco/Foundation/src/WindowsConsoleChannel.cpp @@ -12,6 +12,8 @@ // +#if defined(POCO_OS_FAMILY_WINDOWS) + #include "Poco/WindowsConsoleChannel.h" #include "Poco/Message.h" #if defined(POCO_WIN32_UTF8) @@ -300,3 +302,5 @@ void WindowsColorConsoleChannel::initColors() } // namespace Poco + +#endif diff --git a/contrib/poco/Net/include/Poco/Net/HTTPClientSession.h b/contrib/poco/Net/include/Poco/Net/HTTPClientSession.h index 2f2e21c5..d3bdcf62 100644 --- a/contrib/poco/Net/include/Poco/Net/HTTPClientSession.h +++ b/contrib/poco/Net/include/Poco/Net/HTTPClientSession.h @@ -20,6 +20,7 @@ #include "Poco/Net/Net.h" #include "Poco/Net/HTTPSession.h" +#include "Poco/Net/HTTPSessionFactory.h" #include "Poco/Net/SocketAddress.h" #include "Poco/SharedPtr.h" #include @@ -66,7 +67,7 @@ class Net_API HTTPClientSession: public HTTPSession /// HTTP proxy server configuration. { ProxyConfig(): - port(HTTP_PORT) + port(HTTP_PORT), protocol("http"), tunnel(true) { } @@ -74,6 +75,11 @@ class Net_API HTTPClientSession: public HTTPSession /// Proxy server host name or IP address. Poco::UInt16 port; /// Proxy server TCP port. + std::string protocol; + /// Protocol to use (http or https). + bool tunnel; + /// Use proxy as tunnel (establish 2-way communication through CONNECT request). + /// If tunnel option is 'false' request will be send directly to proxy without CONNECT request. std::string username; /// Proxy server username. std::string password; @@ -120,11 +126,16 @@ class Net_API HTTPClientSession: public HTTPSession /// The port number must not be changed once there is an /// open connection to the server. + void setResolvedHost(std::string resolved_host) { _resolved_host.swap(resolved_host); } + Poco::UInt16 getPort() const; /// Returns the port number of the target HTTP server. - void setProxy(const std::string& host, Poco::UInt16 port = HTTPSession::HTTP_PORT); - /// Sets the proxy host name and port number. + std::string getResolvedAddress() const; + /// Returns the resolved host name and port of the target HTTP server. + + void setProxy(const std::string& host, Poco::UInt16 port = HTTPSession::HTTP_PORT, const std::string& protocol = "http", bool tunnel = true); + /// Sets the proxy host name, port number, protocol (http or https) and tunnel behaviour. void setProxyHost(const std::string& host); /// Sets the host name of the proxy server. @@ -132,12 +143,24 @@ class Net_API HTTPClientSession: public HTTPSession void setProxyPort(Poco::UInt16 port); /// Sets the port number of the proxy server. + void setProxyProtocol(const std::string& protocol); + /// Sets the proxy protocol (http or https). + + void setProxyTunnel(bool tunnel); + /// If 'true' proxy will be used as tunnel. + const std::string& getProxyHost() const; /// Returns the proxy host name. Poco::UInt16 getProxyPort() const; /// Returns the proxy port number. + const std::string& getProxyProtocol() const; + /// Returns the proxy protocol. + + bool isProxyTunnel() const; + /// Returns 'true' if proxy is configured as tunnel. + void setProxyCredentials(const std::string& username, const std::string& password); /// Sets the username and password for proxy authentication. /// Only Basic authentication is supported. @@ -306,8 +329,11 @@ class Net_API HTTPClientSession: public HTTPSession /// Calls proxyConnect() and attaches the resulting StreamSocket /// to the HTTPClientSession. + HTTPSessionFactory _proxySessionFactory; + /// Factory to create HTTPClientSession to proxy. private: std::string _host; + std::string _resolved_host; Poco::UInt16 _port; ProxyConfig _proxyConfig; Poco::Timespan _keepAliveTimeout; @@ -331,6 +357,13 @@ class Net_API HTTPClientSession: public HTTPSession // // inlines // + +inline std::string HTTPClientSession::getResolvedAddress() const +{ + return (_resolved_host.empty() ? _host : _resolved_host) + ':' + std::to_string(_port); +} + + inline const std::string& HTTPClientSession::getHost() const { return _host; @@ -355,6 +388,18 @@ inline Poco::UInt16 HTTPClientSession::getProxyPort() const } +inline const std::string& HTTPClientSession::getProxyProtocol() const +{ + return _proxyConfig.protocol; +} + + +inline bool HTTPClientSession::isProxyTunnel() const +{ + return _proxyConfig.tunnel; +} + + inline const std::string& HTTPClientSession::getProxyUsername() const { return _proxyConfig.username; diff --git a/contrib/poco/Net/include/Poco/Net/SocketImpl.h b/contrib/poco/Net/include/Poco/Net/SocketImpl.h index 20462f00..d1fec1de 100644 --- a/contrib/poco/Net/include/Poco/Net/SocketImpl.h +++ b/contrib/poco/Net/include/Poco/Net/SocketImpl.h @@ -213,6 +213,9 @@ class Net_API SocketImpl: public Poco::RefCountedObject /// Returns true if the next operation corresponding to /// mode will not block, false otherwise. + bool pollImpl(Poco::Timespan& timeout, int mode); + /// Modifies `timeout` + virtual void setSendBufferSize(int size); /// Sets the size of the send buffer. @@ -447,7 +450,7 @@ class Net_API SocketImpl: public Poco::RefCountedObject static void error(int code, const std::string& arg); /// Throws an appropriate exception for the given error code. -private: +protected: SocketImpl(const SocketImpl&); SocketImpl& operator = (const SocketImpl&); diff --git a/contrib/poco/Net/src/HTTPClientSession.cpp b/contrib/poco/Net/src/HTTPClientSession.cpp index c2b81703..323e9526 100644 --- a/contrib/poco/Net/src/HTTPClientSession.cpp +++ b/contrib/poco/Net/src/HTTPClientSession.cpp @@ -13,6 +13,7 @@ #include "Poco/Net/HTTPClientSession.h" +#include "Poco/Net/HTTPSessionInstantiator.h" #include "Poco/Net/HTTPRequest.h" #include "Poco/Net/HTTPResponse.h" #include "Poco/Net/HTTPHeaderStream.h" @@ -25,6 +26,7 @@ #include "Poco/CountingStream.h" #include "Poco/RegularExpression.h" #include +#include using Poco::NumberFormatter; @@ -47,6 +49,7 @@ HTTPClientSession::HTTPClientSession(): _expectResponseBody(false), _responseReceived(false) { + _proxySessionFactory.registerProtocol("http", new HTTPSessionInstantiator); } @@ -60,6 +63,7 @@ HTTPClientSession::HTTPClientSession(const StreamSocket& socket): _expectResponseBody(false), _responseReceived(false) { + _proxySessionFactory.registerProtocol("http", new HTTPSessionInstantiator); } @@ -73,6 +77,7 @@ HTTPClientSession::HTTPClientSession(const SocketAddress& address): _expectResponseBody(false), _responseReceived(false) { + _proxySessionFactory.registerProtocol("http", new HTTPSessionInstantiator); } @@ -86,6 +91,7 @@ HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port) _expectResponseBody(false), _responseReceived(false) { + _proxySessionFactory.registerProtocol("http", new HTTPSessionInstantiator); } @@ -99,11 +105,13 @@ HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port, _expectResponseBody(false), _responseReceived(false) { + _proxySessionFactory.registerProtocol("http", new HTTPSessionInstantiator); } HTTPClientSession::~HTTPClientSession() { + _proxySessionFactory.unregisterProtocol("http"); } @@ -125,14 +133,19 @@ void HTTPClientSession::setPort(Poco::UInt16 port) } -void HTTPClientSession::setProxy(const std::string& host, Poco::UInt16 port) +void HTTPClientSession::setProxy(const std::string& host, Poco::UInt16 port, const std::string& protocol, bool tunnel) { + if (protocol != "http" && protocol != "https") + throw IllegalStateException("Protocol must be either http or https"); + if (!connected()) { _proxyConfig.host = host; _proxyConfig.port = port; + _proxyConfig.protocol = protocol; + _proxyConfig.tunnel = tunnel; } - else throw IllegalStateException("Cannot set the proxy host and port for an already connected session"); + else throw IllegalStateException("Cannot set the proxy host, port and protocol for an already connected session"); } @@ -154,6 +167,27 @@ void HTTPClientSession::setProxyPort(Poco::UInt16 port) } +void HTTPClientSession::setProxyProtocol(const std::string& protocol) +{ + if (protocol != "http" && protocol != "https") + throw IllegalStateException("Protocol must be either http or https"); + + if (!connected()) + _proxyConfig.protocol = protocol; + else + throw IllegalStateException("Cannot set the proxy port number for an already connected session"); +} + + +void HTTPClientSession::setProxyTunnel(bool tunnel) +{ + if (!connected()) + _proxyConfig.tunnel = tunnel; + else + throw IllegalStateException("Cannot set the proxy tunnel for an already connected session"); +} + + void HTTPClientSession::setProxyCredentials(const std::string& username, const std::string& password) { _proxyConfig.username = username; @@ -360,7 +394,7 @@ int HTTPClientSession::write(const char* buffer, std::streamsize length) _reconnect = false; return rc; } - catch (IOException&) + catch (Poco::Exception&) { if (_reconnect) { @@ -380,7 +414,7 @@ void HTTPClientSession::reconnect() { if (_proxyConfig.host.empty() || bypassProxy()) { - SocketAddress addr(_host, _port); + SocketAddress addr(_resolved_host.empty() ? _host : _resolved_host, _port); connect(addr); } else @@ -395,8 +429,13 @@ std::string HTTPClientSession::proxyRequestPrefix() const { std::string result("http://"); result.append(_host); - result.append(":"); - NumberFormatter::append(result, _port); + /// Do not append default by default, since this may break some servers. + /// One example of such server is GCS (Google Cloud Storage). + if (_port != HTTPSession::HTTP_PORT) + { + result.append(":"); + NumberFormatter::append(result, _port); + } return result; } @@ -430,23 +469,28 @@ void HTTPClientSession::proxyAuthenticateImpl(HTTPRequest& request) StreamSocket HTTPClientSession::proxyConnect() { - ProxyConfig emptyProxyConfig; - HTTPClientSession proxySession(getProxyHost(), getProxyPort(), emptyProxyConfig); - proxySession.setTimeout(getTimeout()); + URI proxyUri; + proxyUri.setScheme(getProxyProtocol()); + proxyUri.setHost(getProxyHost()); + proxyUri.setPort(getProxyPort()); + + SharedPtr proxySession (_proxySessionFactory.createClientSession(proxyUri)); + + proxySession->setTimeout(getTimeout()); std::string targetAddress(_host); targetAddress.append(":"); NumberFormatter::append(targetAddress, _port); HTTPRequest proxyRequest(HTTPRequest::HTTP_CONNECT, targetAddress, HTTPMessage::HTTP_1_1); HTTPResponse proxyResponse; proxyRequest.set("Proxy-Connection", "keep-alive"); - proxyRequest.set("Host", getHost()); + proxyRequest.set("Host", targetAddress); proxyAuthenticateImpl(proxyRequest); - proxySession.setKeepAlive(true); - proxySession.sendRequest(proxyRequest); - proxySession.receiveResponse(proxyResponse); + proxySession->setKeepAlive(true); + proxySession->sendRequest(proxyRequest); + proxySession->receiveResponse(proxyResponse); if (proxyResponse.getStatus() != HTTPResponse::HTTP_OK) throw HTTPException("Cannot establish proxy connection", proxyResponse.getReason()); - return proxySession.detachSocket(); + return proxySession->detachSocket(); } diff --git a/contrib/poco/Net/src/SocketImpl.cpp b/contrib/poco/Net/src/SocketImpl.cpp index 6bc216dd..160ff6bd 100644 --- a/contrib/poco/Net/src/SocketImpl.cpp +++ b/contrib/poco/Net/src/SocketImpl.cpp @@ -24,16 +24,14 @@ #ifndef POCO_HAVE_FD_POLL #define POCO_HAVE_FD_POLL 1 #endif -#elif defined(POCO_OS_FAMILY_BSD) +#elif defined(POCO_OS_FAMILY_UNIX) #ifndef POCO_HAVE_FD_POLL #define POCO_HAVE_FD_POLL 1 #endif #endif -#if defined(POCO_HAVE_FD_EPOLL) -#include -#elif defined(POCO_HAVE_FD_POLL) +#if defined(POCO_HAVE_FD_POLL) #ifndef _WIN32 #include #endif @@ -324,14 +322,22 @@ int SocketImpl::sendBytes(const void* buffer, int length, int flags) rc = ::send(_sockfd, reinterpret_cast(buffer), length, flags); } while (_blocking && rc < 0 && lastError() == POCO_EINTR); - if (rc < 0) error(); + if (rc < 0) + { + int err = lastError(); + if (err == POCO_EAGAIN || err == POCO_ETIMEDOUT) + throw TimeoutException(); + else + error(err); + } return rc; } int SocketImpl::receiveBytes(void* buffer, int length, int flags) { - if (_isBrokenTimeout) + bool blocking = _blocking && (flags & MSG_DONTWAIT) == 0; + if (_isBrokenTimeout && blocking) { if (_recvTimeout.totalMicroseconds() != 0) { @@ -346,11 +352,11 @@ int SocketImpl::receiveBytes(void* buffer, int length, int flags) if (_sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); rc = ::recv(_sockfd, reinterpret_cast(buffer), length, flags); } - while (_blocking && rc < 0 && lastError() == POCO_EINTR); + while (blocking && rc < 0 && lastError() == POCO_EINTR); if (rc < 0) { int err = lastError(); - if (err == POCO_EAGAIN && !_blocking) + if ((err == POCO_EAGAIN || err == POCO_EWOULDBLOCK) && !blocking) ; else if (err == POCO_EAGAIN || err == POCO_ETIMEDOUT) throw TimeoutException(err); @@ -441,61 +447,12 @@ bool SocketImpl::secure() const } -bool SocketImpl::poll(const Poco::Timespan& timeout, int mode) +bool SocketImpl::pollImpl(Poco::Timespan& remainingTime, int mode) { poco_socket_t sockfd = _sockfd; if (sockfd == POCO_INVALID_SOCKET) throw InvalidSocketException(); -#if defined(POCO_HAVE_FD_EPOLL) - - int epollfd = epoll_create(1); - if (epollfd < 0) - { - error("Can't create epoll queue"); - } - - struct epoll_event evin; - memset(&evin, 0, sizeof(evin)); - - if (mode & SELECT_READ) - evin.events |= EPOLLIN; - if (mode & SELECT_WRITE) - evin.events |= EPOLLOUT; - if (mode & SELECT_ERROR) - evin.events |= EPOLLERR; - - if (epoll_ctl(epollfd, EPOLL_CTL_ADD, sockfd, &evin) < 0) - { - ::close(epollfd); - error("Can't insert socket to epoll queue"); - } - - Poco::Timespan remainingTime(timeout); - int rc; - do - { - struct epoll_event evout; - memset(&evout, 0, sizeof(evout)); - - Poco::Timestamp start; - rc = epoll_wait(epollfd, &evout, 1, remainingTime.totalMilliseconds()); - if (rc < 0 && lastError() == POCO_EINTR) - { - Poco::Timestamp end; - Poco::Timespan waited = end - start; - if (waited < remainingTime) - remainingTime -= waited; - else - remainingTime = 0; - } - } - while (rc < 0 && lastError() == POCO_EINTR); - - ::close(epollfd); - if (rc < 0) error(); - return rc > 0; - -#elif defined(POCO_HAVE_FD_POLL) +#if defined(POCO_HAVE_FD_POLL) pollfd pollBuf; @@ -504,7 +461,6 @@ bool SocketImpl::poll(const Poco::Timespan& timeout, int mode) if (mode & SELECT_READ) pollBuf.events |= POLLIN; if (mode & SELECT_WRITE) pollBuf.events |= POLLOUT; - Poco::Timespan remainingTime(timeout); int rc; do { @@ -514,7 +470,11 @@ bool SocketImpl::poll(const Poco::Timespan& timeout, int mode) #else rc = ::poll(&pollBuf, 1, remainingTime.totalMilliseconds()); #endif - if (rc < 0 && lastError() == POCO_EINTR) + /// Decrease timeout in case of retriable error. + /// + /// But do this only if the timeout is positive, + /// since negative timeout means an infinite timeout. + if (rc < 0 && lastError() == POCO_EINTR && remainingTime > 0) { Poco::Timestamp end; Poco::Timespan waited = end - start; @@ -548,7 +508,6 @@ bool SocketImpl::poll(const Poco::Timespan& timeout, int mode) { FD_SET(sockfd, &fdExcept); } - Poco::Timespan remainingTime(timeout); int errorCode = POCO_ENOERR; int rc; do @@ -572,9 +531,14 @@ bool SocketImpl::poll(const Poco::Timespan& timeout, int mode) if (rc < 0) error(errorCode); return rc > 0; -#endif // POCO_HAVE_FD_EPOLL +#endif // POCO_HAVE_FD_POLL } +bool SocketImpl::poll(const Poco::Timespan& timeout, int mode) +{ + Poco::Timespan remainingTime(timeout); + return pollImpl(remainingTime, mode); +} void SocketImpl::setSendBufferSize(int size) { @@ -606,14 +570,13 @@ int SocketImpl::getReceiveBufferSize() void SocketImpl::setSendTimeout(const Poco::Timespan& timeout) { -#if defined(_WIN32) && !defined(POCO_BROKEN_TIMEOUTS) +#if defined(_WIN32) int value = (int) timeout.totalMilliseconds(); setOption(SOL_SOCKET, SO_SNDTIMEO, value); -#elif !defined(POCO_BROKEN_TIMEOUTS) +#else setOption(SOL_SOCKET, SO_SNDTIMEO, timeout); #endif - if (_isBrokenTimeout) - _sndTimeout = timeout; + _sndTimeout = timeout; } @@ -635,16 +598,13 @@ Poco::Timespan SocketImpl::getSendTimeout() void SocketImpl::setReceiveTimeout(const Poco::Timespan& timeout) { -#ifndef POCO_BROKEN_TIMEOUTS #if defined(_WIN32) int value = (int) timeout.totalMilliseconds(); setOption(SOL_SOCKET, SO_RCVTIMEO, value); #else setOption(SOL_SOCKET, SO_RCVTIMEO, timeout); #endif -#endif - if (_isBrokenTimeout) - _recvTimeout = timeout; + _recvTimeout = timeout; } @@ -940,7 +900,11 @@ int SocketImpl::socketError() void SocketImpl::init(int af) { +#ifdef SOCK_CLOEXEC + initSocket(af, SOCK_STREAM|SOCK_CLOEXEC); +#else initSocket(af, SOCK_STREAM); +#endif }