You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by rp...@apache.org on 2007/12/08 21:10:30 UTC

svn commit: r602542 - in /httpd/httpd/trunk: CHANGES include/ap_mmn.h modules/proxy/mod_proxy.h modules/proxy/mod_proxy_http.c modules/proxy/proxy_util.c server/scoreboard.c

Author: rpluem
Date: Sat Dec  8 12:10:29 2007
New Revision: 602542

URL: http://svn.apache.org/viewvc?rev=602542&view=rev
Log:
* Enable the proxy to keep connections persistent in the HTTPS case.

  Basicly the persistence is created by keeping the conn_rec structure
  created for our backend connection (whether http or https) in the connection
  pool. This required to adjust scoreboard.c in a way that its functions can
  properly deal with a NULL scoreboard handle by ignoring the call or returning
  an error code.

Modified:
    httpd/httpd/trunk/CHANGES
    httpd/httpd/trunk/include/ap_mmn.h
    httpd/httpd/trunk/modules/proxy/mod_proxy.h
    httpd/httpd/trunk/modules/proxy/mod_proxy_http.c
    httpd/httpd/trunk/modules/proxy/proxy_util.c
    httpd/httpd/trunk/server/scoreboard.c

Modified: httpd/httpd/trunk/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/CHANGES?rev=602542&r1=602541&r2=602542&view=diff
==============================================================================
--- httpd/httpd/trunk/CHANGES [utf-8] (original)
+++ httpd/httpd/trunk/CHANGES [utf-8] Sat Dec  8 12:10:29 2007
@@ -2,6 +2,9 @@
 Changes with Apache 2.3.0
 [ When backported to 2.2.x, remove entry from this file ]
 
+  *) mod_proxy: Keep connections to the backend persistent in the HTTPS case.
+     [Ruediger Pluem]
+
   *) rotatelogs: Improve atomicity when using -l and cleaup code.
      PR 44004 [Rainer Jung]
 

Modified: httpd/httpd/trunk/include/ap_mmn.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_mmn.h?rev=602542&r1=602541&r2=602542&view=diff
==============================================================================
--- httpd/httpd/trunk/include/ap_mmn.h (original)
+++ httpd/httpd/trunk/include/ap_mmn.h Sat Dec  8 12:10:29 2007
@@ -143,6 +143,7 @@
  * 20071108.2 (2.3.0-dev)  Add st and keep fields to struct util_ldap_connection_t
  * 20071108.3 (2.3.0-dev)  Add API guarantee for adding connection filters
  *                         with non-NULL request_rec pointer (ap_add_*_filter*)
+ * 20071108.4 (2.3.0-dev)  Add ap_proxy_ssl_connection_cleanup
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
@@ -150,7 +151,7 @@
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20071108
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 3                    /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 4                    /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a

Modified: httpd/httpd/trunk/modules/proxy/mod_proxy.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_proxy.h?rev=602542&r1=602541&r2=602542&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/proxy/mod_proxy.h (original)
+++ httpd/httpd/trunk/modules/proxy/mod_proxy.h Sat Dec  8 12:10:29 2007
@@ -483,6 +483,8 @@
 PROXY_DECLARE(void) ap_proxy_table_unmerge(apr_pool_t *p, apr_table_t *t, char *key);
 /* DEPRECATED (will be replaced with ap_proxy_connect_backend */
 PROXY_DECLARE(int) ap_proxy_connect_to_backend(apr_socket_t **, const char *, apr_sockaddr_t *, const char *, proxy_server_conf *, server_rec *, apr_pool_t *);
+PROXY_DECLARE(apr_status_t) ap_proxy_ssl_connection_cleanup(proxy_conn_rec *conn,
+                                                            request_rec *r);
 PROXY_DECLARE(int) ap_proxy_ssl_enable(conn_rec *c);
 PROXY_DECLARE(int) ap_proxy_ssl_disable(conn_rec *c);
 PROXY_DECLARE(int) ap_proxy_conn_is_https(conn_rec *c);

Modified: httpd/httpd/trunk/modules/proxy/mod_proxy_http.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_proxy_http.c?rev=602542&r1=602541&r2=602542&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/proxy/mod_proxy_http.c (original)
+++ httpd/httpd/trunk/modules/proxy/mod_proxy_http.c Sat Dec  8 12:10:29 2007
@@ -1824,14 +1824,10 @@
 
 
     backend->is_ssl = is_ssl;
-    /*
-     * TODO: Currently we cannot handle persistent SSL backend connections,
-     * because we recreate backend->connection for each request and thus
-     * try to initialize an already existing SSL connection. This does
-     * not work.
-     */
-    if (is_ssl)
-        backend->close = 1;
+
+    if (is_ssl) {
+        ap_proxy_ssl_connection_cleanup(backend, r);
+    }
 
     /* Step One: Determine Who To Connect To */
     if ((status = ap_proxy_determine_connection(p, r, conf, worker, backend,

Modified: httpd/httpd/trunk/modules/proxy/proxy_util.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/proxy_util.c?rev=602542&r1=602541&r2=602542&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/proxy/proxy_util.c (original)
+++ httpd/httpd/trunk/modules/proxy/proxy_util.c Sat Dec  8 12:10:29 2007
@@ -1599,6 +1599,9 @@
     /* determine if the connection need to be closed */
     if (conn->close) {
         apr_pool_t *p = conn->pool;
+        if (conn->connection) {
+            apr_pool_cleanup_kill(conn->pool, conn, connection_cleanup);
+        }
         apr_pool_clear(conn->pool);
         memset(conn, 0, sizeof(proxy_conn_rec));
         conn->pool = p;
@@ -1619,6 +1622,54 @@
     return APR_SUCCESS;
 }
 
+static apr_status_t socket_cleanup(proxy_conn_rec *conn)
+{
+    if (conn->sock) {
+        apr_socket_close(conn->sock);
+        conn->sock = NULL;
+    }
+    if (conn->connection) {
+        apr_pool_cleanup_kill(conn->pool, conn, connection_cleanup);
+        conn->connection = NULL;
+    }
+    return APR_SUCCESS;
+}
+
+PROXY_DECLARE(apr_status_t) ap_proxy_ssl_connection_cleanup(proxy_conn_rec *conn,
+                                                            request_rec *r)
+{
+    apr_bucket_brigade *bb;
+    apr_status_t rv;
+
+    /*
+     * If we have an existing SSL connection it might be possible that the
+     * server sent some SSL message we have not read so far (e.g. a SSL
+     * shutdown message if the server closed the keepalive connection while
+     * the connection was held unused in our pool).
+     * So ensure that if present (=> APR_NONBLOCK_READ) it is read and
+     * processed. We don't expect any data to be in the returned brigade.
+     */
+    if (conn->sock && conn->connection) {
+        bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+        rv = ap_get_brigade(conn->connection->input_filters, bb,
+                            AP_MODE_READBYTES, APR_NONBLOCK_READ,
+                            HUGE_STRING_LEN);
+        if ((rv != APR_SUCCESS) && !APR_STATUS_IS_EAGAIN(rv)) {
+            socket_cleanup(conn);
+        }
+        if (!APR_BRIGADE_EMPTY(bb)) {
+            apr_off_t len;
+
+            rv = apr_brigade_length(bb, 0, &len);
+            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r,
+                          "proxy: SSL cleanup brigade contained %"
+                          APR_OFF_T_FMT " bytes of data.", len);
+        }
+        apr_brigade_destroy(bb);
+    }
+    return APR_SUCCESS;
+}
+
 /* reslist constructor */
 static apr_status_t connection_constructor(void **resource, void *params,
                                            apr_pool_t *pool)
@@ -1895,11 +1946,6 @@
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                  "proxy: %s: has released connection for (%s)",
                  proxy_function, conn->worker->hostname);
-    /* If there is a connection kill it's cleanup */
-    if (conn->connection) {
-        apr_pool_cleanup_kill(conn->connection->pool, conn, connection_cleanup);
-        conn->connection = NULL;
-    }
     connection_cleanup(conn);
 
     return OK;
@@ -1972,14 +2018,7 @@
             conn->hostname = apr_pstrdup(conn->pool, uri->hostname);
             conn->port = uri->port;
         }
-        if (conn->sock) {
-            apr_socket_close(conn->sock);
-            conn->sock = NULL;
-        }
-        if (conn->connection) {
-            apr_pool_cleanup_kill(conn->connection->pool, conn, connection_cleanup);
-            conn->connection = NULL;
-        }
+        socket_cleanup(conn);
         err = apr_sockaddr_info_get(&(conn->addr),
                                     conn->hostname, APR_UNSPEC,
                                     conn->port, 0,
@@ -2131,8 +2170,7 @@
          * relatively small compared to connection lifetime
          */
         if (!(connected = is_socket_connected(conn->sock))) {
-            apr_socket_close(conn->sock);
-            conn->sock = NULL;
+            socket_cleanup(conn);
             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                          "proxy: %s: backend socket is disconnected.",
                          proxy_function);
@@ -2156,6 +2194,7 @@
             backend_addr = backend_addr->next;
             continue;
         }
+        conn->connection = NULL;
 
 #if !defined(TPF) && !defined(BEOS)
         if (worker->recv_buffer_size > 0 &&
@@ -2245,13 +2284,19 @@
     apr_sockaddr_t *backend_addr = conn->addr;
     int rc;
     apr_interval_time_t current_timeout;
+    apr_bucket_alloc_t *bucket_alloc;
 
+    if (conn->connection) {
+        return OK;
+    }
+
+    bucket_alloc = apr_bucket_alloc_create(conn->pool);
     /*
      * The socket is now open, create a new backend server connection
      */
-    conn->connection = ap_run_create_connection(c->pool, s, conn->sock,
-                                                c->id, c->sbh,
-                                                c->bucket_alloc);
+    conn->connection = ap_run_create_connection(conn->pool, s, conn->sock,
+                                                0, NULL,
+                                                bucket_alloc);
 
     if (!conn->connection) {
         /*
@@ -2263,15 +2308,14 @@
                      "new connection to %pI (%s)", proxy_function,
                      backend_addr, conn->hostname);
         /* XXX: Will be closed when proxy_conn is closed */
-        apr_socket_close(conn->sock);
-        conn->sock = NULL;
+        socket_cleanup(conn);
         return HTTP_INTERNAL_SERVER_ERROR;
     }
     /*
      * register the connection cleanup to client connection
      * so that the connection can be closed or reused
      */
-    apr_pool_cleanup_register(c->pool, (void *)conn,
+    apr_pool_cleanup_register(conn->pool, (void *)conn,
                               connection_cleanup,
                               apr_pool_cleanup_null);
 

Modified: httpd/httpd/trunk/server/scoreboard.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/scoreboard.c?rev=602542&r1=602541&r2=602542&view=diff
==============================================================================
--- httpd/httpd/trunk/server/scoreboard.c (original)
+++ httpd/httpd/trunk/server/scoreboard.c Sat Dec  8 12:10:29 2007
@@ -352,6 +352,9 @@
 {
     worker_score *ws;
 
+    if (!sb)
+        return;
+
     ws = &ap_scoreboard_image->servers[sb->child_num][sb->thread_num];
 
 #ifdef HAVE_TIMES
@@ -479,6 +482,9 @@
 AP_DECLARE(int) ap_update_child_status(ap_sb_handle_t *sbh, int status,
                                       request_rec *r)
 {
+    if (!sbh)
+        return -1;
+
     return ap_update_child_status_from_indexes(sbh->child_num, sbh->thread_num,
                                                status, r);
 }
@@ -487,6 +493,9 @@
 {
     worker_score *ws;
 
+    if (!sbh)
+        return;
+
     if (sbh->child_num < 0) {
         return;
     }
@@ -512,6 +521,9 @@
 
 AP_DECLARE(worker_score *) ap_get_scoreboard_worker(ap_sb_handle_t *sbh)
 {
+    if (!sbh)
+        return NULL;
+
     return ap_get_scoreboard_worker_from_indexes(sbh->child_num,
                                                  sbh->thread_num);
 }