summaryrefslogtreecommitdiff
path: root/modules/ssl/mod_ssl.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/ssl/mod_ssl.c')
-rw-r--r--modules/ssl/mod_ssl.c76
1 files changed, 63 insertions, 13 deletions
diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c
index d1f6fbbc1f..b06c7beabe 100644
--- a/modules/ssl/mod_ssl.c
+++ b/modules/ssl/mod_ssl.c
@@ -30,6 +30,7 @@
#include "util_md5.h"
#include "util_mutex.h"
#include "ap_provider.h"
+#include "ap_mpm.h"
#include "http_config.h"
#include "mod_proxy.h" /* for proxy_hook_section_post_config() */
@@ -689,31 +690,80 @@ static int ssl_hook_process_connection(conn_rec* c)
{
SSLConnRec *sslconn = myConnConfig(c);
+ int status = DECLINED;
+
if (sslconn && !sslconn->disabled) {
/* On an active SSL connection, let the input filters initialize
* themselves which triggers the handshake, which again triggers
* all kinds of useful things such as SNI and ALPN.
*/
apr_bucket_brigade* temp;
- apr_status_t rv;
+
+ int again_mpm = 0;
temp = apr_brigade_create(c->pool, c->bucket_alloc);
- rv = ap_get_brigade(c->input_filters, temp,
- AP_MODE_INIT, APR_BLOCK_READ, 0);
- apr_brigade_destroy(temp);
- if (APR_SUCCESS != APR_SUCCESS) {
- if (c->cs) {
- c->cs->state = CONN_STATE_LINGER;
+ if (ap_mpm_query(AP_MPMQ_CAN_AGAIN, &again_mpm) != APR_SUCCESS) {
+ again_mpm = 0;
+ }
+
+ if (again_mpm) {
+
+ /* Take advantage of an async MPM. If we see an EAGAIN,
+ * loop round and don't block.
+ */
+ conn_state_t *cs = c->cs;
+
+ apr_status_t rv;
+
+ rv = ap_get_brigade(c->input_filters, temp,
+ AP_MODE_INIT, APR_NONBLOCK_READ, 0);
+
+ if (rv == APR_SUCCESS) {
+ /* great news, lets continue */
+
+ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(10370)
+ "SSL handshake completed, continuing");
+
+ status = DECLINED;
}
- ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(10373)
- "SSL handshake was not completed, "
- "closing connection");
- return OK;
+ else if (rv == APR_EAGAIN) {
+ /* we've been asked to come around again, don't block */
+
+ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(10371)
+ "SSL handshake in progress, continuing");
+
+ status = AGAIN;
+ }
+ else if (rv == AP_FILTER_ERROR) {
+ /* handshake error, but mod_ssl handled it */
+
+ ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, APLOGNO(10372)
+ "SSL handshake failed, returning error response");
+
+ status = DECLINED;
+ }
+ else {
+ /* we failed, give up */
+
+ cs->state = CONN_STATE_LINGER;
+
+ ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, c, APLOGNO(10373)
+ "SSL handshake was not completed, "
+ "closing connection");
+
+ status = OK;
+ }
+ }
+ else {
+ ap_get_brigade(c->input_filters, temp,
+ AP_MODE_INIT, APR_BLOCK_READ, 0);
}
+
+ apr_brigade_destroy(temp);
}
-
- return DECLINED;
+
+ return status;
}
/*