Rebuild for 3.0.17 stable
[privoxy.git] / gateway.c
index d45e3e7..b3dff39 100644 (file)
--- a/gateway.c
+++ b/gateway.c
@@ -1,4 +1,4 @@
-const char gateway_rcs[] = "$Id: gateway.c,v 1.53 2009/05/16 13:27:20 fabiankeil Exp $";
+const char gateway_rcs[] = "$Id: gateway.c,v 1.64 2009/10/03 10:37:49 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/gateway.c,v $
@@ -7,7 +7,7 @@ const char gateway_rcs[] = "$Id: gateway.c,v 1.53 2009/05/16 13:27:20 fabiankeil
  *                using a "forwarder" (i.e. HTTP proxy and/or a SOCKS4
  *                or SOCKS5 proxy).
  *
- * Copyright   :  Written by and Copyright (C) 2001-2009 the SourceForge
+ * Copyright   :  Written by and Copyright (C) 2001-2009 the
  *                Privoxy team. http://www.privoxy.org/
  *
  *                Based on the Internet Junkbuster originally written
@@ -125,13 +125,13 @@ struct socks_reply {
 
 static const char socks_userid[] = "anonymous";
 
-#ifdef FEATURE_CONNECTION_KEEP_ALIVE
+#ifdef FEATURE_CONNECTION_SHARING
 
 #define MAX_REUSABLE_CONNECTIONS 100
 static unsigned int keep_alive_timeout = DEFAULT_KEEP_ALIVE_TIMEOUT;
 
 static struct reusable_connection reusable_connection[MAX_REUSABLE_CONNECTIONS];
-static int mark_connection_unused(jb_socket sfd);
+static int mark_connection_unused(const struct reusable_connection *connection);
 
 /*********************************************************************
  *
@@ -169,29 +169,23 @@ extern void initialize_reusable_connections(void)
  *
  * Function    :  remember_connection
  *
- * Description :  Remembers a connection for reuse later on.
+ * Description :  Remembers a server connection for reuse later on.
  *
  * Parameters  :
- *          1  :  sfd  = Open socket to remember.
- *          2  :  http = The destination for the connection.
- *          3  :  fwd  = The forwarder settings used.
- *          4  :  timeout = Number of seconds after which the
- *                          connection shouldn't be reused.
+ *          1  :  connection = The server connection to remember.
  *
  * Returns     : void
  *
  *********************************************************************/
-void remember_connection(jb_socket sfd,
-                         const struct http_request *http,
-                         const struct forward_spec *fwd,
-                         unsigned int timeout)
+void remember_connection(const struct reusable_connection *connection)
 {
    unsigned int slot = 0;
    int free_slot_found = FALSE;
 
-   assert(sfd != JB_INVALID_SOCKET);
+   assert(NULL != connection);
+   assert(connection->sfd != JB_INVALID_SOCKET);
 
-   if (mark_connection_unused(sfd))
+   if (mark_connection_unused(connection))
    {
       return;
    }
@@ -206,7 +200,7 @@ void remember_connection(jb_socket sfd,
          assert(reusable_connection[slot].in_use == 0);
          log_error(LOG_LEVEL_CONNECT,
             "Remembering socket %d for %s:%d in slot %d.",
-            sfd, http->host, http->port, slot);
+            connection->sfd, connection->host, connection->port, slot);
          free_slot_found = TRUE;
          break;
       }
@@ -216,35 +210,36 @@ void remember_connection(jb_socket sfd,
    {
       log_error(LOG_LEVEL_CONNECT,
         "No free slots found to remembering socket for %s:%d. Last slot %d.",
-        http->host, http->port, slot);
+        connection->host, connection->port, slot);
       privoxy_mutex_unlock(&connection_reuse_mutex);
-      close_socket(sfd);
+      close_socket(connection->sfd);
       return;
    }
 
-   assert(NULL != http->host);
-   reusable_connection[slot].host = strdup(http->host);
+   assert(NULL != connection->host);
+   reusable_connection[slot].host = strdup(connection->host);
    if (NULL == reusable_connection[slot].host)
    {
       log_error(LOG_LEVEL_FATAL, "Out of memory saving socket.");
    }
-   reusable_connection[slot].sfd = sfd;
-   reusable_connection[slot].port = http->port;
+   reusable_connection[slot].sfd = connection->sfd;
+   reusable_connection[slot].port = connection->port;
    reusable_connection[slot].in_use = 0;
-   reusable_connection[slot].timestamp = time(NULL);
-   reusable_connection[slot].keep_alive_timeout = timeout;
+   reusable_connection[slot].timestamp = connection->timestamp;
+   reusable_connection->request_sent = connection->request_sent;
+   reusable_connection->response_received = connection->response_received;
+   reusable_connection[slot].keep_alive_timeout = connection->keep_alive_timeout;
 
-   assert(NULL != fwd);
    assert(reusable_connection[slot].gateway_host == NULL);
    assert(reusable_connection[slot].gateway_port == 0);
    assert(reusable_connection[slot].forwarder_type == SOCKS_NONE);
    assert(reusable_connection[slot].forward_host == NULL);
    assert(reusable_connection[slot].forward_port == 0);
 
-   reusable_connection[slot].forwarder_type = fwd->type;
-   if (NULL != fwd->gateway_host)
+   reusable_connection[slot].forwarder_type = connection->forwarder_type;
+   if (NULL != connection->gateway_host)
    {
-      reusable_connection[slot].gateway_host = strdup(fwd->gateway_host);
+      reusable_connection[slot].gateway_host = strdup(connection->gateway_host);
       if (NULL == reusable_connection[slot].gateway_host)
       {
          log_error(LOG_LEVEL_FATAL, "Out of memory saving gateway_host.");
@@ -254,11 +249,11 @@ void remember_connection(jb_socket sfd,
    {
       reusable_connection[slot].gateway_host = NULL;
    }
-   reusable_connection[slot].gateway_port = fwd->gateway_port;
+   reusable_connection[slot].gateway_port = connection->gateway_port;
 
-   if (NULL != fwd->forward_host)
+   if (NULL != connection->forward_host)
    {
-      reusable_connection[slot].forward_host = strdup(fwd->forward_host);
+      reusable_connection[slot].forward_host = strdup(connection->forward_host);
       if (NULL == reusable_connection[slot].forward_host)
       {
          log_error(LOG_LEVEL_FATAL, "Out of memory saving forward_host.");
@@ -268,12 +263,14 @@ void remember_connection(jb_socket sfd,
    {
       reusable_connection[slot].forward_host = NULL;
    }
-   reusable_connection[slot].forward_port = fwd->forward_port;
+   reusable_connection[slot].forward_port = connection->forward_port;
 
    privoxy_mutex_unlock(&connection_reuse_mutex);
 }
+#endif /* def FEATURE_CONNECTION_SHARING */
 
 
+#ifdef FEATURE_CONNECTION_KEEP_ALIVE
 /*********************************************************************
  *
  * Function    :  mark_connection_closed
@@ -293,6 +290,8 @@ void mark_connection_closed(struct reusable_connection *closed_connection)
    freez(closed_connection->host);
    closed_connection->port = 0;
    closed_connection->timestamp = 0;
+   closed_connection->request_sent = 0;
+   closed_connection->response_received = 0;
    closed_connection->keep_alive_timeout = 0;
    closed_connection->forwarder_type = SOCKS_NONE;
    freez(closed_connection->gateway_host);
@@ -300,8 +299,10 @@ void mark_connection_closed(struct reusable_connection *closed_connection)
    freez(closed_connection->forward_host);
    closed_connection->forward_port = 0;
 }
+#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
 
 
+#ifdef FEATURE_CONNECTION_SHARING
 /*********************************************************************
  *
  * Function    :  forget_connection
@@ -345,8 +346,10 @@ void forget_connection(jb_socket sfd)
 
    privoxy_mutex_unlock(&connection_reuse_mutex);
 }
+#endif /* def FEATURE_CONNECTION_SHARING */
 
 
+#ifdef FEATURE_CONNECTION_KEEP_ALIVE
 /*********************************************************************
  *
  * Function    :  connection_destination_matches
@@ -396,8 +399,10 @@ int connection_destination_matches(const struct reusable_connection *connection,
    return (!strcmpic(connection->host, http->host));
 
 }
+#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
 
 
+#ifdef FEATURE_CONNECTION_SHARING
 /*********************************************************************
  *
  * Function    :  close_unusable_connections
@@ -423,20 +428,23 @@ int close_unusable_connections(void)
          && (JB_INVALID_SOCKET != reusable_connection[slot].sfd))
       {
          time_t time_open = time(NULL) - reusable_connection[slot].timestamp;
+         time_t latency = (reusable_connection[slot].response_received -
+            reusable_connection[slot].request_sent) / 2;
 
-         if (reusable_connection[slot].keep_alive_timeout < time_open)
+         if (reusable_connection[slot].keep_alive_timeout < time_open + latency)
          {
             log_error(LOG_LEVEL_CONNECT,
                "The connection to %s:%d in slot %d timed out. "
-               "Closing socket %d. Timeout is: %d.",
+               "Closing socket %d. Timeout is: %d. Assumed latency: %d.",
                reusable_connection[slot].host,
                reusable_connection[slot].port, slot,
                reusable_connection[slot].sfd,
-               reusable_connection[slot].keep_alive_timeout);
+               reusable_connection[slot].keep_alive_timeout,
+               latency);
             close_socket(reusable_connection[slot].sfd);
             mark_connection_closed(&reusable_connection[slot]);
          }
-         else if (!socket_is_still_usable(reusable_connection[slot].sfd))
+         else if (!socket_is_still_alive(reusable_connection[slot].sfd))
          {
             log_error(LOG_LEVEL_CONNECT,
                "The connection to %s:%d in slot %d is no longer usable. "
@@ -495,8 +503,13 @@ static jb_socket get_reusable_connection(const struct http_request *http,
             reusable_connection[slot].in_use = TRUE;
             sfd = reusable_connection[slot].sfd;
             log_error(LOG_LEVEL_CONNECT,
-               "Found reusable socket %d for %s:%d in slot %d.",
-               sfd, reusable_connection[slot].host, reusable_connection[slot].port, slot);
+               "Found reusable socket %d for %s:%d in slot %d. "
+               "Timestamp made %d seconds ago. Timeout: %d. Latency: %d.",
+               sfd, reusable_connection[slot].host, reusable_connection[slot].port,
+               slot, time(NULL) - reusable_connection[slot].timestamp,
+               reusable_connection[slot].keep_alive_timeout,
+               (int)(reusable_connection[slot].response_received -
+               reusable_connection[slot].request_sent));
             break;
          }
       }
@@ -516,33 +529,33 @@ static jb_socket get_reusable_connection(const struct http_request *http,
  * Description :  Gives a remembered connection free for reuse.
  *
  * Parameters  :
- *          1  :  sfd = The socket belonging to the connection in question.
+ *          1  :  connection = The connection in question.
  *
  * Returns     :  TRUE => Socket found and marked as unused.
  *                FALSE => Socket not found.
  *
  *********************************************************************/
-static int mark_connection_unused(jb_socket sfd)
+static int mark_connection_unused(const struct reusable_connection *connection)
 {
    unsigned int slot = 0;
    int socket_found = FALSE;
 
-   assert(sfd != JB_INVALID_SOCKET);
+   assert(connection->sfd != JB_INVALID_SOCKET);
 
    privoxy_mutex_lock(&connection_reuse_mutex);
 
    for (slot = 0; slot < SZ(reusable_connection); slot++)
    {
-      if (reusable_connection[slot].sfd == sfd)
+      if (reusable_connection[slot].sfd == connection->sfd)
       {
          assert(reusable_connection[slot].in_use);
          socket_found = TRUE;
          log_error(LOG_LEVEL_CONNECT,
             "Marking open socket %d for %s:%d in slot %d as unused.",
-            sfd, reusable_connection[slot].host,
+            connection->sfd, reusable_connection[slot].host,
             reusable_connection[slot].port, slot);
          reusable_connection[slot].in_use = 0;
-         reusable_connection[slot].timestamp = time(NULL);
+         reusable_connection[slot].timestamp = connection->timestamp;
          break;
       }
    }
@@ -571,7 +584,7 @@ void set_keep_alive_timeout(unsigned int timeout)
 {
    keep_alive_timeout = timeout;
 }
-#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
+#endif /* def FEATURE_CONNECTION_SHARING */
 
 
 /*********************************************************************
@@ -597,8 +610,9 @@ jb_socket forwarded_connect(const struct forward_spec * fwd,
    int dest_port;
    jb_socket sfd = JB_INVALID_SOCKET;
 
-#ifdef FEATURE_CONNECTION_KEEP_ALIVE
-   if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING))
+#ifdef FEATURE_CONNECTION_SHARING
+   if ((csp->config->feature_flags & RUNTIME_FEATURE_CONNECTION_SHARING)
+      && !(csp->flags & CSP_FLAG_SERVER_SOCKET_TAINTED))
    {
       sfd = get_reusable_connection(http, fwd);
       if (JB_INVALID_SOCKET != sfd)
@@ -606,7 +620,7 @@ jb_socket forwarded_connect(const struct forward_spec * fwd,
          return sfd;
       }
    }
-#endif /* def FEATURE_CONNECTION_KEEP_ALIVE */
+#endif /* def FEATURE_CONNECTION_SHARING */
 
    /* Figure out if we need to connect to the web server or a HTTP proxy. */
    if (fwd->forward_host)
@@ -681,7 +695,7 @@ static jb_socket socks4_connect(const struct forward_spec * fwd,
                                 int target_port,
                                 struct client_state *csp)
 {
-   unsigned int web_server_addr;
+   unsigned long web_server_addr;
    char buf[BUFFER_SIZE];
    struct socks_op    *c = (struct socks_op    *)buf;
    struct socks_reply *s = (struct socks_reply *)buf;