aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVincent Richard <[email protected]>2010-08-05 12:30:22 +0200
committerVincent Richard <[email protected]>2010-08-05 12:30:22 +0200
commitd6a8b099ede9aec517c8206070c741269bbf2328 (patch)
treecf9034aaf8e065cab016447db91c095452b7855a /src
parentAdded section about deleting messages from store. (diff)
downloadvmime-d6a8b099ede9aec517c8206070c741269bbf2328.tar.gz
vmime-d6a8b099ede9aec517c8206070c741269bbf2328.zip
Connection time out.
Diffstat (limited to 'src')
-rw-r--r--src/net/imap/IMAPConnection.cpp2
-rw-r--r--src/net/pop3/POP3Store.cpp2
-rw-r--r--src/net/smtp/SMTPTransport.cpp2
-rw-r--r--src/platforms/posix/posixSocket.cpp125
4 files changed, 121 insertions, 10 deletions
diff --git a/src/net/imap/IMAPConnection.cpp b/src/net/imap/IMAPConnection.cpp
index 825a002b..e2b60ed9 100644
--- a/src/net/imap/IMAPConnection.cpp
+++ b/src/net/imap/IMAPConnection.cpp
@@ -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
diff --git a/src/net/pop3/POP3Store.cpp b/src/net/pop3/POP3Store.cpp
index e5e8ba75..9d554c6d 100644
--- a/src/net/pop3/POP3Store.cpp
+++ b/src/net/pop3/POP3Store.cpp
@@ -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
diff --git a/src/net/smtp/SMTPTransport.cpp b/src/net/smtp/SMTPTransport.cpp
index 917a56c8..71f166bc 100644
--- a/src/net/smtp/SMTPTransport.cpp
+++ b/src/net/smtp/SMTPTransport.cpp
@@ -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
diff --git a/src/platforms/posix/posixSocket.cpp b/src/platforms/posix/posixSocket.cpp
index 807ec47c..b8bb8b18 100644
--- a/src/platforms/posix/posixSocket.cpp
+++ b/src/platforms/posix/posixSocket.cpp
@@ -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);
}