mirror of
https://github.com/mirror/wget.git
synced 2025-01-01 07:50:11 +08:00
Fix SSL/TLS timeout issues.
* connect.c (fd_read, fd_peek): Let implementation take care about timeout. * gnutls.c (_do_handshake, _do_reauth, wgnutls_read_timeout): Fix support for interactive timeout. * gnutls.c (wgnutls_peek): Let wgnutls_read_timeout() take care about timeout. * openssl.c (openssl_read_peek): Fix 0 (-1) timeout. * retr.c (fd_read_body): Avoid wrong 'interactive timeout'.
This commit is contained in:
parent
c12a295496
commit
7a3a82faf8
@ -941,11 +941,13 @@ fd_read (int fd, char *buf, int bufsize, double timeout)
|
|||||||
struct transport_info *info;
|
struct transport_info *info;
|
||||||
LAZY_RETRIEVE_INFO (info);
|
LAZY_RETRIEVE_INFO (info);
|
||||||
|
|
||||||
if (!poll_internal (fd, info, WAIT_FOR_READ, timeout))
|
/* let imp->reader take care about timeout.
|
||||||
return -1;
|
(or in worst case timeout can be 2*timeout) */
|
||||||
if (info && info->imp->reader)
|
if (info && info->imp->reader)
|
||||||
return info->imp->reader (fd, buf, bufsize, info->ctx, timeout);
|
return info->imp->reader (fd, buf, bufsize, info->ctx, timeout);
|
||||||
else
|
|
||||||
|
if (!poll_internal (fd, info, WAIT_FOR_READ, timeout))
|
||||||
|
return -1;
|
||||||
return sock_read (fd, buf, bufsize);
|
return sock_read (fd, buf, bufsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -966,11 +968,12 @@ fd_peek (int fd, char *buf, int bufsize, double timeout)
|
|||||||
{
|
{
|
||||||
struct transport_info *info;
|
struct transport_info *info;
|
||||||
LAZY_RETRIEVE_INFO (info);
|
LAZY_RETRIEVE_INFO (info);
|
||||||
if (!poll_internal (fd, info, WAIT_FOR_READ, timeout))
|
|
||||||
return -1;
|
|
||||||
if (info && info->imp->peeker)
|
if (info && info->imp->peeker)
|
||||||
return info->imp->peeker (fd, buf, bufsize, info->ctx, timeout);
|
return info->imp->peeker (fd, buf, bufsize, info->ctx, timeout);
|
||||||
else
|
|
||||||
|
if (!poll_internal (fd, info, WAIT_FOR_READ, timeout))
|
||||||
|
return -1;
|
||||||
return sock_peek (fd, buf, bufsize);
|
return sock_peek (fd, buf, bufsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
241
src/gnutls.c
241
src/gnutls.c
@ -58,12 +58,20 @@ as that of the covered work. */
|
|||||||
|
|
||||||
#include "host.h"
|
#include "host.h"
|
||||||
|
|
||||||
|
struct st_read_timer
|
||||||
|
{
|
||||||
|
double timeout;
|
||||||
|
double next_timeout;
|
||||||
|
struct ptimer *timer;
|
||||||
|
int timed_out;
|
||||||
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_do_handshake (gnutls_session_t session, int fd, double timeout, int is_nonblock);
|
_do_handshake (gnutls_session_t session, int fd, struct st_read_timer *timeout);
|
||||||
|
|
||||||
#if GNUTLS_VERSION_NUMBER >= 0x030604
|
#if GNUTLS_VERSION_NUMBER >= 0x030604
|
||||||
static int
|
static int
|
||||||
_do_reauth (gnutls_session_t session, int fd, double timeout, int is_nonblock);
|
_do_reauth (gnutls_session_t session, int fd, struct st_read_timer *timeout);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -255,17 +263,14 @@ wgnutls_read_timeout (int fd, char *buf, int bufsize, void *arg, double timeout)
|
|||||||
#ifdef F_GETFL
|
#ifdef F_GETFL
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
#endif
|
#endif
|
||||||
int ret = 0;
|
|
||||||
struct ptimer *timer = NULL;
|
|
||||||
struct wgnutls_transport_context *ctx = arg;
|
struct wgnutls_transport_context *ctx = arg;
|
||||||
int timed_out = 0;
|
int ret = gnutls_record_check_pending (ctx->session);
|
||||||
double next_timeout;
|
struct st_read_timer read_timer = {(timeout == -1 ? opt.read_timeout : timeout), 0, NULL, 0};
|
||||||
|
|
||||||
errno = 0;
|
if (ret)
|
||||||
if (timeout == -1)
|
return gnutls_record_recv (ctx->session, buf, MIN (ret, bufsize));
|
||||||
timeout = opt.read_timeout;
|
|
||||||
next_timeout = timeout;
|
if (read_timer.timeout)
|
||||||
if (timeout)
|
|
||||||
{
|
{
|
||||||
#ifdef F_GETFL
|
#ifdef F_GETFL
|
||||||
flags = fcntl (fd, F_GETFL, 0);
|
flags = fcntl (fd, F_GETFL, 0);
|
||||||
@ -280,63 +285,83 @@ wgnutls_read_timeout (int fd, char *buf, int bufsize, void *arg, double timeout)
|
|||||||
return -1;
|
return -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
timer = ptimer_new ();
|
read_timer.timer = ptimer_new ();
|
||||||
if (timer == NULL)
|
if (read_timer.timer == NULL)
|
||||||
{
|
{
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto timer_err;
|
goto timer_err;
|
||||||
}
|
}
|
||||||
|
read_timer.next_timeout = read_timer.timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = ctx->last_error;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
ret = GNUTLS_E_AGAIN;
|
if (ret == GNUTLS_E_REHANDSHAKE)
|
||||||
if (timeout)
|
|
||||||
{
|
{
|
||||||
next_timeout = timeout - ptimer_measure (timer);
|
int err;
|
||||||
if (next_timeout <= 0)
|
DEBUGP (("GnuTLS: *** REHANDSHAKE while reading\n"));
|
||||||
|
if ((err = _do_handshake (ctx->session, fd, &read_timer)) != 0)
|
||||||
{
|
{
|
||||||
timed_out = 1;
|
ret = err;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* (rehandshake, reauth) needs some workaround for interactive timeout */
|
|
||||||
if (timeout == 0 || gnutls_record_check_pending (ctx->session)
|
|
||||||
|| 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, opt.read_timeout, 1)) == 0)
|
|
||||||
ret = GNUTLS_E_AGAIN; /* restart reading */
|
|
||||||
}
|
|
||||||
#if GNUTLS_VERSION_NUMBER >= 0x030604
|
#if GNUTLS_VERSION_NUMBER >= 0x030604
|
||||||
if (!timed_out && ret == GNUTLS_E_REAUTH_REQUEST)
|
else if (ret == GNUTLS_E_REAUTH_REQUEST)
|
||||||
{
|
{
|
||||||
|
int err;
|
||||||
DEBUGP (("GnuTLS: *** re-authentication while reading\n"));
|
DEBUGP (("GnuTLS: *** re-authentication while reading\n"));
|
||||||
if ((ret = _do_reauth (ctx->session, fd, opt.read_timeout, 1)) == 0)
|
if ((err = _do_reauth (ctx->session, fd, &read_timer)) != 0)
|
||||||
ret = GNUTLS_E_AGAIN; /* restart reading */
|
{
|
||||||
|
ret = err;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
do
|
||||||
}
|
|
||||||
while (ret == GNUTLS_E_INTERRUPTED || (ret == GNUTLS_E_AGAIN && !timed_out));
|
|
||||||
|
|
||||||
if (timeout)
|
|
||||||
{
|
{
|
||||||
ptimer_destroy (timer);
|
ret = gnutls_record_recv (ctx->session, buf, bufsize);
|
||||||
|
if (ret == GNUTLS_E_AGAIN && read_timer.timer)
|
||||||
|
{
|
||||||
|
int err = select_fd_nb (fd, read_timer.next_timeout, WAIT_FOR_READ);
|
||||||
|
if (err <= 0)
|
||||||
|
{
|
||||||
|
if (err == 0)
|
||||||
|
read_timer.timed_out = 1;
|
||||||
|
goto break_all;
|
||||||
|
}
|
||||||
|
if ( (read_timer.next_timeout = read_timer.timeout - ptimer_measure (read_timer.timer)) <= 0 )
|
||||||
|
{
|
||||||
|
read_timer.timed_out = 1;
|
||||||
|
goto break_all;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED);
|
||||||
|
}
|
||||||
|
while (ret == GNUTLS_E_REHANDSHAKE
|
||||||
|
#if GNUTLS_VERSION_NUMBER >= 0x030604
|
||||||
|
|| ret == GNUTLS_E_REAUTH_REQUEST
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
|
break_all:
|
||||||
|
if (read_timer.timer)
|
||||||
|
{
|
||||||
|
ptimer_destroy (read_timer.timer);
|
||||||
timer_err: ;
|
timer_err: ;
|
||||||
#ifdef F_GETFL
|
#ifdef F_GETFL
|
||||||
if (fcntl (fd, F_SETFL, flags) < 0)
|
if (fcntl (fd, F_SETFL, flags) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
#else
|
#else
|
||||||
|
{
|
||||||
const int zero = 0;
|
const int zero = 0;
|
||||||
if (ioctl (fd, FIONBIO, &zero) < 0)
|
if (ioctl (fd, FIONBIO, &zero) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
if (timed_out && ret == GNUTLS_E_AGAIN)
|
if (read_timer.timed_out)
|
||||||
errno = ETIMEDOUT;
|
errno = ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,7 +371,7 @@ timer_err: ;
|
|||||||
static int
|
static int
|
||||||
wgnutls_read (int fd, char *buf, int bufsize, void *arg, double timeout)
|
wgnutls_read (int fd, char *buf, int bufsize, void *arg, double timeout)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret;
|
||||||
struct wgnutls_transport_context *ctx = arg;
|
struct wgnutls_transport_context *ctx = arg;
|
||||||
|
|
||||||
if (ctx->peeklen)
|
if (ctx->peeklen)
|
||||||
@ -362,21 +387,37 @@ wgnutls_read (int fd, char *buf, int bufsize, void *arg, double timeout)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = wgnutls_read_timeout (fd, buf, bufsize, arg, timeout);
|
ret = wgnutls_read_timeout (fd, buf, bufsize, arg, timeout);
|
||||||
if (ret < 0)
|
|
||||||
ctx->last_error = ret;
|
ctx->last_error = ret;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
wgnutls_write (int fd _GL_UNUSED, char *buf, int bufsize, void *arg)
|
wgnutls_write (int fd _GL_UNUSED, char *buf, int bufsize, void *arg)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
struct wgnutls_transport_context *ctx = arg;
|
struct wgnutls_transport_context *ctx = arg;
|
||||||
|
int ret = ctx->last_error;
|
||||||
|
|
||||||
|
/* it should never happen,
|
||||||
|
placed here only for debug msg. */
|
||||||
|
if (ret == GNUTLS_E_REHANDSHAKE)
|
||||||
|
{
|
||||||
|
DEBUGP (("GnuTLS: *** REHANDSHAKE while writing\n"));
|
||||||
|
if ((ret = _do_handshake (ctx->session, fd, NULL)) != 0)
|
||||||
|
goto ext;
|
||||||
|
}
|
||||||
|
#if GNUTLS_VERSION_NUMBER >= 0x030604
|
||||||
|
else if (ret == GNUTLS_E_REAUTH_REQUEST)
|
||||||
|
{
|
||||||
|
DEBUGP (("GnuTLS: *** re-authentication while writing\n"));
|
||||||
|
if ((ret = _do_reauth (ctx->session, fd, NULL)) != 0)
|
||||||
|
goto ext;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
do
|
do
|
||||||
ret = gnutls_record_send (ctx->session, buf, bufsize);
|
ret = gnutls_record_send (ctx->session, buf, bufsize);
|
||||||
while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
|
while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
|
||||||
if (ret < 0)
|
ext:
|
||||||
ctx->last_error = ret;
|
ctx->last_error = ret;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -386,11 +427,13 @@ wgnutls_poll (int fd, double timeout, int wait_for, void *arg)
|
|||||||
{
|
{
|
||||||
struct wgnutls_transport_context *ctx = arg;
|
struct wgnutls_transport_context *ctx = arg;
|
||||||
|
|
||||||
if (timeout)
|
if ((wait_for & WAIT_FOR_READ)
|
||||||
return ctx->peeklen || gnutls_record_check_pending (ctx->session)
|
&& (ctx->peeklen || gnutls_record_check_pending (ctx->session)))
|
||||||
|| select_fd (fd, timeout, wait_for);
|
return 1;
|
||||||
else
|
|
||||||
return ctx->peeklen || gnutls_record_check_pending (ctx->session);
|
if (timeout == -1)
|
||||||
|
timeout = opt.read_timeout;
|
||||||
|
return select_fd (fd, timeout, wait_for);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -410,13 +453,14 @@ wgnutls_peek (int fd, char *buf, int bufsize, void *arg, double timeout)
|
|||||||
bufsize = sizeof ctx->peekbuf;
|
bufsize = sizeof ctx->peekbuf;
|
||||||
|
|
||||||
if (bufsize > offset)
|
if (bufsize > offset)
|
||||||
{
|
{ /* let wgnutls_read_timeout() take care about timeout */
|
||||||
if (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)
|
&& select_fd (fd, 0.0, WAIT_FOR_READ) <= 0)
|
||||||
read = 0;
|
read = 0;
|
||||||
else
|
else*/
|
||||||
read = wgnutls_read_timeout (fd, buf + offset, bufsize - offset,
|
read = wgnutls_read_timeout (fd, buf + offset, bufsize - offset,
|
||||||
ctx, timeout);
|
ctx, timeout);
|
||||||
|
ctx->last_error = read;
|
||||||
if (read < 0)
|
if (read < 0)
|
||||||
{
|
{
|
||||||
if (offset)
|
if (offset)
|
||||||
@ -440,8 +484,17 @@ static const char *
|
|||||||
wgnutls_errstr (int fd _GL_UNUSED, void *arg)
|
wgnutls_errstr (int fd _GL_UNUSED, void *arg)
|
||||||
{
|
{
|
||||||
struct wgnutls_transport_context *ctx = arg;
|
struct wgnutls_transport_context *ctx = arg;
|
||||||
return (ctx->last_error == GNUTLS_E_AGAIN && errno == ETIMEDOUT ?
|
|
||||||
strerror (ETIMEDOUT) : gnutls_strerror (ctx->last_error));
|
if (ctx->last_error > 0
|
||||||
|
|| ((ctx->last_error == GNUTLS_E_AGAIN
|
||||||
|
|| ctx->last_error == GNUTLS_E_REHANDSHAKE
|
||||||
|
#if GNUTLS_VERSION_NUMBER >= 0x030604
|
||||||
|
|| ctx->last_error == GNUTLS_E_REAUTH_REQUEST
|
||||||
|
#endif
|
||||||
|
) && errno == ETIMEDOUT))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return gnutls_strerror (ctx->last_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -469,14 +522,16 @@ static struct transport_implementation wgnutls_transport =
|
|||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_do_handshake (gnutls_session_t session, int fd, double timeout, int is_nonblock)
|
_do_handshake (gnutls_session_t session, int fd, struct st_read_timer *read_timer)
|
||||||
{
|
{
|
||||||
#ifdef F_GETFL
|
#ifdef F_GETFL
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
#endif
|
#endif
|
||||||
int err;
|
int err;
|
||||||
|
double next_timeout = (read_timer ? read_timer->next_timeout : opt.read_timeout);
|
||||||
|
|
||||||
if (!is_nonblock && timeout)
|
/* if (read_timer != NULL) - fd is already non blocking */
|
||||||
|
if (!read_timer && next_timeout)
|
||||||
{
|
{
|
||||||
#ifdef F_GETFL
|
#ifdef F_GETFL
|
||||||
flags = fcntl (fd, F_GETFL, 0);
|
flags = fcntl (fd, F_GETFL, 0);
|
||||||
@ -497,30 +552,46 @@ _do_handshake (gnutls_session_t session, int fd, double timeout, int is_nonblock
|
|||||||
{
|
{
|
||||||
err = gnutls_handshake (session);
|
err = gnutls_handshake (session);
|
||||||
|
|
||||||
if (timeout && err == GNUTLS_E_AGAIN)
|
if (err == GNUTLS_E_AGAIN && next_timeout)
|
||||||
{
|
{
|
||||||
|
int sel;
|
||||||
if (gnutls_record_get_direction (session))
|
if (gnutls_record_get_direction (session))
|
||||||
{
|
{
|
||||||
/* wait for writeability */
|
/* wait for writeability */
|
||||||
err = select_fd_nb (fd, timeout, WAIT_FOR_WRITE);
|
sel = WAIT_FOR_WRITE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* wait for readability */
|
/* wait for readability */
|
||||||
err = select_fd_nb (fd, timeout, WAIT_FOR_READ);
|
sel = WAIT_FOR_READ;
|
||||||
}
|
}
|
||||||
|
sel = select_fd_nb (fd, next_timeout, sel);
|
||||||
|
|
||||||
if (err <= 0)
|
if (sel <= 0)
|
||||||
{
|
{
|
||||||
if (err == 0)
|
if (sel == 0)
|
||||||
|
{
|
||||||
|
if (read_timer)
|
||||||
|
goto read_timedout;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
errno = ETIMEDOUT;
|
errno = ETIMEDOUT;
|
||||||
err = -1;
|
err = -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (read_timer)
|
||||||
err = GNUTLS_E_AGAIN;
|
{
|
||||||
|
if ( (read_timer->next_timeout = read_timer->timeout - ptimer_measure (read_timer->timer)) <= 0 )
|
||||||
|
{
|
||||||
|
read_timedout: /* return GNUTLS_E_REHANDSHAKE for gnutls_read */
|
||||||
|
err = GNUTLS_E_REHANDSHAKE;
|
||||||
|
read_timer->timed_out = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
next_timeout = read_timer->next_timeout;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (err < 0)
|
else if (err < 0)
|
||||||
{
|
{
|
||||||
@ -537,7 +608,7 @@ _do_handshake (gnutls_session_t session, int fd, double timeout, int is_nonblock
|
|||||||
}
|
}
|
||||||
while (err && gnutls_error_is_fatal (err) == 0);
|
while (err && gnutls_error_is_fatal (err) == 0);
|
||||||
|
|
||||||
if (!is_nonblock && timeout)
|
if (!read_timer && next_timeout)
|
||||||
{
|
{
|
||||||
#ifdef F_GETFL
|
#ifdef F_GETFL
|
||||||
if (fcntl (fd, F_SETFL, flags) < 0)
|
if (fcntl (fd, F_SETFL, flags) < 0)
|
||||||
@ -554,14 +625,16 @@ _do_handshake (gnutls_session_t session, int fd, double timeout, int is_nonblock
|
|||||||
|
|
||||||
#if GNUTLS_VERSION_NUMBER >= 0x030604
|
#if GNUTLS_VERSION_NUMBER >= 0x030604
|
||||||
static int
|
static int
|
||||||
_do_reauth (gnutls_session_t session, int fd, double timeout, int is_nonblock)
|
_do_reauth (gnutls_session_t session, int fd, struct st_read_timer *read_timer)
|
||||||
{
|
{
|
||||||
#ifdef F_GETFL
|
#ifdef F_GETFL
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
#endif
|
#endif
|
||||||
int err;
|
int err;
|
||||||
|
double next_timeout = (read_timer ? read_timer->next_timeout : opt.read_timeout);
|
||||||
|
|
||||||
if (!is_nonblock && timeout)
|
/* if (read_timer != NULL) - fd is already non blocking */
|
||||||
|
if (!read_timer && next_timeout)
|
||||||
{
|
{
|
||||||
#ifdef F_GETFL
|
#ifdef F_GETFL
|
||||||
flags = fcntl (fd, F_GETFL, 0);
|
flags = fcntl (fd, F_GETFL, 0);
|
||||||
@ -582,30 +655,46 @@ _do_reauth (gnutls_session_t session, int fd, double timeout, int is_nonblock)
|
|||||||
{
|
{
|
||||||
err = gnutls_reauth (session, 0);
|
err = gnutls_reauth (session, 0);
|
||||||
|
|
||||||
if (timeout && err == GNUTLS_E_AGAIN)
|
if (err == GNUTLS_E_AGAIN && next_timeout)
|
||||||
{
|
{
|
||||||
|
int sel;
|
||||||
if (gnutls_record_get_direction (session))
|
if (gnutls_record_get_direction (session))
|
||||||
{
|
{
|
||||||
/* wait for writeability */
|
/* wait for writeability */
|
||||||
err = select_fd_nb (fd, timeout, WAIT_FOR_WRITE);
|
sel = WAIT_FOR_WRITE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* wait for readability */
|
/* wait for readability */
|
||||||
err = select_fd_nb (fd, timeout, WAIT_FOR_READ);
|
sel = WAIT_FOR_READ;
|
||||||
}
|
}
|
||||||
|
sel = select_fd_nb (fd, next_timeout, sel);
|
||||||
|
|
||||||
if (err <= 0)
|
if (sel <= 0)
|
||||||
{
|
{
|
||||||
if (err == 0)
|
if (sel == 0)
|
||||||
|
{
|
||||||
|
if (read_timer)
|
||||||
|
goto read_timedout;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
errno = ETIMEDOUT;
|
errno = ETIMEDOUT;
|
||||||
err = -1;
|
err = -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (read_timer)
|
||||||
err = GNUTLS_E_AGAIN;
|
{
|
||||||
|
if ( (read_timer->next_timeout = read_timer->timeout - ptimer_measure (read_timer->timer)) <= 0 )
|
||||||
|
{
|
||||||
|
read_timedout: /* return GNUTLS_E_REAUTH_REQUEST for gnutls_read */
|
||||||
|
err = GNUTLS_E_REAUTH_REQUEST;
|
||||||
|
read_timer->timed_out = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
next_timeout = read_timer->next_timeout;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (err < 0)
|
else if (err < 0)
|
||||||
{
|
{
|
||||||
@ -614,7 +703,7 @@ _do_reauth (gnutls_session_t session, int fd, double timeout, int is_nonblock)
|
|||||||
}
|
}
|
||||||
while (err && gnutls_error_is_fatal (err) == 0);
|
while (err && gnutls_error_is_fatal (err) == 0);
|
||||||
|
|
||||||
if (!is_nonblock && timeout)
|
if (!read_timer && next_timeout)
|
||||||
{
|
{
|
||||||
#ifdef F_GETFL
|
#ifdef F_GETFL
|
||||||
if (fcntl (fd, F_SETFL, flags) < 0)
|
if (fcntl (fd, F_SETFL, flags) < 0)
|
||||||
@ -840,7 +929,7 @@ ssl_connect_wget (int fd, const char *hostname, int *continue_session)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = _do_handshake (session, fd, opt.read_timeout, 0);
|
err = _do_handshake (session, fd, NULL);
|
||||||
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
{
|
{
|
||||||
|
@ -482,7 +482,8 @@ struct openssl_read_args
|
|||||||
int retval;
|
int retval;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void openssl_read_peek_callback(void *arg)
|
static void
|
||||||
|
openssl_read_peek_callback(void *arg)
|
||||||
{
|
{
|
||||||
struct openssl_read_args *args = (struct openssl_read_args *) arg;
|
struct openssl_read_args *args = (struct openssl_read_args *) arg;
|
||||||
struct openssl_transport_context *ctx = args->ctx;
|
struct openssl_transport_context *ctx = args->ctx;
|
||||||
@ -506,9 +507,6 @@ openssl_read_peek (int fd, char *buf, int bufsize, void *arg, double timeout, ss
|
|||||||
struct openssl_transport_context *ctx = arg;
|
struct openssl_transport_context *ctx = arg;
|
||||||
int ret = SSL_pending (ctx->conn);
|
int ret = SSL_pending (ctx->conn);
|
||||||
|
|
||||||
if (bufsize == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
ret = fn (ctx->conn, buf, MIN (bufsize, ret));
|
ret = fn (ctx->conn, buf, MIN (bufsize, ret));
|
||||||
else
|
else
|
||||||
@ -520,7 +518,6 @@ openssl_read_peek (int fd, char *buf, int bufsize, void *arg, double timeout, ss
|
|||||||
args.fn = fn;
|
args.fn = fn;
|
||||||
args.ctx = ctx;
|
args.ctx = ctx;
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
if (timeout == -1)
|
if (timeout == -1)
|
||||||
timeout = opt.read_timeout;
|
timeout = opt.read_timeout;
|
||||||
|
|
||||||
@ -540,13 +537,13 @@ openssl_read_peek (int fd, char *buf, int bufsize, void *arg, double timeout, ss
|
|||||||
#ifdef F_GETFL
|
#ifdef F_GETFL
|
||||||
#define NONBLOCK_DECL int flags = 0;
|
#define NONBLOCK_DECL int flags = 0;
|
||||||
#define FD_SET_NONBLOCKED(_fd) \
|
#define FD_SET_NONBLOCKED(_fd) \
|
||||||
flags = fcntl (_fd, F_GETFL, 0);\
|
flags = fcntl (_fd, F_GETFL, 0); \
|
||||||
if (flags < 0)\
|
if (flags < 0) \
|
||||||
return flags;\
|
return flags; \
|
||||||
if (fcntl (_fd, F_SETFL, flags | O_NONBLOCK))\
|
if (fcntl (_fd, F_SETFL, flags | O_NONBLOCK)) \
|
||||||
return -1;
|
return -1;
|
||||||
#define FD_SET_BLOCKED(_fd) \
|
#define FD_SET_BLOCKED(_fd) \
|
||||||
if (fcntl (_fd, F_SETFL, flags) < 0)\
|
if (fcntl (_fd, F_SETFL, flags) < 0) \
|
||||||
return -1;
|
return -1;
|
||||||
#else
|
#else
|
||||||
#define NONBLOCK_DECL
|
#define NONBLOCK_DECL
|
||||||
@ -574,8 +571,7 @@ openssl_read_peek (int fd, char *buf, int bufsize, void *arg, double timeout, ss
|
|||||||
_ret = -1; \
|
_ret = -1; \
|
||||||
else \
|
else \
|
||||||
{ \
|
{ \
|
||||||
if (_timeout == -1) \
|
double next_timeout = _timeout;
|
||||||
_timeout = opt.read_timeout;
|
|
||||||
|
|
||||||
#define TIMER_FREE(_fd) \
|
#define TIMER_FREE(_fd) \
|
||||||
ptimer_destroy (timer); \
|
ptimer_destroy (timer); \
|
||||||
@ -590,7 +586,6 @@ openssl_read_peek (int fd, char *buf, int bufsize, void *arg, double timeout, ss
|
|||||||
#define TIMER_WAIT(_fd, _conn, _ret, _timeout) \
|
#define TIMER_WAIT(_fd, _conn, _ret, _timeout) \
|
||||||
{ \
|
{ \
|
||||||
int wait_for; \
|
int wait_for; \
|
||||||
double next_timeout; \
|
|
||||||
int err = SSL_get_error(_conn, _ret); \
|
int err = SSL_get_error(_conn, _ret); \
|
||||||
if (err == SSL_ERROR_WANT_READ) \
|
if (err == SSL_ERROR_WANT_READ) \
|
||||||
wait_for = WAIT_FOR_READ; \
|
wait_for = WAIT_FOR_READ; \
|
||||||
@ -598,20 +593,18 @@ openssl_read_peek (int fd, char *buf, int bufsize, void *arg, double timeout, ss
|
|||||||
wait_for = WAIT_FOR_WRITE; \
|
wait_for = WAIT_FOR_WRITE; \
|
||||||
else \
|
else \
|
||||||
break; \
|
break; \
|
||||||
next_timeout = _timeout - ptimer_measure (timer); \
|
|
||||||
if (next_timeout < 0) \
|
|
||||||
{ \
|
|
||||||
timed_out = 1; \
|
|
||||||
break; \
|
|
||||||
} \
|
|
||||||
err = select_fd_nb (_fd, next_timeout, wait_for); \
|
err = select_fd_nb (_fd, next_timeout, wait_for); \
|
||||||
if (err <= 0) \
|
if (err <= 0) \
|
||||||
{ \
|
{ \
|
||||||
if (err == 0) \
|
if (err == 0) \
|
||||||
|
timedout: \
|
||||||
timed_out = 1; \
|
timed_out = 1; \
|
||||||
_ret = -1; \
|
_ret = -1; \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
|
next_timeout = _timeout - ptimer_measure (timer); \
|
||||||
|
if (next_timeout <= 0) \
|
||||||
|
goto timedout; \
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -638,13 +631,10 @@ static int
|
|||||||
openssl_read_peek (int fd, char *buf, int bufsize, void *arg, double timeout, ssl_fn_t fn)
|
openssl_read_peek (int fd, char *buf, int bufsize, void *arg, double timeout, ssl_fn_t fn)
|
||||||
{
|
{
|
||||||
struct openssl_transport_context *ctx = arg;
|
struct openssl_transport_context *ctx = arg;
|
||||||
int ret;
|
int ret = SSL_pending (ctx->conn);
|
||||||
|
|
||||||
if (bufsize == 0)
|
if (timeout == -1)
|
||||||
return 0;
|
timeout = opt.read_timeout;
|
||||||
/* 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,
|
/* If we have data available for immediate read, simply return that,
|
||||||
or do blocked read when timeout == 0 */
|
or do blocked read when timeout == 0 */
|
||||||
if (ret || timeout == 0)
|
if (ret || timeout == 0)
|
||||||
@ -689,7 +679,7 @@ openssl_poll (int fd, double timeout, int wait_for, void *arg)
|
|||||||
{
|
{
|
||||||
struct openssl_transport_context *ctx = arg;
|
struct openssl_transport_context *ctx = arg;
|
||||||
SSL *conn = ctx->conn;
|
SSL *conn = ctx->conn;
|
||||||
if (SSL_pending (conn))
|
if ((wait_for & WAIT_FOR_READ) && SSL_pending (conn))
|
||||||
return 1;
|
return 1;
|
||||||
/* if (timeout == 0)
|
/* if (timeout == 0)
|
||||||
return 1; */
|
return 1; */
|
||||||
|
@ -417,6 +417,8 @@ fd_read_body (const char *downloaded_filename, int fd, FILE *out, wgint toread,
|
|||||||
timeout, so that the gauge can be updated regularly even
|
timeout, so that the gauge can be updated regularly even
|
||||||
when the data arrives very slowly or stalls. */
|
when the data arrives very slowly or stalls. */
|
||||||
tmout = 0.95;
|
tmout = 0.95;
|
||||||
|
/* avoid wrong 'interactive timeout' */
|
||||||
|
errno = 0;
|
||||||
if (opt.read_timeout)
|
if (opt.read_timeout)
|
||||||
{
|
{
|
||||||
double waittm;
|
double waittm;
|
||||||
|
Loading…
Reference in New Issue
Block a user