mirror of
https://github.com/nghttp2/nghttp2.git
synced 2025-12-08 19:18:53 +08:00
Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a8d5e5dd9 | ||
|
|
9bcb0ffdef | ||
|
|
1945d0f02a | ||
|
|
4870edb33d | ||
|
|
3abb162969 | ||
|
|
4242478f39 | ||
|
|
4fa2ffe292 | ||
|
|
301df2a856 | ||
|
|
f3b7f4140b | ||
|
|
878b873c69 | ||
|
|
2ca8cf36b7 | ||
|
|
2224b98c9c | ||
|
|
a7031da364 | ||
|
|
cebfdacc5a | ||
|
|
39f89f4a60 | ||
|
|
46b70c1db8 | ||
|
|
5537503172 | ||
|
|
81cc550eb9 | ||
|
|
0a6de0d378 | ||
|
|
25d1de0278 | ||
|
|
39eb8b8a6b | ||
|
|
c050fca177 | ||
|
|
19309823aa | ||
|
|
90bcdb0dda | ||
|
|
17ec30e45c | ||
|
|
07f763be49 | ||
|
|
69119f47c4 | ||
|
|
b0b792e735 | ||
|
|
8aab74ad36 | ||
|
|
f418d1239f | ||
|
|
5b51320dc5 | ||
|
|
d2e81da9e2 |
@@ -67,6 +67,8 @@ required:
|
||||
* zlib >= 1.2.3
|
||||
|
||||
ALPN support requires OpenSSL >= 1.0.2 (released 22 January 2015).
|
||||
LibreSSL >= 2.2.0 can be used instead of OpenSSL, but OpenSSL has more
|
||||
features than LibreSSL at the time of this writing.
|
||||
|
||||
To enable the SPDY protocol in the application program ``nghttpx`` and
|
||||
``h2load``, the following package is required:
|
||||
|
||||
11
configure.ac
11
configure.ac
@@ -25,7 +25,7 @@ dnl Do not change user variables!
|
||||
dnl http://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html
|
||||
|
||||
AC_PREREQ(2.61)
|
||||
AC_INIT([nghttp2], [1.0.2], [t-tujikawa@users.sourceforge.net])
|
||||
AC_INIT([nghttp2], [1.0.4], [t-tujikawa@users.sourceforge.net])
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
|
||||
LT_PREREQ([2.2.6])
|
||||
@@ -48,7 +48,7 @@ AC_CONFIG_HEADERS([config.h])
|
||||
dnl See versioning rule:
|
||||
dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||
AC_SUBST(LT_CURRENT, 14)
|
||||
AC_SUBST(LT_REVISION, 2)
|
||||
AC_SUBST(LT_REVISION, 4)
|
||||
AC_SUBST(LT_AGE, 0)
|
||||
|
||||
major=`echo $PACKAGE_VERSION |cut -d. -f1 | sed -e "s/[^0-9]//g"`
|
||||
@@ -464,11 +464,12 @@ fi
|
||||
|
||||
AM_CONDITIONAL([ENABLE_EXAMPLES], [ test "x${enable_examples}" = "xyes" ])
|
||||
|
||||
# third-party only be built if either enable_examples or enable_app is
|
||||
# yes
|
||||
# third-party only be built when needed
|
||||
|
||||
enable_third_party=no
|
||||
if test "x${enable_examples}" = "xyes" || test "x${enable_app}" = "xyes"; then
|
||||
if test "x${enable_examples}" = "xyes" ||
|
||||
test "x${enable_app}" = "xyes" ||
|
||||
test "x${enable_asio_lib}" = "xyes"; then
|
||||
enable_third_party=yes
|
||||
fi
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "H2LOAD" "1" "June 12, 2015" "1.0.2" "nghttp2"
|
||||
.TH "H2LOAD" "1" "June 23, 2015" "1.0.4" "nghttp2"
|
||||
.SH NAME
|
||||
h2load \- HTTP/2 benchmarking tool
|
||||
.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "NGHTTP" "1" "June 12, 2015" "1.0.2" "nghttp2"
|
||||
.TH "NGHTTP" "1" "June 23, 2015" "1.0.4" "nghttp2"
|
||||
.SH NAME
|
||||
nghttp \- HTTP/2 experimental client
|
||||
.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "NGHTTPD" "1" "June 12, 2015" "1.0.2" "nghttp2"
|
||||
.TH "NGHTTPD" "1" "June 23, 2015" "1.0.4" "nghttp2"
|
||||
.SH NAME
|
||||
nghttpd \- HTTP/2 experimental server
|
||||
.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "NGHTTPX" "1" "June 12, 2015" "1.0.2" "nghttp2"
|
||||
.TH "NGHTTPX" "1" "June 23, 2015" "1.0.4" "nghttp2"
|
||||
.SH NAME
|
||||
nghttpx \- HTTP/2 experimental proxy
|
||||
.
|
||||
@@ -203,9 +203,11 @@ backend addresses specified by \fI\%\-b\fP option.
|
||||
.TP
|
||||
.B \-\-backend\-http1\-connections\-per\-host=<N>
|
||||
Set maximum number of backend concurrent HTTP/1
|
||||
connections per host. This option is meaningful when \fI\%\-s\fP
|
||||
option is used. To limit the number of connections per
|
||||
frontend for default mode, use
|
||||
connections per origin host. This option is meaningful
|
||||
when \fI\%\-s\fP option is used. The origin host is determined
|
||||
by authority portion of requset URI (or :authority
|
||||
header field for HTTP/2). To limit the number of
|
||||
connections per frontend for default mode, use
|
||||
\fI\%\-\-backend\-http1\-connections\-per\-frontend\fP\&.
|
||||
.sp
|
||||
Default: \fB8\fP
|
||||
@@ -890,9 +892,10 @@ both old and new configurations use same filename, new binary does not
|
||||
delete the socket and continues to use it.
|
||||
.SH OCSP STAPLING
|
||||
.sp
|
||||
OCSP query is done using external perl script \fBfetch\-ocsp\-response\fP,
|
||||
which has been developed as part of h2o project
|
||||
(\fI\%https://github.com/h2o/h2o\fP).
|
||||
OCSP query is done using external Python script
|
||||
\fBfetch\-ocsp\-response\fP, which has been originally developed in Perl
|
||||
as part of h2o project (\fI\%https://github.com/h2o/h2o\fP), and was
|
||||
translated into Python.
|
||||
.sp
|
||||
The script file is usually installed under
|
||||
\fB$(prefix)/share/nghttp2/\fP directory. The actual path to script can
|
||||
|
||||
@@ -172,9 +172,11 @@ Performance
|
||||
.. option:: --backend-http1-connections-per-host=<N>
|
||||
|
||||
Set maximum number of backend concurrent HTTP/1
|
||||
connections per host. This option is meaningful when :option:`-s`
|
||||
option is used. To limit the number of connections per
|
||||
frontend for default mode, use
|
||||
connections per origin host. This option is meaningful
|
||||
when :option:`-s` option is used. The origin host is determined
|
||||
by authority portion of requset URI (or :authority
|
||||
header field for HTTP/2). To limit the number of
|
||||
connections per frontend for default mode, use
|
||||
:option:`--backend-http1-connections-per-frontend`\.
|
||||
|
||||
Default: ``8``
|
||||
@@ -805,9 +807,10 @@ delete the socket and continues to use it.
|
||||
OCSP STAPLING
|
||||
-------------
|
||||
|
||||
OCSP query is done using external perl script ``fetch-ocsp-response``,
|
||||
which has been developed as part of h2o project
|
||||
(https://github.com/h2o/h2o).
|
||||
OCSP query is done using external Python script
|
||||
``fetch-ocsp-response``, which has been originally developed in Perl
|
||||
as part of h2o project (https://github.com/h2o/h2o), and was
|
||||
translated into Python.
|
||||
|
||||
The script file is usually installed under
|
||||
``$(prefix)/share/nghttp2/`` directory. The actual path to script can
|
||||
|
||||
@@ -87,9 +87,10 @@ delete the socket and continues to use it.
|
||||
OCSP STAPLING
|
||||
-------------
|
||||
|
||||
OCSP query is done using external perl script ``fetch-ocsp-response``,
|
||||
which has been developed as part of h2o project
|
||||
(https://github.com/h2o/h2o).
|
||||
OCSP query is done using external Python script
|
||||
``fetch-ocsp-response``, which has been originally developed in Perl
|
||||
as part of h2o project (https://github.com/h2o/h2o), and was
|
||||
translated into Python.
|
||||
|
||||
The script file is usually installed under
|
||||
``$(prefix)/share/nghttp2/`` directory. The actual path to script can
|
||||
|
||||
@@ -510,6 +510,28 @@ func TestH2H1SNI(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2H1TLSXfp tests nghttpx sends x-forwarded-proto header field
|
||||
// with http value since :scheme is http, even if the frontend
|
||||
// connection is encrypted.
|
||||
func TestH2H1TLSXfp(t *testing.T) {
|
||||
st := newServerTesterTLS(nil, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("x-forwarded-proto"), "http"; got != want {
|
||||
t.Errorf("x-forwarded-proto: want %v; got %v", want, got)
|
||||
}
|
||||
})
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http2(requestParam{
|
||||
name: "TestH2H1TLSXfp",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http2() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 200; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2H1ServerPush tests server push using Link header field from
|
||||
// backend server.
|
||||
func TestH2H1ServerPush(t *testing.T) {
|
||||
@@ -831,3 +853,25 @@ func TestH2H2NoHostRewrite(t *testing.T) {
|
||||
t.Errorf("request-host: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestH2H2TLSXfp tests nghttpx sends x-forwarded-proto header field
|
||||
// with http value since :scheme is http, even if the frontend
|
||||
// connection is encrypted.
|
||||
func TestH2H2TLSXfp(t *testing.T) {
|
||||
st := newServerTesterTLS([]string{"--http2-bridge"}, t, func(w http.ResponseWriter, r *http.Request) {
|
||||
if got, want := r.Header.Get("x-forwarded-proto"), "http"; got != want {
|
||||
t.Errorf("x-forwarded-proto: want %v; got %v", want, got)
|
||||
}
|
||||
})
|
||||
defer st.Close()
|
||||
|
||||
res, err := st.http2(requestParam{
|
||||
name: "TestH2H2TLSXfp",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Error st.http2() = %v", err)
|
||||
}
|
||||
if got, want := res.status, 200; got != want {
|
||||
t.Errorf("res.status: %v; want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -601,15 +601,12 @@ nghttp2_session_reprioritize_stream(nghttp2_session *session,
|
||||
nghttp2_priority_spec pri_spec_default;
|
||||
const nghttp2_priority_spec *pri_spec = pri_spec_in;
|
||||
|
||||
assert(pri_spec->stream_id != stream->stream_id);
|
||||
|
||||
if (!nghttp2_stream_in_dep_tree(stream)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pri_spec->stream_id == stream->stream_id) {
|
||||
return nghttp2_session_terminate_session_with_reason(
|
||||
session, NGHTTP2_PROTOCOL_ERROR, "depend on itself");
|
||||
}
|
||||
|
||||
if (pri_spec->stream_id != 0) {
|
||||
dep_stream = nghttp2_session_get_stream_raw(session, pri_spec->stream_id);
|
||||
|
||||
@@ -3674,6 +3671,11 @@ int nghttp2_session_on_priority_received(nghttp2_session *session,
|
||||
"PRIORITY: stream_id == 0");
|
||||
}
|
||||
|
||||
if (frame->priority.pri_spec.stream_id == frame->hd.stream_id) {
|
||||
return nghttp2_session_terminate_session_with_reason(
|
||||
session, NGHTTP2_PROTOCOL_ERROR, "depend on itself");
|
||||
}
|
||||
|
||||
if (!session->server) {
|
||||
/* Re-prioritization works only in server */
|
||||
return session_call_on_frame_received(session, frame);
|
||||
@@ -6306,8 +6308,8 @@ int nghttp2_session_pack_data(nghttp2_session *session, nghttp2_bufs *bufs,
|
||||
return rv;
|
||||
}
|
||||
|
||||
session_outbound_item_schedule(session, stream->item,
|
||||
stream->effective_weight);
|
||||
session_outbound_item_schedule(
|
||||
session, stream->item, nghttp2_stream_compute_effective_weight(stream));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -731,7 +731,8 @@ int nghttp2_session_update_local_settings(nghttp2_session *session,
|
||||
|
||||
/*
|
||||
* Re-prioritize |stream|. The new priority specification is
|
||||
* |pri_spec|.
|
||||
* |pri_spec|. Caller must ensure that stream->hd.stream_id !=
|
||||
* pri_spec->stream_id.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
|
||||
@@ -60,7 +60,6 @@ void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
|
||||
stream->dpri = NGHTTP2_STREAM_DPRI_NO_ITEM;
|
||||
stream->num_substreams = 1;
|
||||
stream->weight = weight;
|
||||
stream->effective_weight = stream->weight;
|
||||
stream->sum_dep_weight = 0;
|
||||
stream->sum_norest_weight = 0;
|
||||
|
||||
@@ -107,9 +106,9 @@ static int stream_push_item(nghttp2_stream *stream, nghttp2_session *session) {
|
||||
weight. This will delay low priority stream, which is good.
|
||||
OTOH, this may incur delay for high priority item. Will
|
||||
see. */
|
||||
item->cycle =
|
||||
session->last_cycle +
|
||||
NGHTTP2_DATA_PAYLOADLEN * NGHTTP2_MAX_WEIGHT / stream->effective_weight;
|
||||
item->cycle = session->last_cycle +
|
||||
NGHTTP2_DATA_PAYLOADLEN * NGHTTP2_MAX_WEIGHT /
|
||||
nghttp2_stream_compute_effective_weight(stream);
|
||||
|
||||
rv = nghttp2_pq_push(&session->ob_da_pq, item);
|
||||
if (rv != 0) {
|
||||
@@ -133,13 +132,6 @@ static int stream_push_item(nghttp2_stream *stream, nghttp2_session *session) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static nghttp2_stream *stream_first_sib(nghttp2_stream *stream) {
|
||||
for (; stream->sib_prev; stream = stream->sib_prev)
|
||||
;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
static nghttp2_stream *stream_last_sib(nghttp2_stream *stream) {
|
||||
for (; stream->sib_next; stream = stream->sib_next)
|
||||
;
|
||||
@@ -147,17 +139,12 @@ static nghttp2_stream *stream_last_sib(nghttp2_stream *stream) {
|
||||
return stream;
|
||||
}
|
||||
|
||||
static nghttp2_stream *stream_update_dep_length(nghttp2_stream *stream,
|
||||
ssize_t delta) {
|
||||
static void stream_update_dep_length(nghttp2_stream *stream, ssize_t delta) {
|
||||
stream->num_substreams += delta;
|
||||
|
||||
stream = stream_first_sib(stream);
|
||||
|
||||
if (stream->dep_prev) {
|
||||
return stream_update_dep_length(stream->dep_prev, delta);
|
||||
stream_update_dep_length(stream->dep_prev, delta);
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream,
|
||||
@@ -167,47 +154,6 @@ int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream,
|
||||
return nghttp2_max(1, weight);
|
||||
}
|
||||
|
||||
int32_t nghttp2_stream_dep_distributed_effective_weight(nghttp2_stream *stream,
|
||||
int32_t weight) {
|
||||
if (stream->sum_norest_weight == 0) {
|
||||
return stream->effective_weight;
|
||||
}
|
||||
|
||||
weight = stream->effective_weight * weight / stream->sum_norest_weight;
|
||||
|
||||
return nghttp2_max(1, weight);
|
||||
}
|
||||
|
||||
static void stream_update_dep_set_rest(nghttp2_stream *stream);
|
||||
|
||||
/* Updates effective_weight of descendant streams in subtree of
|
||||
|stream|. We assume that stream->effective_weight is already set
|
||||
right. */
|
||||
static void stream_update_dep_effective_weight(nghttp2_stream *stream) {
|
||||
nghttp2_stream *si;
|
||||
|
||||
DEBUGF(fprintf(stderr, "stream: update_dep_effective_weight "
|
||||
"stream(%p)=%d, weight=%d, sum_norest_weight=%d\n",
|
||||
stream, stream->stream_id, stream->weight,
|
||||
stream->sum_norest_weight));
|
||||
|
||||
/* stream->sum_norest_weight == 0 means there is no
|
||||
NGHTTP2_STREAM_DPRI_TOP under stream */
|
||||
if (stream->dpri != NGHTTP2_STREAM_DPRI_NO_ITEM ||
|
||||
stream->sum_norest_weight == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
if (si->dpri != NGHTTP2_STREAM_DPRI_REST) {
|
||||
si->effective_weight =
|
||||
nghttp2_stream_dep_distributed_effective_weight(stream, si->weight);
|
||||
|
||||
stream_update_dep_effective_weight(si);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void stream_update_dep_set_rest(nghttp2_stream *stream) {
|
||||
if (stream == NULL) {
|
||||
return;
|
||||
@@ -233,27 +179,41 @@ static void stream_update_dep_set_rest(nghttp2_stream *stream) {
|
||||
|
||||
/*
|
||||
* Performs dfs starting |stream|, search stream which can become
|
||||
* NGHTTP2_STREAM_DPRI_TOP and set its dpri.
|
||||
* NGHTTP2_STREAM_DPRI_TOP and set its dpri. This function also
|
||||
* updates sum_norest_weight if stream->dpri ==
|
||||
* NGHTTP2_STREAM_DPRI_NO_ITEM. This function returns nonzero if
|
||||
* stream's subtree contains at least one NGHTTP2_STRAEM_DPRI_TOP
|
||||
* stream.
|
||||
*/
|
||||
static void stream_update_dep_set_top(nghttp2_stream *stream) {
|
||||
static int stream_update_dep_set_top(nghttp2_stream *stream) {
|
||||
nghttp2_stream *si;
|
||||
|
||||
if (stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
|
||||
return;
|
||||
if (!stream) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
stream->sum_norest_weight = 0;
|
||||
|
||||
if (stream->dpri == NGHTTP2_STREAM_DPRI_REST) {
|
||||
DEBUGF(
|
||||
fprintf(stderr, "stream: stream=%d item is top\n", stream->stream_id));
|
||||
|
||||
stream->dpri = NGHTTP2_STREAM_DPRI_TOP;
|
||||
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
stream_update_dep_set_top(si);
|
||||
if (stream_update_dep_set_top(si)) {
|
||||
stream->sum_norest_weight += si->weight;
|
||||
}
|
||||
}
|
||||
|
||||
return stream->sum_norest_weight > 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -288,6 +248,10 @@ static int stream_update_dep_queue_top(nghttp2_stream *stream,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stream->sum_norest_weight == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
rv = stream_update_dep_queue_top(si, session);
|
||||
|
||||
@@ -300,72 +264,113 @@ static int stream_update_dep_queue_top(nghttp2_stream *stream,
|
||||
}
|
||||
|
||||
/*
|
||||
* Updates stream->sum_norest_weight recursively. We have to gather
|
||||
* effective sum of weight of descendants. If stream->dpri ==
|
||||
* NGHTTP2_STREAM_DPRI_NO_ITEM, we have to go deeper and check that
|
||||
* any of its descendants has dpri value of NGHTTP2_STREAM_DPRI_TOP.
|
||||
* If so, we have to add weight of its direct descendants to
|
||||
* stream->sum_norest_weight. To make this work, this function
|
||||
* returns 1 if any of its descendants has dpri value of
|
||||
* NGHTTP2_STREAM_DPRI_TOP, otherwise 0.
|
||||
* Updates stream->sum_norest_weight recursively towards root.
|
||||
* |delta| must not be 0. We have to gather effective sum of weight
|
||||
* of descendants. |delta| is added to stream->sum_norest_weight. If
|
||||
* stream->sum_norest_weight becomes 0, we have to update parent
|
||||
* stream, decreasing its sum_norest_weight by stream->weight. If
|
||||
* stream->sum_norest_weight becomes from 0 to positive, then we have
|
||||
* to update parent stream, increasing its sum_norest_weight by
|
||||
* stream->weight. Otherwise, we stop recursive call.
|
||||
*/
|
||||
static int stream_update_dep_sum_norest_weight(nghttp2_stream *stream) {
|
||||
nghttp2_stream *si;
|
||||
static void stream_update_dep_sum_norest_weight(nghttp2_stream *stream,
|
||||
int32_t delta) {
|
||||
int32_t old;
|
||||
|
||||
stream->sum_norest_weight = 0;
|
||||
|
||||
if (stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
|
||||
return 1;
|
||||
if (!stream) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (stream->dpri == NGHTTP2_STREAM_DPRI_REST) {
|
||||
return 0;
|
||||
assert(delta != 0);
|
||||
assert(stream->sum_norest_weight + delta >= 0);
|
||||
|
||||
old = stream->sum_norest_weight;
|
||||
stream->sum_norest_weight += delta;
|
||||
|
||||
if (old == 0) {
|
||||
assert(delta > 0);
|
||||
stream_update_dep_sum_norest_weight(stream->dep_prev, stream->weight);
|
||||
return;
|
||||
}
|
||||
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
assert(old > 0);
|
||||
|
||||
if (stream_update_dep_sum_norest_weight(si)) {
|
||||
stream->sum_norest_weight += si->weight;
|
||||
if (stream->sum_norest_weight == 0) {
|
||||
stream_update_dep_sum_norest_weight(stream->dep_prev, -stream->weight);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns stream whose dpri is NGHTTP2_STREAM_DPRI_NO_ITEM along the
|
||||
* path following stream->dep_prev (stream's ancestors, including
|
||||
* itself). In other words, find stream which blocks the descendant
|
||||
* streams. If there is no such stream, returns NULL.
|
||||
*/
|
||||
static nghttp2_stream *stream_get_dep_blocking(nghttp2_stream *stream) {
|
||||
for (; stream; stream = stream->dep_prev) {
|
||||
if (stream->dpri != NGHTTP2_STREAM_DPRI_NO_ITEM) {
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
|
||||
return stream->sum_norest_weight > 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int stream_update_dep_on_attach_item(nghttp2_stream *stream,
|
||||
nghttp2_session *session) {
|
||||
nghttp2_stream *root_stream;
|
||||
nghttp2_stream *blocking_stream;
|
||||
int rv;
|
||||
|
||||
stream->dpri = NGHTTP2_STREAM_DPRI_REST;
|
||||
|
||||
blocking_stream = stream_get_dep_blocking(stream->dep_prev);
|
||||
|
||||
/* If we found REST or TOP in ascendants, we don't have to update
|
||||
any metadata. */
|
||||
if (blocking_stream) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
stream->dpri = NGHTTP2_STREAM_DPRI_TOP;
|
||||
if (stream->sum_norest_weight == 0) {
|
||||
stream_update_dep_sum_norest_weight(stream->dep_prev, stream->weight);
|
||||
} else {
|
||||
stream_update_dep_set_rest(stream->dep_next);
|
||||
}
|
||||
|
||||
root_stream = nghttp2_stream_get_dep_root(stream);
|
||||
if (!stream->item->queued) {
|
||||
DEBUGF(fprintf(stderr, "stream: stream=%d enqueue\n", stream->stream_id));
|
||||
rv = stream_push_item(stream, session);
|
||||
|
||||
DEBUGF(fprintf(stderr, "root=%p, stream=%p\n", root_stream, stream));
|
||||
if (rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
stream_update_dep_set_top(root_stream);
|
||||
|
||||
stream_update_dep_sum_norest_weight(root_stream);
|
||||
stream_update_dep_effective_weight(root_stream);
|
||||
|
||||
return stream_update_dep_queue_top(root_stream, session);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stream_update_dep_on_detach_item(nghttp2_stream *stream,
|
||||
nghttp2_session *session) {
|
||||
nghttp2_stream *root_stream;
|
||||
if (stream->dpri == NGHTTP2_STREAM_DPRI_REST) {
|
||||
stream->dpri = NGHTTP2_STREAM_DPRI_NO_ITEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stream->dpri == NGHTTP2_STREAM_DPRI_NO_ITEM) {
|
||||
/* nghttp2_stream_defer_item() does not clear stream->item, but
|
||||
set dpri = NGHTTP2_STREAM_DPRI_NO_ITEM. Catch this case
|
||||
here. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
stream->dpri = NGHTTP2_STREAM_DPRI_NO_ITEM;
|
||||
|
||||
root_stream = nghttp2_stream_get_dep_root(stream);
|
||||
if (stream_update_dep_set_top(stream) == 0) {
|
||||
stream_update_dep_sum_norest_weight(stream->dep_prev, -stream->weight);
|
||||
return 0;
|
||||
}
|
||||
|
||||
stream_update_dep_set_top(root_stream);
|
||||
|
||||
stream_update_dep_sum_norest_weight(root_stream);
|
||||
stream_update_dep_effective_weight(root_stream);
|
||||
|
||||
return stream_update_dep_queue_top(root_stream, session);
|
||||
return stream_update_dep_queue_top(stream->dep_next, session);
|
||||
}
|
||||
|
||||
int nghttp2_stream_attach_item(nghttp2_stream *stream,
|
||||
@@ -465,22 +470,8 @@ void nghttp2_stream_promise_fulfilled(nghttp2_stream *stream) {
|
||||
}
|
||||
|
||||
nghttp2_stream *nghttp2_stream_get_dep_root(nghttp2_stream *stream) {
|
||||
for (;;) {
|
||||
if (stream->sib_prev) {
|
||||
stream = stream->sib_prev;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stream->dep_prev) {
|
||||
stream = stream->dep_prev;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
for (; stream->dep_prev; stream = stream->dep_prev)
|
||||
;
|
||||
return stream;
|
||||
}
|
||||
|
||||
@@ -501,12 +492,25 @@ int nghttp2_stream_dep_subtree_find(nghttp2_stream *stream,
|
||||
return nghttp2_stream_dep_subtree_find(stream->dep_next, target);
|
||||
}
|
||||
|
||||
int32_t nghttp2_stream_compute_effective_weight(nghttp2_stream *stream) {
|
||||
int32_t weight;
|
||||
|
||||
if (!stream->dep_prev) {
|
||||
return stream->weight;
|
||||
}
|
||||
|
||||
weight = nghttp2_stream_compute_effective_weight(stream->dep_prev) *
|
||||
stream->weight / stream->dep_prev->sum_norest_weight;
|
||||
|
||||
return nghttp2_max(1, weight);
|
||||
}
|
||||
|
||||
void nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,
|
||||
nghttp2_stream *stream) {
|
||||
nghttp2_stream *si;
|
||||
nghttp2_stream *root_stream;
|
||||
nghttp2_stream *blocking_stream;
|
||||
|
||||
assert(stream->item == NULL);
|
||||
assert(stream->dpri == NGHTTP2_STREAM_DPRI_NO_ITEM);
|
||||
|
||||
DEBUGF(fprintf(stderr,
|
||||
"stream: dep_insert dep_stream(%p)=%d, stream(%p)=%d\n",
|
||||
@@ -515,34 +519,57 @@ void nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,
|
||||
stream->sum_dep_weight = dep_stream->sum_dep_weight;
|
||||
dep_stream->sum_dep_weight = stream->weight;
|
||||
|
||||
blocking_stream = stream_get_dep_blocking(dep_stream);
|
||||
|
||||
stream->sum_norest_weight = 0;
|
||||
|
||||
if (dep_stream->dep_next) {
|
||||
assert(dep_stream->num_substreams >= 1);
|
||||
/* num_substreams includes node itself */
|
||||
stream->num_substreams = dep_stream->num_substreams;
|
||||
|
||||
for (si = dep_stream->dep_next; si; si = si->sib_next) {
|
||||
stream->num_substreams += si->num_substreams;
|
||||
si->dep_prev = stream;
|
||||
if (!blocking_stream && (si->dpri == NGHTTP2_STREAM_DPRI_TOP ||
|
||||
(si->dpri == NGHTTP2_STREAM_DPRI_NO_ITEM &&
|
||||
si->sum_norest_weight))) {
|
||||
stream->sum_norest_weight += si->weight;
|
||||
}
|
||||
}
|
||||
|
||||
stream->dep_next = dep_stream->dep_next;
|
||||
stream->dep_next->dep_prev = stream;
|
||||
}
|
||||
|
||||
dep_stream->dep_next = stream;
|
||||
stream->dep_prev = dep_stream;
|
||||
|
||||
root_stream = stream_update_dep_length(dep_stream, 1);
|
||||
if (stream->sum_norest_weight) {
|
||||
dep_stream->sum_norest_weight = stream->weight;
|
||||
}
|
||||
|
||||
stream_update_dep_sum_norest_weight(root_stream);
|
||||
stream_update_dep_effective_weight(root_stream);
|
||||
stream_update_dep_length(dep_stream, 1);
|
||||
|
||||
++stream->roots->num_streams;
|
||||
}
|
||||
|
||||
static void link_dep(nghttp2_stream *dep_stream, nghttp2_stream *stream) {
|
||||
dep_stream->dep_next = stream;
|
||||
stream->dep_prev = dep_stream;
|
||||
static void set_dep_prev(nghttp2_stream *stream, nghttp2_stream *dep) {
|
||||
for (; stream; stream = stream->sib_next) {
|
||||
stream->dep_prev = dep;
|
||||
}
|
||||
}
|
||||
|
||||
static void link_sib(nghttp2_stream *prev_stream, nghttp2_stream *stream) {
|
||||
prev_stream->sib_next = stream;
|
||||
stream->sib_prev = prev_stream;
|
||||
static void link_dep(nghttp2_stream *dep_stream, nghttp2_stream *stream) {
|
||||
dep_stream->dep_next = stream;
|
||||
if (stream) {
|
||||
stream->dep_prev = dep_stream;
|
||||
}
|
||||
}
|
||||
|
||||
static void link_sib(nghttp2_stream *a, nghttp2_stream *b) {
|
||||
a->sib_next = b;
|
||||
if (b) {
|
||||
b->sib_prev = a;
|
||||
}
|
||||
}
|
||||
|
||||
static void insert_link_dep(nghttp2_stream *dep_stream,
|
||||
@@ -555,8 +582,6 @@ static void insert_link_dep(nghttp2_stream *dep_stream,
|
||||
|
||||
link_sib(stream, sib_next);
|
||||
|
||||
sib_next->dep_prev = NULL;
|
||||
|
||||
link_dep(dep_stream, stream);
|
||||
}
|
||||
|
||||
@@ -574,10 +599,11 @@ static void unlink_sib(nghttp2_stream *stream) {
|
||||
* |
|
||||
* dep_next
|
||||
*/
|
||||
dep_next->dep_prev = NULL;
|
||||
|
||||
link_sib(prev, dep_next);
|
||||
|
||||
set_dep_prev(dep_next, stream->dep_prev);
|
||||
|
||||
if (stream->sib_next) {
|
||||
link_sib(stream_last_sib(dep_next), stream->sib_next);
|
||||
}
|
||||
@@ -613,9 +639,12 @@ static void unlink_dep(nghttp2_stream *stream) {
|
||||
*/
|
||||
link_dep(prev, dep_next);
|
||||
|
||||
set_dep_prev(dep_next, stream->dep_prev);
|
||||
|
||||
if (stream->sib_next) {
|
||||
link_sib(stream_last_sib(dep_next), stream->sib_next);
|
||||
}
|
||||
|
||||
} else if (stream->sib_next) {
|
||||
/*
|
||||
* prev
|
||||
@@ -634,14 +663,12 @@ static void unlink_dep(nghttp2_stream *stream) {
|
||||
|
||||
void nghttp2_stream_dep_add(nghttp2_stream *dep_stream,
|
||||
nghttp2_stream *stream) {
|
||||
nghttp2_stream *root_stream;
|
||||
|
||||
assert(stream->item == NULL);
|
||||
assert(stream->dpri == NGHTTP2_STREAM_DPRI_NO_ITEM);
|
||||
|
||||
DEBUGF(fprintf(stderr, "stream: dep_add dep_stream(%p)=%d, stream(%p)=%d\n",
|
||||
dep_stream, dep_stream->stream_id, stream, stream->stream_id));
|
||||
|
||||
root_stream = stream_update_dep_length(dep_stream, 1);
|
||||
stream_update_dep_length(dep_stream, 1);
|
||||
|
||||
dep_stream->sum_dep_weight += stream->weight;
|
||||
|
||||
@@ -651,38 +678,50 @@ void nghttp2_stream_dep_add(nghttp2_stream *dep_stream,
|
||||
insert_link_dep(dep_stream, stream);
|
||||
}
|
||||
|
||||
stream_update_dep_sum_norest_weight(root_stream);
|
||||
stream_update_dep_effective_weight(root_stream);
|
||||
|
||||
++stream->roots->num_streams;
|
||||
}
|
||||
|
||||
void nghttp2_stream_dep_remove(nghttp2_stream *stream) {
|
||||
nghttp2_stream *prev, *next, *dep_prev, *si, *root_stream;
|
||||
int32_t sum_dep_weight_delta;
|
||||
nghttp2_stream *next, *dep_prev, *si, *blocking_stream;
|
||||
int32_t sum_dep_weight_delta, sum_norest_weight_delta;
|
||||
|
||||
root_stream = NULL;
|
||||
assert(stream->dpri == NGHTTP2_STREAM_DPRI_NO_ITEM);
|
||||
|
||||
DEBUGF(fprintf(stderr, "stream: dep_remove stream(%p)=%d\n", stream,
|
||||
stream->stream_id));
|
||||
|
||||
blocking_stream = stream_get_dep_blocking(stream->dep_prev);
|
||||
|
||||
/* Distribute weight of |stream| to direct descendants */
|
||||
sum_dep_weight_delta = -stream->weight;
|
||||
|
||||
sum_norest_weight_delta = 0;
|
||||
|
||||
/* blocking_stream == NULL means that ascendants are all
|
||||
NGHTTP2_STREAM_DPRI_NO_ITEM */
|
||||
if (!blocking_stream && stream->sum_norest_weight) {
|
||||
sum_norest_weight_delta -= stream->weight;
|
||||
}
|
||||
|
||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||
si->weight = nghttp2_stream_dep_distributed_weight(stream, si->weight);
|
||||
|
||||
sum_dep_weight_delta += si->weight;
|
||||
|
||||
if (!blocking_stream &&
|
||||
(si->dpri == NGHTTP2_STREAM_DPRI_TOP ||
|
||||
(si->dpri == NGHTTP2_STREAM_DPRI_NO_ITEM && si->sum_norest_weight))) {
|
||||
sum_norest_weight_delta += si->weight;
|
||||
}
|
||||
}
|
||||
|
||||
prev = stream_first_sib(stream);
|
||||
|
||||
dep_prev = prev->dep_prev;
|
||||
dep_prev = stream->dep_prev;
|
||||
|
||||
if (dep_prev) {
|
||||
root_stream = stream_update_dep_length(dep_prev, -1);
|
||||
stream_update_dep_length(dep_prev, -1);
|
||||
|
||||
dep_prev->sum_dep_weight += sum_dep_weight_delta;
|
||||
dep_prev->sum_norest_weight += sum_norest_weight_delta;
|
||||
}
|
||||
|
||||
if (stream->sib_prev) {
|
||||
@@ -702,22 +741,15 @@ void nghttp2_stream_dep_remove(nghttp2_stream *stream) {
|
||||
si->sib_prev = NULL;
|
||||
si->sib_next = NULL;
|
||||
|
||||
/* We already distributed weight of |stream| to this. */
|
||||
si->effective_weight = si->weight;
|
||||
|
||||
nghttp2_stream_roots_add(si->roots, si);
|
||||
|
||||
si = next;
|
||||
}
|
||||
}
|
||||
|
||||
if (root_stream) {
|
||||
stream_update_dep_sum_norest_weight(root_stream);
|
||||
stream_update_dep_effective_weight(root_stream);
|
||||
}
|
||||
|
||||
stream->num_substreams = 1;
|
||||
stream->sum_dep_weight = 0;
|
||||
stream->sum_norest_weight = 0;
|
||||
|
||||
stream->dep_prev = NULL;
|
||||
stream->dep_next = NULL;
|
||||
@@ -732,7 +764,8 @@ int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
|
||||
nghttp2_session *session) {
|
||||
nghttp2_stream *last_sib;
|
||||
nghttp2_stream *dep_next;
|
||||
nghttp2_stream *root_stream;
|
||||
nghttp2_stream *blocking_stream;
|
||||
nghttp2_stream *si;
|
||||
size_t delta_substreams;
|
||||
|
||||
DEBUGF(fprintf(stderr, "stream: dep_insert_subtree dep_stream(%p)=%d "
|
||||
@@ -741,7 +774,7 @@ int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
|
||||
|
||||
delta_substreams = stream->num_substreams;
|
||||
|
||||
stream_update_dep_set_rest(stream);
|
||||
blocking_stream = stream_get_dep_blocking(dep_stream);
|
||||
|
||||
if (dep_stream->dep_next) {
|
||||
/* dep_stream->num_substreams includes dep_stream itself */
|
||||
@@ -752,7 +785,9 @@ int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
|
||||
|
||||
dep_next = dep_stream->dep_next;
|
||||
|
||||
if (!blocking_stream && dep_stream->sum_norest_weight) {
|
||||
stream_update_dep_set_rest(dep_next);
|
||||
}
|
||||
|
||||
link_dep(dep_stream, stream);
|
||||
|
||||
@@ -760,11 +795,13 @@ int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
|
||||
last_sib = stream_last_sib(stream->dep_next);
|
||||
|
||||
link_sib(last_sib, dep_next);
|
||||
|
||||
dep_next->dep_prev = NULL;
|
||||
} else {
|
||||
link_dep(stream, dep_next);
|
||||
}
|
||||
|
||||
for (si = dep_next; si; si = si->sib_next) {
|
||||
si->dep_prev = stream;
|
||||
}
|
||||
} else {
|
||||
link_dep(dep_stream, stream);
|
||||
|
||||
@@ -772,27 +809,33 @@ int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
|
||||
dep_stream->sum_dep_weight = stream->weight;
|
||||
}
|
||||
|
||||
root_stream = stream_update_dep_length(dep_stream, delta_substreams);
|
||||
stream_update_dep_length(dep_stream, delta_substreams);
|
||||
|
||||
stream_update_dep_set_top(root_stream);
|
||||
if (blocking_stream) {
|
||||
stream_update_dep_set_rest(stream);
|
||||
|
||||
stream_update_dep_sum_norest_weight(root_stream);
|
||||
stream_update_dep_effective_weight(root_stream);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return stream_update_dep_queue_top(root_stream, session);
|
||||
if (stream_update_dep_set_top(stream) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
dep_stream->sum_norest_weight = stream->weight;
|
||||
stream_update_dep_sum_norest_weight(dep_stream->dep_prev, dep_stream->weight);
|
||||
|
||||
return stream_update_dep_queue_top(stream, session);
|
||||
}
|
||||
|
||||
int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
|
||||
nghttp2_stream *stream,
|
||||
nghttp2_session *session) {
|
||||
nghttp2_stream *root_stream;
|
||||
nghttp2_stream *blocking_stream;
|
||||
|
||||
DEBUGF(fprintf(stderr, "stream: dep_add_subtree dep_stream(%p)=%d "
|
||||
"stream(%p)=%d\n",
|
||||
dep_stream, dep_stream->stream_id, stream, stream->stream_id));
|
||||
|
||||
stream_update_dep_set_rest(stream);
|
||||
|
||||
if (dep_stream->dep_next) {
|
||||
dep_stream->sum_dep_weight += stream->weight;
|
||||
|
||||
@@ -804,46 +847,52 @@ int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
|
||||
dep_stream->sum_dep_weight = stream->weight;
|
||||
}
|
||||
|
||||
root_stream = stream_update_dep_length(dep_stream, stream->num_substreams);
|
||||
stream_update_dep_length(dep_stream, stream->num_substreams);
|
||||
|
||||
stream_update_dep_set_top(root_stream);
|
||||
blocking_stream = stream_get_dep_blocking(dep_stream);
|
||||
|
||||
stream_update_dep_sum_norest_weight(root_stream);
|
||||
stream_update_dep_effective_weight(root_stream);
|
||||
if (blocking_stream) {
|
||||
/* We cannot make any assumption for stream if its dpri is not
|
||||
NGHTTP2_DPRI_TOP. Just dfs under stream here. */
|
||||
stream_update_dep_set_rest(stream);
|
||||
|
||||
return stream_update_dep_queue_top(root_stream, session);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
|
||||
stream_update_dep_sum_norest_weight(dep_stream, stream->weight);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stream_update_dep_set_top(stream) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Newly added subtree contributes to dep_stream's
|
||||
sum_norest_weight */
|
||||
stream_update_dep_sum_norest_weight(dep_stream, stream->weight);
|
||||
|
||||
return stream_update_dep_queue_top(stream, session);
|
||||
}
|
||||
|
||||
void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream) {
|
||||
nghttp2_stream *prev, *next, *dep_prev, *root_stream;
|
||||
nghttp2_stream *next, *dep_prev, *blocking_stream;
|
||||
|
||||
DEBUGF(fprintf(stderr, "stream: dep_remove_subtree stream(%p)=%d\n", stream,
|
||||
stream->stream_id));
|
||||
|
||||
if (stream->sib_prev) {
|
||||
prev = stream->sib_prev;
|
||||
|
||||
prev->sib_next = stream->sib_next;
|
||||
if (prev->sib_next) {
|
||||
prev->sib_next->sib_prev = prev;
|
||||
}
|
||||
|
||||
prev = stream_first_sib(prev);
|
||||
|
||||
dep_prev = prev->dep_prev;
|
||||
|
||||
link_sib(stream->sib_prev, stream->sib_next);
|
||||
dep_prev = stream->dep_prev;
|
||||
} else if (stream->dep_prev) {
|
||||
dep_prev = stream->dep_prev;
|
||||
next = stream->sib_next;
|
||||
|
||||
dep_prev->dep_next = next;
|
||||
link_dep(dep_prev, next);
|
||||
|
||||
if (next) {
|
||||
next->dep_prev = dep_prev;
|
||||
|
||||
next->sib_prev = NULL;
|
||||
}
|
||||
|
||||
} else {
|
||||
nghttp2_stream_roots_remove(stream->roots, stream);
|
||||
|
||||
@@ -853,10 +902,15 @@ void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream) {
|
||||
if (dep_prev) {
|
||||
dep_prev->sum_dep_weight -= stream->weight;
|
||||
|
||||
root_stream = stream_update_dep_length(dep_prev, -stream->num_substreams);
|
||||
stream_update_dep_length(dep_prev, -stream->num_substreams);
|
||||
|
||||
stream_update_dep_sum_norest_weight(root_stream);
|
||||
stream_update_dep_effective_weight(root_stream);
|
||||
blocking_stream = stream_get_dep_blocking(dep_prev);
|
||||
|
||||
if (!blocking_stream && (stream->dpri == NGHTTP2_STREAM_DPRI_TOP ||
|
||||
(stream->dpri == NGHTTP2_STREAM_DPRI_NO_ITEM &&
|
||||
stream->sum_norest_weight))) {
|
||||
stream_update_dep_sum_norest_weight(dep_prev, -stream->weight);
|
||||
}
|
||||
}
|
||||
|
||||
stream->sib_prev = NULL;
|
||||
@@ -871,14 +925,9 @@ int nghttp2_stream_dep_make_root(nghttp2_stream *stream,
|
||||
|
||||
nghttp2_stream_roots_add(stream->roots, stream);
|
||||
|
||||
stream_update_dep_set_rest(stream);
|
||||
|
||||
stream->effective_weight = stream->weight;
|
||||
|
||||
stream_update_dep_set_top(stream);
|
||||
|
||||
stream_update_dep_sum_norest_weight(stream);
|
||||
stream_update_dep_effective_weight(stream);
|
||||
if (stream_update_dep_set_top(stream) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return stream_update_dep_queue_top(stream, session);
|
||||
}
|
||||
@@ -908,6 +957,13 @@ nghttp2_stream_dep_all_your_stream_are_belong_to_us(nghttp2_stream *stream,
|
||||
stream->sum_dep_weight += first->weight;
|
||||
stream->num_substreams += first->num_substreams;
|
||||
|
||||
if (stream->dpri != NGHTTP2_STREAM_DPRI_NO_ITEM &&
|
||||
(first->dpri == NGHTTP2_STREAM_DPRI_TOP ||
|
||||
(first->dpri == NGHTTP2_STREAM_DPRI_NO_ITEM &&
|
||||
first->sum_norest_weight))) {
|
||||
stream_update_dep_set_rest(first);
|
||||
}
|
||||
|
||||
for (si = first->root_next; si; si = si->root_next) {
|
||||
|
||||
assert(si != stream);
|
||||
@@ -918,7 +974,15 @@ nghttp2_stream_dep_all_your_stream_are_belong_to_us(nghttp2_stream *stream,
|
||||
stream->sum_dep_weight += si->weight;
|
||||
stream->num_substreams += si->num_substreams;
|
||||
|
||||
if (stream->dpri != NGHTTP2_STREAM_DPRI_NO_ITEM &&
|
||||
(si->dpri == NGHTTP2_STREAM_DPRI_TOP ||
|
||||
(si->dpri == NGHTTP2_STREAM_DPRI_NO_ITEM &&
|
||||
si->sum_norest_weight))) {
|
||||
stream_update_dep_set_rest(si);
|
||||
}
|
||||
|
||||
link_sib(prev, si);
|
||||
si->dep_prev = stream;
|
||||
|
||||
prev = si;
|
||||
}
|
||||
@@ -928,8 +992,7 @@ nghttp2_stream_dep_all_your_stream_are_belong_to_us(nghttp2_stream *stream,
|
||||
|
||||
sib_next = stream->dep_next;
|
||||
|
||||
sib_next->dep_prev = NULL;
|
||||
|
||||
first->dep_prev = stream;
|
||||
link_sib(first, sib_next);
|
||||
link_dep(stream, prev);
|
||||
} else {
|
||||
|
||||
@@ -209,13 +209,14 @@ struct nghttp2_stream {
|
||||
int32_t local_window_size;
|
||||
/* weight of this stream */
|
||||
int32_t weight;
|
||||
/* effective weight of this stream in belonging dependency tree */
|
||||
int32_t effective_weight;
|
||||
/* sum of weight (not effective_weight) of direct descendants */
|
||||
/* sum of weight of direct descendants */
|
||||
int32_t sum_dep_weight;
|
||||
/* sum of weight of direct descendants which have at least one
|
||||
descendant with dpri == NGHTTP2_STREAM_DPRI_TOP. We use this
|
||||
value to calculate effective weight. */
|
||||
value to calculate effective weight. This value is only
|
||||
meaningful iff dpri == NGHTTP2_STREAM_DPRI_NO_ITEM and all
|
||||
streams along the path to the root stream (follow dep_prev) have
|
||||
NGHTTP2_STREAM_DPRI_NO_ITEM. */
|
||||
int32_t sum_norest_weight;
|
||||
nghttp2_stream_state state;
|
||||
/* status code from remote server */
|
||||
@@ -325,21 +326,12 @@ int nghttp2_stream_dep_subtree_find(nghttp2_stream *stream,
|
||||
|
||||
/*
|
||||
* Computes distributed weight of a stream of the |weight| under the
|
||||
* |stream| if |stream| is removed from a dependency tree. The result
|
||||
* is computed using stream->weight rather than
|
||||
* stream->effective_weight.
|
||||
* |stream| if |stream| is removed from a dependency tree.
|
||||
*/
|
||||
int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream,
|
||||
int32_t weight);
|
||||
|
||||
/*
|
||||
* Computes effective weight of a stream of the |weight| under the
|
||||
* |stream|. The result is computed using stream->effective_weight
|
||||
* rather than stream->weight. This function is used to determine
|
||||
* weight in dependency tree.
|
||||
*/
|
||||
int32_t nghttp2_stream_dep_distributed_effective_weight(nghttp2_stream *stream,
|
||||
int32_t weight);
|
||||
int32_t nghttp2_stream_compute_effective_weight(nghttp2_stream *stream);
|
||||
|
||||
/*
|
||||
* Makes the |stream| depend on the |dep_stream|. This dependency is
|
||||
|
||||
@@ -142,13 +142,13 @@ def send_and_receive_ocsp(respder_fn, cmd, cert_fn, issuer_fn, ocsp_uri,
|
||||
# obtain response (without verification)
|
||||
sys.stderr.write('sending OCSP request to {}\n'.format(ocsp_uri))
|
||||
args = [
|
||||
cmd, 'ocsp', '-issuer', issuer_fn, '-cert', cert_fn, '-url', ocsp_uri
|
||||
cmd, 'ocsp', '-issuer', issuer_fn, '-cert', cert_fn, '-url', ocsp_uri,
|
||||
'-noverify', '-respout', respder_fn
|
||||
]
|
||||
if openssl_version.lower().startswith('openssl 1.'):
|
||||
ver = openssl_version.lower()
|
||||
if ver.startswith('openssl 1.') or ver.startswith('libressl '):
|
||||
args.extend(['-header', 'Host', ocsp_host])
|
||||
args.extend(['-noverify', '-respout', respder_fn])
|
||||
resp = run_openssl(args, allow_tempfail=True)
|
||||
|
||||
return resp.decode('utf-8')
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@ def fetch_ocsp_response(cmd, cert_fn, tempdir, issuer_fn=None):
|
||||
'fetch-ocsp-response (using {})\n'.format(openssl_version))
|
||||
|
||||
ocsp_uri = extract_ocsp_uri(cmd, cert_fn)
|
||||
ocsp_host = urlparse(ocsp_uri).hostname
|
||||
ocsp_host = urlparse(ocsp_uri).netloc
|
||||
|
||||
if not issuer_fn:
|
||||
issuer_fn = os.path.join(tempdir, 'issuer.crt')
|
||||
|
||||
@@ -100,8 +100,8 @@ template <typename Array> void append_nv(Stream *stream, const Array &nva) {
|
||||
} // namespace
|
||||
|
||||
Config::Config()
|
||||
: stream_read_timeout(60.), stream_write_timeout(60.), data_ptr(nullptr),
|
||||
padding(0), num_worker(1), max_concurrent_streams(100),
|
||||
: stream_read_timeout(1_min), stream_write_timeout(1_min),
|
||||
data_ptr(nullptr), padding(0), num_worker(1), max_concurrent_streams(100),
|
||||
header_table_size(-1), port(0), verbose(false), daemon(false),
|
||||
verify_client(false), no_tls(false), error_gzip(false),
|
||||
early_response(false), hexdump(false), echo_upload(false) {}
|
||||
@@ -453,7 +453,7 @@ int Http2Handler::fill_wb() {
|
||||
|
||||
int Http2Handler::read_clear() {
|
||||
int rv;
|
||||
std::array<uint8_t, 8192> buf;
|
||||
std::array<uint8_t, 8_k> buf;
|
||||
|
||||
for (;;) {
|
||||
ssize_t nread;
|
||||
@@ -570,7 +570,7 @@ int Http2Handler::tls_handshake() {
|
||||
}
|
||||
|
||||
int Http2Handler::read_tls() {
|
||||
std::array<uint8_t, 8192> buf;
|
||||
std::array<uint8_t, 8_k> buf;
|
||||
|
||||
ERR_clear_error();
|
||||
|
||||
@@ -1768,12 +1768,13 @@ int HttpServer::run() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SSL_CTX_set_options(ssl_ctx,
|
||||
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
||||
SSL_OP_NO_COMPRESSION |
|
||||
auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
|
||||
SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION |
|
||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
|
||||
SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_TICKET |
|
||||
SSL_OP_CIPHER_SERVER_PREFERENCE);
|
||||
SSL_OP_CIPHER_SERVER_PREFERENCE;
|
||||
|
||||
SSL_CTX_set_options(ssl_ctx, ssl_opts);
|
||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
|
||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
|
||||
#include "http2.h"
|
||||
#include "buffer.h"
|
||||
#include "template.h"
|
||||
|
||||
namespace nghttp2 {
|
||||
|
||||
@@ -155,7 +156,7 @@ public:
|
||||
|
||||
struct ev_loop *get_loop() const;
|
||||
|
||||
using WriteBuf = Buffer<65536>;
|
||||
using WriteBuf = Buffer<64_k>;
|
||||
|
||||
WriteBuf *get_wb();
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
#include "app_helper.h"
|
||||
#include "util.h"
|
||||
#include "http2.h"
|
||||
#include "template.h"
|
||||
|
||||
namespace nghttp2 {
|
||||
|
||||
@@ -463,7 +464,7 @@ ssize_t deflate_data(uint8_t *out, size_t outlen, const uint8_t *in,
|
||||
size_t inlen) {
|
||||
int rv;
|
||||
z_stream zst;
|
||||
uint8_t temp_out[8192];
|
||||
uint8_t temp_out[8_k];
|
||||
auto temp_outlen = sizeof(temp_out);
|
||||
|
||||
zst.next_in = Z_NULL;
|
||||
|
||||
@@ -313,7 +313,7 @@ bool session_impl::setup_session() {
|
||||
return false;
|
||||
}
|
||||
|
||||
const uint32_t window_size = 256 * 1024 * 1024;
|
||||
const uint32_t window_size = 256_m;
|
||||
|
||||
std::array<nghttp2_settings_entry, 2> iv{
|
||||
{{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100},
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
|
||||
#include <nghttp2/asio_http2_client.h>
|
||||
|
||||
#include "template.h"
|
||||
|
||||
namespace nghttp2 {
|
||||
namespace asio_http2 {
|
||||
namespace client {
|
||||
@@ -90,8 +92,8 @@ public:
|
||||
void do_write();
|
||||
|
||||
protected:
|
||||
boost::array<uint8_t, 8192> rb_;
|
||||
boost::array<uint8_t, 65536> wb_;
|
||||
boost::array<uint8_t, 8_k> rb_;
|
||||
boost::array<uint8_t, 64_k> wb_;
|
||||
std::size_t wblen_;
|
||||
|
||||
private:
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "asio_server_http2_handler.h"
|
||||
#include "asio_server_serve_mux.h"
|
||||
#include "util.h"
|
||||
#include "template.h"
|
||||
|
||||
namespace nghttp2 {
|
||||
|
||||
@@ -153,9 +154,9 @@ private:
|
||||
std::shared_ptr<http2_handler> handler_;
|
||||
|
||||
/// Buffer for incoming data.
|
||||
boost::array<uint8_t, 8192> buffer_;
|
||||
boost::array<uint8_t, 8_k> buffer_;
|
||||
|
||||
boost::array<uint8_t, 65536> outbuf_;
|
||||
boost::array<uint8_t, 64_k> outbuf_;
|
||||
|
||||
bool writing_;
|
||||
};
|
||||
|
||||
@@ -49,11 +49,13 @@ configure_tls_context_easy(boost::system::error_code &ec,
|
||||
|
||||
auto ctx = tls_context.native_handle();
|
||||
|
||||
SSL_CTX_set_options(ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
||||
SSL_OP_NO_COMPRESSION |
|
||||
auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
|
||||
SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION |
|
||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
|
||||
SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_TICKET |
|
||||
SSL_OP_CIPHER_SERVER_PREFERENCE);
|
||||
SSL_OP_CIPHER_SERVER_PREFERENCE;
|
||||
|
||||
SSL_CTX_set_options(ctx, ssl_opts);
|
||||
SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
|
||||
SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
|
||||
|
||||
|
||||
@@ -49,6 +49,10 @@ extern "C" {
|
||||
#include "comp_helper.h"
|
||||
}
|
||||
|
||||
#include "template.h"
|
||||
|
||||
namespace nghttp2 {
|
||||
|
||||
typedef struct {
|
||||
size_t table_size;
|
||||
size_t deflate_table_size;
|
||||
@@ -122,7 +126,7 @@ static void deflate_hd(nghttp2_hd_deflater *deflater,
|
||||
ssize_t rv;
|
||||
nghttp2_bufs bufs;
|
||||
|
||||
nghttp2_bufs_init2(&bufs, 4096, 16, 0, nghttp2_mem_default());
|
||||
nghttp2_bufs_init2(&bufs, 4_k, 16, 0, nghttp2_mem_default());
|
||||
|
||||
rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, (nghttp2_nv *)nva.data(),
|
||||
nva.size());
|
||||
@@ -448,3 +452,7 @@ int main(int argc, char **argv) {
|
||||
output_sum, comp_ratio);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace nghttp2
|
||||
|
||||
int main(int argc, char **argv) { return nghttp2::main(argc, argv); }
|
||||
|
||||
@@ -292,7 +292,8 @@ const char *get_tls_protocol(SSL *ssl) {
|
||||
|
||||
namespace {
|
||||
void print_server_tmp_key(SSL *ssl) {
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
// libressl does not have SSL_get_server_tmp_key
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10002000L && defined(SSL_get_server_tmp_key)
|
||||
EVP_PKEY *key;
|
||||
|
||||
if (!SSL_get_server_tmp_key(ssl, &key)) {
|
||||
@@ -505,7 +506,7 @@ int Client::on_write() {
|
||||
}
|
||||
|
||||
int Client::read_clear() {
|
||||
uint8_t buf[8192];
|
||||
uint8_t buf[8_k];
|
||||
|
||||
for (;;) {
|
||||
ssize_t nread;
|
||||
@@ -625,7 +626,7 @@ int Client::tls_handshake() {
|
||||
}
|
||||
|
||||
int Client::read_tls() {
|
||||
uint8_t buf[8192];
|
||||
uint8_t buf[8_k];
|
||||
|
||||
ERR_clear_error();
|
||||
|
||||
@@ -1276,10 +1277,11 @@ int main(int argc, char **argv) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
SSL_CTX_set_options(ssl_ctx,
|
||||
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
||||
SSL_OP_NO_COMPRESSION |
|
||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
|
||||
auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
|
||||
SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION |
|
||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
|
||||
|
||||
SSL_CTX_set_options(ssl_ctx, ssl_opts);
|
||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
|
||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
|
||||
#include "http2.h"
|
||||
#include "buffer.h"
|
||||
#include "template.h"
|
||||
|
||||
using namespace nghttp2;
|
||||
|
||||
@@ -200,7 +201,7 @@ struct Client {
|
||||
// The number of requests this client has done so far.
|
||||
size_t req_done;
|
||||
int fd;
|
||||
Buffer<65536> wb;
|
||||
Buffer<64_k> wb;
|
||||
|
||||
enum { ERR_CONNECT_FAIL = -100 };
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ struct Header {
|
||||
bool no_index;
|
||||
};
|
||||
|
||||
typedef std::vector<Header> Headers;
|
||||
using Headers = std::vector<Header>;
|
||||
|
||||
namespace http2 {
|
||||
|
||||
|
||||
@@ -228,7 +228,7 @@ template <typename Memchunk> struct Memchunks {
|
||||
size_t len;
|
||||
};
|
||||
|
||||
using Memchunk16K = Memchunk<16384>;
|
||||
using Memchunk16K = Memchunk<16_k>;
|
||||
using MemchunkPool = Pool<Memchunk16K>;
|
||||
using DefaultMemchunks = Memchunks<Memchunk16K>;
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ constexpr auto anchors = std::array<Anchor, 5>{{
|
||||
} // namespace
|
||||
|
||||
Config::Config()
|
||||
: output_upper_thres(1024 * 1024), padding(0),
|
||||
: padding(0),
|
||||
peer_max_concurrent_streams(NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS),
|
||||
header_table_size(-1), weight(NGHTTP2_DEFAULT_WEIGHT), multiply(1),
|
||||
timeout(0.), window_bits(-1), connection_window_bits(-1), verbose(0),
|
||||
@@ -175,6 +175,37 @@ std::string Request::make_reqpath() const {
|
||||
return path;
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Perform special handling |host| if it is IPv6 literal and includes
|
||||
// zone ID per RFC 6874.
|
||||
std::string decode_host(std::string host) {
|
||||
auto zone_start = std::find(std::begin(host), std::end(host), '%');
|
||||
if (zone_start == std::end(host) ||
|
||||
!util::ipv6_numeric_addr(
|
||||
std::string(std::begin(host), zone_start).c_str())) {
|
||||
return std::move(host);
|
||||
}
|
||||
// case: ::1%
|
||||
if (zone_start + 1 == std::end(host)) {
|
||||
host.pop_back();
|
||||
return std::move(host);
|
||||
}
|
||||
// case: ::1%12 or ::1%1
|
||||
if (zone_start + 3 >= std::end(host)) {
|
||||
return std::move(host);
|
||||
}
|
||||
// If we see "%25", followed by more characters, then decode %25 as
|
||||
// '%'.
|
||||
auto zone_id_src = (*(zone_start + 1) == '2' && *(zone_start + 2) == '5')
|
||||
? zone_start + 3
|
||||
: zone_start + 1;
|
||||
auto zone_id = util::percentDecode(zone_id_src, std::end(host));
|
||||
host.erase(zone_start + 1, std::end(host));
|
||||
host += zone_id;
|
||||
return std::move(host);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
nghttp2_priority_spec resolve_dep(int res_type) {
|
||||
nghttp2_priority_spec pri_spec;
|
||||
@@ -331,7 +362,7 @@ int submit_request(HttpClient *client, const Headers &headers, Request *req) {
|
||||
if (config.continuation) {
|
||||
for (size_t i = 0; i < 6; ++i) {
|
||||
build_headers.emplace_back("continuation-test-" + util::utos(i + 1),
|
||||
std::string(4096, '-'));
|
||||
std::string(4_k, '-'));
|
||||
}
|
||||
}
|
||||
auto num_initial_headers = build_headers.size();
|
||||
@@ -603,7 +634,7 @@ void HttpClient::disconnect() {
|
||||
int HttpClient::read_clear() {
|
||||
ev_timer_again(loop, &rt);
|
||||
|
||||
std::array<uint8_t, 8192> buf;
|
||||
std::array<uint8_t, 8_k> buf;
|
||||
|
||||
for (;;) {
|
||||
ssize_t nread;
|
||||
@@ -1118,7 +1149,7 @@ int HttpClient::read_tls() {
|
||||
|
||||
ERR_clear_error();
|
||||
|
||||
std::array<uint8_t, 8192> buf;
|
||||
std::array<uint8_t, 8_k> buf;
|
||||
for (;;) {
|
||||
auto rv = SSL_read(ssl, buf.data(), buf.size());
|
||||
|
||||
@@ -1205,8 +1236,14 @@ void HttpClient::update_hostport() {
|
||||
scheme = util::get_uri_field(reqvec[0]->uri.c_str(), reqvec[0]->u, UF_SCHEMA);
|
||||
std::stringstream ss;
|
||||
if (reqvec[0]->is_ipv6_literal_addr()) {
|
||||
// we may have zone ID, which must start with "%25", or "%". RFC
|
||||
// 6874 defines "%25" only, and just "%" is allowed for just
|
||||
// convenience to end-user input.
|
||||
auto host =
|
||||
util::get_uri_field(reqvec[0]->uri.c_str(), reqvec[0]->u, UF_HOST);
|
||||
auto end = std::find(std::begin(host), std::end(host), '%');
|
||||
ss << "[";
|
||||
util::write_uri_field(ss, reqvec[0]->uri.c_str(), reqvec[0]->u, UF_HOST);
|
||||
ss.write(host.c_str(), end - std::begin(host));
|
||||
ss << "]";
|
||||
} else {
|
||||
util::write_uri_field(ss, reqvec[0]->uri.c_str(), reqvec[0]->u, UF_HOST);
|
||||
@@ -1488,7 +1525,7 @@ int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
|
||||
|
||||
if (req->inflater) {
|
||||
while (len > 0) {
|
||||
const size_t MAX_OUTLEN = 4096;
|
||||
const size_t MAX_OUTLEN = 4_k;
|
||||
std::array<uint8_t, MAX_OUTLEN> out;
|
||||
size_t outlen = MAX_OUTLEN;
|
||||
size_t tlen = len;
|
||||
@@ -1968,10 +2005,12 @@ int communicate(
|
||||
result = -1;
|
||||
goto fin;
|
||||
}
|
||||
SSL_CTX_set_options(ssl_ctx,
|
||||
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
||||
SSL_OP_NO_COMPRESSION |
|
||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
|
||||
|
||||
auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
|
||||
SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION |
|
||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
|
||||
|
||||
SSL_CTX_set_options(ssl_ctx, ssl_opts);
|
||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
|
||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
||||
if (SSL_CTX_set_cipher_list(ssl_ctx, CIPHER_LIST) == 0) {
|
||||
@@ -2036,6 +2075,8 @@ int communicate(
|
||||
client.record_domain_lookup_end_time();
|
||||
|
||||
if (client.initiate_connection() != 0) {
|
||||
std::cerr << "[ERROR] Could not connect to " << host << ", port " << port
|
||||
<< std::endl;
|
||||
goto fin;
|
||||
}
|
||||
ev_run(loop, 0);
|
||||
@@ -2205,7 +2246,7 @@ int run(char **uris, int n) {
|
||||
<< std::endl;
|
||||
}
|
||||
while (1) {
|
||||
std::array<char, 1024> buf;
|
||||
std::array<char, 1_k> buf;
|
||||
ssize_t rret, wret;
|
||||
while ((rret = read(0, buf.data(), buf.size())) == -1 &&
|
||||
errno == EINTR)
|
||||
@@ -2255,29 +2296,35 @@ int run(char **uris, int n) {
|
||||
http_parser_url u;
|
||||
memset(&u, 0, sizeof(u));
|
||||
auto uri = strip_fragment(uris[i]);
|
||||
if (http_parser_parse_url(uri.c_str(), uri.size(), 0, &u) == 0 &&
|
||||
util::has_uri_field(u, UF_SCHEMA)) {
|
||||
uint16_t port = util::has_uri_field(u, UF_PORT)
|
||||
if (http_parser_parse_url(uri.c_str(), uri.size(), 0, &u) != 0) {
|
||||
std::cerr << "[ERROR] Could not parse URI " << uri << std::endl;
|
||||
continue;
|
||||
}
|
||||
if (!util::has_uri_field(u, UF_SCHEMA)) {
|
||||
std::cerr << "[ERROR] URI " << uri << " does not have scheme part"
|
||||
<< std::endl;
|
||||
continue;
|
||||
}
|
||||
auto port = util::has_uri_field(u, UF_PORT)
|
||||
? u.port
|
||||
: util::get_default_port(uri.c_str(), u);
|
||||
auto host = decode_host(util::get_uri_field(uri.c_str(), u, UF_HOST));
|
||||
if (!util::fieldeq(uri.c_str(), u, UF_SCHEMA, prev_scheme.c_str()) ||
|
||||
!util::fieldeq(uri.c_str(), u, UF_HOST, prev_host.c_str()) ||
|
||||
port != prev_port) {
|
||||
host != prev_host || port != prev_port) {
|
||||
if (!requests.empty()) {
|
||||
if (communicate(prev_scheme, prev_host, prev_port,
|
||||
std::move(requests), callbacks) != 0) {
|
||||
if (communicate(prev_scheme, prev_host, prev_port, std::move(requests),
|
||||
callbacks) != 0) {
|
||||
++failures;
|
||||
}
|
||||
requests.clear();
|
||||
}
|
||||
prev_scheme = util::get_uri_field(uri.c_str(), u, UF_SCHEMA);
|
||||
prev_host = util::get_uri_field(uri.c_str(), u, UF_HOST);
|
||||
prev_host = std::move(host);
|
||||
prev_port = port;
|
||||
}
|
||||
requests.emplace_back(uri, data_fd == -1 ? nullptr : &data_prd,
|
||||
data_stat.st_size);
|
||||
}
|
||||
}
|
||||
if (!requests.empty()) {
|
||||
if (communicate(prev_scheme, prev_host, prev_port, std::move(requests),
|
||||
callbacks) != 0) {
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
#include "buffer.h"
|
||||
#include "http2.h"
|
||||
#include "nghttp2_gzip.h"
|
||||
#include "template.h"
|
||||
|
||||
namespace nghttp2 {
|
||||
|
||||
@@ -68,7 +69,6 @@ struct Config {
|
||||
std::string datafile;
|
||||
std::string harfile;
|
||||
nghttp2_option *http2_option;
|
||||
size_t output_upper_thres;
|
||||
size_t padding;
|
||||
ssize_t peer_max_concurrent_streams;
|
||||
ssize_t header_table_size;
|
||||
@@ -260,7 +260,7 @@ struct HttpClient {
|
||||
// true if the response message of HTTP Upgrade request is fully
|
||||
// received. It is not relevant the upgrade succeeds, or not.
|
||||
bool upgrade_response_complete;
|
||||
Buffer<65536> wb;
|
||||
Buffer<64_k> wb;
|
||||
// SETTINGS payload sent as token68 in HTTP Upgrade
|
||||
std::array<uint8_t, 128> settings_payload;
|
||||
|
||||
|
||||
25
src/shrpx.cc
25
src/shrpx.cc
@@ -710,8 +710,7 @@ int event_loop() {
|
||||
}
|
||||
if (auto_tls_ticket_key) {
|
||||
// Renew ticket key every 12hrs
|
||||
ev_timer_init(&renew_ticket_key_timer, renew_ticket_key_cb, 0.,
|
||||
12 * 3600.);
|
||||
ev_timer_init(&renew_ticket_key_timer, renew_ticket_key_cb, 0., 12_h);
|
||||
renew_ticket_key_timer.data = conn_handler.get();
|
||||
ev_timer_again(loop, &renew_ticket_key_timer);
|
||||
|
||||
@@ -831,16 +830,16 @@ void fill_default_config() {
|
||||
mod_config()->cert_file = nullptr;
|
||||
|
||||
// Read timeout for HTTP2 upstream connection
|
||||
mod_config()->http2_upstream_read_timeout = 180.;
|
||||
mod_config()->http2_upstream_read_timeout = 3_min;
|
||||
|
||||
// Read timeout for non-HTTP2 upstream connection
|
||||
mod_config()->upstream_read_timeout = 180.;
|
||||
mod_config()->upstream_read_timeout = 3_min;
|
||||
|
||||
// Write timeout for HTTP2/non-HTTP2 upstream connection
|
||||
mod_config()->upstream_write_timeout = 30.;
|
||||
|
||||
// Read/Write timeouts for downstream connection
|
||||
mod_config()->downstream_read_timeout = 180.;
|
||||
mod_config()->downstream_read_timeout = 3_min;
|
||||
mod_config()->downstream_write_timeout = 30.;
|
||||
|
||||
// Read timeout for HTTP/2 stream
|
||||
@@ -945,17 +944,17 @@ void fill_default_config() {
|
||||
mod_config()->downstream_connections_per_host = 8;
|
||||
mod_config()->downstream_connections_per_frontend = 0;
|
||||
mod_config()->listener_disable_timeout = 0.;
|
||||
mod_config()->downstream_request_buffer_size = 16 * 1024;
|
||||
mod_config()->downstream_response_buffer_size = 16 * 1024;
|
||||
mod_config()->downstream_request_buffer_size = 16_k;
|
||||
mod_config()->downstream_response_buffer_size = 16_k;
|
||||
mod_config()->no_server_push = false;
|
||||
mod_config()->host_unix = false;
|
||||
mod_config()->http2_downstream_connections_per_worker = 0;
|
||||
// ocsp update interval = 14400 secs = 4 hours, borrowed from h2o
|
||||
mod_config()->ocsp_update_interval = 14400.;
|
||||
mod_config()->ocsp_update_interval = 4_h;
|
||||
mod_config()->fetch_ocsp_response_file =
|
||||
strcopy(PKGDATADIR "/fetch-ocsp-response");
|
||||
mod_config()->no_ocsp = false;
|
||||
mod_config()->header_field_buffer = 64 * 1024;
|
||||
mod_config()->header_field_buffer = 64_k;
|
||||
mod_config()->max_header_fields = 100;
|
||||
}
|
||||
} // namespace
|
||||
@@ -1075,9 +1074,11 @@ Performance:
|
||||
backend addresses specified by -b option.
|
||||
--backend-http1-connections-per-host=<N>
|
||||
Set maximum number of backend concurrent HTTP/1
|
||||
connections per host. This option is meaningful when -s
|
||||
option is used. To limit the number of connections per
|
||||
frontend for default mode, use
|
||||
connections per origin host. This option is meaningful
|
||||
when -s option is used. The origin host is determined
|
||||
by authority portion of requset URI (or :authority
|
||||
header field for HTTP/2). To limit the number of
|
||||
connections per frontend for default mode, use
|
||||
--backend-http1-connections-per-frontend.
|
||||
Default: )" << get_config()->downstream_connections_per_host
|
||||
<< R"(
|
||||
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
Worker *get_worker() const;
|
||||
|
||||
using WriteBuf = Buffer<32768>;
|
||||
using ReadBuf = Buffer<8192>;
|
||||
using ReadBuf = Buffer<8_k>;
|
||||
|
||||
WriteBuf *get_wb();
|
||||
ReadBuf *get_rb();
|
||||
|
||||
@@ -455,7 +455,7 @@ int ConnectionHandler::start_ocsp_update(const char *cert_file) {
|
||||
}
|
||||
|
||||
void ConnectionHandler::read_ocsp_chunk() {
|
||||
std::array<uint8_t, 4096> buf;
|
||||
std::array<uint8_t, 4_k> buf;
|
||||
for (;;) {
|
||||
ssize_t n;
|
||||
while ((n = read(ocsp_.fd, buf.data(), buf.size())) == -1 && errno == EINTR)
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
HostEntry();
|
||||
};
|
||||
|
||||
typedef std::map<std::string, HostEntry> HostEntryMap;
|
||||
using HostEntryMap = std::map<std::string, HostEntry>;
|
||||
|
||||
// conn_max_per_host == 0 means no limit for downstream connection.
|
||||
DownstreamQueue(size_t conn_max_per_host = 0, bool unified_host = true);
|
||||
|
||||
@@ -316,13 +316,11 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||
nva.reserve(nheader + 8 + cookies.size() +
|
||||
get_config()->add_request_headers.size());
|
||||
|
||||
std::string via_value;
|
||||
std::string xff_value;
|
||||
std::string scheme, uri_authority, path, query;
|
||||
|
||||
nva.push_back(http2::make_nv_lc(
|
||||
":method", http2::to_method_string(downstream_->get_request_method())));
|
||||
|
||||
auto &scheme = downstream_->get_request_http2_scheme();
|
||||
|
||||
if (downstream_->get_request_method() == HTTP_CONNECT) {
|
||||
if (authority) {
|
||||
nva.push_back(http2::make_nv_lc(":authority", authority));
|
||||
@@ -331,9 +329,8 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||
http2::make_nv_ls(":authority", downstream_->get_request_path()));
|
||||
}
|
||||
} else {
|
||||
assert(!downstream_->get_request_http2_scheme().empty());
|
||||
nva.push_back(
|
||||
http2::make_nv_ls(":scheme", downstream_->get_request_http2_scheme()));
|
||||
assert(!scheme.empty());
|
||||
nva.push_back(http2::make_nv_ls(":scheme", scheme));
|
||||
|
||||
if (authority) {
|
||||
nva.push_back(http2::make_nv_lc(":authority", authority));
|
||||
@@ -362,6 +359,7 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||
nva.push_back(http2::make_nv(nv.name, nv.value, nv.no_index));
|
||||
}
|
||||
|
||||
std::string xff_value;
|
||||
auto xff = downstream_->get_request_header(http2::HD_X_FORWARDED_FOR);
|
||||
if (get_config()->add_x_forwarded_for) {
|
||||
if (xff && !get_config()->strip_incoming_x_forwarded_for) {
|
||||
@@ -378,17 +376,10 @@ int Http2DownstreamConnection::push_request_headers() {
|
||||
if (!get_config()->http2_proxy && !get_config()->client_proxy &&
|
||||
downstream_->get_request_method() != HTTP_CONNECT) {
|
||||
// We use same protocol with :scheme header field
|
||||
if (scheme.empty()) {
|
||||
if (client_handler_->get_ssl()) {
|
||||
nva.push_back(http2::make_nv_ll("x-forwarded-proto", "https"));
|
||||
} else {
|
||||
nva.push_back(http2::make_nv_ll("x-forwarded-proto", "http"));
|
||||
}
|
||||
} else {
|
||||
nva.push_back(http2::make_nv_ls("x-forwarded-proto", scheme));
|
||||
}
|
||||
}
|
||||
|
||||
std::string via_value;
|
||||
auto via = downstream_->get_request_header(http2::HD_VIA);
|
||||
if (get_config()->no_via) {
|
||||
if (via) {
|
||||
|
||||
@@ -177,7 +177,7 @@ public:
|
||||
CONNECTION_CHECK_STARTED
|
||||
};
|
||||
|
||||
using ReadBuf = Buffer<8192>;
|
||||
using ReadBuf = Buffer<8_k>;
|
||||
using WriteBuf = Buffer<32768>;
|
||||
|
||||
private:
|
||||
|
||||
@@ -251,6 +251,9 @@ int HttpDownstreamConnection::push_request_headers() {
|
||||
// Assume that method and request path do not contain \r\n.
|
||||
std::string hdrs = http2::to_method_string(downstream_->get_request_method());
|
||||
hdrs += ' ';
|
||||
|
||||
auto &scheme = downstream_->get_request_http2_scheme();
|
||||
|
||||
if (connect_method) {
|
||||
if (authority) {
|
||||
hdrs += authority;
|
||||
@@ -260,8 +263,8 @@ int HttpDownstreamConnection::push_request_headers() {
|
||||
} else if (get_config()->http2_proxy || get_config()->client_proxy) {
|
||||
// Construct absolute-form request target because we are going to
|
||||
// send a request to a HTTP/1 proxy.
|
||||
assert(!downstream_->get_request_http2_scheme().empty());
|
||||
hdrs += downstream_->get_request_http2_scheme();
|
||||
assert(!scheme.empty());
|
||||
hdrs += scheme;
|
||||
hdrs += "://";
|
||||
|
||||
if (authority) {
|
||||
@@ -344,8 +347,8 @@ int HttpDownstreamConnection::push_request_headers() {
|
||||
if (!get_config()->http2_proxy && !get_config()->client_proxy &&
|
||||
!connect_method) {
|
||||
hdrs += "X-Forwarded-Proto: ";
|
||||
assert(!downstream_->get_request_http2_scheme().empty());
|
||||
hdrs += downstream_->get_request_http2_scheme();
|
||||
assert(!scheme.empty());
|
||||
hdrs += scheme;
|
||||
hdrs += "\r\n";
|
||||
}
|
||||
auto via = downstream_->get_request_header(http2::HD_VIA);
|
||||
@@ -726,7 +729,7 @@ int HttpDownstreamConnection::on_read() {
|
||||
}
|
||||
|
||||
ev_timer_again(conn_.loop, &conn_.rt);
|
||||
std::array<uint8_t, 8192> buf;
|
||||
std::array<uint8_t, 8_k> buf;
|
||||
int rv;
|
||||
|
||||
if (downstream_->get_upgraded()) {
|
||||
|
||||
@@ -125,7 +125,7 @@ Log::~Log() {
|
||||
return;
|
||||
}
|
||||
|
||||
char buf[4096];
|
||||
char buf[4_k];
|
||||
auto tty = lgconf->errorlog_tty;
|
||||
|
||||
lgconf->update_tstamp(std::chrono::system_clock::now());
|
||||
@@ -172,7 +172,7 @@ void upstream_accesslog(const std::vector<LogFragment> &lfv,
|
||||
return;
|
||||
}
|
||||
|
||||
char buf[4096];
|
||||
char buf[4_k];
|
||||
|
||||
auto downstream = lgsp.downstream;
|
||||
|
||||
|
||||
@@ -215,6 +215,14 @@ void on_ctrl_recv_callback(spdylay_session *session, spdylay_frame_type type,
|
||||
return;
|
||||
}
|
||||
|
||||
// For other than CONNECT method, path must start with "/", except
|
||||
// for OPTIONS method, which can take "*" as path.
|
||||
if (!is_connect && path->value[0] != '/' &&
|
||||
(method_token != HTTP_OPTIONS || path->value != "*")) {
|
||||
upstream->rst_stream(downstream, SPDYLAY_PROTOCOL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
downstream->set_request_method(method_token);
|
||||
if (is_connect) {
|
||||
downstream->set_request_http2_authority(path->value);
|
||||
@@ -456,7 +464,7 @@ SpdyUpstream::SpdyUpstream(uint16_t version, ClientHandler *handler)
|
||||
rv = spdylay_session_server_new(&session_, version, &callbacks, this);
|
||||
assert(rv == 0);
|
||||
|
||||
uint32_t max_buffer = 65536;
|
||||
uint32_t max_buffer = 64_k;
|
||||
rv = spdylay_session_set_option(session_,
|
||||
SPDYLAY_OPT_MAX_RECV_CTRL_FRAME_BUFFER,
|
||||
&max_buffer, sizeof(max_buffer));
|
||||
|
||||
@@ -338,12 +338,14 @@ SSL_CTX *create_ssl_context(const char *private_key_file,
|
||||
DIE();
|
||||
}
|
||||
|
||||
SSL_CTX_set_options(
|
||||
ssl_ctx,
|
||||
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION |
|
||||
auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
|
||||
SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION |
|
||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
|
||||
SSL_OP_SINGLE_ECDH_USE | SSL_OP_SINGLE_DH_USE |
|
||||
SSL_OP_CIPHER_SERVER_PREFERENCE | get_config()->tls_proto_mask);
|
||||
SSL_OP_CIPHER_SERVER_PREFERENCE |
|
||||
get_config()->tls_proto_mask;
|
||||
|
||||
SSL_CTX_set_options(ssl_ctx, ssl_opts);
|
||||
|
||||
const unsigned char sid_ctx[] = "shrpx";
|
||||
SSL_CTX_set_session_id_context(ssl_ctx, sid_ctx, sizeof(sid_ctx) - 1);
|
||||
@@ -493,11 +495,13 @@ SSL_CTX *create_ssl_client_context() {
|
||||
LOG(FATAL) << ERR_error_string(ERR_get_error(), nullptr);
|
||||
DIE();
|
||||
}
|
||||
SSL_CTX_set_options(ssl_ctx,
|
||||
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
||||
SSL_OP_NO_COMPRESSION |
|
||||
|
||||
auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
|
||||
SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION |
|
||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
|
||||
get_config()->tls_proto_mask);
|
||||
get_config()->tls_proto_mask;
|
||||
|
||||
SSL_CTX_set_options(ssl_ctx, ssl_opts);
|
||||
|
||||
const char *ciphers;
|
||||
if (get_config()->ciphers) {
|
||||
|
||||
@@ -145,6 +145,26 @@ template <typename T> void dlist_delete_all(DList<T> &dl) {
|
||||
}
|
||||
}
|
||||
|
||||
// User-defined literals for K, M, and G (powers of 1024)
|
||||
|
||||
constexpr unsigned long long operator"" _k(unsigned long long k) {
|
||||
return k * 1024;
|
||||
}
|
||||
|
||||
constexpr unsigned long long operator"" _m(unsigned long long m) {
|
||||
return m * 1024 * 1024;
|
||||
}
|
||||
|
||||
constexpr unsigned long long operator"" _g(unsigned long long g) {
|
||||
return g * 1024 * 1024 * 1024;
|
||||
}
|
||||
|
||||
// User-defined literals for time, converted into double in seconds
|
||||
|
||||
constexpr double operator"" _h(unsigned long long h) { return h * 60 * 60; }
|
||||
|
||||
constexpr double operator"" _min(unsigned long long min) { return min * 60; }
|
||||
|
||||
} // namespace nghttp2
|
||||
|
||||
#endif // TEMPLATE_H
|
||||
|
||||
@@ -52,11 +52,11 @@ namespace nghttp2 {
|
||||
// The additional HTTP/2 protocol ALPN protocol identifier we also
|
||||
// supports for our applications to make smooth migration into final
|
||||
// h2 ALPN ID.
|
||||
#define NGHTTP2_H2_16_ALPN "\x5h2-16"
|
||||
#define NGHTTP2_H2_16 "h2-16"
|
||||
constexpr const char NGHTTP2_H2_16_ALPN[] = "\x5h2-16";
|
||||
constexpr const char NGHTTP2_H2_16[] = "h2-16";
|
||||
|
||||
#define NGHTTP2_H2_14_ALPN "\x5h2-14"
|
||||
#define NGHTTP2_H2_14 "h2-14"
|
||||
constexpr const char NGHTTP2_H2_14_ALPN[] = "\x5h2-14";
|
||||
constexpr const char NGHTTP2_H2_14[] = "h2-14";
|
||||
|
||||
namespace util {
|
||||
|
||||
|
||||
@@ -266,6 +266,8 @@ int main(int argc _U_, char *argv[] _U_) {
|
||||
test_nghttp2_session_send_data_callback) ||
|
||||
!CU_add_test(pSuite, "session_on_begin_headers_temporal_failure",
|
||||
test_nghttp2_session_on_begin_headers_temporal_failure) ||
|
||||
!CU_add_test(pSuite, "session_defer_then_close",
|
||||
test_nghttp2_session_defer_then_close) ||
|
||||
!CU_add_test(pSuite, "http_mandatory_headers",
|
||||
test_nghttp2_http_mandatory_headers) ||
|
||||
!CU_add_test(pSuite, "http_content_length",
|
||||
|
||||
@@ -2163,6 +2163,22 @@ void test_nghttp2_session_on_priority_received(void) {
|
||||
|
||||
nghttp2_frame_priority_free(&frame.priority);
|
||||
nghttp2_session_del(session);
|
||||
|
||||
/* Check again dep_stream_id == stream_id, and stream_id is idle */
|
||||
nghttp2_session_server_new(&session, &callbacks, &user_data);
|
||||
|
||||
nghttp2_priority_spec_init(&pri_spec, 1, 16, 0);
|
||||
|
||||
nghttp2_frame_priority_init(&frame.priority, 1, &pri_spec);
|
||||
|
||||
CU_ASSERT(0 == nghttp2_session_on_priority_received(session, &frame));
|
||||
|
||||
item = nghttp2_session_get_next_ob_item(session);
|
||||
|
||||
CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
|
||||
|
||||
nghttp2_frame_priority_free(&frame.priority);
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
||||
void test_nghttp2_session_on_rst_stream_received(void) {
|
||||
@@ -5526,7 +5542,7 @@ void test_nghttp2_session_stream_dep_add(void) {
|
||||
|
||||
check_stream_dep_sib(a, NULL, b, NULL, NULL);
|
||||
check_stream_dep_sib(b, a, NULL, NULL, c);
|
||||
check_stream_dep_sib(c, NULL, d, b, NULL);
|
||||
check_stream_dep_sib(c, a, d, b, NULL);
|
||||
check_stream_dep_sib(d, c, NULL, NULL, NULL);
|
||||
|
||||
CU_ASSERT(4 == session->roots.num_streams);
|
||||
@@ -5559,7 +5575,7 @@ void test_nghttp2_session_stream_dep_add(void) {
|
||||
check_stream_dep_sib(a, NULL, e, NULL, NULL);
|
||||
check_stream_dep_sib(e, a, b, NULL, NULL);
|
||||
check_stream_dep_sib(b, e, NULL, NULL, c);
|
||||
check_stream_dep_sib(c, NULL, d, b, NULL);
|
||||
check_stream_dep_sib(c, e, d, b, NULL);
|
||||
check_stream_dep_sib(d, c, NULL, NULL, NULL);
|
||||
|
||||
CU_ASSERT(5 == session->roots.num_streams);
|
||||
@@ -5621,7 +5637,7 @@ void test_nghttp2_session_stream_dep_remove(void) {
|
||||
|
||||
nghttp2_session_del(session);
|
||||
|
||||
/* Remove left most stream */
|
||||
/* Remove right most stream */
|
||||
nghttp2_session_server_new(&session, &callbacks, NULL);
|
||||
|
||||
a = open_stream(session, 1);
|
||||
@@ -5667,19 +5683,20 @@ void test_nghttp2_session_stream_dep_remove(void) {
|
||||
|
||||
nghttp2_session_del(session);
|
||||
|
||||
/* Remove right most stream */
|
||||
/* Remove left most stream */
|
||||
nghttp2_session_server_new(&session, &callbacks, NULL);
|
||||
|
||||
a = open_stream(session, 1);
|
||||
b = open_stream_with_dep(session, 3, a);
|
||||
c = open_stream_with_dep(session, 5, a);
|
||||
d = open_stream_with_dep(session, 7, c);
|
||||
e = open_stream_with_dep(session, 9, c);
|
||||
|
||||
/* a
|
||||
* |
|
||||
* c--b
|
||||
* |
|
||||
* d
|
||||
* e--d
|
||||
*/
|
||||
|
||||
nghttp2_stream_dep_remove(c);
|
||||
@@ -5687,23 +5704,26 @@ void test_nghttp2_session_stream_dep_remove(void) {
|
||||
/* becomes:
|
||||
* a
|
||||
* |
|
||||
* d--b
|
||||
* e--d--b
|
||||
*/
|
||||
|
||||
CU_ASSERT(3 == a->num_substreams);
|
||||
CU_ASSERT(4 == a->num_substreams);
|
||||
CU_ASSERT(1 == b->num_substreams);
|
||||
CU_ASSERT(1 == c->num_substreams);
|
||||
CU_ASSERT(1 == d->num_substreams);
|
||||
CU_ASSERT(1 == e->num_substreams);
|
||||
|
||||
CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
|
||||
CU_ASSERT(0 == b->sum_dep_weight);
|
||||
CU_ASSERT(0 == d->sum_dep_weight);
|
||||
CU_ASSERT(0 == c->sum_dep_weight);
|
||||
CU_ASSERT(0 == e->sum_dep_weight);
|
||||
|
||||
check_stream_dep_sib(a, NULL, d, NULL, NULL);
|
||||
check_stream_dep_sib(b, NULL, NULL, d, NULL);
|
||||
check_stream_dep_sib(a, NULL, e, NULL, NULL);
|
||||
check_stream_dep_sib(b, a, NULL, d, NULL);
|
||||
check_stream_dep_sib(c, NULL, NULL, NULL, NULL);
|
||||
check_stream_dep_sib(d, a, NULL, NULL, b);
|
||||
check_stream_dep_sib(d, a, NULL, e, b);
|
||||
check_stream_dep_sib(e, a, NULL, NULL, d);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
|
||||
@@ -5763,10 +5783,10 @@ void test_nghttp2_session_stream_dep_remove(void) {
|
||||
CU_ASSERT(0 == f->sum_dep_weight);
|
||||
|
||||
check_stream_dep_sib(a, NULL, d, NULL, NULL);
|
||||
check_stream_dep_sib(b, NULL, NULL, e, NULL);
|
||||
check_stream_dep_sib(b, a, NULL, e, NULL);
|
||||
check_stream_dep_sib(c, NULL, NULL, NULL, NULL);
|
||||
check_stream_dep_sib(e, NULL, NULL, f, b);
|
||||
check_stream_dep_sib(f, NULL, NULL, d, e);
|
||||
check_stream_dep_sib(e, a, NULL, f, b);
|
||||
check_stream_dep_sib(f, a, NULL, d, e);
|
||||
check_stream_dep_sib(d, a, NULL, NULL, f);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
@@ -5822,8 +5842,8 @@ void test_nghttp2_session_stream_dep_add_subtree(void) {
|
||||
CU_ASSERT(0 == f->sum_dep_weight);
|
||||
|
||||
check_stream_dep_sib(a, NULL, e, NULL, NULL);
|
||||
check_stream_dep_sib(b, NULL, NULL, c, NULL);
|
||||
check_stream_dep_sib(c, NULL, d, e, b);
|
||||
check_stream_dep_sib(b, a, NULL, c, NULL);
|
||||
check_stream_dep_sib(c, a, d, e, b);
|
||||
check_stream_dep_sib(d, c, NULL, NULL, NULL);
|
||||
check_stream_dep_sib(e, a, f, NULL, c);
|
||||
check_stream_dep_sib(f, e, NULL, NULL, NULL);
|
||||
@@ -5877,8 +5897,8 @@ void test_nghttp2_session_stream_dep_add_subtree(void) {
|
||||
check_stream_dep_sib(a, NULL, e, NULL, NULL);
|
||||
check_stream_dep_sib(e, a, f, NULL, NULL);
|
||||
check_stream_dep_sib(f, e, NULL, NULL, c);
|
||||
check_stream_dep_sib(b, NULL, NULL, c, NULL);
|
||||
check_stream_dep_sib(c, NULL, d, f, b);
|
||||
check_stream_dep_sib(b, e, NULL, c, NULL);
|
||||
check_stream_dep_sib(c, e, d, f, b);
|
||||
check_stream_dep_sib(d, c, NULL, NULL, NULL);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
@@ -6011,7 +6031,7 @@ void test_nghttp2_session_stream_dep_remove_subtree(void) {
|
||||
|
||||
check_stream_dep_sib(a, NULL, b, NULL, NULL);
|
||||
check_stream_dep_sib(b, a, NULL, NULL, e);
|
||||
check_stream_dep_sib(e, NULL, NULL, b, NULL);
|
||||
check_stream_dep_sib(e, a, NULL, b, NULL);
|
||||
check_stream_dep_sib(c, NULL, d, NULL, NULL);
|
||||
check_stream_dep_sib(d, c, NULL, NULL, NULL);
|
||||
|
||||
@@ -6022,6 +6042,10 @@ void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void) {
|
||||
nghttp2_session *session;
|
||||
nghttp2_session_callbacks callbacks;
|
||||
nghttp2_stream *a, *b, *c, *d;
|
||||
nghttp2_outbound_item *db, *dc;
|
||||
nghttp2_mem *mem;
|
||||
|
||||
mem = nghttp2_mem_default();
|
||||
|
||||
memset(&callbacks, 0, sizeof(callbacks));
|
||||
|
||||
@@ -6057,6 +6081,10 @@ void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void) {
|
||||
CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
|
||||
CU_ASSERT(0 == b->sum_dep_weight);
|
||||
|
||||
CU_ASSERT(0 == a->sum_norest_weight);
|
||||
CU_ASSERT(0 == b->sum_norest_weight);
|
||||
CU_ASSERT(0 == c->sum_norest_weight);
|
||||
|
||||
check_stream_dep_sib(c, NULL, a, NULL, NULL);
|
||||
check_stream_dep_sib(a, c, b, NULL, NULL);
|
||||
check_stream_dep_sib(b, a, NULL, NULL, NULL);
|
||||
@@ -6066,9 +6094,7 @@ void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void) {
|
||||
nghttp2_session_server_new(&session, &callbacks, NULL);
|
||||
|
||||
a = open_stream(session, 1);
|
||||
|
||||
b = open_stream(session, 3);
|
||||
|
||||
c = open_stream(session, 5);
|
||||
|
||||
/*
|
||||
@@ -6093,9 +6119,13 @@ void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void) {
|
||||
CU_ASSERT(0 == b->sum_dep_weight);
|
||||
CU_ASSERT(0 == a->sum_dep_weight);
|
||||
|
||||
CU_ASSERT(0 == a->sum_norest_weight);
|
||||
CU_ASSERT(0 == b->sum_norest_weight);
|
||||
CU_ASSERT(0 == c->sum_norest_weight);
|
||||
|
||||
check_stream_dep_sib(c, NULL, b, NULL, NULL);
|
||||
check_stream_dep_sib(b, c, NULL, NULL, a);
|
||||
check_stream_dep_sib(a, NULL, NULL, b, NULL);
|
||||
check_stream_dep_sib(a, c, NULL, b, NULL);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
|
||||
@@ -6134,8 +6164,100 @@ void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void) {
|
||||
CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
|
||||
CU_ASSERT(0 == b->sum_dep_weight);
|
||||
|
||||
CU_ASSERT(0 == a->sum_norest_weight);
|
||||
CU_ASSERT(0 == b->sum_norest_weight);
|
||||
CU_ASSERT(0 == c->sum_norest_weight);
|
||||
CU_ASSERT(0 == d->sum_norest_weight);
|
||||
|
||||
check_stream_dep_sib(c, NULL, a, NULL, NULL);
|
||||
check_stream_dep_sib(d, NULL, NULL, a, NULL);
|
||||
check_stream_dep_sib(d, c, NULL, a, NULL);
|
||||
check_stream_dep_sib(a, c, b, NULL, d);
|
||||
check_stream_dep_sib(b, a, NULL, NULL, NULL);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
|
||||
nghttp2_session_server_new(&session, &callbacks, NULL);
|
||||
|
||||
a = open_stream(session, 1);
|
||||
b = open_stream_with_dep(session, 3, a);
|
||||
|
||||
c = open_stream(session, 5);
|
||||
d = open_stream_with_dep(session, 7, c);
|
||||
|
||||
/* a c
|
||||
* | |
|
||||
* b d
|
||||
*/
|
||||
|
||||
db = create_data_ob_item(mem);
|
||||
|
||||
nghttp2_stream_attach_item(b, db, session);
|
||||
|
||||
nghttp2_stream_dep_remove_subtree(c);
|
||||
CU_ASSERT(0 ==
|
||||
nghttp2_stream_dep_all_your_stream_are_belong_to_us(c, session));
|
||||
|
||||
/*
|
||||
* c
|
||||
* |
|
||||
* a--d
|
||||
* |
|
||||
* b
|
||||
*/
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == b->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
|
||||
|
||||
CU_ASSERT(16 == a->sum_norest_weight);
|
||||
CU_ASSERT(16 == c->sum_norest_weight);
|
||||
CU_ASSERT(0 == d->sum_norest_weight);
|
||||
|
||||
check_stream_dep_sib(c, NULL, a, NULL, NULL);
|
||||
check_stream_dep_sib(d, c, NULL, a, NULL);
|
||||
check_stream_dep_sib(a, c, b, NULL, d);
|
||||
check_stream_dep_sib(b, a, NULL, NULL, NULL);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
|
||||
nghttp2_session_server_new(&session, &callbacks, NULL);
|
||||
|
||||
a = open_stream(session, 1);
|
||||
b = open_stream_with_dep(session, 3, a);
|
||||
|
||||
c = open_stream(session, 5);
|
||||
d = open_stream_with_dep(session, 7, c);
|
||||
|
||||
/* a c
|
||||
* | |
|
||||
* b d
|
||||
*/
|
||||
|
||||
db = create_data_ob_item(mem);
|
||||
dc = create_data_ob_item(mem);
|
||||
|
||||
nghttp2_stream_attach_item(b, db, session);
|
||||
nghttp2_stream_attach_item(c, dc, session);
|
||||
|
||||
nghttp2_stream_dep_remove_subtree(c);
|
||||
CU_ASSERT(0 ==
|
||||
nghttp2_stream_dep_all_your_stream_are_belong_to_us(c, session));
|
||||
|
||||
/*
|
||||
* c
|
||||
* |
|
||||
* a--d
|
||||
* |
|
||||
* b
|
||||
*/
|
||||
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == b->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == c->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
|
||||
|
||||
check_stream_dep_sib(c, NULL, a, NULL, NULL);
|
||||
check_stream_dep_sib(d, c, NULL, a, NULL);
|
||||
check_stream_dep_sib(a, c, b, NULL, d);
|
||||
check_stream_dep_sib(b, a, NULL, NULL, NULL);
|
||||
|
||||
@@ -6145,7 +6267,7 @@ void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void) {
|
||||
void test_nghttp2_session_stream_attach_item(void) {
|
||||
nghttp2_session *session;
|
||||
nghttp2_session_callbacks callbacks;
|
||||
nghttp2_stream *a, *b, *c, *d;
|
||||
nghttp2_stream *a, *b, *c, *d, *e;
|
||||
nghttp2_outbound_item *da, *db, *dc, *dd;
|
||||
nghttp2_mem *mem;
|
||||
|
||||
@@ -6176,7 +6298,7 @@ void test_nghttp2_session_stream_attach_item(void) {
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
|
||||
|
||||
CU_ASSERT(16 == b->effective_weight);
|
||||
CU_ASSERT(16 == nghttp2_stream_compute_effective_weight(b));
|
||||
|
||||
CU_ASSERT(16 == a->sum_norest_weight);
|
||||
|
||||
@@ -6191,8 +6313,8 @@ void test_nghttp2_session_stream_attach_item(void) {
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == c->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
|
||||
|
||||
CU_ASSERT(16 * 16 / 32 == b->effective_weight);
|
||||
CU_ASSERT(16 * 16 / 32 == c->effective_weight);
|
||||
CU_ASSERT(16 * 16 / 32 == nghttp2_stream_compute_effective_weight(b));
|
||||
CU_ASSERT(16 * 16 / 32 == nghttp2_stream_compute_effective_weight(c));
|
||||
|
||||
CU_ASSERT(32 == a->sum_norest_weight);
|
||||
|
||||
@@ -6207,7 +6329,7 @@ void test_nghttp2_session_stream_attach_item(void) {
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == c->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
|
||||
|
||||
CU_ASSERT(16 == a->effective_weight);
|
||||
CU_ASSERT(16 == nghttp2_stream_compute_effective_weight(a));
|
||||
|
||||
CU_ASSERT(1 == da->queued);
|
||||
|
||||
@@ -6218,8 +6340,8 @@ void test_nghttp2_session_stream_attach_item(void) {
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == c->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
|
||||
|
||||
CU_ASSERT(16 * 16 / 32 == b->effective_weight);
|
||||
CU_ASSERT(16 * 16 / 32 == c->effective_weight);
|
||||
CU_ASSERT(16 * 16 / 32 == nghttp2_stream_compute_effective_weight(b));
|
||||
CU_ASSERT(16 * 16 / 32 == nghttp2_stream_compute_effective_weight(c));
|
||||
|
||||
dd = create_data_ob_item(mem);
|
||||
|
||||
@@ -6230,8 +6352,8 @@ void test_nghttp2_session_stream_attach_item(void) {
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == c->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == d->dpri);
|
||||
|
||||
CU_ASSERT(16 * 16 / 32 == b->effective_weight);
|
||||
CU_ASSERT(16 * 16 / 32 == c->effective_weight);
|
||||
CU_ASSERT(16 * 16 / 32 == nghttp2_stream_compute_effective_weight(b));
|
||||
CU_ASSERT(16 * 16 / 32 == nghttp2_stream_compute_effective_weight(c));
|
||||
|
||||
CU_ASSERT(0 == dd->queued);
|
||||
|
||||
@@ -6242,8 +6364,8 @@ void test_nghttp2_session_stream_attach_item(void) {
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == d->dpri);
|
||||
|
||||
CU_ASSERT(16 * 16 / 32 == b->effective_weight);
|
||||
CU_ASSERT(16 * 16 / 32 == d->effective_weight);
|
||||
CU_ASSERT(16 * 16 / 32 == nghttp2_stream_compute_effective_weight(b));
|
||||
CU_ASSERT(16 * 16 / 32 == nghttp2_stream_compute_effective_weight(d));
|
||||
|
||||
CU_ASSERT(1 == dd->queued);
|
||||
|
||||
@@ -6254,10 +6376,58 @@ void test_nghttp2_session_stream_attach_item(void) {
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == d->dpri);
|
||||
|
||||
CU_ASSERT(16 * 16 / 16 == d->effective_weight);
|
||||
CU_ASSERT(16 * 16 / 16 == nghttp2_stream_compute_effective_weight(d));
|
||||
|
||||
CU_ASSERT(1 == dd->queued);
|
||||
|
||||
/* exercises insertion */
|
||||
e = open_stream_with_dep_excl(session, 9, a);
|
||||
|
||||
/* a
|
||||
* |
|
||||
* e
|
||||
* |
|
||||
* c--b
|
||||
* |
|
||||
* d
|
||||
*/
|
||||
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == e->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == b->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == d->dpri);
|
||||
|
||||
CU_ASSERT(16 * 16 / 16 == nghttp2_stream_compute_effective_weight(d));
|
||||
|
||||
CU_ASSERT(16 == a->sum_norest_weight);
|
||||
CU_ASSERT(16 == e->sum_norest_weight);
|
||||
CU_ASSERT(16 == c->sum_norest_weight);
|
||||
CU_ASSERT(0 == b->sum_norest_weight);
|
||||
|
||||
/* exercises deletion */
|
||||
nghttp2_stream_dep_remove(e);
|
||||
|
||||
/* a
|
||||
* |
|
||||
* c--b
|
||||
* |
|
||||
* d
|
||||
*/
|
||||
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == b->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == d->dpri);
|
||||
|
||||
CU_ASSERT(16 * 16 / 16 == nghttp2_stream_compute_effective_weight(d));
|
||||
|
||||
/* e's weight 16 is distributed equally among c and b, both now have
|
||||
weight 8 each. */
|
||||
CU_ASSERT(8 == a->sum_norest_weight);
|
||||
CU_ASSERT(16 == c->sum_norest_weight);
|
||||
CU_ASSERT(0 == b->sum_norest_weight);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
||||
@@ -6265,7 +6435,7 @@ void test_nghttp2_session_stream_attach_item_subtree(void) {
|
||||
nghttp2_session *session;
|
||||
nghttp2_session_callbacks callbacks;
|
||||
nghttp2_stream *a, *b, *c, *d, *e, *f;
|
||||
nghttp2_outbound_item *db, *dd, *de;
|
||||
nghttp2_outbound_item *da, *db, *dd, *de;
|
||||
nghttp2_mem *mem;
|
||||
|
||||
mem = nghttp2_mem_default();
|
||||
@@ -6281,6 +6451,8 @@ void test_nghttp2_session_stream_attach_item_subtree(void) {
|
||||
|
||||
e = open_stream(session, 9);
|
||||
f = open_stream_with_dep(session, 11, e);
|
||||
e->weight = 32;
|
||||
|
||||
/*
|
||||
* a e
|
||||
* | |
|
||||
@@ -6304,8 +6476,12 @@ void test_nghttp2_session_stream_attach_item_subtree(void) {
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
|
||||
|
||||
CU_ASSERT(16 == b->effective_weight);
|
||||
CU_ASSERT(16 == e->effective_weight);
|
||||
CU_ASSERT(16 == nghttp2_stream_compute_effective_weight(b));
|
||||
CU_ASSERT(32 == nghttp2_stream_compute_effective_weight(e));
|
||||
|
||||
CU_ASSERT(16 == a->sum_norest_weight);
|
||||
CU_ASSERT(0 == c->sum_norest_weight);
|
||||
CU_ASSERT(0 == d->sum_norest_weight);
|
||||
|
||||
/* Insert subtree e under a */
|
||||
|
||||
@@ -6329,7 +6505,9 @@ void test_nghttp2_session_stream_attach_item_subtree(void) {
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
|
||||
|
||||
CU_ASSERT(16 == e->effective_weight);
|
||||
CU_ASSERT(16 == nghttp2_stream_compute_effective_weight(e));
|
||||
|
||||
CU_ASSERT(32 == a->sum_norest_weight);
|
||||
|
||||
/* Remove subtree b */
|
||||
|
||||
@@ -6354,8 +6532,8 @@ void test_nghttp2_session_stream_attach_item_subtree(void) {
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
|
||||
|
||||
CU_ASSERT(16 == b->effective_weight);
|
||||
CU_ASSERT(16 == e->effective_weight);
|
||||
CU_ASSERT(16 == nghttp2_stream_compute_effective_weight(b));
|
||||
CU_ASSERT(16 == nghttp2_stream_compute_effective_weight(e));
|
||||
|
||||
/* Remove subtree a */
|
||||
|
||||
@@ -6391,10 +6569,15 @@ void test_nghttp2_session_stream_attach_item_subtree(void) {
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
|
||||
|
||||
CU_ASSERT(32 == a->sum_norest_weight);
|
||||
CU_ASSERT(0 == c->sum_norest_weight);
|
||||
|
||||
dd = create_data_ob_item(mem);
|
||||
|
||||
nghttp2_stream_attach_item(d, dd, session);
|
||||
|
||||
CU_ASSERT(16 == c->sum_norest_weight);
|
||||
|
||||
/* Add subtree c to a */
|
||||
|
||||
nghttp2_stream_dep_remove_subtree(c);
|
||||
@@ -6415,11 +6598,11 @@ void test_nghttp2_session_stream_attach_item_subtree(void) {
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
|
||||
|
||||
CU_ASSERT(16 == b->effective_weight);
|
||||
CU_ASSERT(16 * 16 / 32 == e->effective_weight);
|
||||
CU_ASSERT(16 * 16 / 32 == e->effective_weight);
|
||||
CU_ASSERT(16 == nghttp2_stream_compute_effective_weight(b));
|
||||
CU_ASSERT(16 * 16 / 48 == nghttp2_stream_compute_effective_weight(d));
|
||||
CU_ASSERT(16 * 32 / 48 == nghttp2_stream_compute_effective_weight(e));
|
||||
|
||||
CU_ASSERT(32 == a->sum_norest_weight);
|
||||
CU_ASSERT(48 == a->sum_norest_weight);
|
||||
CU_ASSERT(16 == c->sum_norest_weight);
|
||||
|
||||
/* Insert b under a */
|
||||
@@ -6444,10 +6627,9 @@ void test_nghttp2_session_stream_attach_item_subtree(void) {
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == e->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
|
||||
|
||||
CU_ASSERT(16 == b->effective_weight);
|
||||
CU_ASSERT(16 == nghttp2_stream_compute_effective_weight(b));
|
||||
|
||||
CU_ASSERT(16 == a->sum_norest_weight);
|
||||
CU_ASSERT(0 == b->sum_norest_weight);
|
||||
|
||||
/* Remove subtree b */
|
||||
|
||||
@@ -6470,7 +6652,76 @@ void test_nghttp2_session_stream_attach_item_subtree(void) {
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
|
||||
|
||||
CU_ASSERT(0 == a->sum_norest_weight);
|
||||
CU_ASSERT(0 == b->sum_norest_weight);
|
||||
|
||||
/* Remove subtree c, and detach item from b, and then re-add
|
||||
subtree c under b */
|
||||
|
||||
nghttp2_stream_dep_remove_subtree(c);
|
||||
nghttp2_stream_detach_item(b, session);
|
||||
nghttp2_stream_dep_add_subtree(b, c, session);
|
||||
|
||||
/*
|
||||
* b a
|
||||
* |
|
||||
* e--c
|
||||
* | |
|
||||
* f d
|
||||
*/
|
||||
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == a->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == b->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == d->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
|
||||
|
||||
CU_ASSERT(48 == b->sum_norest_weight);
|
||||
|
||||
/* Attach data to a, and add subtree a under b */
|
||||
|
||||
da = create_data_ob_item(mem);
|
||||
nghttp2_stream_attach_item(a, da, session);
|
||||
nghttp2_stream_dep_add_subtree(b, a, session);
|
||||
|
||||
/*
|
||||
* b
|
||||
* |
|
||||
* a--e--c
|
||||
* | |
|
||||
* f d
|
||||
*/
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == a->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == b->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == d->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
|
||||
|
||||
CU_ASSERT(64 == b->sum_norest_weight);
|
||||
|
||||
/* Remove subtree c, and add under f */
|
||||
nghttp2_stream_dep_remove_subtree(c);
|
||||
nghttp2_stream_dep_insert_subtree(f, c, session);
|
||||
|
||||
/*
|
||||
* b
|
||||
* |
|
||||
* a--e
|
||||
* |
|
||||
* f
|
||||
* |
|
||||
* c
|
||||
* |
|
||||
* d
|
||||
*/
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == a->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == b->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == c->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == d->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == e->dpri);
|
||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
|
||||
|
||||
CU_ASSERT(48 == b->sum_norest_weight);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
@@ -7218,6 +7469,45 @@ void test_nghttp2_session_on_begin_headers_temporal_failure(void) {
|
||||
nghttp2_bufs_free(&bufs);
|
||||
}
|
||||
|
||||
void test_nghttp2_session_defer_then_close(void) {
|
||||
nghttp2_session *session;
|
||||
nghttp2_session_callbacks callbacks;
|
||||
nghttp2_data_provider prd;
|
||||
int rv;
|
||||
const uint8_t *datap;
|
||||
ssize_t datalen;
|
||||
nghttp2_frame frame;
|
||||
|
||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||
callbacks.send_callback = null_send_callback;
|
||||
|
||||
nghttp2_session_client_new(&session, &callbacks, NULL);
|
||||
|
||||
prd.read_callback = defer_data_source_read_callback;
|
||||
|
||||
rv = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), &prd, NULL);
|
||||
CU_ASSERT(rv > 0);
|
||||
|
||||
/* This sends HEADERS */
|
||||
datalen = nghttp2_session_mem_send(session, &datap);
|
||||
|
||||
CU_ASSERT(datalen > 0);
|
||||
|
||||
/* This makes DATA item deferred */
|
||||
datalen = nghttp2_session_mem_send(session, &datap);
|
||||
|
||||
CU_ASSERT(datalen == 0);
|
||||
|
||||
nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_CANCEL);
|
||||
|
||||
/* Assertion failure; GH-264 */
|
||||
rv = nghttp2_session_on_rst_stream_received(session, &frame);
|
||||
|
||||
CU_ASSERT(rv == 0);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
||||
static void check_nghttp2_http_recv_headers_fail(
|
||||
nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
|
||||
int stream_state, const nghttp2_nv *nva, size_t nvlen) {
|
||||
|
||||
@@ -126,6 +126,7 @@ void test_nghttp2_session_cancel_reserved_remote(void);
|
||||
void test_nghttp2_session_reset_pending_headers(void);
|
||||
void test_nghttp2_session_send_data_callback(void);
|
||||
void test_nghttp2_session_on_begin_headers_temporal_failure(void);
|
||||
void test_nghttp2_session_defer_then_close(void);
|
||||
void test_nghttp2_http_mandatory_headers(void);
|
||||
void test_nghttp2_http_content_length(void);
|
||||
void test_nghttp2_http_content_length_mismatch(void);
|
||||
|
||||
Reference in New Issue
Block a user