Connection time out.

This commit is contained in:
Vincent Richard 2010-08-05 10:30:22 +00:00
parent 7a51887dba
commit d6a8b099ed
7 changed files with 143 additions and 11 deletions

View File

@ -99,7 +99,7 @@ void IMAPConnection::connect()
m_timeoutHandler = store->getTimeoutHandlerFactory()->create();
// Create and connect the socket
m_socket = store->getSocketFactory()->create();
m_socket = store->getSocketFactory()->create(m_timeoutHandler);
#if VMIME_HAVE_TLS_SUPPORT
if (store->isIMAPS()) // dedicated port/IMAPS

View File

@ -138,7 +138,7 @@ void POP3Store::connect()
m_timeoutHandler = getTimeoutHandlerFactory()->create();
// Create and connect the socket
m_socket = getSocketFactory()->create();
m_socket = getSocketFactory()->create(m_timeoutHandler);
#if VMIME_HAVE_TLS_SUPPORT
if (m_isPOP3S) // dedicated port/POP3S

View File

@ -100,7 +100,7 @@ void SMTPTransport::connect()
m_timeoutHandler = getTimeoutHandlerFactory()->create();
// Create and connect the socket
m_socket = getSocketFactory()->create();
m_socket = getSocketFactory()->create(m_timeoutHandler);
#if VMIME_HAVE_TLS_SUPPORT
if (m_isSMTPS) // dedicated port/SMTPS

View File

@ -49,8 +49,8 @@ namespace posix {
// posixSocket
//
posixSocket::posixSocket()
: m_desc(-1)
posixSocket::posixSocket(ref <vmime::net::timeoutHandler> th)
: m_timeoutHandler(th), m_desc(-1)
{
}
@ -105,11 +105,115 @@ void posixSocket::connect(const vmime::string& address, const vmime::port_t port
if (sock < 0)
continue; // try next
if (::connect(sock, res->ai_addr, res->ai_addrlen) < 0)
if (m_timeoutHandler != NULL)
{
::close(sock);
sock = -1;
continue; // try next
::fcntl(sock, F_SETFL, ::fcntl(sock, F_GETFL) | O_NONBLOCK);
if (::connect(sock, res->ai_addr, res->ai_addrlen) < 0)
{
switch (errno)
{
case 0:
case EINPROGRESS:
case EINTR:
#if defined(EAGAIN)
case EAGAIN:
#endif // EAGAIN
#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
case EWOULDBLOCK:
#endif // EWOULDBLOCK
// Connection in progress
break;
default:
::close(sock);
sock = -1;
continue; // try next
}
// Wait for socket to be connected.
// We will check for time out every second.
fd_set fds;
FD_ZERO(&fds);
FD_SET(sock, &fds);
fd_set fdsError;
FD_ZERO(&fdsError);
FD_SET(sock, &fdsError);
struct timeval tm;
tm.tv_sec = 1;
tm.tv_usec = 0;
m_timeoutHandler->resetTimeOut();
bool connected = false;
do
{
const int ret = select(sock + 1, NULL, &fds, &fdsError, &tm);
// Success
if (ret > 0)
{
connected = true;
break;
}
// Error
else if (ret < -1)
{
if (errno != EINTR)
{
// Cancel connection
break;
}
}
// 1-second timeout
else if (ret == 0)
{
if (m_timeoutHandler->isTimeOut())
{
if (!m_timeoutHandler->handleTimeOut())
{
// Cancel connection
break;
}
else
{
// Reset timeout and keep waiting for connection
m_timeoutHandler->resetTimeOut();
}
}
else
{
// Keep waiting for connection
}
}
::sched_yield();
} while (true);
if (!connected)
{
::close(sock);
sock = -1;
continue; // try next
}
break;
}
}
else
{
if (::connect(sock, res->ai_addr, res->ai_addrlen) < 0)
{
::close(sock);
sock = -1;
continue; // try next
}
}
}
@ -325,7 +429,14 @@ void posixSocket::throwSocketError(const int err)
ref <vmime::net::socket> posixSocketFactory::create()
{
return vmime::create <posixSocket>();
ref <vmime::net::timeoutHandler> th = NULL;
return vmime::create <posixSocket>(th);
}
ref <vmime::net::socket> posixSocketFactory::create(ref <vmime::net::timeoutHandler> th)
{
return vmime::create <posixSocket>(th);
}

View File

@ -260,6 +260,11 @@ public:
{
return vmime::create <T>();
}
vmime::ref <vmime::net::socket> create(vmime::ref <vmime::net::timeoutHandler> /* th */)
{
return vmime::create <T>();
}
};

View File

@ -27,6 +27,8 @@
#include "vmime/base.hpp"
#include "vmime/net/timeoutHandler.hpp"
namespace vmime {
namespace net {
@ -117,7 +119,18 @@ public:
virtual ~socketFactory() { }
/** Creates a socket without timeout handler.
*
* @return a new socket
*/
virtual ref <socket> create() = 0;
/** Creates a socket with the specified timeout handler.
*
* @param th timeout handler
* @return a new socket
*/
virtual ref <socket> create(ref <timeoutHandler> th) = 0;
};

View File

@ -40,7 +40,7 @@ class posixSocket : public vmime::net::socket
{
public:
posixSocket();
posixSocket(ref <vmime::net::timeoutHandler> th);
~posixSocket();
void connect(const vmime::string& address, const vmime::port_t port);
@ -61,6 +61,8 @@ protected:
private:
ref <vmime::net::timeoutHandler> m_timeoutHandler;
char m_buffer[65536];
int m_desc;
};
@ -72,6 +74,7 @@ class posixSocketFactory : public vmime::net::socketFactory
public:
ref <vmime::net::socket> create();
ref <vmime::net::socket> create(ref <vmime::net::timeoutHandler> th);
};