From 6ba5f354a3f6361df97001f028e4f351973c9915 Mon Sep 17 00:00:00 2001 From: rofl0r Date: Wed, 18 Mar 2026 16:44:53 +0000 Subject: [PATCH] fix catching timed-out socket due to some ancient piece of code that's supposed to fix a bug in 1990's internet explorer, sockets were switched between blocking and non-blocking mode, making it hard to differentiate when socket timeouts kicked in. with the IE bug workaround removed, sockets are now always in blocking mode so we no longer need to catch EAGAIN/EWOULDBLOCK and treat them specially, they now always are treated as an error (whenever they are returned, the timeout kicked in). this should fix once and for all the cases where tinyproxy would not respect the user-provided socket timeouts, potentially causing endless loops. --- src/buffer.c | 14 ----------- src/reqs.c | 67 ++++++---------------------------------------------- src/sock.c | 27 --------------------- 3 files changed, 7 insertions(+), 101 deletions(-) diff --git a/src/buffer.c b/src/buffer.c index b3381838..4cf15a0f 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -241,13 +241,6 @@ ssize_t read_buffer (int fd, struct buffer_s * buffptr) bytesin = -1; } else { switch (errno) { -#ifdef EWOULDBLOCK - case EWOULDBLOCK: -#else -# ifdef EAGAIN - case EAGAIN: -# endif -#endif case EINTR: bytesin = 0; break; @@ -295,13 +288,6 @@ ssize_t write_buffer (int fd, struct buffer_s * buffptr) return bytessent; } else { switch (errno) { -#ifdef EWOULDBLOCK - case EWOULDBLOCK: -#else -# ifdef EAGAIN - case EAGAIN: -# endif -#endif case EINTR: return 0; case ENOBUFS: diff --git a/src/reqs.c b/src/reqs.c index 94ce7673..a82fff34 100644 --- a/src/reqs.c +++ b/src/reqs.c @@ -524,11 +524,10 @@ static struct request_s *process_request (struct conn_s *connptr, * server headers can be processed. * - rjkaes */ -static int pull_client_data (struct conn_s *connptr, long int length, int iehack) +static int pull_client_data (struct conn_s *connptr, long int length) { char *buffer; ssize_t len; - int ret; buffer = (char *) safemalloc (min (MAXBUFFSIZE, (unsigned long int) length)); @@ -549,43 +548,6 @@ static int pull_client_data (struct conn_s *connptr, long int length, int iehack length -= len; } while (length > 0); - if (iehack) { - /* - * BUG FIX: Internet Explorer will leave two bytes (carriage - * return and line feed) at the end of a POST message. These - * need to be eaten for tinyproxy to work correctly. - */ - ret = socket_nonblocking (connptr->client_fd); - if (ret != 0) { - log_message(LOG_ERR, "Failed to set the client socket " - "to non-blocking: %s", strerror(errno)); - goto ERROR_EXIT; - } - - len = recv (connptr->client_fd, buffer, 2, MSG_PEEK); - - ret = socket_blocking (connptr->client_fd); - if (ret != 0) { - log_message(LOG_ERR, "Failed to set the client socket " - "to blocking: %s", strerror(errno)); - goto ERROR_EXIT; - } - - if (len < 0 && errno != EAGAIN) - goto ERROR_EXIT; - - if ((len == 2) && CHECK_CRLF (buffer, len)) { - ssize_t bytes_read; - - bytes_read = read (connptr->client_fd, buffer, 2); - if (bytes_read == -1) { - log_message - (LOG_WARNING, - "Could not read two bytes from POST message"); - } - } - } - safefree (buffer); return 0; @@ -615,7 +577,7 @@ static int pull_client_data_chunked (struct conn_s *connptr) { chunklen = strtol (buffer, (char**)0, 16); if (chunklen < 0) goto ERROR_EXIT; - if (pull_client_data (connptr, chunklen+2, 0) < 0) + if (pull_client_data (connptr, chunklen+2) < 0) goto ERROR_EXIT; if(!chunklen) break; @@ -1008,7 +970,7 @@ process_client_headers (struct conn_s *connptr, pseudomap *hashofheaders) PULL_CLIENT_DATA: if (connptr->content_length.client > 0) { ret = pull_client_data (connptr, - connptr->content_length.client, 1); + connptr->content_length.client); } else if (connptr->content_length.client == -2) ret = pull_client_data_chunked (connptr); @@ -1195,8 +1157,8 @@ static int process_server_headers (struct conn_s *connptr) } /* - * Switch the sockets into nonblocking mode and begin relaying the bytes - * between the two connections. We continue to use the buffering code + * Begin relaying the bytes between the two connections. + * We continue to use the buffering code * since we want to be able to buffer a certain amount for slower * connections (as this was the reason why I originally modified * tinyproxy oh so long ago...) @@ -1269,14 +1231,6 @@ static void relay_connection (struct conn_s *connptr) /* * Try to send any remaining data to the server if we can. */ - ret = socket_blocking (connptr->server_fd); - if (ret != 0) { - log_message(LOG_ERR, - "Failed to set server socket to blocking: %s", - strerror(errno)); - return; - } - while (buffer_size (connptr->cbuffer) > 0) { if (write_buffer (connptr->server_fd, connptr->cbuffer) < 0) break; @@ -1573,16 +1527,9 @@ static void auth_error(struct conn_s *connptr, int code) { } /* - * This is the main drive for each connection. As you can tell, for the - * first few steps we are using a blocking socket. If you remember the - * older tinyproxy code, this use to be a very confusing state machine. - * Well, no more! :) The sockets are only switched into nonblocking mode - * when we start the relay portion. This makes most of the original - * tinyproxy code, which was confusing, redundant. Hail progress. - * - rjkaes - + * This is the main drive for each connection. * this function is called directly from child_thread() with the newly - * received fd from accept(). + * received fd from accept(). */ void handle_connection (struct conn_s *connptr, union sockaddr_union* addr) { diff --git a/src/sock.c b/src/sock.c index b3b0920d..ec8ad4c8 100644 --- a/src/sock.c +++ b/src/sock.c @@ -212,33 +212,6 @@ int opensock (const char *host, int port, const char *bind_to) return sockfd; } -/* - * Set the socket to non blocking -rjkaes - */ -int socket_nonblocking (int sock) -{ - int flags; - - assert (sock >= 0); - - flags = fcntl (sock, F_GETFL, 0); - return fcntl (sock, F_SETFL, flags | O_NONBLOCK); -} - -/* - * Set the socket to blocking -rjkaes - */ -int socket_blocking (int sock) -{ - int flags; - - assert (sock >= 0); - - flags = fcntl (sock, F_GETFL, 0); - return fcntl (sock, F_SETFL, flags & ~O_NONBLOCK); -} - - /** * Try to listen on one socket based on the addrinfo * as returned from getaddrinfo.