107 lines
4.3 KiB
Diff
107 lines
4.3 KiB
Diff
|
--- include/httpd.h.orig
|
||
|
+++ include/httpd.h
|
||
|
@@ -1175,12 +1175,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... */
|
||
|
--- modules/ssl/ssl_engine_io.c.orig
|
||
|
+++ modules/ssl/ssl_engine_io.c
|
||
|
@@ -775,6 +775,18 @@ static apr_status_t ssl_filter_write(ap_
|
||
|
*/
|
||
|
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.");
|
||
|
@@ -1902,8 +1914,10 @@ void ssl_io_filter_init(conn_rec *c, req
|
||
|
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);
|
||
|
|
||
|
--- server/mpm/event/event.c.orig
|
||
|
+++ server/mpm/event/event.c
|
||
|
@@ -790,7 +790,10 @@ static int start_lingering_close_common(
|
||
|
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)) {
|
||
|
@@ -938,6 +941,7 @@ static void process_socket(apr_thread_t
|
||
|
*/
|
||
|
cs->pub.state = CONN_STATE_READ_REQUEST_LINE;
|
||
|
|
||
|
+ cs->pub.sense = CONN_SENSE_DEFAULT;
|
||
|
}
|
||
|
else {
|
||
|
c = cs->c;
|
||
|
@@ -946,9 +950,11 @@ static void process_socket(apr_thread_t
|
||
|
}
|
||
|
|
||
|
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);
|
||
|
@@ -994,7 +1000,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;
|