Rename socket_is_still_usable() to socket_is_still_alive().
[privoxy.git] / jcc.c
diff --git a/jcc.c b/jcc.c
index eac7a76..22e59ec 100644 (file)
--- a/jcc.c
+++ b/jcc.c
@@ -1,4 +1,4 @@
-const char jcc_rcs[] = "$Id: jcc.c,v 1.311 2010/01/03 12:37:14 fabiankeil Exp $";
+const char jcc_rcs[] = "$Id: jcc.c,v 1.315 2010/04/12 16:51:31 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/jcc.c,v $
@@ -6,7 +6,7 @@ const char jcc_rcs[] = "$Id: jcc.c,v 1.311 2010/01/03 12:37:14 fabiankeil Exp $"
  * Purpose     :  Main file.  Contains main() method, main loop, and
  *                the main connection-handling function.
  *
- * Copyright   :  Written by and Copyright (C) 2001-2009 the SourceForge
+ * Copyright   :  Written by and Copyright (C) 2001-2010 the
  *                Privoxy team. http://www.privoxy.org/
  *
  *                Based on the Internet Junkbuster originally written
@@ -711,7 +711,7 @@ static void send_crunch_response(const struct client_state *csp, struct http_res
 
       /*
        * Extract the status code from the actual head
-       * that was send to the client. It is the only
+       * that will be send to the client. It is the only
        * way to get it right for all requests, including
        * the fixed ones for out-of-memory problems.
        *
@@ -840,6 +840,7 @@ static int crunch_response_triggered(struct client_state *csp, const struct crun
    {
       /* Deliver, log and free the interception response. */
       send_crunch_response(csp, rsp);
+      csp->flags |= CSP_FLAG_CRUNCHED;
       return TRUE;
    }
 
@@ -859,6 +860,7 @@ static int crunch_response_triggered(struct client_state *csp, const struct crun
          {
             /* Deliver, log and free the interception response. */
             send_crunch_response(csp, rsp);
+            csp->flags |= CSP_FLAG_CRUNCHED;
 #ifdef FEATURE_STATISTICS
             if (c->flags & CF_COUNT_AS_REJECT)
             {
@@ -1567,11 +1569,16 @@ static jb_err parse_client_request(struct client_state *csp)
  *
  * Function    :  chat
  *
- * Description :  Once a connection to the client has been accepted,
+ * Description :  Once a connection from the client has been accepted,
  *                this function is called (via serve()) to handle the
- *                main business of the communication.  When this
- *                function returns, the caller must close the client
- *                socket handle.
+ *                main business of the communication.  This function
+ *                returns after dealing with a single request. It can
+ *                be called multiple times witht the same client socket
+ *                if the client is keeping the connection alive.
+ *
+ *                The decision whether or not a client connection will
+ *                be kept alive is up to the caller which also must
+ *                close the client socket when done.
  *
  *                FIXME: chat is nearly thousand lines long.
  *                Ridiculous.
@@ -1717,7 +1724,7 @@ static void chat(struct client_state *csp)
 
 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
    if ((csp->server_connection.sfd != JB_INVALID_SOCKET)
-      && socket_is_still_usable(csp->server_connection.sfd)
+      && socket_is_still_alive(csp->server_connection.sfd)
       && connection_destination_matches(&csp->server_connection, http, fwd))
    {
       log_error(LOG_LEVEL_CONNECT,
@@ -2021,7 +2028,7 @@ static void chat(struct client_state *csp)
       if (FD_ISSET(csp->server_connection.sfd, &rfds))
       {
 #ifdef FEATURE_CONNECTION_KEEP_ALIVE
-         if (!socket_is_still_usable(csp->cfd))
+         if (!socket_is_still_alive(csp->cfd))
          {
 #ifdef _WIN32
             log_error(LOG_LEVEL_CONNECT,
@@ -2509,42 +2516,59 @@ static void serve(struct client_state *csp)
 
       chat(csp);
 
+      /*
+       * If the request has been crunched,
+       * the calculated latency is zero.
+       */
       latency = (unsigned)(csp->server_connection.response_received -
          csp->server_connection.request_sent) / 2;
 
       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->server_connection.sfd != JB_INVALID_SOCKET)
-         && socket_is_still_usable(csp->server_connection.sfd);
+         && (((csp->flags & CSP_FLAG_SERVER_CONNECTION_KEEP_ALIVE)
+               && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED))
+            || (csp->flags & CSP_FLAG_CRUNCHED))
+         && (csp->cfd != JB_INVALID_SOCKET);
 
-      if (continue_chatting)
+      if (continue_chatting && !(csp->flags & CSP_FLAG_CRUNCHED))
       {
-         if (!(csp->flags & CSP_FLAG_SERVER_KEEP_ALIVE_TIMEOUT_SET))
+         continue_chatting = (csp->server_connection.sfd != JB_INVALID_SOCKET)
+            && socket_is_still_alive(csp->server_connection.sfd);
+         if (continue_chatting)
          {
-            csp->server_connection.keep_alive_timeout = csp->config->default_server_timeout;
-            log_error(LOG_LEVEL_CONNECT,
-               "The server didn't specify how long the connection will stay open. "
-               "Assumed timeout is: %u.", csp->server_connection.keep_alive_timeout);
+            if (!(csp->flags & CSP_FLAG_SERVER_KEEP_ALIVE_TIMEOUT_SET))
+            {
+               csp->server_connection.keep_alive_timeout = csp->config->default_server_timeout;
+               log_error(LOG_LEVEL_CONNECT,
+                  "The server didn't specify how long the connection will stay open. "
+                  "Assumed timeout is: %u.", csp->server_connection.keep_alive_timeout);
+            }
+            continue_chatting = (latency < csp->server_connection.keep_alive_timeout);
          }
-         continue_chatting = (latency < csp->server_connection.keep_alive_timeout);
       }
 
       if (continue_chatting)
       {
          unsigned int client_timeout;
 
-         client_timeout = (unsigned)csp->server_connection.keep_alive_timeout - latency;
-
-         log_error(LOG_LEVEL_CONNECT,
-            "Waiting for the next client request on socket %d. "
-            "Keeping the server socket %d to %s open.",
-            csp->cfd, csp->server_connection.sfd, csp->server_connection.host);
+         if (csp->server_connection.sfd != JB_INVALID_SOCKET)
+         {
+            client_timeout = (unsigned)csp->server_connection.keep_alive_timeout - latency;
+            log_error(LOG_LEVEL_CONNECT,
+               "Waiting for the next client request on socket %d. "
+               "Keeping the server socket %d to %s open.",
+               csp->cfd, csp->server_connection.sfd, csp->server_connection.host);
+         }
+         else
+         {
+            client_timeout = 1; /* XXX: Use something else here? */
+            log_error(LOG_LEVEL_CONNECT,
+               "Waiting for the next client request on socket %d. "
+               "No server socket to keep open.", csp->cfd);
+         }
          if ((csp->flags & CSP_FLAG_CLIENT_CONNECTION_KEEP_ALIVE)
             && data_is_available(csp->cfd, (int)client_timeout)
-            && socket_is_still_usable(csp->cfd))
+            && socket_is_still_alive(csp->cfd))
          {
             log_error(LOG_LEVEL_CONNECT, "Client request arrived in "
                "time or the client closed the connection on socket %d.",
@@ -2582,7 +2606,7 @@ static void serve(struct client_state *csp)
                 csp->cfd);
 #ifdef FEATURE_CONNECTION_SHARING
             if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING)
-               && (socket_is_still_usable(csp->server_connection.sfd)))
+               && (socket_is_still_alive(csp->server_connection.sfd)))
             {
                time_t time_open = time(NULL) - csp->server_connection.timestamp;