Commit f8c68219 authored by Stefan Eissing's avatar Stefan Eissing
Browse files

more good things from trunk

parent ce255155
Loading
Loading
Loading
Loading
+38 −23
Original line number Diff line number Diff line
@@ -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;
@@ -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)
@@ -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;
@@ -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;
@@ -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;
@@ -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;
        }
@@ -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;
+2 −1
Original line number Diff line number Diff line
@@ -94,6 +94,7 @@ int h2_tls_disable(conn_rec *c)
    return 0;
}


/*******************************************************************************
 * Register various hooks
 */
@@ -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);
    
+23 −3
Original line number Diff line number Diff line
@@ -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;
    }
@@ -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;
    }
@@ -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));
@@ -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;
@@ -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
@@ -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 */
@@ -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));
+20 −13
Original line number Diff line number Diff line
@@ -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"
@@ -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);
        }
@@ -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);
+8 −31
Original line number Diff line number Diff line
@@ -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;
        }
@@ -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
@@ -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)) {
@@ -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