From 3467f2fa3bbff0dab6865a0ed08475ed3573c230 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 28 May 2010 15:05:32 -0400 Subject: [PATCH] Fix logic in correcting high values from FIONREAD The old logic made sense back when buffer.c was an enormous linear buffer, but it doesn't make any sense for the chain-based implementation. This patch also refactors the ioctl{socket}? call into its own function. --- buffer.c | 45 +++++++++++++++++++++------------------------ 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/buffer.c b/buffer.c index 6e0a8380..7b0262f3 100644 --- a/buffer.c +++ b/buffer.c @@ -1856,13 +1856,31 @@ _evbuffer_read_setup_vecs(struct evbuffer *buf, ev_ssize_t howmuch, return i; } +static int +get_n_bytes_readable_on_socket(evutil_socket_t fd) +{ +#if defined(FIONREAD) && defined(WIN32) + unsigned long lng = EVBUFFER_MAX_READ; + if (ioctlsocket(fd, FIONREAD, &lng) < 0) + return -1; + return (int)lng; +#elif defined(FIONREAD) + int n = EVBUFFER_MAX_READ; + if (ioctl(fd, FIONREAD, &n) < 0) + return -1; + return n; +#else + return EVBUFFER_MAX_READ; +#endif +} + /* TODO(niels): should this function return ev_ssize_t and take ev_ssize_t * as howmuch? */ int evbuffer_read(struct evbuffer *buf, evutil_socket_t fd, int howmuch) { struct evbuffer_chain *chain, **chainp; - int n = EVBUFFER_MAX_READ; + int n; int result; #ifdef USE_IOVEC_IMPL @@ -1870,9 +1888,6 @@ evbuffer_read(struct evbuffer *buf, evutil_socket_t fd, int howmuch) #else unsigned char *p; #endif -#if defined(FIONREAD) && defined(WIN32) - unsigned long lng = EVBUFFER_MAX_READ; -#endif EVBUFFER_LOCK(buf); @@ -1883,27 +1898,9 @@ evbuffer_read(struct evbuffer *buf, evutil_socket_t fd, int howmuch) goto done; } -#if defined(FIONREAD) -#ifdef WIN32 - if (ioctlsocket(fd, FIONREAD, &lng) == -1 || (n=lng) <= 0) { -#else - if (ioctl(fd, FIONREAD, &n) == -1 || n <= 0) { -#endif + n = get_n_bytes_readable_on_socket(fd); + if (n <= 0 || n > EVBUFFER_MAX_READ) n = EVBUFFER_MAX_READ; - } else if (n > EVBUFFER_MAX_READ && n > howmuch) { - /* - * It's possible that a lot of data is available for - * reading. We do not want to exhaust resources - * before the reader has a chance to do something - * about it. If the reader does not tell us how much - * data we should read, we artificially limit it. - */ - if (chain == NULL || n < EVBUFFER_MAX_READ) - n = EVBUFFER_MAX_READ; - else if ((size_t)n > chain->buffer_len << 2) - n = chain->buffer_len << 2; - } -#endif if (howmuch < 0 || howmuch > n) howmuch = n; -- 2.40.0