From 344d96539d6886fc8c071a7af718e4132743ecc8 Mon Sep 17 00:00:00 2001 From: Vincent Richard Date: Wed, 14 Sep 2005 22:03:56 +0000 Subject: [PATCH] Non-blocking socket input/output. --- src/platforms/posix/posixHandler.cpp | 8 ++++ src/platforms/posix/posixSocket.cpp | 65 ++++++++++++++++++---------- 2 files changed, 51 insertions(+), 22 deletions(-) diff --git a/src/platforms/posix/posixHandler.cpp b/src/platforms/posix/posixHandler.cpp index 48d96984..d3faa4d4 100644 --- a/src/platforms/posix/posixHandler.cpp +++ b/src/platforms/posix/posixHandler.cpp @@ -33,6 +33,10 @@ #include +#ifdef _POSIX_PRIORITY_SCHEDULING + #include +#endif // _POSIX_PRIORITY_SCHEDULING + namespace vmime { namespace platforms { @@ -201,7 +205,11 @@ vmime::utility::childProcessFactory* posixHandler::getChildProcessFactory() cons void posixHandler::wait() const { +#ifdef _POSIX_PRIORITY_SCHEDULING + ::sched_yield(); +#else ::sleep(1); +#endif // _POSIX_PRIORITY_SCHEDULING } diff --git a/src/platforms/posix/posixSocket.cpp b/src/platforms/posix/posixSocket.cpp index 32b657fd..01c06b4f 100644 --- a/src/platforms/posix/posixSocket.cpp +++ b/src/platforms/posix/posixSocket.cpp @@ -18,6 +18,7 @@ // #include "vmime/platforms/posix/posixSocket.hpp" +#include "vmime/platforms/posix/posixHandler.hpp" #include #include @@ -121,12 +122,19 @@ void posixSocket::connect(const vmime::string& address, const vmime::port_t port ("Error while connecting socket.", e); } } + + ::fcntl(m_desc, F_SETFL, ::fcntl(m_desc, F_GETFL) | O_NONBLOCK); } const bool posixSocket::isConnected() const { - return (m_desc != -1); + if (m_desc == -1) + return false; + + char buff; + + return ::recv(m_desc, &buff, 1, MSG_PEEK) != 0; } @@ -144,47 +152,60 @@ void posixSocket::disconnect() void posixSocket::receive(vmime::string& buffer) { - ::ssize_t ret = ::recv(m_desc, m_buffer, sizeof(m_buffer), 0); - - if (ret == -1) - { - // Error or no data - return; - } - else if (ret > 0) - { - buffer = vmime::string(m_buffer, ret); - } + const int size = receiveRaw(m_buffer, sizeof(m_buffer)); + buffer = vmime::string(m_buffer, size); } const int posixSocket::receiveRaw(char* buffer, const int count) { - ::ssize_t ret = ::recv(m_desc, buffer, count, 0); + const int ret = ::recv(m_desc, buffer, count, 0); - if (ret == -1) + if (ret < 0) { - // Error or no data - return (0); + if (errno != EAGAIN) + throwSocketError(errno); + + // No data available at this time + return 0; } - else + else if (ret == 0) { - return (ret); + // Host shutdown + throwSocketError(ENOTCONN); } + + return ret; } void posixSocket::send(const vmime::string& buffer) { - if (::send(m_desc, buffer.data(), buffer.length(), 0) == -1) - throwSocketError(errno); + sendRaw(buffer.data(), buffer.length()); } void posixSocket::sendRaw(const char* buffer, const int count) { - if (::send(m_desc, buffer, count, 0) == -1) - throwSocketError(errno); + int size = count; + + while (size > 0) + { + const int ret = ::send(m_desc, buffer, size, 0); + + if (ret < 0) + { + if (errno != EAGAIN) + throwSocketError(errno); + + platformDependant::getHandler()->wait(); + } + else + { + buffer += ret; + size -= ret; + } + } }