aboutsummaryrefslogtreecommitdiffstats
path: root/camel/camel-tcp-stream-ssl.c
diff options
context:
space:
mode:
Diffstat (limited to 'camel/camel-tcp-stream-ssl.c')
-rw-r--r--camel/camel-tcp-stream-ssl.c33
1 files changed, 22 insertions, 11 deletions
diff --git a/camel/camel-tcp-stream-ssl.c b/camel/camel-tcp-stream-ssl.c
index 820912ffa5..791083186c 100644
--- a/camel/camel-tcp-stream-ssl.c
+++ b/camel/camel-tcp-stream-ssl.c
@@ -1028,7 +1028,7 @@ stream_connect (CamelTcpStream *stream, struct hostent *host, int port)
{
CamelTcpStreamSSL *ssl = CAMEL_TCP_STREAM_SSL (stream);
PRNetAddr netaddr;
- PRFileDesc *fd;
+ PRFileDesc *fd, *cancel_fd;
g_return_val_if_fail (host != NULL, -1);
@@ -1070,26 +1070,37 @@ stream_connect (CamelTcpStream *stream, struct hostent *host, int port)
fd = ssl_fd;
}
-
- if (PR_Connect (fd, &netaddr, CONNECT_TIMEOUT) == PR_FAILURE) {
+
+ cancel_fd = camel_operation_cancel_prfd(NULL);
+
+ if (PR_Connect (fd, &netaddr, cancel_fd?0:CONNECT_TIMEOUT) == PR_FAILURE) {
int errnosave;
set_errno (PR_GetError ());
- if (errno == EINPROGRESS) {
+ if (errno == EINPROGRESS || (cancel_fd && errno == ETIMEDOUT)) {
gboolean connected = FALSE;
- PRPollDesc poll;
+ PRPollDesc poll[2];
+
+ poll[0].fd = fd;
+ poll[0].in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
+ poll[1].fd = cancel_fd;
+ poll[1].in_flags = PR_POLL_READ;
do {
- poll.fd = fd;
- poll.in_flags = PR_POLL_WRITE | PR_POLL_EXCEPT;
- poll.out_flags = 0;
-
- if (PR_Poll (&poll, 1, CONNECT_TIMEOUT) == PR_FAILURE) {
+ poll[0].out_flags = 0;
+ poll[1].out_flags = 0;
+
+ if (PR_Poll (poll, cancel_fd?2:1, CONNECT_TIMEOUT) == PR_FAILURE) {
set_errno (PR_GetError ());
goto exception;
}
- if (PR_GetConnectStatus (&poll) == PR_FAILURE) {
+ if (poll[1].out_flags == PR_POLL_READ) {
+ errno = EINTR;
+ goto exception;
+ }
+
+ if (PR_ConnectContinue(fd, poll[0].out_flags) == PR_FAILURE) {
set_errno (PR_GetError ());
if (errno != EINPROGRESS)
goto exception;