apr_status_t h2_mplx_out_rst(h2_mplx *m, int stream_id, int error) { apr_status_t status; int acquired; AP_DEBUG_ASSERT(m); if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) { h2_io *io = h2_io_set_get(m->stream_ios, stream_id); if (io && !io->rst_error && !io->orphaned) { h2_io_rst(io, error); if (!io->response) { h2_io_set_add(m->ready_ios, io); } H2_MPLX_IO_OUT(APLOG_TRACE2, m, io, "h2_mplx_out_rst"); have_out_data_for(m, stream_id); h2_io_signal(io, H2_IO_WRITE); } else { status = APR_ECONNABORTED; } leave_mutex(m, acquired); } return status; }
apr_status_t h2_mplx_out_write(h2_mplx *m, int stream_id, ap_filter_t* f, apr_bucket_brigade *bb, apr_table_t *trailers, struct apr_thread_cond_t *iowait) { apr_status_t status; int acquired; AP_DEBUG_ASSERT(m); if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) { h2_io *io = h2_io_set_get(m->stream_ios, stream_id); if (io && !io->orphaned) { status = out_write(m, io, f, bb, trailers, iowait); ap_log_cerror(APLOG_MARK, APLOG_TRACE1, status, m->c, "h2_mplx(%ld-%d): write with trailers=%s", m->id, io->id, trailers? "yes" : "no"); H2_MPLX_IO_OUT(APLOG_TRACE2, m, io, "h2_mplx_out_write"); have_out_data_for(m, stream_id); } else { status = APR_ECONNABORTED; } leave_mutex(m, acquired); } return status; }
apr_status_t h2_mplx_out_rst(h2_mplx *m, int stream_id, int error) { apr_status_t status; AP_DEBUG_ASSERT(m); if (m->aborted) { return APR_ECONNABORTED; } status = apr_thread_mutex_lock(m->lock); if (APR_SUCCESS == status) { if (!m->aborted) { h2_io *io = h2_io_set_get(m->stream_ios, stream_id); if (io && !io->rst_error && !io->orphaned) { h2_io_rst(io, error); if (!io->response) { h2_io_set_add(m->ready_ios, io); } H2_MPLX_IO_OUT(APLOG_TRACE2, m, io, "h2_mplx_out_rst"); have_out_data_for(m, stream_id); if (io->output_drained) { apr_thread_cond_signal(io->output_drained); } } else { status = APR_ECONNABORTED; } } apr_thread_mutex_unlock(m->lock); } return status; }
static apr_status_t out_open(h2_mplx *m, int stream_id, h2_response *response, ap_filter_t* f, apr_bucket_brigade *bb, struct apr_thread_cond_t *iowait) { apr_status_t status = APR_SUCCESS; h2_io *io = h2_io_set_get(m->stream_ios, stream_id); if (io && !io->orphaned) { if (f) { ap_log_cerror(APLOG_MARK, APLOG_TRACE1, 0, f->c, "h2_mplx(%ld-%d): open response: %d, rst=%d", m->id, stream_id, response->http_status, response->rst_error); } h2_io_set_response(io, response); h2_io_set_add(m->ready_ios, io); if (response && response->http_status < 300) { /* we might see some file buckets in the output, see * if we have enough handles reserved. */ check_tx_reservation(m); } if (bb) { status = out_write(m, io, f, bb, response->trailers, iowait); } have_out_data_for(m, stream_id); } else { status = APR_ECONNABORTED; } return status; }
apr_status_t h2_mplx_out_write(h2_mplx *m, int stream_id, ap_filter_t* f, apr_bucket_brigade *bb, struct apr_thread_cond_t *iowait) { apr_status_t status; AP_DEBUG_ASSERT(m); if (m->aborted) { return APR_ECONNABORTED; } status = apr_thread_mutex_lock(m->lock); if (APR_SUCCESS == status) { if (!m->aborted) { h2_io *io = h2_io_set_get(m->stream_ios, stream_id); if (io) { status = out_write(m, io, f, bb, iowait); have_out_data_for(m, stream_id); if (m->aborted) { return APR_ECONNABORTED; } } else { status = APR_ECONNABORTED; } } if (m->lock) { apr_thread_mutex_unlock(m->lock); } } return status; }
static apr_status_t out_open(h2_mplx *m, int stream_id, h2_response *response, ap_filter_t* f, apr_bucket_brigade *bb, struct apr_thread_cond_t *iowait) { apr_status_t status = APR_SUCCESS; h2_io *io = h2_io_set_get(m->stream_ios, stream_id); if (io) { if (f) { ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, f->c, "h2_mplx(%ld-%d): open response: %s", m->id, stream_id, response->status); } io->response = h2_response_copy(io->pool, response); h2_io_set_add(m->ready_ios, io); if (bb) { status = out_write(m, io, f, bb, iowait); } have_out_data_for(m, stream_id); } else { status = APR_ECONNABORTED; } return status; }
apr_status_t h2_mplx_out_close(h2_mplx *m, int stream_id, apr_table_t *trailers) { apr_status_t status; AP_DEBUG_ASSERT(m); if (m->aborted) { return APR_ECONNABORTED; } status = apr_thread_mutex_lock(m->lock); if (APR_SUCCESS == status) { if (!m->aborted) { h2_io *io = h2_io_set_get(m->stream_ios, stream_id); if (io && !io->orphaned) { if (!io->response && !io->rst_error) { /* In case a close comes before a response was created, * insert an error one so that our streams can properly * reset. */ h2_response *r = h2_response_die(stream_id, APR_EGENERAL, io->request, m->pool); status = out_open(m, stream_id, r, NULL, NULL, NULL); ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, m->c, "h2_mplx(%ld-%d): close, no response, no rst", m->id, io->id); } ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, m->c, "h2_mplx(%ld-%d): close with trailers=%s", m->id, io->id, trailers? "yes" : "no"); status = h2_io_out_close(io, trailers); H2_MPLX_IO_OUT(APLOG_TRACE2, m, io, "h2_mplx_out_close"); have_out_data_for(m, stream_id); if (m->aborted) { /* if we were the last output, the whole session might * have gone down in the meantime. */ return APR_SUCCESS; } } else { status = APR_ECONNABORTED; } } apr_thread_mutex_unlock(m->lock); } return status; }
apr_status_t h2_mplx_out_close(h2_mplx *m, int stream_id) { apr_status_t status; AP_DEBUG_ASSERT(m); if (m->aborted) { return APR_ECONNABORTED; } status = apr_thread_mutex_lock(m->lock); if (APR_SUCCESS == status) { if (!m->aborted) { h2_io *io = h2_io_set_get(m->stream_ios, stream_id); if (io) { if (!io->response->ngheader) { /* In case a close comes before a response was created, * insert an error one so that our streams can properly * reset. */ h2_response *r = h2_response_create(stream_id, "500", NULL, m->pool); status = out_open(m, stream_id, r, NULL, NULL, NULL); } status = h2_io_out_close(io); have_out_data_for(m, stream_id); if (m->aborted) { /* if we were the last output, the whole session might * have gone down in the meantime. */ return APR_SUCCESS; } } else { status = APR_ECONNABORTED; } } apr_thread_mutex_unlock(m->lock); } return status; }
apr_status_t h2_mplx_out_write(h2_mplx *m, int stream_id, ap_filter_t* f, apr_bucket_brigade *bb, apr_table_t *trailers, struct apr_thread_cond_t *iowait) { apr_status_t status; AP_DEBUG_ASSERT(m); if (m->aborted) { return APR_ECONNABORTED; } status = apr_thread_mutex_lock(m->lock); if (APR_SUCCESS == status) { if (!m->aborted) { h2_io *io = h2_io_set_get(m->stream_ios, stream_id); if (io && !io->orphaned) { status = out_write(m, io, f, bb, trailers, iowait); ap_log_cerror(APLOG_MARK, APLOG_DEBUG, status, m->c, "h2_mplx(%ld-%d): write with trailers=%s", m->id, io->id, trailers? "yes" : "no"); H2_MPLX_IO_OUT(APLOG_TRACE2, m, io, "h2_mplx_out_write"); have_out_data_for(m, stream_id); if (m->aborted) { return APR_ECONNABORTED; } } else { status = APR_ECONNABORTED; } } if (m->lock) { apr_thread_mutex_unlock(m->lock); } } return status; }
apr_status_t h2_mplx_out_close(h2_mplx *m, int stream_id, apr_table_t *trailers) { apr_status_t status; int acquired; AP_DEBUG_ASSERT(m); if ((status = enter_mutex(m, &acquired)) == APR_SUCCESS) { h2_io *io = h2_io_set_get(m->stream_ios, stream_id); if (io && !io->orphaned) { if (!io->response && !io->rst_error) { /* In case a close comes before a response was created, * insert an error one so that our streams can properly * reset. */ h2_response *r = h2_response_die(stream_id, APR_EGENERAL, io->request, m->pool); status = out_open(m, stream_id, r, NULL, NULL, NULL); ap_log_cerror(APLOG_MARK, APLOG_TRACE1, status, m->c, "h2_mplx(%ld-%d): close, no response, no rst", m->id, io->id); } ap_log_cerror(APLOG_MARK, APLOG_TRACE1, status, m->c, "h2_mplx(%ld-%d): close with trailers=%s", m->id, io->id, trailers? "yes" : "no"); status = h2_io_out_close(io, trailers); H2_MPLX_IO_OUT(APLOG_TRACE2, m, io, "h2_mplx_out_close"); have_out_data_for(m, stream_id); } else { status = APR_ECONNABORTED; } leave_mutex(m, acquired); } return status; }