X-Git-Url: http://www.privoxy.org/gitweb/?a=blobdiff_plain;f=jcc.c;h=ed17ba8278cb71ef105633a6ee1e6ee1f51c8c81;hb=63a8b3ec23c0bad6b6d7f6251abaa7ea6d030e1f;hp=cc37def13756410fa57ad0d69f4c4b2780a3fa49;hpb=e693e665a5012fba131bf207821e31164f27d72b;p=privoxy.git diff --git a/jcc.c b/jcc.c index cc37def1..ed17ba82 100644 --- a/jcc.c +++ b/jcc.c @@ -1,4 +1,4 @@ -const char jcc_rcs[] = "$Id: jcc.c,v 1.254 2009/06/11 11:44:25 fabiankeil Exp $"; +const char jcc_rcs[] = "$Id: jcc.c,v 1.264 2009/07/07 16:42:26 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/jcc.c,v $ @@ -236,15 +236,6 @@ static const char MISSING_DESTINATION_RESPONSE[] = "Connection: close\r\n\r\n" "Bad request. Privoxy was unable to extract the destination.\r\n"; -/* XXX: should be a template */ -static const char NO_SERVER_DATA_RESPONSE[] = - "HTTP/1.0 502 Server or forwarder response empty\r\n" - "Proxy-Agent: Privoxy " VERSION "\r\n" - "Content-Type: text/plain\r\n" - "Connection: close\r\n\r\n" - "Empty server or forwarder response.\r\n" - "The connection has been closed but Privoxy didn't receive any data.\r\n"; - /* XXX: should be a template */ static const char INVALID_SERVER_HEADERS_RESPONSE[] = "HTTP/1.0 502 Server or forwarder response invalid\r\n" @@ -666,6 +657,9 @@ static const char *crunch_reason(const struct http_response *rsp) case RSP_REASON_CONNECTION_TIMEOUT: reason = "Connection timeout"; break; + case RSP_REASON_NO_SERVER_DATA: + reason = "No server data received"; + break; default: reason = "No reason recorded"; break; @@ -1147,8 +1141,9 @@ static void mark_server_socket_tainted(struct client_state *csp) { if ((csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE)) { - log_error(LOG_LEVEL_CONNECT, "Unsetting keep-alive flag."); - csp->flags &= ~CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE; + log_error(LOG_LEVEL_CONNECT, + "Marking the server socket %d tainted.", csp->sfd); + csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED; } } @@ -1420,6 +1415,15 @@ static jb_err parse_client_request(struct client_state *csp) struct http_request *http = csp->http; jb_err err; +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + if ((!strcmpic(csp->http->ver, "HTTP/1.1")) + && (csp->http->ssl == 0)) + { + /* Assume persistence until further notice */ + csp->flags |= CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE; + } +#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ + err = sed(csp, FILTER_CLIENT_HEADERS); if (JB_ERR_OK != err) { @@ -1448,6 +1452,39 @@ static jb_err parse_client_request(struct client_state *csp) return JB_ERR_PARSE; } +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + if ((csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE)) + { + if (csp->iob->cur[0] != '\0') + { + csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED; + if (!strcmpic(csp->http->gpc, "POST")) + { + /* XXX: this is an incomplete hack */ + csp->flags &= ~CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ; + log_error(LOG_LEVEL_CONNECT, + "POST request detected. The connection will not be kept alive."); + } + else + { + /* XXX: and so is this */ + csp->flags |= CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ; + log_error(LOG_LEVEL_CONNECT, + "Possible pipeline attempt detected. The connection will not " + "be kept alive and we will only serve the first request."); + /* Nuke the pipelined requests from orbit, just to be sure. */ + csp->iob->buf[0] = '\0'; + csp->iob->eod = csp->iob->cur = csp->iob->buf; + } + } + else + { + csp->flags |= CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ; + log_error(LOG_LEVEL_CONNECT, "Complete client request received."); + } + } +#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ + return JB_ERR_OK; } @@ -1733,7 +1770,17 @@ static void chat(struct client_state *csp) #else FD_ZERO(&rfds); #endif - FD_SET(csp->cfd, &rfds); +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + if ((csp->flags & CSP_FLAG_CLIENT_REQUEST_COMPLETELY_READ)) + { + maxfd = csp->sfd; + } + else +#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ + { + FD_SET(csp->cfd, &rfds); + } + FD_SET(csp->sfd, &rfds); #ifdef FEATURE_CONNECTION_KEEP_ALIVE @@ -2097,9 +2144,10 @@ static void chat(struct client_state *csp) /* Did we actually get anything? */ if (NULL == csp->headers->first) { - log_error(LOG_LEVEL_ERROR, "Empty server or forwarder response."); + log_error(LOG_LEVEL_ERROR, + "Empty server or forwarder response received on socket %d.", csp->sfd); log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 502 0", csp->ip_addr_str, http->cmd); - write_socket(csp->cfd, NO_SERVER_DATA_RESPONSE, strlen(NO_SERVER_DATA_RESPONSE)); + send_crunch_response(csp, error_response(csp, "no-server-data")); free_http_request(http); mark_server_socket_tainted(csp); return; @@ -2285,6 +2333,7 @@ static void serve(struct client_state *csp) continue_chatting = (csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE) && (csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE) + && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED) && (csp->cfd != JB_INVALID_SOCKET) && (csp->sfd != JB_INVALID_SOCKET) && socket_is_still_usable(csp->sfd); @@ -3074,7 +3123,7 @@ static jb_socket bind_port_helper(struct configuration_spec * config) (NULL != config->haddr) ? config->haddr : "INADDR_ANY", config->hport); default : - log_error(LOG_LEVEL_FATAL, "can't bind to %s:%d: because %E", + log_error(LOG_LEVEL_FATAL, "can't bind to %s:%d: %E", (NULL != config->haddr) ? config->haddr : "INADDR_ANY", config->hport); }