diff --git a/Net/Net_vs100.sln b/Net/Net_vs100.sln index c166d637d..7275646b5 100644 --- a/Net/Net_vs100.sln +++ b/Net/Net_vs100.sln @@ -1,60 +1,60 @@ -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Net", "Net_vs100.vcxproj", "{B057A1FE-09F7-465E-B8B5-E1B659051D76}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestSuite", "testsuite\TestSuite_vs100.vcxproj", "{D5EFBF27-B934-4B8D-8AE5-6EC00374819C}" - ProjectSection(ProjectDependencies) = postProject - {B057A1FE-09F7-465E-B8B5-E1B659051D76} = {B057A1FE-09F7-465E-B8B5-E1B659051D76} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - debug_shared|Win32 = debug_shared|Win32 - release_shared|Win32 = release_shared|Win32 - debug_static_mt|Win32 = debug_static_mt|Win32 - release_static_mt|Win32 = release_static_mt|Win32 - debug_static_md|Win32 = debug_static_md|Win32 - release_static_md|Win32 = release_static_md|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {B057A1FE-09F7-465E-B8B5-E1B659051D76}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 - {B057A1FE-09F7-465E-B8B5-E1B659051D76}.debug_shared|Win32.Build.0 = debug_shared|Win32 - {B057A1FE-09F7-465E-B8B5-E1B659051D76}.debug_shared|Win32.Deploy.0 = debug_shared|Win32 - {B057A1FE-09F7-465E-B8B5-E1B659051D76}.release_shared|Win32.ActiveCfg = release_shared|Win32 - {B057A1FE-09F7-465E-B8B5-E1B659051D76}.release_shared|Win32.Build.0 = release_shared|Win32 - {B057A1FE-09F7-465E-B8B5-E1B659051D76}.release_shared|Win32.Deploy.0 = release_shared|Win32 - {B057A1FE-09F7-465E-B8B5-E1B659051D76}.debug_static_mt|Win32.ActiveCfg = debug_static_mt|Win32 - {B057A1FE-09F7-465E-B8B5-E1B659051D76}.debug_static_mt|Win32.Build.0 = debug_static_mt|Win32 - {B057A1FE-09F7-465E-B8B5-E1B659051D76}.debug_static_mt|Win32.Deploy.0 = debug_static_mt|Win32 - {B057A1FE-09F7-465E-B8B5-E1B659051D76}.release_static_mt|Win32.ActiveCfg = release_static_mt|Win32 - {B057A1FE-09F7-465E-B8B5-E1B659051D76}.release_static_mt|Win32.Build.0 = release_static_mt|Win32 - {B057A1FE-09F7-465E-B8B5-E1B659051D76}.release_static_mt|Win32.Deploy.0 = release_static_mt|Win32 - {B057A1FE-09F7-465E-B8B5-E1B659051D76}.debug_static_md|Win32.ActiveCfg = debug_static_md|Win32 - {B057A1FE-09F7-465E-B8B5-E1B659051D76}.debug_static_md|Win32.Build.0 = debug_static_md|Win32 - {B057A1FE-09F7-465E-B8B5-E1B659051D76}.debug_static_md|Win32.Deploy.0 = debug_static_md|Win32 - {B057A1FE-09F7-465E-B8B5-E1B659051D76}.release_static_md|Win32.ActiveCfg = release_static_md|Win32 - {B057A1FE-09F7-465E-B8B5-E1B659051D76}.release_static_md|Win32.Build.0 = release_static_md|Win32 - {B057A1FE-09F7-465E-B8B5-E1B659051D76}.release_static_md|Win32.Deploy.0 = release_static_md|Win32 - {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 - {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.debug_shared|Win32.Build.0 = debug_shared|Win32 - {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.debug_shared|Win32.Deploy.0 = debug_shared|Win32 - {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.release_shared|Win32.ActiveCfg = release_shared|Win32 - {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.release_shared|Win32.Build.0 = release_shared|Win32 - {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.release_shared|Win32.Deploy.0 = release_shared|Win32 - {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.debug_static_mt|Win32.ActiveCfg = debug_static_mt|Win32 - {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.debug_static_mt|Win32.Build.0 = debug_static_mt|Win32 - {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.debug_static_mt|Win32.Deploy.0 = debug_static_mt|Win32 - {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.release_static_mt|Win32.ActiveCfg = release_static_mt|Win32 - {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.release_static_mt|Win32.Build.0 = release_static_mt|Win32 - {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.release_static_mt|Win32.Deploy.0 = release_static_mt|Win32 - {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.debug_static_md|Win32.ActiveCfg = debug_static_md|Win32 - {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.debug_static_md|Win32.Build.0 = debug_static_md|Win32 - {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.debug_static_md|Win32.Deploy.0 = debug_static_md|Win32 - {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.release_static_md|Win32.ActiveCfg = release_static_md|Win32 - {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.release_static_md|Win32.Build.0 = release_static_md|Win32 - {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.release_static_md|Win32.Deploy.0 = release_static_md|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Net", "Net_vs100.vcxproj", "{B057A1FE-09F7-465E-B8B5-E1B659051D76}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestSuite", "testsuite\TestSuite_vs100.vcxproj", "{D5EFBF27-B934-4B8D-8AE5-6EC00374819C}" + ProjectSection(ProjectDependencies) = postProject + {B057A1FE-09F7-465E-B8B5-E1B659051D76} = {B057A1FE-09F7-465E-B8B5-E1B659051D76} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + debug_shared|Win32 = debug_shared|Win32 + debug_static_md|Win32 = debug_static_md|Win32 + debug_static_mt|Win32 = debug_static_mt|Win32 + release_shared|Win32 = release_shared|Win32 + release_static_md|Win32 = release_static_md|Win32 + release_static_mt|Win32 = release_static_mt|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.debug_shared|Win32.Deploy.0 = debug_shared|Win32 + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.debug_static_md|Win32.ActiveCfg = debug_static_md|Win32 + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.debug_static_md|Win32.Build.0 = debug_static_md|Win32 + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.debug_static_md|Win32.Deploy.0 = debug_static_md|Win32 + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.debug_static_mt|Win32.ActiveCfg = debug_static_mt|Win32 + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.debug_static_mt|Win32.Build.0 = debug_static_mt|Win32 + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.debug_static_mt|Win32.Deploy.0 = debug_static_mt|Win32 + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.release_shared|Win32.Build.0 = release_shared|Win32 + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.release_shared|Win32.Deploy.0 = release_shared|Win32 + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.release_static_md|Win32.ActiveCfg = release_static_md|Win32 + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.release_static_md|Win32.Build.0 = release_static_md|Win32 + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.release_static_md|Win32.Deploy.0 = release_static_md|Win32 + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.release_static_mt|Win32.ActiveCfg = release_static_mt|Win32 + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.release_static_mt|Win32.Build.0 = release_static_mt|Win32 + {B057A1FE-09F7-465E-B8B5-E1B659051D76}.release_static_mt|Win32.Deploy.0 = release_static_mt|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.debug_shared|Win32.ActiveCfg = debug_shared|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.debug_shared|Win32.Build.0 = debug_shared|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.debug_shared|Win32.Deploy.0 = debug_shared|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.debug_static_md|Win32.ActiveCfg = debug_static_md|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.debug_static_md|Win32.Build.0 = debug_static_md|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.debug_static_md|Win32.Deploy.0 = debug_static_md|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.debug_static_mt|Win32.ActiveCfg = debug_static_mt|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.debug_static_mt|Win32.Build.0 = debug_static_mt|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.debug_static_mt|Win32.Deploy.0 = debug_static_mt|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.release_shared|Win32.ActiveCfg = release_shared|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.release_shared|Win32.Build.0 = release_shared|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.release_shared|Win32.Deploy.0 = release_shared|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.release_static_md|Win32.ActiveCfg = release_static_md|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.release_static_md|Win32.Build.0 = release_static_md|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.release_static_md|Win32.Deploy.0 = release_static_md|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.release_static_mt|Win32.ActiveCfg = release_static_mt|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.release_static_mt|Win32.Build.0 = release_static_mt|Win32 + {D5EFBF27-B934-4B8D-8AE5-6EC00374819C}.release_static_mt|Win32.Deploy.0 = release_static_mt|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Net/include/Poco/Net/Socket.h b/Net/include/Poco/Net/Socket.h index 059a7882f..e057b3a8c 100644 --- a/Net/include/Poco/Net/Socket.h +++ b/Net/include/Poco/Net/Socket.h @@ -142,7 +142,7 @@ public: bool poll(const Poco::Timespan& timeout, int mode) const; /// Determines the status of the socket, using a - /// call to select(). + /// call to poll() or select(). /// /// The mode argument is constructed by combining the values /// of the SelectMode enumeration. @@ -315,6 +315,23 @@ protected: /// Returns the socket descriptor for this socket. private: + +#if defined(POCO_HAVE_FD_POLL) +class FDCompare + /// Utility functor used to compare socket file descriptors. + /// Used in poll() member function. +{ +public: + FDCompare(int fd): _fd(fd) { } + inline bool operator()(const Socket& socket) const + { return socket.sockfd() == _fd; } + +private: + FDCompare(); + int _fd; +}; +#endif + SocketImpl* _pImpl; }; @@ -604,6 +621,15 @@ inline bool Socket::supportsIPv4() } +inline bool Socket::supportsIPv6() +{ +#if defined(POCO_HAVE_IPv6) + return true; +#else + return false; +#endif +} + } } // namespace Poco::Net diff --git a/Net/src/Socket.cpp b/Net/src/Socket.cpp index ae1c7b8d6..aa2ff980b 100644 --- a/Net/src/Socket.cpp +++ b/Net/src/Socket.cpp @@ -41,6 +41,12 @@ #include // FD_SET needs memset on some platforms, so we can't use #if defined(POCO_HAVE_FD_EPOLL) #include +#elif defined(POCO_HAVE_FD_POLL) +#include "Poco/SharedPtr.h" +#include +typedef Poco::SharedPtr > SharedPollArray; #endif @@ -226,6 +232,88 @@ int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exce std::swap(exceptList, readyExceptList); return readList.size() + writeList.size() + exceptList.size(); +#elif defined(POCO_HAVE_FD_POLL) + + nfds_t nfd = readList.size() + writeList.size() + exceptList.size(); + if (0 == nfd) return 0; + + SharedPollArray pPollArr = new pollfd[nfd]; + + int idx = 0; + for (SocketList::iterator it = readList.begin(); it != readList.end(); ++it) + { + pPollArr[idx].fd = int(it->sockfd()); + pPollArr[idx++].events |= POLLIN; + } + + SocketList::iterator begR = readList.begin(); + SocketList::iterator endR = readList.end(); + for (SocketList::iterator it = writeList.begin(); it != writeList.end(); ++it) + { + SocketList::iterator pos = std::find(begR, endR, *it); + if (pos != endR) + { + pPollArr[pos-begR].events |= POLLOUT; + --nfd; + } + else + { + pPollArr[idx].fd = int(it->sockfd()); + pPollArr[idx++].events |= POLLOUT; + } + } + + SocketList::iterator begW = writeList.begin(); + SocketList::iterator endW = writeList.end(); + for (SocketList::iterator it = exceptList.begin(); it != exceptList.end(); ++it) + { + SocketList::iterator pos = std::find(begR, endR, *it); + if (pos != endR) --nfd; + else + { + SocketList::iterator pos = std::find(begW, endW, *it); + if (pos != endW) --nfd; + else pPollArr[idx++].fd = int(it->sockfd()); + } + } + + Poco::Timespan remainingTime(timeout); + int rc; + do + { + Poco::Timestamp start; + rc = ::poll(pPollArr, nfd, timeout.totalMilliseconds()); + if (rc < 0 && SocketImpl::lastError() == POCO_EINTR) + { + Poco::Timestamp end; + Poco::Timespan waited = end - start; + if (waited < remainingTime) remainingTime -= waited; + else remainingTime = 0; + } + } + while (rc < 0 && SocketImpl::lastError() == POCO_EINTR); + if (rc < 0) SocketImpl::error(); + + SocketList readyReadList; + SocketList readyWriteList; + SocketList readyExceptList; + + SocketList::iterator begE = exceptList.begin(); + SocketList::iterator endE = exceptList.end(); + for (int idx = 0; idx < nfd; ++idx) + { + SocketList::iterator slIt = std::find_if(begR, endR, Socket::FDCompare(pPollArr[idx].fd)); + if (POLLIN & pPollArr[idx].revents && slIt != endR) readyReadList.push_back(*slIt); + slIt = std::find_if(begW, endW, Socket::FDCompare(pPollArr[idx].fd)); + if (POLLOUT & pPollArr[idx].revents && slIt != endW) readyWriteList.push_back(*slIt); + slIt = std::find_if(begE, endE, Socket::FDCompare(pPollArr[idx].fd)); + if (POLLERR & pPollArr[idx].revents && slIt != endE) readyExceptList.push_back(*slIt); + } + std::swap(readList, readyReadList); + std::swap(writeList, readyWriteList); + std::swap(exceptList, readyExceptList); + return readList.size() + writeList.size() + exceptList.size(); + #else fd_set fdRead; @@ -327,14 +415,4 @@ int Socket::select(SocketList& readList, SocketList& writeList, SocketList& exce } -bool Socket::supportsIPv6() -{ -#if defined(POCO_HAVE_IPv6) - return true; -#else - return false; -#endif -} - - } } // namespace Poco::Net diff --git a/Net/src/SocketImpl.cpp b/Net/src/SocketImpl.cpp index 800a4cac2..730618b5c 100644 --- a/Net/src/SocketImpl.cpp +++ b/Net/src/SocketImpl.cpp @@ -42,9 +42,16 @@ #include // FD_SET needs memset on some platforms, so we can't use #if defined(POCO_HAVE_FD_EPOLL) #include +#elif defined(POCO_HAVE_FD_POLL) +#include #endif +#if defined(sun) || defined(__sun) || defined(__sun__) +#include +#include +#endif + using Poco::IOException; using Poco::TimeoutException; using Poco::InvalidArgumentException; @@ -464,8 +471,36 @@ bool SocketImpl::poll(const Poco::Timespan& timeout, int mode) while (rc < 0 && lastError() == POCO_EINTR); ::close(epollfd); - if (rc < 0) error(); - return rc > 0; + if (rc < 0) error(); + return rc > 0; + +#elif defined(POCO_HAVE_FD_POLL) + + pollfd pollBuf; + + memset(&pollBuf, 0, sizeof(pollfd)); + pollBuf.fd = _sockfd; + if (mode & SELECT_READ) pollBuf.events |= POLLIN; + if (mode & SELECT_WRITE) pollBuf.events |= POLLOUT; + + Poco::Timespan remainingTime(timeout); + int rc; + do + { + Poco::Timestamp start; + rc = ::poll(&pollBuf, 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); #else @@ -969,77 +1004,77 @@ void SocketImpl::error(int code, const std::string& arg) switch (code) { case POCO_ESYSNOTREADY: - throw NetException("Net subsystem not ready"); + throw NetException("Net subsystem not ready", code); case POCO_ENOTINIT: - throw NetException("Net subsystem not initialized"); + throw NetException("Net subsystem not initialized", code); case POCO_EINTR: - throw IOException("Interrupted"); + throw IOException("Interrupted", code); case POCO_EACCES: - throw IOException("Permission denied"); + throw IOException("Permission denied", code); case POCO_EFAULT: - throw IOException("Bad address"); + throw IOException("Bad address", code); case POCO_EINVAL: - throw InvalidArgumentException(); + throw InvalidArgumentException(code); case POCO_EMFILE: - throw IOException("Too many open files"); + throw IOException("Too many open files", code); case POCO_EWOULDBLOCK: - throw IOException("Operation would block"); + throw IOException("Operation would block", code); case POCO_EINPROGRESS: - throw IOException("Operation now in progress"); + throw IOException("Operation now in progress", code); case POCO_EALREADY: - throw IOException("Operation already in progress"); + throw IOException("Operation already in progress", code); case POCO_ENOTSOCK: - throw IOException("Socket operation attempted on non-socket"); + throw IOException("Socket operation attempted on non-socket", code); case POCO_EDESTADDRREQ: - throw NetException("Destination address required"); + throw NetException("Destination address required", code); case POCO_EMSGSIZE: - throw NetException("Message too long"); + throw NetException("Message too long", code); case POCO_EPROTOTYPE: - throw NetException("Wrong protocol type"); + throw NetException("Wrong protocol type", code); case POCO_ENOPROTOOPT: - throw NetException("Protocol not available"); + throw NetException("Protocol not available", code); case POCO_EPROTONOSUPPORT: - throw NetException("Protocol not supported"); + throw NetException("Protocol not supported", code); case POCO_ESOCKTNOSUPPORT: - throw NetException("Socket type not supported"); + throw NetException("Socket type not supported", code); case POCO_ENOTSUP: - throw NetException("Operation not supported"); + throw NetException("Operation not supported", code); case POCO_EPFNOSUPPORT: - throw NetException("Protocol family not supported"); + throw NetException("Protocol family not supported", code); case POCO_EAFNOSUPPORT: - throw NetException("Address family not supported"); + throw NetException("Address family not supported", code); case POCO_EADDRINUSE: - throw NetException("Address already in use", arg); + throw NetException("Address already in use", arg, code); case POCO_EADDRNOTAVAIL: - throw NetException("Cannot assign requested address", arg); + throw NetException("Cannot assign requested address", arg, code); case POCO_ENETDOWN: - throw NetException("Network is down"); + throw NetException("Network is down", code); case POCO_ENETUNREACH: - throw NetException("Network is unreachable"); + throw NetException("Network is unreachable", code); case POCO_ENETRESET: - throw NetException("Network dropped connection on reset"); + throw NetException("Network dropped connection on reset", code); case POCO_ECONNABORTED: - throw ConnectionAbortedException(); + throw ConnectionAbortedException(code); case POCO_ECONNRESET: - throw ConnectionResetException(); + throw ConnectionResetException(code); case POCO_ENOBUFS: - throw IOException("No buffer space available"); + throw IOException("No buffer space available", code); case POCO_EISCONN: - throw NetException("Socket is already connected"); + throw NetException("Socket is already connected", code); case POCO_ENOTCONN: - throw NetException("Socket is not connected"); + throw NetException("Socket is not connected", code); case POCO_ESHUTDOWN: - throw NetException("Cannot send after socket shutdown"); + throw NetException("Cannot send after socket shutdown", code); case POCO_ETIMEDOUT: - throw TimeoutException(); + throw TimeoutException(code); case POCO_ECONNREFUSED: - throw ConnectionRefusedException(arg); + throw ConnectionRefusedException(arg, code); case POCO_EHOSTDOWN: - throw NetException("Host is down", arg); + throw NetException("Host is down", arg, code); case POCO_EHOSTUNREACH: - throw NetException("No route to host", arg); + throw NetException("No route to host", arg, code); default: - throw IOException(NumberFormatter::format(code), arg); + throw IOException(NumberFormatter::format(code), arg, code); } }