-*- coding: utf-8 -*-
Changes with Apache 2.4.29
+ *) mod_http2: v0.10.12, removed optimization for mutex handling in bucket
+ beams that could lead to assertion failure in edge cases.
+ [Stefan Eissing]
+
*) mod_proxy: Fix regression for non decimal loadfactor parameter introduced
in 2.4.28. [Jim Jagielski]
PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
[ start all new proposals below, under PATCHES PROPOSED. ]
- *) mod_http2: Fix race condition on request body handling.
- 2.4.x patch: svn merge -c 1804096,1807238,1809981,1810088,1810089 ^/httpd/httpd/trunk .
- +1: icing, steffenal, ylavic
-
*) mod_rewrite,core: Avoid the 'Vary: Host' response header when HTTP_HOST
is used in a condition that evaluates to true.
trunk patch: http://svn.apache.org/r1808746
static apr_status_t enter_yellow(h2_bucket_beam *beam, h2_beam_lock *pbl)
{
- h2_beam_mutex_enter *enter = beam->m_enter;
- if (enter) {
- void *ctx = beam->m_ctx;
- if (ctx) {
- return enter(ctx, pbl);
- }
- }
- pbl->mutex = NULL;
- pbl->leave = NULL;
- return APR_SUCCESS;
+ return mutex_enter(beam, pbl);
}
static void leave_yellow(h2_bucket_beam *beam, h2_beam_lock *pbl)
{
h2_bucket_beam *beam = data;
apr_status_t status = APR_SUCCESS;
- int safe_send = !beam->m_enter || (beam->owner == H2_BEAM_OWNER_SEND);
- int safe_recv = !beam->m_enter || (beam->owner == H2_BEAM_OWNER_RECV);
+ int safe_send = (beam->owner == H2_BEAM_OWNER_SEND);
+ int safe_recv = (beam->owner == H2_BEAM_OWNER_RECV);
/*
* Owner of the beam is going away, depending on which side it owns,
- * cleanup strategies will differ with multi-thread protection
- * still in place (beam->m_enter).
+ * cleanup strategies will differ.
*
* In general, receiver holds references to memory from sender.
* Clean up receiver first, if safe, then cleanup sender, if safe.
return buffer_size;
}
-void h2_beam_mutex_set(h2_bucket_beam *beam,
- h2_beam_mutex_enter m_enter,
- void *m_ctx)
-{
- h2_beam_lock bl;
-
- if (enter_yellow(beam, &bl) == APR_SUCCESS) {
- beam->m_enter = m_enter;
- beam->m_ctx = m_ctx;
- leave_yellow(beam, &bl);
- }
-}
-
-void h2_beam_mutex_enable(h2_bucket_beam *beam)
-{
- h2_beam_mutex_set(beam, mutex_enter, beam);
-}
-
-void h2_beam_mutex_disable(h2_bucket_beam *beam)
-{
- h2_beam_mutex_set(beam, NULL, NULL);
-}
-
void h2_beam_timeout_set(h2_bucket_beam *beam, apr_interval_time_t timeout)
{
h2_beam_lock bl;
* via the h2_beam_send(). It gives the beam to the green thread which then
* can receive buckets into its own brigade via h2_beam_receive().
*
- * Sending and receiving can happen concurrently, if a thread mutex is set
- * for the beam, see h2_beam_mutex_set.
+ * Sending and receiving can happen concurrently.
*
* The beam can limit the amount of data it accepts via the buffer_size. This
- * can also be adjusted during its lifetime. When the beam not only gets a
- * mutex but als a condition variable (in h2_beam_mutex_set()), sends and
- * receives can be done blocking. A timeout can be set for such blocks.
+ * can also be adjusted during its lifetime. Sends and receives can be done blocking.
+ * A timeout can be set for such blocks.
*
* Care needs to be taken when terminating the beam. The beam registers at
* the pool it was created with and will cleanup after itself. However, if
struct apr_thread_mutex_t *lock;
struct apr_thread_cond_t *change;
- void *m_ctx;
- h2_beam_mutex_enter *m_enter;
apr_off_t cons_bytes_reported; /* amount of bytes reported as consumed */
h2_beam_ev_callback *cons_ev_cb;
*/
apr_status_t h2_beam_wait_empty(h2_bucket_beam *beam, apr_read_type_e block);
-void h2_beam_mutex_set(h2_bucket_beam *beam,
- h2_beam_mutex_enter m_enter,
- void *m_ctx);
-
-void h2_beam_mutex_enable(h2_bucket_beam *beam);
-void h2_beam_mutex_disable(h2_bucket_beam *beam);
-
/**
* Set/get the timeout for blocking read/write operations. Only works
* if a mutex has been set for the beam.
h2_beam_on_file_beam(stream->output, h2_beam_no_files, NULL);
}
- /* time to protect the beam against multi-threaded use */
- h2_beam_mutex_enable(stream->output);
-
/* we might see some file buckets in the output, see
* if we have enough handles reserved. */
check_data_for(m, stream, 0);
H2_STRM_MSG(stream, "task_done, stream open"));
if (stream->input) {
h2_beam_leave(stream->input);
- h2_beam_mutex_disable(stream->input);
- }
- if (stream->output) {
- h2_beam_mutex_disable(stream->output);
}
/* more data will not arrive, resume the stream */
H2_STRM_MSG(stream, "task_done, in hold"));
if (stream->input) {
h2_beam_leave(stream->input);
- h2_beam_mutex_disable(stream->input);
- }
- if (stream->output) {
- h2_beam_mutex_disable(stream->output);
}
stream_joined(m, stream);
}
h2_ctx_create_for(c, task);
apr_table_setn(c->notes, H2_TASK_ID_NOTE, task->id);
- if (task->input.beam) {
- h2_beam_mutex_enable(task->input.beam);
- }
-
h2_slave_run_pre_connection(c, ap_get_conn_socket(c));
task->input.bb = apr_brigade_create(task->pool, c->bucket_alloc);
}
}
+/* base64 url encoding ****************************************************************************/
+
static const int BASE64URL_UINT6[] = {
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0 */
n = ((BASE64URL_UINT6[ e[mlen+0] ] << 18) +
(BASE64URL_UINT6[ e[mlen+1] ] << 12));
*d++ = n >> 16;
+ remain = 1;
break;
case 3:
n = ((BASE64URL_UINT6[ e[mlen+0] ] << 18) +
(BASE64URL_UINT6[ e[mlen+2] ] << 6));
*d++ = n >> 16;
*d++ = n >> 8 & 0xffu;
+ remain = 2;
break;
default: /* do nothing */
break;
}
const char *h2_util_base64url_encode(const char *data,
- apr_size_t len, apr_pool_t *pool)
+ apr_size_t dlen, apr_pool_t *pool)
{
- apr_size_t mlen = ((len+2)/3)*3;
- apr_size_t slen = (mlen/3)*4;
- apr_size_t i;
+ long i, len = (int)dlen;
+ apr_size_t slen = ((dlen+2)/3)*4 + 1; /* 0 terminated */
const unsigned char *udata = (const unsigned char*)data;
- char *enc, *p = apr_pcalloc(pool, slen+1); /* 0 terminated */
+ char *enc, *p = apr_pcalloc(pool, slen);
enc = p;
- for (i = 0; i < mlen; i+= 3) {
+ for (i = 0; i < len-2; i+= 3) {
*p++ = BASE64URL_CHARS[ (udata[i] >> 2) & 0x3fu ];
- *p++ = BASE64URL_CHARS[ ((udata[i] << 4) +
- ((i+1 < len)? (udata[i+1] >> 4) : 0)) & 0x3fu ];
- *p++ = BASE64URL_CHARS[ ((udata[i+1] << 2) +
- ((i+2 < len)? (udata[i+2] >> 6) : 0)) & 0x3fu ];
- if (i+2 < len) {
- *p++ = BASE64URL_CHARS[ udata[i+2] & 0x3fu ];
- }
+ *p++ = BASE64URL_CHARS[ ((udata[i] << 4) + (udata[i+1] >> 4)) & 0x3fu ];
+ *p++ = BASE64URL_CHARS[ ((udata[i+1] << 2) + (udata[i+2] >> 6)) & 0x3fu ];
+ *p++ = BASE64URL_CHARS[ udata[i+2] & 0x3fu ];
}
- return enc;
-}
-
-int h2_util_contains_token(apr_pool_t *pool, const char *s, const char *token)
-{
- char *c;
- if (s) {
- if (!apr_strnatcasecmp(s, token)) { /* the simple life */
- return 1;
- }
-
- for (c = ap_get_token(pool, &s, 0); c && *c;
- c = *s? ap_get_token(pool, &s, 0) : NULL) {
- if (!apr_strnatcasecmp(c, token)) { /* seeing the token? */
- return 1;
- }
- while (*s++ == ';') { /* skip parameters */
- ap_get_token(pool, &s, 0);
- }
- if (*s++ != ',') { /* need comma separation */
- return 0;
- }
+ if (i < len) {
+ *p++ = BASE64URL_CHARS[ (udata[i] >> 2) & 0x3fu ];
+ if (i == (len - 1)) {
+ *p++ = BASE64URL_CHARS[ (udata[i] << 4) & 0x3fu ];
}
- }
- return 0;
-}
-
-const char *h2_util_first_token_match(apr_pool_t *pool, const char *s,
- const char *tokens[], apr_size_t len)
-{
- char *c;
- apr_size_t i;
- if (s && *s) {
- for (c = ap_get_token(pool, &s, 0); c && *c;
- c = *s? ap_get_token(pool, &s, 0) : NULL) {
- for (i = 0; i < len; ++i) {
- if (!apr_strnatcasecmp(c, tokens[i])) {
- return tokens[i];
- }
- }
- while (*s++ == ';') { /* skip parameters */
- ap_get_token(pool, &s, 0);
- }
- if (*s++ != ',') { /* need comma separation */
- return 0;
- }
+ else {
+ *p++ = BASE64URL_CHARS[ ((udata[i] << 4) + (udata[i+1] >> 4)) & 0x3fu ];
+ *p++ = BASE64URL_CHARS[ (udata[i+1] << 2) & 0x3fu ];
}
}
- return NULL;
+ *p++ = '\0';
+ return enc;
}
-
/*******************************************************************************
* ihash - hash for structs with int identifier
******************************************************************************/
*/
apr_size_t h2_util_table_bytes(apr_table_t *t, apr_size_t pair_extra);
-/**
- * Return != 0 iff the string s contains the token, as specified in
- * HTTP header syntax, rfc7230.
- */
-int h2_util_contains_token(apr_pool_t *pool, const char *s, const char *token);
-
-const char *h2_util_first_token_match(apr_pool_t *pool, const char *s,
- const char *tokens[], apr_size_t len);
-
/** Match a header value against a string constance, case insensitive */
#define H2_HD_MATCH_LIT(l, name, nlen) \
((nlen == sizeof(l) - 1) && !apr_strnatcasecmp(l, name))
* @macro
* Version number of the http2 module as c string
*/
-#define MOD_HTTP2_VERSION "1.10.10"
+#define MOD_HTTP2_VERSION "1.10.12"
/**
* @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 0x010a0a
+#define MOD_HTTP2_VERSION_NUM 0x010a0b
#endif /* mod_h2_h2_version_h */
}
}
+ ap_log_error(APLOG_MARK, APLOG_TRACE2, 0, workers->s,
+ "h2_workers: new thread for slot %d", slot->id);
/* thread will either immediately start work or add itself
* to the idle queue */
apr_thread_create(&slot->thread, workers->thread_attr, slot_run, slot,