static int report_consumption(h2_bucket_beam *beam)
{
int rv = 0;
- if (apr_atomic_read32(&beam->cons_ev_pending)) {
- if (beam->cons_io_cb) {
- beam->cons_io_cb(beam->cons_ctx, beam, beam->received_bytes
- - beam->cons_bytes_reported);
- rv = 1;
- }
- beam->cons_bytes_reported = beam->received_bytes;
- apr_atomic_set32(&beam->cons_ev_pending, 0);
+ if (beam->cons_io_cb) {
+ beam->cons_io_cb(beam->cons_ctx, beam, beam->received_bytes
+ - beam->cons_bytes_reported);
+ rv = 1;
}
+ beam->cons_bytes_reported = beam->received_bytes;
return rv;
}
}
if (transferred_buckets > 0) {
- apr_atomic_set32(&beam->cons_ev_pending, 1);
if (beam->cons_ev_cb) {
beam->cons_ev_cb(beam->cons_ctx, beam);
}
int h2_beam_report_consumption(h2_bucket_beam *beam)
{
- if (apr_atomic_read32(&beam->cons_ev_pending)) {
- h2_beam_lock bl;
- if (enter_yellow(beam, &bl) == APR_SUCCESS) {
- int rv = report_consumption(beam);
- leave_yellow(beam, &bl);
- return rv;
- }
+ h2_beam_lock bl;
+ int rv = 0;
+ if (enter_yellow(beam, &bl) == APR_SUCCESS) {
+ rv = report_consumption(beam);
+ leave_yellow(beam, &bl);
}
- return 0;
+ return rv;
}
void h2_beam_log(h2_bucket_beam *beam, conn_rec *c, int level, const char *msg)
h2_beam_mutex_enter *m_enter;
struct apr_thread_cond_t *m_cond;
- apr_uint32_t cons_ev_pending; /* != 0, consumer event pending */
apr_off_t cons_bytes_reported; /* amount of bytes reported as consumed */
h2_beam_ev_callback *cons_ev_cb;
h2_beam_io_callback *cons_io_cb;
void *cons_ctx;
- apr_uint32_t prod_ev_pending; /* != 0, producer event pending */
apr_off_t prod_bytes_reported; /* amount of bytes reported as produced */
h2_beam_io_callback *prod_io_cb;
void *prod_ctx;
static void stream_output_consumed(void *ctx,
h2_bucket_beam *beam, apr_off_t length)
{
- h2_task *task = ctx;
+ h2_stream *stream = ctx;
+ h2_task *task = stream->task;
if (length > 0 && task && task->assigned) {
h2_req_engine_out_consumed(task->assigned, task->c, length);
}
"h2_mplx(%s): out open", stream->task->id);
}
- h2_beam_on_consumed(stream->output, NULL, stream_output_consumed, stream->task);
+ h2_beam_on_consumed(stream->output, NULL, stream_output_consumed, stream);
h2_beam_on_produced(stream->output, output_produced, m);
beamed_count = h2_beam_get_files_beamed(stream->output);
if (m->tx_handles_reserved >= beamed_count) {
s = apr_table_get(req->headers, "Content-Length");
if (!s) {
- /* no content-length given */
+ /* HTTP/2 does not need a Content-Length for framing, but our
+ * internal request processing is used to HTTP/1.1, so we
+ * need to either add a Content-Length or a Transfer-Encoding
+ * if any content can be expected. */
if (!eos) {
/* We have not seen a content-length and have no eos,
* simulate a chunked encoding for our HTTP/1.1 infrastructure,
#include <http_log.h>
#include <scoreboard.h>
+#include <mpm_common.h>
+
#include "h2_private.h"
#include "h2.h"
#include "h2_bucket_eos.h"
{
nghttp2_session_callbacks *callbacks = NULL;
nghttp2_option *options = NULL;
+ apr_allocator_t *allocator;
+ apr_thread_mutex_t *mutex;
uint32_t n;
-
apr_pool_t *pool = NULL;
- apr_status_t status = apr_pool_create(&pool, c->pool);
h2_session *session;
+
+ apr_status_t status = apr_allocator_create(&allocator);
if (status != APR_SUCCESS) {
return NULL;
}
+ apr_allocator_max_free_set(allocator, ap_max_mem_free);
+ apr_pool_create_ex(&pool, c->pool, NULL, allocator);
+ if (!pool) {
+ apr_allocator_destroy(allocator);
+ return NULL;
+ }
apr_pool_tag(pool, "h2_session");
-
+ apr_allocator_owner_set(allocator, pool);
+ status = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, pool);
+ if (status != APR_SUCCESS) {
+ apr_pool_destroy(pool);
+ return NULL;
+ }
+ apr_allocator_mutex_set(allocator, mutex);
+
/* get h2_session a lifetime beyond its pool and everything
* connected to it. */
session = apr_pcalloc(pool, sizeof(h2_session));
/* start pushed stream */
ap_assert(stream->request == NULL);
ap_assert(stream->rtmp != NULL);
- status = h2_request_end_headers(stream->rtmp, stream->pool, 0);
+ status = h2_request_end_headers(stream->rtmp, stream->pool, 1);
if (status != APR_SUCCESS) {
return status;
}
/* request HEADER */
ap_assert(stream->request == NULL);
ap_assert(stream->rtmp != NULL);
- status = h2_request_end_headers(stream->rtmp, stream->pool, 0);
+ status = h2_request_end_headers(stream->rtmp, stream->pool, eos);
if (status != APR_SUCCESS) {
return status;
}
* @macro
* Version number of the http2 module as c string
*/
-#define MOD_HTTP2_VERSION "1.9.1"
+#define MOD_HTTP2_VERSION "1.9.2"
/**
* @macro
* release. This is a 24 bit number with 8 bits for major number, 8 bits
* for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203.
*/
-#define MOD_HTTP2_VERSION_NUM 0x010901
+#define MOD_HTTP2_VERSION_NUM 0x010902
#endif /* mod_h2_h2_version_h */