fix get_request_entity()
get_request_entity()'s purpose is to drain remaining unread bytes in the request read pipe before handing out an error page, and kinda surprisingly, also when connection to the stathost is done. in the stathost case tinyproxy just skipped proper processing and jumped to the error handler code, and remembering whether a connection to the stathost was desired in a variable, then doing things a bit differently depending on whether it's set. i tried to fix issues with get_request_entity in88153e944f
(which is basically the right fix for the issue it tried to solve, but incomplete), and resulting from there in78cc5b72b1
. the latter fix wasn't quite right since we're not supposed to check whether the socket is ready for writing, and having a return value of 2 instead of 1 got resulted in some of the if statements not kicking in when they should have. this also resulted in the stathost page no longer working. after in-depth study of the issue i realized that we only need to call get_request_entity() when the headers aren't completely read, additional to setting the proper connection timeout as88153e944f
already implemented. the changes of78cc5b72b1
have been reverted.
This commit is contained in:
parent
bfe59856b2
commit
c64ac9edbe
19
src/reqs.c
19
src/reqs.c
@ -1439,19 +1439,21 @@ connect_to_upstream (struct conn_s *connptr, struct request_s *request)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* this function "drains" remaining bytes in the read pipe from
|
||||||
|
the client. it's usually only called on error before displaying
|
||||||
|
an error code/page. */
|
||||||
static int
|
static int
|
||||||
get_request_entity(struct conn_s *connptr)
|
get_request_entity(struct conn_s *connptr)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
fd_set rset, wset;
|
fd_set rset;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
|
||||||
FD_ZERO (&rset);
|
FD_ZERO (&rset);
|
||||||
FD_SET (connptr->client_fd, &rset);
|
FD_SET (connptr->client_fd, &rset);
|
||||||
memcpy(&wset, &rset, sizeof wset);
|
|
||||||
tv.tv_sec = config->idletimeout;
|
tv.tv_sec = config->idletimeout;
|
||||||
tv.tv_usec = 0;
|
tv.tv_usec = 0;
|
||||||
ret = select (connptr->client_fd + 1, &rset, &wset, NULL, &tv);
|
ret = select (connptr->client_fd + 1, &rset, NULL, NULL, &tv);
|
||||||
|
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
log_message (LOG_ERR,
|
log_message (LOG_ERR,
|
||||||
@ -1473,8 +1475,6 @@ get_request_entity(struct conn_s *connptr)
|
|||||||
nread);
|
nread);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
}
|
||||||
} else if (ret == 1 && FD_ISSET (connptr->client_fd, &wset) && connptr->connect_method) {
|
|
||||||
ret = 0;
|
|
||||||
} else {
|
} else {
|
||||||
log_message (LOG_ERR, "strange situation after select: "
|
log_message (LOG_ERR, "strange situation after select: "
|
||||||
"ret = %d, but client_fd (%d) is not readable...",
|
"ret = %d, but client_fd (%d) is not readable...",
|
||||||
@ -1485,7 +1485,7 @@ get_request_entity(struct conn_s *connptr)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_connection_failure(struct conn_s *connptr)
|
static void handle_connection_failure(struct conn_s *connptr, int got_headers)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* First, get the body if there is one.
|
* First, get the body if there is one.
|
||||||
@ -1493,7 +1493,7 @@ static void handle_connection_failure(struct conn_s *connptr)
|
|||||||
* it is still marked for reading and we won't be able
|
* it is still marked for reading and we won't be able
|
||||||
* to send our data properly.
|
* to send our data properly.
|
||||||
*/
|
*/
|
||||||
if (get_request_entity (connptr) < 0) {
|
if (!got_headers && get_request_entity (connptr) < 0) {
|
||||||
log_message (LOG_WARNING,
|
log_message (LOG_WARNING,
|
||||||
"Could not retrieve request entity");
|
"Could not retrieve request entity");
|
||||||
indicate_http_error (connptr, 400, "Bad Request",
|
indicate_http_error (connptr, 400, "Bad Request",
|
||||||
@ -1524,8 +1524,10 @@ void handle_connection (int fd, union sockaddr_union* addr)
|
|||||||
{
|
{
|
||||||
|
|
||||||
#define HC_FAIL() \
|
#define HC_FAIL() \
|
||||||
do {handle_connection_failure(connptr); goto done;} while(0)
|
do {handle_connection_failure(connptr, got_headers); goto done;} \
|
||||||
|
while(0)
|
||||||
|
|
||||||
|
int got_headers = 0;
|
||||||
ssize_t i;
|
ssize_t i;
|
||||||
struct conn_s *connptr;
|
struct conn_s *connptr;
|
||||||
struct request_s *request = NULL;
|
struct request_s *request = NULL;
|
||||||
@ -1619,6 +1621,7 @@ void handle_connection (int fd, union sockaddr_union* addr)
|
|||||||
update_stats (STAT_BADCONN);
|
update_stats (STAT_BADCONN);
|
||||||
HC_FAIL();
|
HC_FAIL();
|
||||||
}
|
}
|
||||||
|
got_headers = 1;
|
||||||
|
|
||||||
if (config->basicauth_list != NULL) {
|
if (config->basicauth_list != NULL) {
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
Loading…
Reference in New Issue
Block a user