]> granicus.if.org Git - apache/commitdiff
core, mod_ssl: Lift the restriction that prevents mod_ssl taking
authorGraham Leggett <minfrin@apache.org>
Mon, 22 Apr 2013 19:48:25 +0000 (19:48 +0000)
committerGraham Leggett <minfrin@apache.org>
Mon, 22 Apr 2013 19:48:25 +0000 (19:48 +0000)
full advantage of the event MPM. Enable the ability for a module
to reverse the sense of a poll event from a read to a write or vice
versa.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1470679 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
include/ap_mmn.h
include/httpd.h
modules/ssl/ssl_engine_io.c
server/mpm/event/event.c
server/mpm/eventopt/eventopt.c

diff --git a/CHANGES b/CHANGES
index 290064da86ed50663c70f48ad01518a9b12a5cbc..8acdf1869979b4e4af06d6fbde6183b4ceb373b7 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,11 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.5.0
 
+  *) core, mod_ssl: Lift the restriction that prevents mod_ssl taking
+     full advantage of the event MPM. Enable the ability for a module
+     to reverse the sense of a poll event from a read to a write or vice
+     versa. [Graham Leggett]
+
   *) core: Add workaround for gcc bug on sparc/64bit. PR 52900.
      [Stefan Fritsch]
 
index 2db39c108b685c12f249c09a2473d80108d55333..56203997d68f9bb3571931fb7db7b02137839280 100644 (file)
  *                         ap_proxy_pass_brigade()
  * 20121222.7 (2.5.0-dev)  Add ap_remove_input|output_filter_byhandle()
  * 20121222.8 (2.5.0-dev)  Add dav_join_error()
+ * 20121222.9 (2.5.0-dev)  Add conn_sense_e
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503235UL /* "AP25" */
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20121222
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 8                   /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 9                   /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
index 6ab82b0d3b2eefdf43c0a638bd39f5624cfbc7ef..2b8f08ab559bd5efce4fa4ba1b25ca6d0ab3dce8 100644 (file)
@@ -1177,12 +1177,20 @@ typedef enum  {
     CONN_STATE_LINGER_SHORT     /* MPM has started lingering close with short timeout */
 } conn_state_e;
 
+typedef enum  {
+    CONN_SENSE_DEFAULT,
+    CONN_SENSE_WANT_READ,       /* next event must be read */
+    CONN_SENSE_WANT_WRITE       /* next event must be write */
+} conn_sense_e;
+
 /**
  * @brief A structure to contain connection state information
  */
 struct conn_state_t {
     /** Current state of the connection */
     conn_state_e state;
+    /** Whether to read instead of write, or write instead of read */
+    conn_sense_e sense;
 };
 
 /* Per-vhost config... */
index a4e76ca31b41d05878c55d3b3be58e25e6fe7fb9..006c84d4f6df8020d4ed0445cca72e24e0809d68 100644 (file)
@@ -777,6 +777,18 @@ static apr_status_t ssl_filter_write(ap_filter_t *f,
              */
             outctx->rc = APR_EAGAIN;
         }
+        else if (ssl_err == SSL_ERROR_WANT_READ) {
+            /*
+             * If OpenSSL wants to read during write, and we were
+             * nonblocking, set the sense explicitly to read and
+             * report as an EAGAIN.
+             *
+             * (This is usually the case when the client forces an SSL
+             * renegotiation which is handled implicitly by OpenSSL.)
+             */
+            outctx->c->cs->sense = CONN_SENSE_WANT_READ;
+            outctx->rc = APR_EAGAIN;
+        }
         else if (ssl_err == SSL_ERROR_SYSCALL) {
             ap_log_cerror(APLOG_MARK, APLOG_INFO, outctx->rc, c, APLOGNO(01993)
                           "SSL output filter write failed.");
@@ -1927,8 +1939,10 @@ void ssl_io_filter_init(conn_rec *c, request_rec *r, SSL *ssl)
     filter_ctx->pbioWrite       = BIO_new(&bio_filter_out_method);
     filter_ctx->pbioWrite->ptr  = (void *)bio_filter_out_ctx_new(filter_ctx, c);
 
-    /* We insert a clogging input filter. Let the core know. */
-    c->clogging_input_filters = 1;
+    /* write is non blocking for the benefit of async mpm */
+    if (c->cs) {
+        BIO_set_nbio(filter_ctx->pbioWrite, 1);
+    }
 
     ssl_io_input_add_filter(filter_ctx, c, r, ssl);
 
index 6526e8ae4d9edd7a449bfe0f604ae27562e63422..8b57b735e590abfcf85f60f60c1bc52631e1c002 100644 (file)
@@ -810,7 +810,10 @@ static int start_lingering_close_common(event_conn_state_t *cs)
     apr_atomic_inc32(&lingering_count);
     apr_thread_mutex_lock(timeout_mutex);
     TO_QUEUE_APPEND(*q, cs);
-    cs->pfd.reqevents = APR_POLLIN | APR_POLLHUP | APR_POLLERR;
+    cs->pfd.reqevents = (
+            cs->pub.sense == CONN_SENSE_WANT_WRITE ? APR_POLLOUT :
+                    APR_POLLIN) | APR_POLLHUP | APR_POLLERR;
+    cs->pub.sense = CONN_SENSE_DEFAULT;
     rv = apr_pollset_add(event_pollset, &cs->pfd);
     apr_thread_mutex_unlock(timeout_mutex);
     if (rv != APR_SUCCESS && !APR_STATUS_IS_EEXIST(rv)) {
@@ -958,6 +961,7 @@ static void process_socket(apr_thread_t *thd, apr_pool_t * p, apr_socket_t * soc
          */
         cs->pub.state = CONN_STATE_READ_REQUEST_LINE;
 
+        cs->pub.sense = CONN_SENSE_DEFAULT;
     }
     else {
         c = cs->c;
@@ -966,9 +970,11 @@ static void process_socket(apr_thread_t *thd, apr_pool_t * p, apr_socket_t * soc
     }
 
     if (c->clogging_input_filters && !c->aborted) {
-        /* Since we have an input filter which 'cloggs' the input stream,
-         * like mod_ssl, lets just do the normal read from input filters,
-         * like the Worker MPM does.
+        /* Since we have an input filter which 'clogs' the input stream,
+         * like mod_ssl used to, lets just do the normal read from input
+         * filters, like the Worker MPM does. Filters that need to write
+         * where they would otherwise read, or read where they would
+         * otherwise write, should set the sense appropriately.
          */
         apr_atomic_inc32(&clogged_count);
         ap_run_process_connection(c);
@@ -1014,7 +1020,10 @@ read_request:
             cs->expiration_time = ap_server_conf->timeout + apr_time_now();
             apr_thread_mutex_lock(timeout_mutex);
             TO_QUEUE_APPEND(write_completion_q, cs);
-            cs->pfd.reqevents = APR_POLLOUT | APR_POLLHUP | APR_POLLERR;
+            cs->pfd.reqevents = (
+                    cs->pub.sense == CONN_SENSE_WANT_READ ? APR_POLLIN :
+                            APR_POLLOUT) | APR_POLLHUP | APR_POLLERR;
+            cs->pub.sense = CONN_SENSE_DEFAULT;
             rc = apr_pollset_add(event_pollset, &cs->pfd);
             apr_thread_mutex_unlock(timeout_mutex);
             return;
index cf42fd9121c20a87cb2217dc83854656901f036e..180f15229bb6132e1cc21feb4bd4a92c72057fd4 100644 (file)
@@ -875,7 +875,10 @@ static int start_lingering_close(event_conn_state_t *cs, ap_equeue_t *eq)
         cs->pub.state = CONN_STATE_LINGER_NORMAL;
     }
     apr_atomic_inc32(&lingering_count);
-    cs->pfd.reqevents = APR_POLLIN | APR_POLLHUP | APR_POLLERR;
+    cs->pfd.reqevents = (
+            cs->pub.sense == CONN_SENSE_WANT_WRITE ? APR_POLLOUT :
+                    APR_POLLIN) | APR_POLLHUP | APR_POLLERR;
+    cs->pub.sense = CONN_SENSE_DEFAULT;
     v->cs = cs;
     if (eq != NULL) {
         ap_equeue_writer_onward(eq);
@@ -1019,6 +1022,7 @@ static void process_socket(apr_thread_t *thd, apr_pool_t * p, apr_socket_t * soc
          */
         cs->pub.state = CONN_STATE_READ_REQUEST_LINE;
 
+        cs->pub.sense = CONN_SENSE_DEFAULT;
     }
     else {
         c = cs->c;
@@ -1027,9 +1031,11 @@ static void process_socket(apr_thread_t *thd, apr_pool_t * p, apr_socket_t * soc
     }
 
     if (c->clogging_input_filters && !c->aborted) {
-        /* Since we have an input filter which 'cloggs' the input stream,
-         * like mod_ssl, lets just do the normal read from input filters,
-         * like the Worker MPM does.
+        /* Since we have an input filter which 'clogs' the input stream,
+         * like mod_ssl used to, lets just do the normal read from input
+         * filters, like the Worker MPM does. Filters that need to write
+         * where they would otherwise read, or read where they would
+         * otherwise write, should set the sense appropriately.
          */
         apr_atomic_inc32(&clogged_count);
         ap_run_process_connection(c);
@@ -1075,7 +1081,10 @@ read_request:
             pollset_op_t *v = ap_equeue_writer_value(eq);
 
             cs->expiration_time = ap_server_conf->timeout + apr_time_now();
-            cs->pfd.reqevents = APR_POLLOUT | APR_POLLHUP | APR_POLLERR;
+            cs->pfd.reqevents = (
+                    cs->pub.sense == CONN_SENSE_WANT_READ ? APR_POLLIN :
+                            APR_POLLOUT) | APR_POLLHUP | APR_POLLERR;
+            cs->pub.sense = CONN_SENSE_DEFAULT;
 
             v->cs = cs;
             v->timeout_type = TIMEOUT_WRITE_COMPLETION;