Loading modules/http2/h2_conn.c +38 −23 Original line number Diff line number Diff line Loading @@ -39,7 +39,7 @@ static struct h2_workers *workers; static apr_status_t h2_session_process(h2_session *session); static apr_status_t h2_conn_loop(h2_session *session); static h2_mpm_type_t mpm_type = H2_MPM_UNKNOWN; static module *mpm_module; Loading Loading @@ -156,7 +156,7 @@ apr_status_t h2_conn_rprocess(request_rec *r) return APR_EGENERAL; } return h2_session_process(session); return h2_conn_loop(session); } apr_status_t h2_conn_main(conn_rec *c) Loading @@ -177,7 +177,7 @@ apr_status_t h2_conn_main(conn_rec *c) return APR_EGENERAL; } status = h2_session_process(session); status = h2_conn_loop(session); /* Make sure this connection gets closed properly. */ c->keepalive = AP_CONN_CLOSE; Loading @@ -188,7 +188,7 @@ apr_status_t h2_conn_main(conn_rec *c) return status; } apr_status_t h2_session_process(h2_session *session) static apr_status_t h2_conn_loop(h2_session *session) { apr_status_t status = APR_SUCCESS; int rv = 0; Loading Loading @@ -283,10 +283,19 @@ apr_status_t h2_session_process(h2_session *session) * submit our settings and need the ACK. */ got_streams = !h2_stream_set_is_empty(session->streams); status = h2_session_read(session, (!got_streams || session->frames_received <= 1)? APR_BLOCK_READ : APR_NONBLOCK_READ); if (!got_streams || session->frames_received <= 1) { if (session->c->cs) { session->c->cs->state = CONN_STATE_WRITE_COMPLETION; } status = h2_session_read(session, APR_BLOCK_READ); } else { if (session->c->cs) { session->c->cs->state = CONN_STATE_HANDLER; } status = h2_session_read(session, APR_NONBLOCK_READ); } switch (status) { case APR_SUCCESS: /* successful read, reset our idle timers */ have_read = 1; Loading @@ -294,21 +303,28 @@ apr_status_t h2_session_process(h2_session *session) break; case APR_EAGAIN: /* non-blocking read, nothing there */ break; case APR_EBADF: /* connection is not there any more */ case APR_EOF: case APR_ECONNABORTED: case APR_ECONNRESET: case APR_TIMEUP: /* blocked read, timed out */ default: if (APR_STATUS_IS_ETIMEDOUT(status) || APR_STATUS_IS_ECONNABORTED(status) || APR_STATUS_IS_ECONNRESET(status) || APR_STATUS_IS_EOF(status) || APR_STATUS_IS_EBADF(status)) { /* common status for a client that has left */ ap_log_cerror( APLOG_MARK, APLOG_DEBUG, status, session->c, "h2_session(%ld): reading", "h2_session(%ld): terminating", session->id); h2_session_abort(session, status, 0); break; default: /* Stolen from mod_reqtimeout to speed up lingering when * a read timeout happened. */ apr_table_setn(session->c->notes, "short-lingering-close", "1"); } else { /* uncommon status, log on INFO so that we see this */ ap_log_cerror( APLOG_MARK, APLOG_INFO, status, session->c, APLOGNO(02950) "h2_session(%ld): error reading, terminating", session->id); } h2_session_abort(session, status, 0); break; } Loading Loading @@ -471,7 +487,6 @@ apr_status_t h2_conn_process(conn_rec *c, apr_socket_t *socket) { AP_DEBUG_ASSERT(c); c->clogging_input_filters = 1; ap_process_connection(c, socket); return APR_SUCCESS; Loading modules/http2/h2_h2.c +2 −1 Original line number Diff line number Diff line Loading @@ -94,6 +94,7 @@ int h2_tls_disable(conn_rec *c) return 0; } /******************************************************************************* * Register various hooks */ Loading @@ -119,7 +120,7 @@ void h2_h2_register_hooks(void) ap_hook_post_read_request(h2_h2_post_read_req, NULL, NULL, APR_HOOK_REALLY_FIRST); } int h2_h2_remove_timeout(conn_rec* c) static int h2_h2_remove_timeout(conn_rec* c) { h2_ctx *ctx = h2_ctx_get(c); Loading modules/http2/h2_io.c +23 −3 Original line number Diff line number Diff line Loading @@ -80,6 +80,10 @@ apr_status_t h2_io_in_read(h2_io *io, apr_bucket_brigade *bb, apr_bucket *last; apr_status_t status; if (io->rst_error) { return APR_ECONNABORTED; } if (!io->bbin || APR_BRIGADE_EMPTY(io->bbin)) { return io->eos_in? APR_EOF : APR_EAGAIN; } Loading @@ -102,6 +106,10 @@ apr_status_t h2_io_in_read(h2_io *io, apr_bucket_brigade *bb, apr_status_t h2_io_in_write(h2_io *io, apr_bucket_brigade *bb) { if (io->rst_error) { return APR_ECONNABORTED; } if (io->eos_in) { return APR_EOF; } Loading @@ -118,6 +126,10 @@ apr_status_t h2_io_in_write(h2_io *io, apr_bucket_brigade *bb) apr_status_t h2_io_in_close(h2_io *io) { if (io->rst_error) { return APR_ECONNABORTED; } if (io->bbin) { APR_BRIGADE_INSERT_TAIL(io->bbin, apr_bucket_eos_create(io->bbin->bucket_alloc)); Loading @@ -132,6 +144,10 @@ apr_status_t h2_io_out_readx(h2_io *io, { apr_status_t status; if (io->rst_error) { return APR_ECONNABORTED; } if (io->eos_out) { *plen = 0; *peos = 1; Loading @@ -158,6 +174,10 @@ apr_status_t h2_io_out_write(h2_io *io, apr_bucket_brigade *bb, apr_status_t status; int start_allowed; if (io->rst_error) { return APR_ECONNABORTED; } if (io->eos_out) { apr_off_t len; /* We have already delivered an EOS bucket to a reader, no Loading Loading @@ -188,9 +208,6 @@ apr_status_t h2_io_out_write(h2_io *io, apr_bucket_brigade *bb, */ start_allowed = *pfile_handles_allowed; if (io->rst_error) { return APR_ECONNABORTED; } status = h2_util_move(io->bbout, bb, maxlen, pfile_handles_allowed, "h2_io_out_write"); /* track # file buckets moved into our pool */ Loading @@ -203,6 +220,9 @@ apr_status_t h2_io_out_write(h2_io *io, apr_bucket_brigade *bb, apr_status_t h2_io_out_close(h2_io *io) { if (io->rst_error) { return APR_ECONNABORTED; } if (!io->eos_out && !h2_util_has_eos(io->bbout, 0)) { APR_BRIGADE_INSERT_TAIL(io->bbout, apr_bucket_eos_create(io->bbout->bucket_alloc)); Loading modules/http2/h2_mplx.c +20 −13 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include "h2_private.h" #include "h2_config.h" #include "h2_conn.h" #include "h2_h2.h" #include "h2_io.h" #include "h2_io_set.h" #include "h2_response.h" Loading Loading @@ -288,18 +289,21 @@ apr_status_t h2_mplx_cleanup_stream(h2_mplx *m, h2_stream *stream) status = apr_thread_mutex_lock(m->lock); if (APR_SUCCESS == status) { h2_io *io = h2_io_set_get(m->stream_ios, stream->id); if (!io || io->task_done) { /* No more io or task already done -> cleanup immediately */ stream_destroy(m, stream, io); } else { if (io) { /* Remove io from ready set, we will never submit it */ h2_io_set_remove(m->ready_ios, io); if (stream->rst_error) { /* Forward error code to fail any further attempt to * write to io */ h2_io_rst(io, stream->rst_error); } /* Remove io from ready set (if there), since we will never submit it */ h2_io_set_remove(m->ready_ios, io); } if (!io || io->task_done) { /* No more io or task already done -> cleanup immediately */ stream_destroy(m, stream, io); } else { /* Add stream to closed set for cleanup when task is done */ h2_stream_set_add(m->closed, stream); } Loading Loading @@ -515,18 +519,21 @@ h2_stream *h2_mplx_next_submit(h2_mplx *m, h2_stream_set *streams) h2_stream_set_response(stream, io->response, io->bbout); } if (io->output_drained) { apr_thread_cond_signal(io->output_drained); } } else { ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, m->c, APLOGNO(02953) "h2_mplx(%ld): stream for response %d not found", m->id, io->id); /* We have the io ready, but the stream has gone away, maybe * reset by the client. Should no longer happen since such * streams should clear io's from the ready queue. */ ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, m->c, APLOGNO(02953) "h2_mplx(%ld): stream for response %d closed, " "resetting io to close request processing", m->id, io->id); h2_io_rst(io, NGHTTP2_ERR_STREAM_CLOSED); } if (io->output_drained) { apr_thread_cond_signal(io->output_drained); } } apr_thread_mutex_unlock(m->lock); Loading modules/http2/h2_session.c +8 −31 Original line number Diff line number Diff line Loading @@ -168,7 +168,7 @@ static int on_data_chunk_recv_cb(nghttp2_session *ngh2, uint8_t flags, session->id, stream_id, (int)len); if (status != APR_SUCCESS) { rv = nghttp2_submit_rst_stream(ngh2, NGHTTP2_FLAG_NONE, stream_id, NGHTTP2_INTERNAL_ERROR); H2_STREAM_RST(stream, NGHTTP2_INTERNAL_ERROR)); if (nghttp2_is_fatal(rv)) { return NGHTTP2_ERR_CALLBACK_FAILURE; } Loading Loading @@ -931,17 +931,18 @@ apr_status_t h2_session_write(h2_session *session, apr_interval_time_t timeout) } /* If we have responses ready, submit them now. */ while ((stream = h2_mplx_next_submit(session->mplx, session->streams)) != NULL) { while (!session->aborted && (stream = h2_mplx_next_submit(session->mplx, session->streams)) != NULL) { status = h2_session_handle_response(session, stream); flush_output = 1; } if (h2_session_resume_streams_with_data(session) > 0) { if (!session->aborted && h2_session_resume_streams_with_data(session) > 0) { flush_output = 1; } if (!flush_output && timeout > 0 && !h2_session_want_write(session)) { if (!session->aborted && !flush_output && timeout > 0 && !h2_session_want_write(session)) { status = h2_mplx_out_trywait(session->mplx, timeout, session->iowait); if (status != APR_TIMEUP Loading Loading @@ -1151,13 +1152,10 @@ apr_status_t h2_session_handle_response(h2_session *session, h2_stream *stream) if (stream->response && stream->response->ngheader) { rv = submit_response(session, stream->response); } else if (stream->rst_error) { rv = nghttp2_submit_rst_stream(session->ngh2, NGHTTP2_FLAG_NONE, stream->id, stream->rst_error); } else { rv = nghttp2_submit_rst_stream(session->ngh2, NGHTTP2_FLAG_NONE, stream->id, NGHTTP2_PROTOCOL_ERROR); stream->id, H2_STREAM_RST(stream, NGHTTP2_PROTOCOL_ERROR)); } if (nghttp2_is_fatal(rv)) { Loading @@ -1179,27 +1177,6 @@ int h2_session_is_done(h2_session *session) && !nghttp2_session_want_write(session->ngh2))); } static int log_stream(void *ctx, h2_stream *stream) { h2_session *session = (h2_session *)ctx; AP_DEBUG_ASSERT(session); ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c, "h2_stream(%ld-%d): in set, suspended=%d, aborted=%d, " "has_data=%d", session->id, stream->id, stream->suspended, stream->aborted, h2_mplx_out_has_data_for(session->mplx, stream->id)); return 1; } void h2_session_log_stats(h2_session *session) { AP_DEBUG_ASSERT(session); ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c, "h2_session(%ld): %d open streams", session->id, (int)h2_stream_set_size(session->streams)); h2_stream_set_iter(session->streams, log_stream, session); } static int frame_print(const nghttp2_frame *frame, char *buffer, size_t maxlen) { char scratch[128]; Loading Loading
modules/http2/h2_conn.c +38 −23 Original line number Diff line number Diff line Loading @@ -39,7 +39,7 @@ static struct h2_workers *workers; static apr_status_t h2_session_process(h2_session *session); static apr_status_t h2_conn_loop(h2_session *session); static h2_mpm_type_t mpm_type = H2_MPM_UNKNOWN; static module *mpm_module; Loading Loading @@ -156,7 +156,7 @@ apr_status_t h2_conn_rprocess(request_rec *r) return APR_EGENERAL; } return h2_session_process(session); return h2_conn_loop(session); } apr_status_t h2_conn_main(conn_rec *c) Loading @@ -177,7 +177,7 @@ apr_status_t h2_conn_main(conn_rec *c) return APR_EGENERAL; } status = h2_session_process(session); status = h2_conn_loop(session); /* Make sure this connection gets closed properly. */ c->keepalive = AP_CONN_CLOSE; Loading @@ -188,7 +188,7 @@ apr_status_t h2_conn_main(conn_rec *c) return status; } apr_status_t h2_session_process(h2_session *session) static apr_status_t h2_conn_loop(h2_session *session) { apr_status_t status = APR_SUCCESS; int rv = 0; Loading Loading @@ -283,10 +283,19 @@ apr_status_t h2_session_process(h2_session *session) * submit our settings and need the ACK. */ got_streams = !h2_stream_set_is_empty(session->streams); status = h2_session_read(session, (!got_streams || session->frames_received <= 1)? APR_BLOCK_READ : APR_NONBLOCK_READ); if (!got_streams || session->frames_received <= 1) { if (session->c->cs) { session->c->cs->state = CONN_STATE_WRITE_COMPLETION; } status = h2_session_read(session, APR_BLOCK_READ); } else { if (session->c->cs) { session->c->cs->state = CONN_STATE_HANDLER; } status = h2_session_read(session, APR_NONBLOCK_READ); } switch (status) { case APR_SUCCESS: /* successful read, reset our idle timers */ have_read = 1; Loading @@ -294,21 +303,28 @@ apr_status_t h2_session_process(h2_session *session) break; case APR_EAGAIN: /* non-blocking read, nothing there */ break; case APR_EBADF: /* connection is not there any more */ case APR_EOF: case APR_ECONNABORTED: case APR_ECONNRESET: case APR_TIMEUP: /* blocked read, timed out */ default: if (APR_STATUS_IS_ETIMEDOUT(status) || APR_STATUS_IS_ECONNABORTED(status) || APR_STATUS_IS_ECONNRESET(status) || APR_STATUS_IS_EOF(status) || APR_STATUS_IS_EBADF(status)) { /* common status for a client that has left */ ap_log_cerror( APLOG_MARK, APLOG_DEBUG, status, session->c, "h2_session(%ld): reading", "h2_session(%ld): terminating", session->id); h2_session_abort(session, status, 0); break; default: /* Stolen from mod_reqtimeout to speed up lingering when * a read timeout happened. */ apr_table_setn(session->c->notes, "short-lingering-close", "1"); } else { /* uncommon status, log on INFO so that we see this */ ap_log_cerror( APLOG_MARK, APLOG_INFO, status, session->c, APLOGNO(02950) "h2_session(%ld): error reading, terminating", session->id); } h2_session_abort(session, status, 0); break; } Loading Loading @@ -471,7 +487,6 @@ apr_status_t h2_conn_process(conn_rec *c, apr_socket_t *socket) { AP_DEBUG_ASSERT(c); c->clogging_input_filters = 1; ap_process_connection(c, socket); return APR_SUCCESS; Loading
modules/http2/h2_h2.c +2 −1 Original line number Diff line number Diff line Loading @@ -94,6 +94,7 @@ int h2_tls_disable(conn_rec *c) return 0; } /******************************************************************************* * Register various hooks */ Loading @@ -119,7 +120,7 @@ void h2_h2_register_hooks(void) ap_hook_post_read_request(h2_h2_post_read_req, NULL, NULL, APR_HOOK_REALLY_FIRST); } int h2_h2_remove_timeout(conn_rec* c) static int h2_h2_remove_timeout(conn_rec* c) { h2_ctx *ctx = h2_ctx_get(c); Loading
modules/http2/h2_io.c +23 −3 Original line number Diff line number Diff line Loading @@ -80,6 +80,10 @@ apr_status_t h2_io_in_read(h2_io *io, apr_bucket_brigade *bb, apr_bucket *last; apr_status_t status; if (io->rst_error) { return APR_ECONNABORTED; } if (!io->bbin || APR_BRIGADE_EMPTY(io->bbin)) { return io->eos_in? APR_EOF : APR_EAGAIN; } Loading @@ -102,6 +106,10 @@ apr_status_t h2_io_in_read(h2_io *io, apr_bucket_brigade *bb, apr_status_t h2_io_in_write(h2_io *io, apr_bucket_brigade *bb) { if (io->rst_error) { return APR_ECONNABORTED; } if (io->eos_in) { return APR_EOF; } Loading @@ -118,6 +126,10 @@ apr_status_t h2_io_in_write(h2_io *io, apr_bucket_brigade *bb) apr_status_t h2_io_in_close(h2_io *io) { if (io->rst_error) { return APR_ECONNABORTED; } if (io->bbin) { APR_BRIGADE_INSERT_TAIL(io->bbin, apr_bucket_eos_create(io->bbin->bucket_alloc)); Loading @@ -132,6 +144,10 @@ apr_status_t h2_io_out_readx(h2_io *io, { apr_status_t status; if (io->rst_error) { return APR_ECONNABORTED; } if (io->eos_out) { *plen = 0; *peos = 1; Loading @@ -158,6 +174,10 @@ apr_status_t h2_io_out_write(h2_io *io, apr_bucket_brigade *bb, apr_status_t status; int start_allowed; if (io->rst_error) { return APR_ECONNABORTED; } if (io->eos_out) { apr_off_t len; /* We have already delivered an EOS bucket to a reader, no Loading Loading @@ -188,9 +208,6 @@ apr_status_t h2_io_out_write(h2_io *io, apr_bucket_brigade *bb, */ start_allowed = *pfile_handles_allowed; if (io->rst_error) { return APR_ECONNABORTED; } status = h2_util_move(io->bbout, bb, maxlen, pfile_handles_allowed, "h2_io_out_write"); /* track # file buckets moved into our pool */ Loading @@ -203,6 +220,9 @@ apr_status_t h2_io_out_write(h2_io *io, apr_bucket_brigade *bb, apr_status_t h2_io_out_close(h2_io *io) { if (io->rst_error) { return APR_ECONNABORTED; } if (!io->eos_out && !h2_util_has_eos(io->bbout, 0)) { APR_BRIGADE_INSERT_TAIL(io->bbout, apr_bucket_eos_create(io->bbout->bucket_alloc)); Loading
modules/http2/h2_mplx.c +20 −13 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include "h2_private.h" #include "h2_config.h" #include "h2_conn.h" #include "h2_h2.h" #include "h2_io.h" #include "h2_io_set.h" #include "h2_response.h" Loading Loading @@ -288,18 +289,21 @@ apr_status_t h2_mplx_cleanup_stream(h2_mplx *m, h2_stream *stream) status = apr_thread_mutex_lock(m->lock); if (APR_SUCCESS == status) { h2_io *io = h2_io_set_get(m->stream_ios, stream->id); if (!io || io->task_done) { /* No more io or task already done -> cleanup immediately */ stream_destroy(m, stream, io); } else { if (io) { /* Remove io from ready set, we will never submit it */ h2_io_set_remove(m->ready_ios, io); if (stream->rst_error) { /* Forward error code to fail any further attempt to * write to io */ h2_io_rst(io, stream->rst_error); } /* Remove io from ready set (if there), since we will never submit it */ h2_io_set_remove(m->ready_ios, io); } if (!io || io->task_done) { /* No more io or task already done -> cleanup immediately */ stream_destroy(m, stream, io); } else { /* Add stream to closed set for cleanup when task is done */ h2_stream_set_add(m->closed, stream); } Loading Loading @@ -515,18 +519,21 @@ h2_stream *h2_mplx_next_submit(h2_mplx *m, h2_stream_set *streams) h2_stream_set_response(stream, io->response, io->bbout); } if (io->output_drained) { apr_thread_cond_signal(io->output_drained); } } else { ap_log_cerror(APLOG_MARK, APLOG_WARNING, 0, m->c, APLOGNO(02953) "h2_mplx(%ld): stream for response %d not found", m->id, io->id); /* We have the io ready, but the stream has gone away, maybe * reset by the client. Should no longer happen since such * streams should clear io's from the ready queue. */ ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, m->c, APLOGNO(02953) "h2_mplx(%ld): stream for response %d closed, " "resetting io to close request processing", m->id, io->id); h2_io_rst(io, NGHTTP2_ERR_STREAM_CLOSED); } if (io->output_drained) { apr_thread_cond_signal(io->output_drained); } } apr_thread_mutex_unlock(m->lock); Loading
modules/http2/h2_session.c +8 −31 Original line number Diff line number Diff line Loading @@ -168,7 +168,7 @@ static int on_data_chunk_recv_cb(nghttp2_session *ngh2, uint8_t flags, session->id, stream_id, (int)len); if (status != APR_SUCCESS) { rv = nghttp2_submit_rst_stream(ngh2, NGHTTP2_FLAG_NONE, stream_id, NGHTTP2_INTERNAL_ERROR); H2_STREAM_RST(stream, NGHTTP2_INTERNAL_ERROR)); if (nghttp2_is_fatal(rv)) { return NGHTTP2_ERR_CALLBACK_FAILURE; } Loading Loading @@ -931,17 +931,18 @@ apr_status_t h2_session_write(h2_session *session, apr_interval_time_t timeout) } /* If we have responses ready, submit them now. */ while ((stream = h2_mplx_next_submit(session->mplx, session->streams)) != NULL) { while (!session->aborted && (stream = h2_mplx_next_submit(session->mplx, session->streams)) != NULL) { status = h2_session_handle_response(session, stream); flush_output = 1; } if (h2_session_resume_streams_with_data(session) > 0) { if (!session->aborted && h2_session_resume_streams_with_data(session) > 0) { flush_output = 1; } if (!flush_output && timeout > 0 && !h2_session_want_write(session)) { if (!session->aborted && !flush_output && timeout > 0 && !h2_session_want_write(session)) { status = h2_mplx_out_trywait(session->mplx, timeout, session->iowait); if (status != APR_TIMEUP Loading Loading @@ -1151,13 +1152,10 @@ apr_status_t h2_session_handle_response(h2_session *session, h2_stream *stream) if (stream->response && stream->response->ngheader) { rv = submit_response(session, stream->response); } else if (stream->rst_error) { rv = nghttp2_submit_rst_stream(session->ngh2, NGHTTP2_FLAG_NONE, stream->id, stream->rst_error); } else { rv = nghttp2_submit_rst_stream(session->ngh2, NGHTTP2_FLAG_NONE, stream->id, NGHTTP2_PROTOCOL_ERROR); stream->id, H2_STREAM_RST(stream, NGHTTP2_PROTOCOL_ERROR)); } if (nghttp2_is_fatal(rv)) { Loading @@ -1179,27 +1177,6 @@ int h2_session_is_done(h2_session *session) && !nghttp2_session_want_write(session->ngh2))); } static int log_stream(void *ctx, h2_stream *stream) { h2_session *session = (h2_session *)ctx; AP_DEBUG_ASSERT(session); ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c, "h2_stream(%ld-%d): in set, suspended=%d, aborted=%d, " "has_data=%d", session->id, stream->id, stream->suspended, stream->aborted, h2_mplx_out_has_data_for(session->mplx, stream->id)); return 1; } void h2_session_log_stats(h2_session *session) { AP_DEBUG_ASSERT(session); ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, session->c, "h2_session(%ld): %d open streams", session->id, (int)h2_stream_set_size(session->streams)); h2_stream_set_iter(session->streams, log_stream, session); } static int frame_print(const nghttp2_frame *frame, char *buffer, size_t maxlen) { char scratch[128]; Loading