aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Richard <[email protected]>2010-08-05 10:30:22 +0000
committerVincent Richard <[email protected]>2010-08-05 10:30:22 +0000
commitd6a8b099ede9aec517c8206070c741269bbf2328 (patch)
treecf9034aaf8e065cab016447db91c095452b7855a
parentAdded section about deleting messages from store. (diff)
downloadvmime-d6a8b099ede9aec517c8206070c741269bbf2328.tar.gz
vmime-d6a8b099ede9aec517c8206070c741269bbf2328.zip
Connection time out.
-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
-rw-r--r--tests/testUtils.hpp5
-rw-r--r--vmime/net/socket.hpp13
-rw-r--r--vmime/platforms/posix/posixSocket.hpp5
7 files changed, 143 insertions, 11 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);
}
diff --git a/tests/testUtils.hpp b/tests/testUtils.hpp
index 9aee153c..aee50dc7 100644
--- a/tests/testUtils.hpp
+++ b/tests/testUtils.hpp
@@ -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>();
+ }
};
diff --git a/vmime/net/socket.hpp b/vmime/net/socket.hpp
index ec6a9d37..b3946494 100644
--- a/vmime/net/socket.hpp
+++ b/vmime/net/socket.hpp
@@ -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;
};
diff --git a/vmime/platforms/posix/posixSocket.hpp b/vmime/platforms/posix/posixSocket.hpp
index 9cd49d4a..7e0c2d39 100644
--- a/vmime/platforms/posix/posixSocket.hpp
+++ b/vmime/platforms/posix/posixSocket.hpp
@@ -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);
};