X-Git-Url: http://www.privoxy.org/gitweb/?a=blobdiff_plain;f=jcc.c;h=faf224f8c95cf57f163a473066b98e2d4b68d97a;hb=b0801f25d3ed133cb53f2c486694d47f73337687;hp=85be466c1e091cdc9df134ba5af4b0325d8a75c0;hpb=83aaee02fdd7ff7a778f0410a311fdc68f14bcc2;p=privoxy.git diff --git a/jcc.c b/jcc.c index 85be466c..faf224f8 100644 --- a/jcc.c +++ b/jcc.c @@ -1,4 +1,4 @@ -const char jcc_rcs[] = "$Id: jcc.c,v 1.262 2009/07/05 12:02:25 fabiankeil Exp $"; +const char jcc_rcs[] = "$Id: jcc.c,v 1.274 2009/07/19 11:19:50 fabiankeil Exp $"; /********************************************************************* * * File : $Source: /cvsroot/ijbswa/current/jcc.c,v $ @@ -1077,6 +1077,8 @@ void save_connection_destination(jb_socket sfd, { assert(sfd != JB_INVALID_SOCKET); assert(NULL != http->host); + + server_connection->sfd = sfd; server_connection->host = strdup(http->host); if (NULL == server_connection->host) { @@ -1415,6 +1417,16 @@ 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 ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_KEEP_ALIVE) + && (!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) { @@ -1449,12 +1461,16 @@ static jb_err parse_client_request(struct client_state *csp) if (csp->iob->cur[0] != '\0') { csp->flags |= CSP_FLAG_SERVER_SOCKET_TAINTED; - if (!strcmpic(csp->http->gpc, "POST")) + if (strcmpic(csp->http->gpc, "GET") + && strcmpic(csp->http->gpc, "HEAD") + && strcmpic(csp->http->gpc, "TRACE") + && strcmpic(csp->http->gpc, "OPTIONS") + && strcmpic(csp->http->gpc, "DELETE")) { /* 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."); + "There might be a request body. The connection will not be kept alive."); } else { @@ -1632,7 +1648,6 @@ static void chat(struct client_state *csp) #ifdef FEATURE_CONNECTION_KEEP_ALIVE if ((csp->sfd != JB_INVALID_SOCKET) - && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED) && socket_is_still_usable(csp->sfd) && connection_destination_matches(&csp->server_connection, http, fwd)) { @@ -1740,6 +1755,8 @@ static void chat(struct client_state *csp) log_error(LOG_LEVEL_CONNECT, "to %s successful", http->hostport); + csp->server_connection.request_sent = time(NULL); + /* we're finished with the client's header */ freez(hdr); @@ -1859,6 +1876,21 @@ static void chat(struct client_state *csp) */ if (FD_ISSET(csp->sfd, &rfds)) { +#ifdef FEATURE_CONNECTION_KEEP_ALIVE + if (!socket_is_still_usable(csp->cfd)) + { +#ifdef _WIN32 + log_error(LOG_LEVEL_CONNECT, + "The server still wants to talk, but the client may already have hung up on us."); +#else + log_error(LOG_LEVEL_CONNECT, + "The server still wants to talk, but the client hung up on us."); + mark_server_socket_tainted(csp); + return; +#endif /* def _WIN32 */ + } +#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */ + fflush(NULL); len = read_socket(csp->sfd, buf, sizeof(buf) - 1); @@ -2185,6 +2217,8 @@ static void chat(struct client_state *csp) log_error(LOG_LEVEL_FATAL, "Out of memory parsing server header"); } + csp->server_connection.response_received = time(NULL); + if (crunch_response_triggered(csp, crunchers_light)) { /* @@ -2292,6 +2326,8 @@ static void chat(struct client_state *csp) log_error(LOG_LEVEL_CLF, "%s - - [%T] \"%s\" 200 %llu", csp->ip_addr_str, http->ocmd, csp->content_length); + + csp->server_connection.timestamp = time(NULL); } @@ -2318,27 +2354,39 @@ static void serve(struct client_state *csp) #ifdef FEATURE_CONNECTION_KEEP_ALIVE static int monitor_thread_running = 0; int continue_chatting = 0; + unsigned int latency = 0; + do { chat(csp); + if ((csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE) + && !(csp->flags & CSP_FLAG_SERVER_KEEP_ALIVE_TIMEOUT_SET)) + { + log_error(LOG_LEVEL_CONNECT, "The server didn't specify how long " + "the connection will stay open. Assume it's only a second."); + csp->server_connection.keep_alive_timeout = 1; + } + 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); + && socket_is_still_usable(csp->sfd) + && (latency < csp->server_connection.keep_alive_timeout); if (continue_chatting) { + unsigned int client_timeout = (unsigned)csp->server_connection.keep_alive_timeout - latency; log_error(LOG_LEVEL_CONNECT, "Waiting for the next client request. " "Keeping the server socket %d to %s open.", csp->sfd, csp->server_connection.host); if ((csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE) - && data_is_available(csp->cfd, (int)csp->server_connection.keep_alive_timeout) + && data_is_available(csp->cfd, (int)client_timeout) && socket_is_still_usable(csp->cfd)) { log_error(LOG_LEVEL_CONNECT, "Client request arrived in " @@ -2371,11 +2419,10 @@ static void serve(struct client_state *csp) { log_error(LOG_LEVEL_CONNECT, "No additional client request received in time."); - if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING)) + if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING) + && (socket_is_still_usable(csp->sfd))) { - remember_connection(csp->sfd, csp->http, - forward_url(csp, csp->http), - csp->server_connection.keep_alive_timeout); + remember_connection(csp, forward_url(csp, csp->http)); csp->sfd = JB_INVALID_SOCKET; close_socket(csp->cfd); csp->cfd = JB_INVALID_SOCKET;