diff --git a/src/connect.c b/src/connect.c
index da84145e..f4f31933 100644
--- a/src/connect.c
+++ b/src/connect.c
@@ -678,8 +678,8 @@ retryable_socket_connect_error (int err)
    should be taken as such (for example, it doesn't implement Wget's
    0-timeout-means-no-timeout semantics.)  */
 
-int
-select_fd (int fd, double maxtime, int wait_for)
+static int
+select_fd_internal (int fd, double maxtime, int wait_for, bool convert_back _GL_UNUSED)
 {
   fd_set fdset;
   fd_set *rd = NULL, *wr = NULL;
@@ -710,7 +710,8 @@ select_fd (int fd, double maxtime, int wait_for)
 #ifdef WINDOWS
     /* gnulib select() converts blocking sockets to nonblocking in windows.
        wget uses blocking sockets so we must convert them back to blocking.  */
-    set_windows_fd_as_blocking_socket (fd);
+    if (convert_back)
+      set_windows_fd_as_blocking_socket (fd);
 #endif
   }
   while (result < 0 && errno == EINTR);
@@ -718,6 +719,20 @@ select_fd (int fd, double maxtime, int wait_for)
   return result;
 }
 
+int
+select_fd (int fd, double maxtime, int wait_for)
+{
+  return select_fd_internal (fd, maxtime, wait_for, true);
+}
+
+#ifdef WINDOWS
+int
+select_fd_nb (int fd, double maxtime, int wait_for)
+{
+  return select_fd_internal (fd, maxtime, wait_for, false);
+}
+#endif
+
 /* Return true if the connection to the remote site established
    through SOCK is still open.
 
@@ -925,10 +940,11 @@ fd_read (int fd, char *buf, int bufsize, double timeout)
 {
   struct transport_info *info;
   LAZY_RETRIEVE_INFO (info);
+
   if (!poll_internal (fd, info, WAIT_FOR_READ, timeout))
     return -1;
   if (info && info->imp->reader)
-    return info->imp->reader (fd, buf, bufsize, info->ctx);
+    return info->imp->reader (fd, buf, bufsize, info->ctx, timeout);
   else
     return sock_read (fd, buf, bufsize);
 }
@@ -953,7 +969,7 @@ fd_peek (int fd, char *buf, int bufsize, double timeout)
   if (!poll_internal (fd, info, WAIT_FOR_READ, timeout))
     return -1;
   if (info && info->imp->peeker)
-    return info->imp->peeker (fd, buf, bufsize, info->ctx);
+    return info->imp->peeker (fd, buf, bufsize, info->ctx, timeout);
   else
     return sock_peek (fd, buf, bufsize);
 }
@@ -1005,6 +1021,7 @@ fd_errstr (int fd)
   /* Don't bother with LAZY_RETRIEVE_INFO, as this will only be called
      in case of error, never in a tight loop.  */
   struct transport_info *info = NULL;
+
   if (transport_map)
     info = hash_table_get (transport_map, (void *)(intptr_t) fd);
 
diff --git a/src/connect.h b/src/connect.h
index fcdbd604..84535591 100644
--- a/src/connect.h
+++ b/src/connect.h
@@ -63,10 +63,10 @@ int select_fd (int, double, int);
 bool test_socket_open (int);
 
 struct transport_implementation {
-  int (*reader) (int, char *, int, void *);
+  int (*reader) (int, char *, int, void *, double);
   int (*writer) (int, char *, int, void *);
   int (*poller) (int, double, int, void *);
-  int (*peeker) (int, char *, int, void *);
+  int (*peeker) (int, char *, int, void *, double);
   const char *(*errstr) (int, void *);
   void (*closer) (int, void *);
 };
@@ -80,4 +80,10 @@ const char *fd_errstr (int);
 void fd_close (int);
 void connect_cleanup (void);
 
+#ifdef WINDOWS
+int select_fd_nb (int, double, int);
+#else
+#define select_fd_nb select_fd
+#endif
+
 #endif /* CONNECT_H */
diff --git a/src/gnutls.c b/src/gnutls.c
index 7ab1f088..d3652dba 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -59,11 +59,11 @@ as that of the covered work.  */
 #include "host.h"
 
 static int
-_do_handshake (gnutls_session_t session, int fd, double timeout);
+_do_handshake (gnutls_session_t session, int fd, double timeout, int is_nonblock);
 
 #if GNUTLS_VERSION_NUMBER >= 0x030604
 static int
-_do_reauth (gnutls_session_t session, int fd, double timeout);
+_do_reauth (gnutls_session_t session, int fd, double timeout, int is_nonblock);
 #endif
 
 static int
@@ -259,7 +259,12 @@ wgnutls_read_timeout (int fd, char *buf, int bufsize, void *arg, double timeout)
   struct ptimer *timer = NULL;
   struct wgnutls_transport_context *ctx = arg;
   int timed_out = 0;
+  double next_timeout;
 
+  errno = 0;
+  if (timeout == -1)
+    timeout = opt.read_timeout;
+  next_timeout = timeout;
   if (timeout)
     {
 #ifdef F_GETFL
@@ -277,36 +282,41 @@ wgnutls_read_timeout (int fd, char *buf, int bufsize, void *arg, double timeout)
 
       timer = ptimer_new ();
       if (timer == NULL)
-        return -1;
+        {
+          ret = -1;
+          goto timer_err;
+        }
     }
 
   do
     {
-      double next_timeout = 0;
+      ret = GNUTLS_E_AGAIN;
       if (timeout)
         {
           next_timeout = timeout - ptimer_measure (timer);
-          if (next_timeout < 0)
-            break;
+          if (next_timeout <= 0)
+            {
+              timed_out = 1;
+              break;
+            }
         }
-
-      ret = GNUTLS_E_AGAIN;
+      /* (rehandshake, reauth) needs some workaround for interactive timeout */
       if (timeout == 0 || gnutls_record_check_pending (ctx->session)
-          || select_fd (fd, next_timeout, WAIT_FOR_READ))
+          || select_fd_nb (fd, next_timeout, WAIT_FOR_READ))
         {
           ret = gnutls_record_recv (ctx->session, buf, bufsize);
           timed_out = timeout && ptimer_measure (timer) >= timeout;
           if (!timed_out && ret == GNUTLS_E_REHANDSHAKE)
             {
               DEBUGP (("GnuTLS: *** REHANDSHAKE while reading\n"));
-              if ((ret = _do_handshake (ctx->session, fd, timeout)) == 0)
+              if ((ret = _do_handshake (ctx->session, fd, opt.read_timeout, 1)) == 0)
                 ret = GNUTLS_E_AGAIN; /* restart reading */
             }
 #if GNUTLS_VERSION_NUMBER >= 0x030604
           if (!timed_out && ret == GNUTLS_E_REAUTH_REQUEST)
             {
               DEBUGP (("GnuTLS: *** re-authentication while reading\n"));
-              if ((ret = _do_reauth (ctx->session, fd, timeout)) == 0)
+              if ((ret = _do_reauth (ctx->session, fd, opt.read_timeout, 1)) == 0)
                 ret = GNUTLS_E_AGAIN; /* restart reading */
             }
 #endif
@@ -317,7 +327,7 @@ wgnutls_read_timeout (int fd, char *buf, int bufsize, void *arg, double timeout)
   if (timeout)
     {
       ptimer_destroy (timer);
-
+timer_err: ;
 #ifdef F_GETFL
       if (fcntl (fd, F_SETFL, flags) < 0)
         return -1;
@@ -326,7 +336,6 @@ wgnutls_read_timeout (int fd, char *buf, int bufsize, void *arg, double timeout)
       if (ioctl (fd, FIONBIO, &zero) < 0)
         return -1;
 #endif
-
       if (timed_out && ret == GNUTLS_E_AGAIN)
         errno = ETIMEDOUT;
     }
@@ -335,7 +344,7 @@ wgnutls_read_timeout (int fd, char *buf, int bufsize, void *arg, double timeout)
 }
 
 static int
-wgnutls_read (int fd, char *buf, int bufsize, void *arg)
+wgnutls_read (int fd, char *buf, int bufsize, void *arg, double timeout)
 {
   int ret = 0;
   struct wgnutls_transport_context *ctx = arg;
@@ -352,7 +361,7 @@ wgnutls_read (int fd, char *buf, int bufsize, void *arg)
       return copysize;
     }
 
-  ret = wgnutls_read_timeout (fd, buf, bufsize, arg, opt.read_timeout);
+  ret = wgnutls_read_timeout (fd, buf, bufsize, arg, timeout);
   if (ret < 0)
     ctx->last_error = ret;
 
@@ -385,7 +394,7 @@ wgnutls_poll (int fd, double timeout, int wait_for, void *arg)
 }
 
 static int
-wgnutls_peek (int fd, char *buf, int bufsize, void *arg)
+wgnutls_peek (int fd, char *buf, int bufsize, void *arg, double timeout)
 {
   int read = 0;
   struct wgnutls_transport_context *ctx = arg;
@@ -402,12 +411,12 @@ wgnutls_peek (int fd, char *buf, int bufsize, void *arg)
 
   if (bufsize > offset)
     {
-      if (opt.read_timeout && gnutls_record_check_pending (ctx->session) == 0
+      if (timeout && gnutls_record_check_pending (ctx->session) == 0
           && select_fd (fd, 0.0, WAIT_FOR_READ) <= 0)
         read = 0;
       else
         read = wgnutls_read_timeout (fd, buf + offset, bufsize - offset,
-                                     ctx, opt.read_timeout);
+                                     ctx, timeout);
       if (read < 0)
         {
           if (offset)
@@ -431,7 +440,8 @@ static const char *
 wgnutls_errstr (int fd _GL_UNUSED, void *arg)
 {
   struct wgnutls_transport_context *ctx = arg;
-  return gnutls_strerror (ctx->last_error);
+  return (ctx->last_error == GNUTLS_E_AGAIN && errno == ETIMEDOUT ?
+          strerror (ETIMEDOUT) : gnutls_strerror (ctx->last_error));
 }
 
 static void
@@ -459,14 +469,14 @@ static struct transport_implementation wgnutls_transport =
 };
 
 static int
-_do_handshake (gnutls_session_t session, int fd, double timeout)
+_do_handshake (gnutls_session_t session, int fd, double timeout, int is_nonblock)
 {
 #ifdef F_GETFL
   int flags = 0;
 #endif
   int err;
 
-  if (timeout)
+  if (!is_nonblock && timeout)
     {
 #ifdef F_GETFL
       flags = fcntl (fd, F_GETFL, 0);
@@ -492,12 +502,12 @@ _do_handshake (gnutls_session_t session, int fd, double timeout)
           if (gnutls_record_get_direction (session))
             {
               /* wait for writeability */
-              err = select_fd (fd, timeout, WAIT_FOR_WRITE);
+              err = select_fd_nb (fd, timeout, WAIT_FOR_WRITE);
             }
           else
             {
               /* wait for readability */
-              err = select_fd (fd, timeout, WAIT_FOR_READ);
+              err = select_fd_nb (fd, timeout, WAIT_FOR_READ);
             }
 
           if (err <= 0)
@@ -527,7 +537,7 @@ _do_handshake (gnutls_session_t session, int fd, double timeout)
     }
   while (err && gnutls_error_is_fatal (err) == 0);
 
-  if (timeout)
+  if (!is_nonblock && timeout)
     {
 #ifdef F_GETFL
       if (fcntl (fd, F_SETFL, flags) < 0)
@@ -544,14 +554,14 @@ _do_handshake (gnutls_session_t session, int fd, double timeout)
 
 #if GNUTLS_VERSION_NUMBER >= 0x030604
 static int
-_do_reauth (gnutls_session_t session, int fd, double timeout)
+_do_reauth (gnutls_session_t session, int fd, double timeout, int is_nonblock)
 {
 #ifdef F_GETFL
   int flags = 0;
 #endif
   int err;
 
-  if (timeout)
+  if (!is_nonblock && timeout)
     {
 #ifdef F_GETFL
       flags = fcntl (fd, F_GETFL, 0);
@@ -577,12 +587,12 @@ _do_reauth (gnutls_session_t session, int fd, double timeout)
           if (gnutls_record_get_direction (session))
             {
               /* wait for writeability */
-              err = select_fd (fd, timeout, WAIT_FOR_WRITE);
+              err = select_fd_nb (fd, timeout, WAIT_FOR_WRITE);
             }
           else
             {
               /* wait for readability */
-              err = select_fd (fd, timeout, WAIT_FOR_READ);
+              err = select_fd_nb (fd, timeout, WAIT_FOR_READ);
             }
 
           if (err <= 0)
@@ -604,7 +614,7 @@ _do_reauth (gnutls_session_t session, int fd, double timeout)
     }
   while (err && gnutls_error_is_fatal (err) == 0);
 
-  if (timeout)
+  if (!is_nonblock && timeout)
     {
 #ifdef F_GETFL
       if (fcntl (fd, F_SETFL, flags) < 0)
@@ -830,7 +840,7 @@ ssl_connect_wget (int fd, const char *hostname, int *continue_session)
         }
     }
 
-  err = _do_handshake (session, fd, opt.connect_timeout);
+  err = _do_handshake (session, fd, opt.read_timeout, 0);
 
   if (err < 0)
     {
diff --git a/src/init.c b/src/init.c
index 52db8952..6f4db4af 100644
--- a/src/init.c
+++ b/src/init.c
@@ -1423,6 +1423,13 @@ cmd_time (const char *com, const char *val, void *place)
   if (!simple_atof (val, end, &number))
     goto err;
 
+  if (number < 0)
+    {
+      fprintf (stderr, _("%s: %s: Negative time period %s\n"),
+               exec_name, com, quote (val));
+      return false;
+    }
+
   *(double *)place = number * mult;
   return true;
 }
diff --git a/src/openssl.c b/src/openssl.c
index 4905cc84..0f578446 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -49,11 +49,16 @@ as that of the covered work.  */
 #endif
 #endif
 
+#include <sys/ioctl.h>
+
 #include "utils.h"
 #include "connect.h"
+#include "ptimer.h"
 #include "url.h"
 #include "ssl.h"
 
+#include <fcntl.h>
+
 #ifdef WINDOWS
 # include <w32sock.h>
 #endif
@@ -80,12 +85,20 @@ init_prng (void)
       /* Get the random file name using RAND_file_name. */
       namebuf[0] = '\0';
       random_file = RAND_file_name (namebuf, sizeof (namebuf));
+      if (!file_exists_p (random_file, NULL))
+        random_file = NULL;
     }
 
   if (random_file && *random_file)
     /* Seed at most 16k (apparently arbitrary value borrowed from
        curl) from random file. */
-    RAND_load_file (random_file, 16384);
+    {
+        int _err = RAND_load_file (random_file, 16384);
+        if(_err == -1)
+          /* later the thread error queue will be cleared */
+          if ( (_err = ERR_peek_last_error ()) )
+              logprintf (LOG_VERBOSE, "WARNING: Could not load random file: %s, %s\n", opt.random_file, ERR_reason_error_string(_err));
+    }
 
 #ifdef HAVE_RAND_EGD
   /* Get random data from EGD if opt.egd_file was used.  */
@@ -427,44 +440,236 @@ struct openssl_transport_context
   char *last_error;             /* last error printed with openssl_errstr */
 };
 
+typedef int (*ssl_fn_t)(SSL *, void *, int);
+
+#ifdef OPENSSL_RUN_WITHTIMEOUT
+
+struct scwt_context
+{
+  SSL *ssl;
+  int result;
+};
+
+static void
+ssl_connect_with_timeout_callback(void *arg)
+{
+  struct scwt_context *ctx = (struct scwt_context *)arg;
+  ctx->result = SSL_connect(ctx->ssl);
+}
+
+static int
+ssl_connect_with_timeout(int fd _GL_UNUSED, SSL *conn, double timeout)
+{
+  struct scwt_context scwt_ctx;
+  scwt_ctx.ssl = conn;
+  errno = 0;
+  if (run_with_timeout(timeout, ssl_connect_with_timeout_callback,
+                       &scwt_ctx))
+    {
+      errno = ETIMEDOUT;
+      return -1;
+    }
+  return scwt_ctx.result;
+}
+
 struct openssl_read_args
 {
   int fd;
   struct openssl_transport_context *ctx;
+  ssl_fn_t fn;
   char *buf;
   int bufsize;
   int retval;
 };
 
-static void openssl_read_callback(void *arg)
+static void openssl_read_peek_callback(void *arg)
 {
   struct openssl_read_args *args = (struct openssl_read_args *) arg;
   struct openssl_transport_context *ctx = args->ctx;
+  ssl_fn_t fn = args->fn;
   SSL *conn = ctx->conn;
   char *buf = args->buf;
   int bufsize = args->bufsize;
   int ret;
 
   do
-    ret = SSL_read (conn, buf, bufsize);
-  while (ret == -1 && SSL_get_error (conn, ret) == SSL_ERROR_SYSCALL
-         && errno == EINTR);
+    {
+      ret = fn (conn, buf, bufsize);
+    }
+  while (ret == -1 && SSL_get_error (conn, ret) == SSL_ERROR_SYSCALL && errno == EINTR);
   args->retval = ret;
 }
 
 static int
-openssl_read (int fd, char *buf, int bufsize, void *arg)
+openssl_read_peek (int fd, char *buf, int bufsize, void *arg, double timeout, ssl_fn_t fn)
 {
-  struct openssl_read_args args;
-  args.fd = fd;
-  args.buf = buf;
-  args.bufsize = bufsize;
-  args.ctx = (struct openssl_transport_context*) arg;
+  struct openssl_transport_context *ctx = arg;
+  int ret = SSL_pending (ctx->conn);
 
-  if (run_with_timeout(opt.read_timeout, openssl_read_callback, &args)) {
-    return -1;
+  if (bufsize == 0)
+    return 0;
+
+  if (ret)
+    ret = fn (ctx->conn, buf, MIN (bufsize, ret));
+  else
+    {
+      struct openssl_read_args args;
+      args.fd = fd;
+      args.buf = buf;
+      args.bufsize = bufsize;
+      args.fn = fn;
+      args.ctx = ctx;
+
+      errno = 0;
+      if (timeout == -1)
+        timeout = opt.read_timeout;
+
+      if (run_with_timeout(timeout, openssl_read_peek_callback, &args))
+        {
+          errno = ETIMEDOUT;
+          ret = -1;
+        }
+      else
+        ret = args.retval;
+    }
+  return ret;
+}
+
+#else /* OPENSSL_RUN_WITHTIMEOUT */
+
+#ifdef F_GETFL
+#define NONBLOCK_DECL int flags = 0;
+#define FD_SET_NONBLOCKED(_fd) \
+  flags = fcntl (_fd, F_GETFL, 0);\
+  if (flags < 0)\
+        return flags;\
+      if (fcntl (_fd, F_SETFL, flags | O_NONBLOCK))\
+        return -1;
+#define FD_SET_BLOCKED(_fd)  \
+  if (fcntl (_fd, F_SETFL, flags) < 0)\
+        return -1;
+#else
+#define NONBLOCK_DECL
+#define FD_SET_NONBLOCKED(_fd) \
+  {\
+    const int one = 1;\
+    if (ioctl (_fd, FIONBIO, &one) < 0)\
+      return -1;\
   }
-  return args.retval;
+#define FD_SET_BLOCKED(_fd)  \
+  {\
+    const int zero = 0;\
+    if (ioctl (_fd, FIONBIO, &zero) < 0)\
+      return -1;\
+  }
+#endif /* F_GETFL */
+
+#define TIMER_INIT(_fd, _ret, _timeout) \
+  { \
+    NONBLOCK_DECL \
+    int timed_out = 0; \
+    FD_SET_NONBLOCKED(_fd) \
+    struct ptimer *timer = ptimer_new (); \
+    if (timer == NULL) \
+      _ret = -1; \
+    else \
+      { \
+        if (_timeout == -1) \
+            _timeout = opt.read_timeout;
+
+#define TIMER_FREE(_fd) \
+        ptimer_destroy (timer); \
+      } \
+    FD_SET_BLOCKED(_fd) \
+    if (timed_out) \
+      { \
+        errno = ETIMEDOUT; \
+      } \
+  }
+
+#define TIMER_WAIT(_fd, _conn, _ret, _timeout) \
+        { \
+          int wait_for; \
+          double next_timeout; \
+          int err = SSL_get_error(_conn, _ret); \
+          if (err == SSL_ERROR_WANT_READ) \
+            wait_for = WAIT_FOR_READ; \
+          else if (err == SSL_ERROR_WANT_WRITE) \
+            wait_for = WAIT_FOR_WRITE; \
+          else \
+            break; \
+          next_timeout = _timeout - ptimer_measure (timer); \
+          if (next_timeout < 0) \
+            { \
+              timed_out = 1; \
+              break; \
+            } \
+          err = select_fd_nb (_fd, next_timeout, wait_for); \
+          if (err <= 0) \
+            { \
+              if (err == 0) \
+                timed_out = 1; \
+              _ret = -1; \
+              break; \
+            } \
+        }
+
+static int
+ssl_connect_with_timeout(int fd, SSL *conn, double timeout)
+{
+  int ret;
+
+  errno = 0;
+  if (timeout == 0)
+    ret = SSL_connect(conn);
+  else
+    {
+      TIMER_INIT(fd, ret, timeout)
+      ERR_clear_error();
+      while( (ret = SSL_connect(conn)) < 0 )
+        TIMER_WAIT(fd, conn, ret, timeout)
+      TIMER_FREE(fd)
+    }
+
+  return ret;
+}
+
+static int
+openssl_read_peek (int fd, char *buf, int bufsize, void *arg, double timeout, ssl_fn_t fn)
+{
+  struct openssl_transport_context *ctx = arg;
+  int ret;
+
+  if (bufsize == 0)
+    return 0;
+  /* avoid wrong 'interactive timeout' when errno == ETIMEDOUT */
+  errno = 0;
+  ret = SSL_pending (ctx->conn);
+  /* If we have data available for immediate read, simply return that,
+     or do blocked read when timeout == 0 */
+  if (ret || timeout == 0)
+    do
+      {
+        ret = fn (ctx->conn, buf, (ret ? MIN (bufsize, ret) : bufsize));
+      }
+    while (ret == -1 && SSL_get_error (ctx->conn, ret) == SSL_ERROR_SYSCALL && errno == EINTR);
+  else
+    {
+      TIMER_INIT(fd, ret, timeout)
+      while( (ret = fn (ctx->conn, buf, bufsize)) <= 0 )
+        TIMER_WAIT(fd, ctx->conn, ret, timeout)
+      TIMER_FREE(fd)
+    }
+
+  return ret;
+}
+
+#endif /* OPENSSL_RUN_WITHTIMEOUT */
+
+static int
+openssl_read (int fd, char *buf, int bufsize, void *arg, double timeout)
+{
+  return openssl_read_peek (fd, buf, bufsize, arg, timeout, SSL_read);
 }
 
 static int
@@ -475,9 +680,7 @@ openssl_write (int fd _GL_UNUSED, char *buf, int bufsize, void *arg)
   SSL *conn = ctx->conn;
   do
     ret = SSL_write (conn, buf, bufsize);
-  while (ret == -1
-         && SSL_get_error (conn, ret) == SSL_ERROR_SYSCALL
-         && errno == EINTR);
+  while (ret == -1 && SSL_get_error (conn, ret) == SSL_ERROR_SYSCALL && errno == EINTR);
   return ret;
 }
 
@@ -488,25 +691,17 @@ openssl_poll (int fd, double timeout, int wait_for, void *arg)
   SSL *conn = ctx->conn;
   if (SSL_pending (conn))
     return 1;
-  if (timeout == 0)
-    return 1;
+  /* if (timeout == 0)
+    return 1; */
+  if (timeout == -1)
+    timeout = opt.read_timeout;
   return select_fd (fd, timeout, wait_for);
 }
 
 static int
-openssl_peek (int fd, char *buf, int bufsize, void *arg)
+openssl_peek (int fd, char *buf, int bufsize, void *arg, double timeout)
 {
-  int ret;
-  struct openssl_transport_context *ctx = arg;
-  SSL *conn = ctx->conn;
-  if (! openssl_poll (fd, 0.0, WAIT_FOR_READ, arg))
-    return 0;
-  do
-    ret = SSL_peek (conn, buf, bufsize);
-  while (ret == -1
-         && SSL_get_error (conn, ret) == SSL_ERROR_SYSCALL
-         && errno == EINTR);
-  return ret;
+  return openssl_read_peek (fd, buf, bufsize, arg, timeout, SSL_peek);
 }
 
 static const char *
@@ -582,19 +777,6 @@ static struct transport_implementation openssl_transport = {
   openssl_peek, openssl_errstr, openssl_close
 };
 
-struct scwt_context
-{
-  SSL *ssl;
-  int result;
-};
-
-static void
-ssl_connect_with_timeout_callback(void *arg)
-{
-  struct scwt_context *ctx = (struct scwt_context *)arg;
-  ctx->result = SSL_connect(ctx->ssl);
-}
-
 static const char *
 _sni_hostname(const char *hostname)
 {
@@ -623,7 +805,6 @@ bool
 ssl_connect_wget (int fd, const char *hostname, int *continue_session)
 {
   SSL *conn;
-  struct scwt_context scwt_ctx;
   struct openssl_transport_context *ctx;
 
   DEBUGP (("Initiating SSL handshake.\n"));
@@ -674,14 +855,9 @@ ssl_connect_wget (int fd, const char *hostname, int *continue_session)
       goto error;
     }
 
-  scwt_ctx.ssl = conn;
-  if (run_with_timeout(opt.read_timeout, ssl_connect_with_timeout_callback,
-                       &scwt_ctx)) {
-    DEBUGP (("SSL handshake timed out.\n"));
-    goto timeout;
-  }
-  if (scwt_ctx.result <= 0 || !SSL_is_init_finished(conn))
-    goto error;
+  if (ssl_connect_with_timeout(fd, conn, opt.read_timeout) <= 0
+      || !SSL_is_init_finished(conn))
+    goto timedout;
 
   ctx = xnew0 (struct openssl_transport_context);
   ctx->conn = conn;
@@ -694,12 +870,17 @@ ssl_connect_wget (int fd, const char *hostname, int *continue_session)
   fd_register_transport (fd, &openssl_transport, ctx);
   DEBUGP (("Handshake successful; connected socket %d to SSL handle 0x%0*lx\n",
            fd, PTR_FORMAT (conn)));
+
+  ERR_clear_error ();
   return true;
 
+ timedout:
+  if (errno == ETIMEDOUT)
+    DEBUGP (("SSL handshake timed out.\n"));
+  else
  error:
-  DEBUGP (("SSL handshake failed.\n"));
+    DEBUGP (("SSL handshake failed.\n"));
   print_errors ();
- timeout:
   if (conn)
     SSL_free (conn);
   return false;