From 5862c2e0e84838f40eda6332650bab10274bb211 Mon Sep 17 00:00:00 2001 From: Tim Ruehsen Date: Thu, 11 Jul 2013 14:29:20 +0200 Subject: [PATCH] add connect timeout to gnutls code --- src/ChangeLog | 6 ++++++ src/gnutls.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 5b978eb..c39cfcb 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2013-07-11 Tim Ruehsen + + * gnutls.c (ssl_connect_wget): respect connect timeout + 2013-04-26 Tomas Hozza (tiny change) * log.c (redirect_output): Use DEFAULT_LOGFILE in diagnostic message diff --git a/src/gnutls.c b/src/gnutls.c index 54422fc..a3b4ecc 100644 --- a/src/gnutls.c +++ b/src/gnutls.c @@ -374,6 +374,9 @@ static struct transport_implementation wgnutls_transport = bool ssl_connect_wget (int fd, const char *hostname) { +#ifdef F_GETFL + int flags = 0; +#endif struct wgnutls_transport_context *ctx; gnutls_session_t session; int err,alert; @@ -441,11 +444,55 @@ ssl_connect_wget (int fd, const char *hostname) return false; } + if (opt.connect_timeout) + { +#ifdef F_GETFL + flags = fcntl (fd, F_GETFL, 0); + if (flags < 0) + return flags; + if (fcntl (fd, F_SETFL, flags | O_NONBLOCK)) + return -1; +#else + /* XXX: Assume it was blocking before. */ + const int one = 1; + if (ioctl (fd, FIONBIO, &one) < 0) + return -1; +#endif + } + /* We don't stop the handshake process for non-fatal errors */ do { err = gnutls_handshake (session); - if (err < 0) + + if (opt.connect_timeout && err == GNUTLS_E_AGAIN) + { + if (gnutls_record_get_direction (session)) + { + /* wait for writeability */ + err = select_fd (fd, opt.connect_timeout, WAIT_FOR_WRITE); + } + else + { + /* wait for readability */ + err = select_fd (fd, opt.connect_timeout, WAIT_FOR_READ); + } + + if (err <= 0) + { + if (err == 0) + { + errno = ETIMEDOUT; + err = -1; + } + + break; + } + + if (err <= 0) + break; + } + else if (err < 0) { logprintf (LOG_NOTQUIET, "GnuTLS: %s\n", gnutls_strerror (err)); if (err == GNUTLS_E_WARNING_ALERT_RECEIVED || @@ -461,6 +508,18 @@ ssl_connect_wget (int fd, const char *hostname) } while (err == GNUTLS_E_WARNING_ALERT_RECEIVED && gnutls_error_is_fatal (err) == 0); + if (opt.connect_timeout) + { +#ifdef F_GETFL + if (fcntl (fd, F_SETFL, flags) < 0) + return -1; +#else + const int zero = 0; + if (ioctl (fd, FIONBIO, &zero) < 0) + return -1; +#endif + } + if (err < 0) { gnutls_deinit (session); @@ -468,7 +527,7 @@ ssl_connect_wget (int fd, const char *hostname) } ctx = xnew0 (struct wgnutls_transport_context); - ctx->session = session; + ctx->session = session; fd_register_transport (fd, &wgnutls_transport, ctx); return true; } -- 1.8.3.2