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
|
* zlib >= 1.2.3
|
||||||
|
|
||||||
ALPN support requires OpenSSL >= 1.0.2 (released 22 January 2015).
|
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
|
To enable the SPDY protocol in the application program ``nghttpx`` and
|
||||||
``h2load``, the following package is required:
|
``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
|
dnl http://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html
|
||||||
|
|
||||||
AC_PREREQ(2.61)
|
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
|
AC_USE_SYSTEM_EXTENSIONS
|
||||||
|
|
||||||
LT_PREREQ([2.2.6])
|
LT_PREREQ([2.2.6])
|
||||||
@@ -48,7 +48,7 @@ AC_CONFIG_HEADERS([config.h])
|
|||||||
dnl See versioning rule:
|
dnl See versioning rule:
|
||||||
dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||||
AC_SUBST(LT_CURRENT, 14)
|
AC_SUBST(LT_CURRENT, 14)
|
||||||
AC_SUBST(LT_REVISION, 2)
|
AC_SUBST(LT_REVISION, 4)
|
||||||
AC_SUBST(LT_AGE, 0)
|
AC_SUBST(LT_AGE, 0)
|
||||||
|
|
||||||
major=`echo $PACKAGE_VERSION |cut -d. -f1 | sed -e "s/[^0-9]//g"`
|
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" ])
|
AM_CONDITIONAL([ENABLE_EXAMPLES], [ test "x${enable_examples}" = "xyes" ])
|
||||||
|
|
||||||
# third-party only be built if either enable_examples or enable_app is
|
# third-party only be built when needed
|
||||||
# yes
|
|
||||||
|
|
||||||
enable_third_party=no
|
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
|
enable_third_party=yes
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.\" Man page generated from reStructuredText.
|
.\" 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
|
.SH NAME
|
||||||
h2load \- HTTP/2 benchmarking tool
|
h2load \- HTTP/2 benchmarking tool
|
||||||
.
|
.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.\" Man page generated from reStructuredText.
|
.\" 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
|
.SH NAME
|
||||||
nghttp \- HTTP/2 experimental client
|
nghttp \- HTTP/2 experimental client
|
||||||
.
|
.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.\" Man page generated from reStructuredText.
|
.\" 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
|
.SH NAME
|
||||||
nghttpd \- HTTP/2 experimental server
|
nghttpd \- HTTP/2 experimental server
|
||||||
.
|
.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.\" Man page generated from reStructuredText.
|
.\" 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
|
.SH NAME
|
||||||
nghttpx \- HTTP/2 experimental proxy
|
nghttpx \- HTTP/2 experimental proxy
|
||||||
.
|
.
|
||||||
@@ -203,9 +203,11 @@ backend addresses specified by \fI\%\-b\fP option.
|
|||||||
.TP
|
.TP
|
||||||
.B \-\-backend\-http1\-connections\-per\-host=<N>
|
.B \-\-backend\-http1\-connections\-per\-host=<N>
|
||||||
Set maximum number of backend concurrent HTTP/1
|
Set maximum number of backend concurrent HTTP/1
|
||||||
connections per host. This option is meaningful when \fI\%\-s\fP
|
connections per origin host. This option is meaningful
|
||||||
option is used. To limit the number of connections per
|
when \fI\%\-s\fP option is used. The origin host is determined
|
||||||
frontend for default mode, use
|
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\&.
|
\fI\%\-\-backend\-http1\-connections\-per\-frontend\fP\&.
|
||||||
.sp
|
.sp
|
||||||
Default: \fB8\fP
|
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.
|
delete the socket and continues to use it.
|
||||||
.SH OCSP STAPLING
|
.SH OCSP STAPLING
|
||||||
.sp
|
.sp
|
||||||
OCSP query is done using external perl script \fBfetch\-ocsp\-response\fP,
|
OCSP query is done using external Python script
|
||||||
which has been developed as part of h2o project
|
\fBfetch\-ocsp\-response\fP, which has been originally developed in Perl
|
||||||
(\fI\%https://github.com/h2o/h2o\fP).
|
as part of h2o project (\fI\%https://github.com/h2o/h2o\fP), and was
|
||||||
|
translated into Python.
|
||||||
.sp
|
.sp
|
||||||
The script file is usually installed under
|
The script file is usually installed under
|
||||||
\fB$(prefix)/share/nghttp2/\fP directory. The actual path to script can
|
\fB$(prefix)/share/nghttp2/\fP directory. The actual path to script can
|
||||||
|
|||||||
@@ -172,9 +172,11 @@ Performance
|
|||||||
.. option:: --backend-http1-connections-per-host=<N>
|
.. option:: --backend-http1-connections-per-host=<N>
|
||||||
|
|
||||||
Set maximum number of backend concurrent HTTP/1
|
Set maximum number of backend concurrent HTTP/1
|
||||||
connections per host. This option is meaningful when :option:`-s`
|
connections per origin host. This option is meaningful
|
||||||
option is used. To limit the number of connections per
|
when :option:`-s` option is used. The origin host is determined
|
||||||
frontend for default mode, use
|
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`\.
|
:option:`--backend-http1-connections-per-frontend`\.
|
||||||
|
|
||||||
Default: ``8``
|
Default: ``8``
|
||||||
@@ -805,9 +807,10 @@ delete the socket and continues to use it.
|
|||||||
OCSP STAPLING
|
OCSP STAPLING
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
OCSP query is done using external perl script ``fetch-ocsp-response``,
|
OCSP query is done using external Python script
|
||||||
which has been developed as part of h2o project
|
``fetch-ocsp-response``, which has been originally developed in Perl
|
||||||
(https://github.com/h2o/h2o).
|
as part of h2o project (https://github.com/h2o/h2o), and was
|
||||||
|
translated into Python.
|
||||||
|
|
||||||
The script file is usually installed under
|
The script file is usually installed under
|
||||||
``$(prefix)/share/nghttp2/`` directory. The actual path to script can
|
``$(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 STAPLING
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
OCSP query is done using external perl script ``fetch-ocsp-response``,
|
OCSP query is done using external Python script
|
||||||
which has been developed as part of h2o project
|
``fetch-ocsp-response``, which has been originally developed in Perl
|
||||||
(https://github.com/h2o/h2o).
|
as part of h2o project (https://github.com/h2o/h2o), and was
|
||||||
|
translated into Python.
|
||||||
|
|
||||||
The script file is usually installed under
|
The script file is usually installed under
|
||||||
``$(prefix)/share/nghttp2/`` directory. The actual path to script can
|
``$(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
|
// TestH2H1ServerPush tests server push using Link header field from
|
||||||
// backend server.
|
// backend server.
|
||||||
func TestH2H1ServerPush(t *testing.T) {
|
func TestH2H1ServerPush(t *testing.T) {
|
||||||
@@ -831,3 +853,25 @@ func TestH2H2NoHostRewrite(t *testing.T) {
|
|||||||
t.Errorf("request-host: %v; want %v", got, want)
|
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;
|
nghttp2_priority_spec pri_spec_default;
|
||||||
const nghttp2_priority_spec *pri_spec = pri_spec_in;
|
const nghttp2_priority_spec *pri_spec = pri_spec_in;
|
||||||
|
|
||||||
|
assert(pri_spec->stream_id != stream->stream_id);
|
||||||
|
|
||||||
if (!nghttp2_stream_in_dep_tree(stream)) {
|
if (!nghttp2_stream_in_dep_tree(stream)) {
|
||||||
return 0;
|
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) {
|
if (pri_spec->stream_id != 0) {
|
||||||
dep_stream = nghttp2_session_get_stream_raw(session, pri_spec->stream_id);
|
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");
|
"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) {
|
if (!session->server) {
|
||||||
/* Re-prioritization works only in server */
|
/* Re-prioritization works only in server */
|
||||||
return session_call_on_frame_received(session, frame);
|
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;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
session_outbound_item_schedule(session, stream->item,
|
session_outbound_item_schedule(
|
||||||
stream->effective_weight);
|
session, stream->item, nghttp2_stream_compute_effective_weight(stream));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -731,7 +731,8 @@ int nghttp2_session_update_local_settings(nghttp2_session *session,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Re-prioritize |stream|. The new priority specification is
|
* 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
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
* negative error codes:
|
* 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->dpri = NGHTTP2_STREAM_DPRI_NO_ITEM;
|
||||||
stream->num_substreams = 1;
|
stream->num_substreams = 1;
|
||||||
stream->weight = weight;
|
stream->weight = weight;
|
||||||
stream->effective_weight = stream->weight;
|
|
||||||
stream->sum_dep_weight = 0;
|
stream->sum_dep_weight = 0;
|
||||||
stream->sum_norest_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.
|
weight. This will delay low priority stream, which is good.
|
||||||
OTOH, this may incur delay for high priority item. Will
|
OTOH, this may incur delay for high priority item. Will
|
||||||
see. */
|
see. */
|
||||||
item->cycle =
|
item->cycle = session->last_cycle +
|
||||||
session->last_cycle +
|
NGHTTP2_DATA_PAYLOADLEN * NGHTTP2_MAX_WEIGHT /
|
||||||
NGHTTP2_DATA_PAYLOADLEN * NGHTTP2_MAX_WEIGHT / stream->effective_weight;
|
nghttp2_stream_compute_effective_weight(stream);
|
||||||
|
|
||||||
rv = nghttp2_pq_push(&session->ob_da_pq, item);
|
rv = nghttp2_pq_push(&session->ob_da_pq, item);
|
||||||
if (rv != 0) {
|
if (rv != 0) {
|
||||||
@@ -133,13 +132,6 @@ static int stream_push_item(nghttp2_stream *stream, nghttp2_session *session) {
|
|||||||
return 0;
|
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) {
|
static nghttp2_stream *stream_last_sib(nghttp2_stream *stream) {
|
||||||
for (; stream->sib_next; stream = stream->sib_next)
|
for (; stream->sib_next; stream = stream->sib_next)
|
||||||
;
|
;
|
||||||
@@ -147,17 +139,12 @@ static nghttp2_stream *stream_last_sib(nghttp2_stream *stream) {
|
|||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
static nghttp2_stream *stream_update_dep_length(nghttp2_stream *stream,
|
static void stream_update_dep_length(nghttp2_stream *stream, ssize_t delta) {
|
||||||
ssize_t delta) {
|
|
||||||
stream->num_substreams += delta;
|
stream->num_substreams += delta;
|
||||||
|
|
||||||
stream = stream_first_sib(stream);
|
|
||||||
|
|
||||||
if (stream->dep_prev) {
|
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,
|
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);
|
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) {
|
static void stream_update_dep_set_rest(nghttp2_stream *stream) {
|
||||||
if (stream == NULL) {
|
if (stream == NULL) {
|
||||||
return;
|
return;
|
||||||
@@ -233,29 +179,43 @@ static void stream_update_dep_set_rest(nghttp2_stream *stream) {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Performs dfs starting |stream|, search stream which can become
|
* 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;
|
nghttp2_stream *si;
|
||||||
|
|
||||||
if (stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
|
if (!stream) {
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream->sum_norest_weight = 0;
|
||||||
|
|
||||||
if (stream->dpri == NGHTTP2_STREAM_DPRI_REST) {
|
if (stream->dpri == NGHTTP2_STREAM_DPRI_REST) {
|
||||||
DEBUGF(
|
DEBUGF(
|
||||||
fprintf(stderr, "stream: stream=%d item is top\n", stream->stream_id));
|
fprintf(stderr, "stream: stream=%d item is top\n", stream->stream_id));
|
||||||
|
|
||||||
stream->dpri = NGHTTP2_STREAM_DPRI_TOP;
|
stream->dpri = NGHTTP2_STREAM_DPRI_TOP;
|
||||||
|
|
||||||
return;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Performs dfs starting |stream|, and dueue stream whose dpri is
|
* Performs dfs starting |stream|, and dueue stream whose dpri is
|
||||||
* NGHTTP2_STREAM_DPRI_TOP and has not been queued yet.
|
* NGHTTP2_STREAM_DPRI_TOP and has not been queued yet.
|
||||||
@@ -288,6 +248,10 @@ static int stream_update_dep_queue_top(nghttp2_stream *stream,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stream->sum_norest_weight == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
for (si = stream->dep_next; si; si = si->sib_next) {
|
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||||
rv = stream_update_dep_queue_top(si, session);
|
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
|
* Updates stream->sum_norest_weight recursively towards root.
|
||||||
* effective sum of weight of descendants. If stream->dpri ==
|
* |delta| must not be 0. We have to gather effective sum of weight
|
||||||
* NGHTTP2_STREAM_DPRI_NO_ITEM, we have to go deeper and check that
|
* of descendants. |delta| is added to stream->sum_norest_weight. If
|
||||||
* any of its descendants has dpri value of NGHTTP2_STREAM_DPRI_TOP.
|
* stream->sum_norest_weight becomes 0, we have to update parent
|
||||||
* If so, we have to add weight of its direct descendants to
|
* stream, decreasing its sum_norest_weight by stream->weight. If
|
||||||
* stream->sum_norest_weight. To make this work, this function
|
* stream->sum_norest_weight becomes from 0 to positive, then we have
|
||||||
* returns 1 if any of its descendants has dpri value of
|
* to update parent stream, increasing its sum_norest_weight by
|
||||||
* NGHTTP2_STREAM_DPRI_TOP, otherwise 0.
|
* stream->weight. Otherwise, we stop recursive call.
|
||||||
*/
|
*/
|
||||||
static int stream_update_dep_sum_norest_weight(nghttp2_stream *stream) {
|
static void stream_update_dep_sum_norest_weight(nghttp2_stream *stream,
|
||||||
nghttp2_stream *si;
|
int32_t delta) {
|
||||||
|
int32_t old;
|
||||||
|
|
||||||
stream->sum_norest_weight = 0;
|
if (!stream) {
|
||||||
|
return;
|
||||||
if (stream->dpri == NGHTTP2_STREAM_DPRI_TOP) {
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stream->dpri == NGHTTP2_STREAM_DPRI_REST) {
|
assert(delta != 0);
|
||||||
return 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)) {
|
if (stream->sum_norest_weight == 0) {
|
||||||
stream->sum_norest_weight += si->weight;
|
stream_update_dep_sum_norest_weight(stream->dep_prev, -stream->weight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return stream->sum_norest_weight > 0;
|
/*
|
||||||
|
* 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 NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stream_update_dep_on_attach_item(nghttp2_stream *stream,
|
static int stream_update_dep_on_attach_item(nghttp2_stream *stream,
|
||||||
nghttp2_session *session) {
|
nghttp2_session *session) {
|
||||||
nghttp2_stream *root_stream;
|
nghttp2_stream *blocking_stream;
|
||||||
|
int rv;
|
||||||
|
|
||||||
stream->dpri = NGHTTP2_STREAM_DPRI_REST;
|
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);
|
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);
|
return 0;
|
||||||
|
|
||||||
stream_update_dep_sum_norest_weight(root_stream);
|
|
||||||
stream_update_dep_effective_weight(root_stream);
|
|
||||||
|
|
||||||
return stream_update_dep_queue_top(root_stream, session);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stream_update_dep_on_detach_item(nghttp2_stream *stream,
|
static int stream_update_dep_on_detach_item(nghttp2_stream *stream,
|
||||||
nghttp2_session *session) {
|
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;
|
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);
|
return stream_update_dep_queue_top(stream->dep_next, session);
|
||||||
|
|
||||||
stream_update_dep_sum_norest_weight(root_stream);
|
|
||||||
stream_update_dep_effective_weight(root_stream);
|
|
||||||
|
|
||||||
return stream_update_dep_queue_top(root_stream, session);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int nghttp2_stream_attach_item(nghttp2_stream *stream,
|
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) {
|
nghttp2_stream *nghttp2_stream_get_dep_root(nghttp2_stream *stream) {
|
||||||
for (;;) {
|
for (; stream->dep_prev; stream = stream->dep_prev)
|
||||||
if (stream->sib_prev) {
|
;
|
||||||
stream = stream->sib_prev;
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stream->dep_prev) {
|
|
||||||
stream = stream->dep_prev;
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return stream;
|
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);
|
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,
|
void nghttp2_stream_dep_insert(nghttp2_stream *dep_stream,
|
||||||
nghttp2_stream *stream) {
|
nghttp2_stream *stream) {
|
||||||
nghttp2_stream *si;
|
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,
|
DEBUGF(fprintf(stderr,
|
||||||
"stream: dep_insert dep_stream(%p)=%d, stream(%p)=%d\n",
|
"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;
|
stream->sum_dep_weight = dep_stream->sum_dep_weight;
|
||||||
dep_stream->sum_dep_weight = stream->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) {
|
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) {
|
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_stream->dep_next;
|
||||||
stream->dep_next->dep_prev = stream;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dep_stream->dep_next = stream;
|
dep_stream->dep_next = stream;
|
||||||
stream->dep_prev = dep_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_length(dep_stream, 1);
|
||||||
stream_update_dep_effective_weight(root_stream);
|
|
||||||
|
|
||||||
++stream->roots->num_streams;
|
++stream->roots->num_streams;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void link_dep(nghttp2_stream *dep_stream, nghttp2_stream *stream) {
|
static void set_dep_prev(nghttp2_stream *stream, nghttp2_stream *dep) {
|
||||||
dep_stream->dep_next = stream;
|
for (; stream; stream = stream->sib_next) {
|
||||||
stream->dep_prev = dep_stream;
|
stream->dep_prev = dep;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void link_sib(nghttp2_stream *prev_stream, nghttp2_stream *stream) {
|
static void link_dep(nghttp2_stream *dep_stream, nghttp2_stream *stream) {
|
||||||
prev_stream->sib_next = stream;
|
dep_stream->dep_next = stream;
|
||||||
stream->sib_prev = prev_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,
|
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);
|
link_sib(stream, sib_next);
|
||||||
|
|
||||||
sib_next->dep_prev = NULL;
|
|
||||||
|
|
||||||
link_dep(dep_stream, stream);
|
link_dep(dep_stream, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,10 +599,11 @@ static void unlink_sib(nghttp2_stream *stream) {
|
|||||||
* |
|
* |
|
||||||
* dep_next
|
* dep_next
|
||||||
*/
|
*/
|
||||||
dep_next->dep_prev = NULL;
|
|
||||||
|
|
||||||
link_sib(prev, dep_next);
|
link_sib(prev, dep_next);
|
||||||
|
|
||||||
|
set_dep_prev(dep_next, stream->dep_prev);
|
||||||
|
|
||||||
if (stream->sib_next) {
|
if (stream->sib_next) {
|
||||||
link_sib(stream_last_sib(dep_next), 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);
|
link_dep(prev, dep_next);
|
||||||
|
|
||||||
|
set_dep_prev(dep_next, stream->dep_prev);
|
||||||
|
|
||||||
if (stream->sib_next) {
|
if (stream->sib_next) {
|
||||||
link_sib(stream_last_sib(dep_next), stream->sib_next);
|
link_sib(stream_last_sib(dep_next), stream->sib_next);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (stream->sib_next) {
|
} else if (stream->sib_next) {
|
||||||
/*
|
/*
|
||||||
* prev
|
* prev
|
||||||
@@ -634,14 +663,12 @@ static void unlink_dep(nghttp2_stream *stream) {
|
|||||||
|
|
||||||
void nghttp2_stream_dep_add(nghttp2_stream *dep_stream,
|
void nghttp2_stream_dep_add(nghttp2_stream *dep_stream,
|
||||||
nghttp2_stream *stream) {
|
nghttp2_stream *stream) {
|
||||||
nghttp2_stream *root_stream;
|
assert(stream->dpri == NGHTTP2_STREAM_DPRI_NO_ITEM);
|
||||||
|
|
||||||
assert(stream->item == NULL);
|
|
||||||
|
|
||||||
DEBUGF(fprintf(stderr, "stream: dep_add dep_stream(%p)=%d, stream(%p)=%d\n",
|
DEBUGF(fprintf(stderr, "stream: dep_add dep_stream(%p)=%d, stream(%p)=%d\n",
|
||||||
dep_stream, dep_stream->stream_id, stream, stream->stream_id));
|
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;
|
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);
|
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;
|
++stream->roots->num_streams;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nghttp2_stream_dep_remove(nghttp2_stream *stream) {
|
void nghttp2_stream_dep_remove(nghttp2_stream *stream) {
|
||||||
nghttp2_stream *prev, *next, *dep_prev, *si, *root_stream;
|
nghttp2_stream *next, *dep_prev, *si, *blocking_stream;
|
||||||
int32_t sum_dep_weight_delta;
|
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,
|
DEBUGF(fprintf(stderr, "stream: dep_remove stream(%p)=%d\n", stream,
|
||||||
stream->stream_id));
|
stream->stream_id));
|
||||||
|
|
||||||
|
blocking_stream = stream_get_dep_blocking(stream->dep_prev);
|
||||||
|
|
||||||
/* Distribute weight of |stream| to direct descendants */
|
/* Distribute weight of |stream| to direct descendants */
|
||||||
sum_dep_weight_delta = -stream->weight;
|
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) {
|
for (si = stream->dep_next; si; si = si->sib_next) {
|
||||||
si->weight = nghttp2_stream_dep_distributed_weight(stream, si->weight);
|
si->weight = nghttp2_stream_dep_distributed_weight(stream, si->weight);
|
||||||
|
|
||||||
sum_dep_weight_delta += 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 = stream->dep_prev;
|
||||||
|
|
||||||
dep_prev = prev->dep_prev;
|
|
||||||
|
|
||||||
if (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_dep_weight += sum_dep_weight_delta;
|
||||||
|
dep_prev->sum_norest_weight += sum_norest_weight_delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stream->sib_prev) {
|
if (stream->sib_prev) {
|
||||||
@@ -702,22 +741,15 @@ void nghttp2_stream_dep_remove(nghttp2_stream *stream) {
|
|||||||
si->sib_prev = NULL;
|
si->sib_prev = NULL;
|
||||||
si->sib_next = 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);
|
nghttp2_stream_roots_add(si->roots, si);
|
||||||
|
|
||||||
si = next;
|
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->num_substreams = 1;
|
||||||
stream->sum_dep_weight = 0;
|
stream->sum_dep_weight = 0;
|
||||||
|
stream->sum_norest_weight = 0;
|
||||||
|
|
||||||
stream->dep_prev = NULL;
|
stream->dep_prev = NULL;
|
||||||
stream->dep_next = NULL;
|
stream->dep_next = NULL;
|
||||||
@@ -732,7 +764,8 @@ int nghttp2_stream_dep_insert_subtree(nghttp2_stream *dep_stream,
|
|||||||
nghttp2_session *session) {
|
nghttp2_session *session) {
|
||||||
nghttp2_stream *last_sib;
|
nghttp2_stream *last_sib;
|
||||||
nghttp2_stream *dep_next;
|
nghttp2_stream *dep_next;
|
||||||
nghttp2_stream *root_stream;
|
nghttp2_stream *blocking_stream;
|
||||||
|
nghttp2_stream *si;
|
||||||
size_t delta_substreams;
|
size_t delta_substreams;
|
||||||
|
|
||||||
DEBUGF(fprintf(stderr, "stream: dep_insert_subtree dep_stream(%p)=%d "
|
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;
|
delta_substreams = stream->num_substreams;
|
||||||
|
|
||||||
stream_update_dep_set_rest(stream);
|
blocking_stream = stream_get_dep_blocking(dep_stream);
|
||||||
|
|
||||||
if (dep_stream->dep_next) {
|
if (dep_stream->dep_next) {
|
||||||
/* dep_stream->num_substreams includes dep_stream itself */
|
/* 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;
|
dep_next = dep_stream->dep_next;
|
||||||
|
|
||||||
|
if (!blocking_stream && dep_stream->sum_norest_weight) {
|
||||||
stream_update_dep_set_rest(dep_next);
|
stream_update_dep_set_rest(dep_next);
|
||||||
|
}
|
||||||
|
|
||||||
link_dep(dep_stream, stream);
|
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);
|
last_sib = stream_last_sib(stream->dep_next);
|
||||||
|
|
||||||
link_sib(last_sib, dep_next);
|
link_sib(last_sib, dep_next);
|
||||||
|
|
||||||
dep_next->dep_prev = NULL;
|
|
||||||
} else {
|
} else {
|
||||||
link_dep(stream, dep_next);
|
link_dep(stream, dep_next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (si = dep_next; si; si = si->sib_next) {
|
||||||
|
si->dep_prev = stream;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
link_dep(dep_stream, stream);
|
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;
|
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);
|
return 0;
|
||||||
stream_update_dep_effective_weight(root_stream);
|
}
|
||||||
|
|
||||||
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,
|
int nghttp2_stream_dep_add_subtree(nghttp2_stream *dep_stream,
|
||||||
nghttp2_stream *stream,
|
nghttp2_stream *stream,
|
||||||
nghttp2_session *session) {
|
nghttp2_session *session) {
|
||||||
nghttp2_stream *root_stream;
|
nghttp2_stream *blocking_stream;
|
||||||
|
|
||||||
DEBUGF(fprintf(stderr, "stream: dep_add_subtree dep_stream(%p)=%d "
|
DEBUGF(fprintf(stderr, "stream: dep_add_subtree dep_stream(%p)=%d "
|
||||||
"stream(%p)=%d\n",
|
"stream(%p)=%d\n",
|
||||||
dep_stream, dep_stream->stream_id, stream, stream->stream_id));
|
dep_stream, dep_stream->stream_id, stream, stream->stream_id));
|
||||||
|
|
||||||
stream_update_dep_set_rest(stream);
|
|
||||||
|
|
||||||
if (dep_stream->dep_next) {
|
if (dep_stream->dep_next) {
|
||||||
dep_stream->sum_dep_weight += stream->weight;
|
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;
|
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);
|
if (blocking_stream) {
|
||||||
stream_update_dep_effective_weight(root_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) {
|
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,
|
DEBUGF(fprintf(stderr, "stream: dep_remove_subtree stream(%p)=%d\n", stream,
|
||||||
stream->stream_id));
|
stream->stream_id));
|
||||||
|
|
||||||
if (stream->sib_prev) {
|
if (stream->sib_prev) {
|
||||||
prev = stream->sib_prev;
|
link_sib(stream->sib_prev, stream->sib_next);
|
||||||
|
dep_prev = stream->dep_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;
|
|
||||||
|
|
||||||
} else if (stream->dep_prev) {
|
} else if (stream->dep_prev) {
|
||||||
dep_prev = stream->dep_prev;
|
dep_prev = stream->dep_prev;
|
||||||
next = stream->sib_next;
|
next = stream->sib_next;
|
||||||
|
|
||||||
dep_prev->dep_next = next;
|
link_dep(dep_prev, next);
|
||||||
|
|
||||||
if (next) {
|
if (next) {
|
||||||
next->dep_prev = dep_prev;
|
|
||||||
|
|
||||||
next->sib_prev = NULL;
|
next->sib_prev = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
nghttp2_stream_roots_remove(stream->roots, stream);
|
nghttp2_stream_roots_remove(stream->roots, stream);
|
||||||
|
|
||||||
@@ -853,10 +902,15 @@ void nghttp2_stream_dep_remove_subtree(nghttp2_stream *stream) {
|
|||||||
if (dep_prev) {
|
if (dep_prev) {
|
||||||
dep_prev->sum_dep_weight -= stream->weight;
|
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);
|
blocking_stream = stream_get_dep_blocking(dep_prev);
|
||||||
stream_update_dep_effective_weight(root_stream);
|
|
||||||
|
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;
|
stream->sib_prev = NULL;
|
||||||
@@ -871,14 +925,9 @@ int nghttp2_stream_dep_make_root(nghttp2_stream *stream,
|
|||||||
|
|
||||||
nghttp2_stream_roots_add(stream->roots, stream);
|
nghttp2_stream_roots_add(stream->roots, stream);
|
||||||
|
|
||||||
stream_update_dep_set_rest(stream);
|
if (stream_update_dep_set_top(stream) == 0) {
|
||||||
|
return 0;
|
||||||
stream->effective_weight = stream->weight;
|
}
|
||||||
|
|
||||||
stream_update_dep_set_top(stream);
|
|
||||||
|
|
||||||
stream_update_dep_sum_norest_weight(stream);
|
|
||||||
stream_update_dep_effective_weight(stream);
|
|
||||||
|
|
||||||
return stream_update_dep_queue_top(stream, session);
|
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->sum_dep_weight += first->weight;
|
||||||
stream->num_substreams += first->num_substreams;
|
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) {
|
for (si = first->root_next; si; si = si->root_next) {
|
||||||
|
|
||||||
assert(si != stream);
|
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->sum_dep_weight += si->weight;
|
||||||
stream->num_substreams += si->num_substreams;
|
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);
|
link_sib(prev, si);
|
||||||
|
si->dep_prev = stream;
|
||||||
|
|
||||||
prev = si;
|
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 = stream->dep_next;
|
||||||
|
|
||||||
sib_next->dep_prev = NULL;
|
first->dep_prev = stream;
|
||||||
|
|
||||||
link_sib(first, sib_next);
|
link_sib(first, sib_next);
|
||||||
link_dep(stream, prev);
|
link_dep(stream, prev);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -209,13 +209,14 @@ struct nghttp2_stream {
|
|||||||
int32_t local_window_size;
|
int32_t local_window_size;
|
||||||
/* weight of this stream */
|
/* weight of this stream */
|
||||||
int32_t weight;
|
int32_t weight;
|
||||||
/* effective weight of this stream in belonging dependency tree */
|
/* sum of weight of direct descendants */
|
||||||
int32_t effective_weight;
|
|
||||||
/* sum of weight (not effective_weight) of direct descendants */
|
|
||||||
int32_t sum_dep_weight;
|
int32_t sum_dep_weight;
|
||||||
/* sum of weight of direct descendants which have at least one
|
/* sum of weight of direct descendants which have at least one
|
||||||
descendant with dpri == NGHTTP2_STREAM_DPRI_TOP. We use this
|
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;
|
int32_t sum_norest_weight;
|
||||||
nghttp2_stream_state state;
|
nghttp2_stream_state state;
|
||||||
/* status code from remote server */
|
/* 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
|
* Computes distributed weight of a stream of the |weight| under the
|
||||||
* |stream| if |stream| is removed from a dependency tree. The result
|
* |stream| if |stream| is removed from a dependency tree.
|
||||||
* is computed using stream->weight rather than
|
|
||||||
* stream->effective_weight.
|
|
||||||
*/
|
*/
|
||||||
int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream,
|
int32_t nghttp2_stream_dep_distributed_weight(nghttp2_stream *stream,
|
||||||
int32_t weight);
|
int32_t weight);
|
||||||
|
|
||||||
/*
|
int32_t nghttp2_stream_compute_effective_weight(nghttp2_stream *stream);
|
||||||
* 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);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Makes the |stream| depend on the |dep_stream|. This dependency is
|
* 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)
|
# obtain response (without verification)
|
||||||
sys.stderr.write('sending OCSP request to {}\n'.format(ocsp_uri))
|
sys.stderr.write('sending OCSP request to {}\n'.format(ocsp_uri))
|
||||||
args = [
|
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(['-header', 'Host', ocsp_host])
|
||||||
args.extend(['-noverify', '-respout', respder_fn])
|
|
||||||
resp = run_openssl(args, allow_tempfail=True)
|
resp = run_openssl(args, allow_tempfail=True)
|
||||||
|
|
||||||
return resp.decode('utf-8')
|
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))
|
'fetch-ocsp-response (using {})\n'.format(openssl_version))
|
||||||
|
|
||||||
ocsp_uri = extract_ocsp_uri(cmd, cert_fn)
|
ocsp_uri = extract_ocsp_uri(cmd, cert_fn)
|
||||||
ocsp_host = urlparse(ocsp_uri).hostname
|
ocsp_host = urlparse(ocsp_uri).netloc
|
||||||
|
|
||||||
if not issuer_fn:
|
if not issuer_fn:
|
||||||
issuer_fn = os.path.join(tempdir, 'issuer.crt')
|
issuer_fn = os.path.join(tempdir, 'issuer.crt')
|
||||||
|
|||||||
@@ -100,8 +100,8 @@ template <typename Array> void append_nv(Stream *stream, const Array &nva) {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Config::Config()
|
Config::Config()
|
||||||
: stream_read_timeout(60.), stream_write_timeout(60.), data_ptr(nullptr),
|
: stream_read_timeout(1_min), stream_write_timeout(1_min),
|
||||||
padding(0), num_worker(1), max_concurrent_streams(100),
|
data_ptr(nullptr), padding(0), num_worker(1), max_concurrent_streams(100),
|
||||||
header_table_size(-1), port(0), verbose(false), daemon(false),
|
header_table_size(-1), port(0), verbose(false), daemon(false),
|
||||||
verify_client(false), no_tls(false), error_gzip(false),
|
verify_client(false), no_tls(false), error_gzip(false),
|
||||||
early_response(false), hexdump(false), echo_upload(false) {}
|
early_response(false), hexdump(false), echo_upload(false) {}
|
||||||
@@ -453,7 +453,7 @@ int Http2Handler::fill_wb() {
|
|||||||
|
|
||||||
int Http2Handler::read_clear() {
|
int Http2Handler::read_clear() {
|
||||||
int rv;
|
int rv;
|
||||||
std::array<uint8_t, 8192> buf;
|
std::array<uint8_t, 8_k> buf;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
@@ -570,7 +570,7 @@ int Http2Handler::tls_handshake() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int Http2Handler::read_tls() {
|
int Http2Handler::read_tls() {
|
||||||
std::array<uint8_t, 8192> buf;
|
std::array<uint8_t, 8_k> buf;
|
||||||
|
|
||||||
ERR_clear_error();
|
ERR_clear_error();
|
||||||
|
|
||||||
@@ -1768,12 +1768,13 @@ int HttpServer::run() {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SSL_CTX_set_options(ssl_ctx,
|
auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
|
||||||
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION |
|
||||||
SSL_OP_NO_COMPRESSION |
|
|
||||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
|
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
|
||||||
SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_TICKET |
|
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_AUTO_RETRY);
|
||||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@
|
|||||||
|
|
||||||
#include "http2.h"
|
#include "http2.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "template.h"
|
||||||
|
|
||||||
namespace nghttp2 {
|
namespace nghttp2 {
|
||||||
|
|
||||||
@@ -155,7 +156,7 @@ public:
|
|||||||
|
|
||||||
struct ev_loop *get_loop() const;
|
struct ev_loop *get_loop() const;
|
||||||
|
|
||||||
using WriteBuf = Buffer<65536>;
|
using WriteBuf = Buffer<64_k>;
|
||||||
|
|
||||||
WriteBuf *get_wb();
|
WriteBuf *get_wb();
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,7 @@
|
|||||||
#include "app_helper.h"
|
#include "app_helper.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "http2.h"
|
#include "http2.h"
|
||||||
|
#include "template.h"
|
||||||
|
|
||||||
namespace nghttp2 {
|
namespace nghttp2 {
|
||||||
|
|
||||||
@@ -463,7 +464,7 @@ ssize_t deflate_data(uint8_t *out, size_t outlen, const uint8_t *in,
|
|||||||
size_t inlen) {
|
size_t inlen) {
|
||||||
int rv;
|
int rv;
|
||||||
z_stream zst;
|
z_stream zst;
|
||||||
uint8_t temp_out[8192];
|
uint8_t temp_out[8_k];
|
||||||
auto temp_outlen = sizeof(temp_out);
|
auto temp_outlen = sizeof(temp_out);
|
||||||
|
|
||||||
zst.next_in = Z_NULL;
|
zst.next_in = Z_NULL;
|
||||||
|
|||||||
@@ -313,7 +313,7 @@ bool session_impl::setup_session() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint32_t window_size = 256 * 1024 * 1024;
|
const uint32_t window_size = 256_m;
|
||||||
|
|
||||||
std::array<nghttp2_settings_entry, 2> iv{
|
std::array<nghttp2_settings_entry, 2> iv{
|
||||||
{{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100},
|
{{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100},
|
||||||
|
|||||||
@@ -31,6 +31,8 @@
|
|||||||
|
|
||||||
#include <nghttp2/asio_http2_client.h>
|
#include <nghttp2/asio_http2_client.h>
|
||||||
|
|
||||||
|
#include "template.h"
|
||||||
|
|
||||||
namespace nghttp2 {
|
namespace nghttp2 {
|
||||||
namespace asio_http2 {
|
namespace asio_http2 {
|
||||||
namespace client {
|
namespace client {
|
||||||
@@ -90,8 +92,8 @@ public:
|
|||||||
void do_write();
|
void do_write();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
boost::array<uint8_t, 8192> rb_;
|
boost::array<uint8_t, 8_k> rb_;
|
||||||
boost::array<uint8_t, 65536> wb_;
|
boost::array<uint8_t, 64_k> wb_;
|
||||||
std::size_t wblen_;
|
std::size_t wblen_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -49,6 +49,7 @@
|
|||||||
#include "asio_server_http2_handler.h"
|
#include "asio_server_http2_handler.h"
|
||||||
#include "asio_server_serve_mux.h"
|
#include "asio_server_serve_mux.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "template.h"
|
||||||
|
|
||||||
namespace nghttp2 {
|
namespace nghttp2 {
|
||||||
|
|
||||||
@@ -153,9 +154,9 @@ private:
|
|||||||
std::shared_ptr<http2_handler> handler_;
|
std::shared_ptr<http2_handler> handler_;
|
||||||
|
|
||||||
/// Buffer for incoming data.
|
/// 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_;
|
bool writing_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -49,11 +49,13 @@ configure_tls_context_easy(boost::system::error_code &ec,
|
|||||||
|
|
||||||
auto ctx = tls_context.native_handle();
|
auto ctx = tls_context.native_handle();
|
||||||
|
|
||||||
SSL_CTX_set_options(ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
|
||||||
SSL_OP_NO_COMPRESSION |
|
SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION |
|
||||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
|
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
|
||||||
SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_TICKET |
|
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_AUTO_RETRY);
|
||||||
SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
|
SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,10 @@ extern "C" {
|
|||||||
#include "comp_helper.h"
|
#include "comp_helper.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "template.h"
|
||||||
|
|
||||||
|
namespace nghttp2 {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t table_size;
|
size_t table_size;
|
||||||
size_t deflate_table_size;
|
size_t deflate_table_size;
|
||||||
@@ -122,7 +126,7 @@ static void deflate_hd(nghttp2_hd_deflater *deflater,
|
|||||||
ssize_t rv;
|
ssize_t rv;
|
||||||
nghttp2_bufs bufs;
|
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(),
|
rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, (nghttp2_nv *)nva.data(),
|
||||||
nva.size());
|
nva.size());
|
||||||
@@ -448,3 +452,7 @@ int main(int argc, char **argv) {
|
|||||||
output_sum, comp_ratio);
|
output_sum, comp_ratio);
|
||||||
return 0;
|
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 {
|
namespace {
|
||||||
void print_server_tmp_key(SSL *ssl) {
|
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;
|
EVP_PKEY *key;
|
||||||
|
|
||||||
if (!SSL_get_server_tmp_key(ssl, &key)) {
|
if (!SSL_get_server_tmp_key(ssl, &key)) {
|
||||||
@@ -505,7 +506,7 @@ int Client::on_write() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int Client::read_clear() {
|
int Client::read_clear() {
|
||||||
uint8_t buf[8192];
|
uint8_t buf[8_k];
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
@@ -625,7 +626,7 @@ int Client::tls_handshake() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int Client::read_tls() {
|
int Client::read_tls() {
|
||||||
uint8_t buf[8192];
|
uint8_t buf[8_k];
|
||||||
|
|
||||||
ERR_clear_error();
|
ERR_clear_error();
|
||||||
|
|
||||||
@@ -1276,10 +1277,11 @@ int main(int argc, char **argv) {
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
SSL_CTX_set_options(ssl_ctx,
|
auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
|
||||||
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION |
|
||||||
SSL_OP_NO_COMPRESSION |
|
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
|
||||||
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_AUTO_RETRY);
|
||||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,7 @@
|
|||||||
|
|
||||||
#include "http2.h"
|
#include "http2.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "template.h"
|
||||||
|
|
||||||
using namespace nghttp2;
|
using namespace nghttp2;
|
||||||
|
|
||||||
@@ -200,7 +201,7 @@ struct Client {
|
|||||||
// The number of requests this client has done so far.
|
// The number of requests this client has done so far.
|
||||||
size_t req_done;
|
size_t req_done;
|
||||||
int fd;
|
int fd;
|
||||||
Buffer<65536> wb;
|
Buffer<64_k> wb;
|
||||||
|
|
||||||
enum { ERR_CONNECT_FAIL = -100 };
|
enum { ERR_CONNECT_FAIL = -100 };
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ struct Header {
|
|||||||
bool no_index;
|
bool no_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<Header> Headers;
|
using Headers = std::vector<Header>;
|
||||||
|
|
||||||
namespace http2 {
|
namespace http2 {
|
||||||
|
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ template <typename Memchunk> struct Memchunks {
|
|||||||
size_t len;
|
size_t len;
|
||||||
};
|
};
|
||||||
|
|
||||||
using Memchunk16K = Memchunk<16384>;
|
using Memchunk16K = Memchunk<16_k>;
|
||||||
using MemchunkPool = Pool<Memchunk16K>;
|
using MemchunkPool = Pool<Memchunk16K>;
|
||||||
using DefaultMemchunks = Memchunks<Memchunk16K>;
|
using DefaultMemchunks = Memchunks<Memchunk16K>;
|
||||||
|
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ constexpr auto anchors = std::array<Anchor, 5>{{
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Config::Config()
|
Config::Config()
|
||||||
: output_upper_thres(1024 * 1024), padding(0),
|
: padding(0),
|
||||||
peer_max_concurrent_streams(NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS),
|
peer_max_concurrent_streams(NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS),
|
||||||
header_table_size(-1), weight(NGHTTP2_DEFAULT_WEIGHT), multiply(1),
|
header_table_size(-1), weight(NGHTTP2_DEFAULT_WEIGHT), multiply(1),
|
||||||
timeout(0.), window_bits(-1), connection_window_bits(-1), verbose(0),
|
timeout(0.), window_bits(-1), connection_window_bits(-1), verbose(0),
|
||||||
@@ -175,6 +175,37 @@ std::string Request::make_reqpath() const {
|
|||||||
return path;
|
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 {
|
namespace {
|
||||||
nghttp2_priority_spec resolve_dep(int res_type) {
|
nghttp2_priority_spec resolve_dep(int res_type) {
|
||||||
nghttp2_priority_spec pri_spec;
|
nghttp2_priority_spec pri_spec;
|
||||||
@@ -331,7 +362,7 @@ int submit_request(HttpClient *client, const Headers &headers, Request *req) {
|
|||||||
if (config.continuation) {
|
if (config.continuation) {
|
||||||
for (size_t i = 0; i < 6; ++i) {
|
for (size_t i = 0; i < 6; ++i) {
|
||||||
build_headers.emplace_back("continuation-test-" + util::utos(i + 1),
|
build_headers.emplace_back("continuation-test-" + util::utos(i + 1),
|
||||||
std::string(4096, '-'));
|
std::string(4_k, '-'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto num_initial_headers = build_headers.size();
|
auto num_initial_headers = build_headers.size();
|
||||||
@@ -603,7 +634,7 @@ void HttpClient::disconnect() {
|
|||||||
int HttpClient::read_clear() {
|
int HttpClient::read_clear() {
|
||||||
ev_timer_again(loop, &rt);
|
ev_timer_again(loop, &rt);
|
||||||
|
|
||||||
std::array<uint8_t, 8192> buf;
|
std::array<uint8_t, 8_k> buf;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
@@ -1118,7 +1149,7 @@ int HttpClient::read_tls() {
|
|||||||
|
|
||||||
ERR_clear_error();
|
ERR_clear_error();
|
||||||
|
|
||||||
std::array<uint8_t, 8192> buf;
|
std::array<uint8_t, 8_k> buf;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
auto rv = SSL_read(ssl, buf.data(), buf.size());
|
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);
|
scheme = util::get_uri_field(reqvec[0]->uri.c_str(), reqvec[0]->u, UF_SCHEMA);
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
if (reqvec[0]->is_ipv6_literal_addr()) {
|
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 << "[";
|
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 << "]";
|
ss << "]";
|
||||||
} else {
|
} else {
|
||||||
util::write_uri_field(ss, reqvec[0]->uri.c_str(), reqvec[0]->u, UF_HOST);
|
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) {
|
if (req->inflater) {
|
||||||
while (len > 0) {
|
while (len > 0) {
|
||||||
const size_t MAX_OUTLEN = 4096;
|
const size_t MAX_OUTLEN = 4_k;
|
||||||
std::array<uint8_t, MAX_OUTLEN> out;
|
std::array<uint8_t, MAX_OUTLEN> out;
|
||||||
size_t outlen = MAX_OUTLEN;
|
size_t outlen = MAX_OUTLEN;
|
||||||
size_t tlen = len;
|
size_t tlen = len;
|
||||||
@@ -1968,10 +2005,12 @@ int communicate(
|
|||||||
result = -1;
|
result = -1;
|
||||||
goto fin;
|
goto fin;
|
||||||
}
|
}
|
||||||
SSL_CTX_set_options(ssl_ctx,
|
|
||||||
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
|
||||||
SSL_OP_NO_COMPRESSION |
|
SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION |
|
||||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
|
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_AUTO_RETRY);
|
||||||
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
|
||||||
if (SSL_CTX_set_cipher_list(ssl_ctx, CIPHER_LIST) == 0) {
|
if (SSL_CTX_set_cipher_list(ssl_ctx, CIPHER_LIST) == 0) {
|
||||||
@@ -2036,6 +2075,8 @@ int communicate(
|
|||||||
client.record_domain_lookup_end_time();
|
client.record_domain_lookup_end_time();
|
||||||
|
|
||||||
if (client.initiate_connection() != 0) {
|
if (client.initiate_connection() != 0) {
|
||||||
|
std::cerr << "[ERROR] Could not connect to " << host << ", port " << port
|
||||||
|
<< std::endl;
|
||||||
goto fin;
|
goto fin;
|
||||||
}
|
}
|
||||||
ev_run(loop, 0);
|
ev_run(loop, 0);
|
||||||
@@ -2205,7 +2246,7 @@ int run(char **uris, int n) {
|
|||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
while (1) {
|
while (1) {
|
||||||
std::array<char, 1024> buf;
|
std::array<char, 1_k> buf;
|
||||||
ssize_t rret, wret;
|
ssize_t rret, wret;
|
||||||
while ((rret = read(0, buf.data(), buf.size())) == -1 &&
|
while ((rret = read(0, buf.data(), buf.size())) == -1 &&
|
||||||
errno == EINTR)
|
errno == EINTR)
|
||||||
@@ -2255,29 +2296,35 @@ int run(char **uris, int n) {
|
|||||||
http_parser_url u;
|
http_parser_url u;
|
||||||
memset(&u, 0, sizeof(u));
|
memset(&u, 0, sizeof(u));
|
||||||
auto uri = strip_fragment(uris[i]);
|
auto uri = strip_fragment(uris[i]);
|
||||||
if (http_parser_parse_url(uri.c_str(), uri.size(), 0, &u) == 0 &&
|
if (http_parser_parse_url(uri.c_str(), uri.size(), 0, &u) != 0) {
|
||||||
util::has_uri_field(u, UF_SCHEMA)) {
|
std::cerr << "[ERROR] Could not parse URI " << uri << std::endl;
|
||||||
uint16_t port = util::has_uri_field(u, UF_PORT)
|
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
|
? u.port
|
||||||
: util::get_default_port(uri.c_str(), u);
|
: 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()) ||
|
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()) ||
|
host != prev_host || port != prev_port) {
|
||||||
port != prev_port) {
|
|
||||||
if (!requests.empty()) {
|
if (!requests.empty()) {
|
||||||
if (communicate(prev_scheme, prev_host, prev_port,
|
if (communicate(prev_scheme, prev_host, prev_port, std::move(requests),
|
||||||
std::move(requests), callbacks) != 0) {
|
callbacks) != 0) {
|
||||||
++failures;
|
++failures;
|
||||||
}
|
}
|
||||||
requests.clear();
|
requests.clear();
|
||||||
}
|
}
|
||||||
prev_scheme = util::get_uri_field(uri.c_str(), u, UF_SCHEMA);
|
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;
|
prev_port = port;
|
||||||
}
|
}
|
||||||
requests.emplace_back(uri, data_fd == -1 ? nullptr : &data_prd,
|
requests.emplace_back(uri, data_fd == -1 ? nullptr : &data_prd,
|
||||||
data_stat.st_size);
|
data_stat.st_size);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (!requests.empty()) {
|
if (!requests.empty()) {
|
||||||
if (communicate(prev_scheme, prev_host, prev_port, std::move(requests),
|
if (communicate(prev_scheme, prev_host, prev_port, std::move(requests),
|
||||||
callbacks) != 0) {
|
callbacks) != 0) {
|
||||||
|
|||||||
@@ -52,6 +52,7 @@
|
|||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "http2.h"
|
#include "http2.h"
|
||||||
#include "nghttp2_gzip.h"
|
#include "nghttp2_gzip.h"
|
||||||
|
#include "template.h"
|
||||||
|
|
||||||
namespace nghttp2 {
|
namespace nghttp2 {
|
||||||
|
|
||||||
@@ -68,7 +69,6 @@ struct Config {
|
|||||||
std::string datafile;
|
std::string datafile;
|
||||||
std::string harfile;
|
std::string harfile;
|
||||||
nghttp2_option *http2_option;
|
nghttp2_option *http2_option;
|
||||||
size_t output_upper_thres;
|
|
||||||
size_t padding;
|
size_t padding;
|
||||||
ssize_t peer_max_concurrent_streams;
|
ssize_t peer_max_concurrent_streams;
|
||||||
ssize_t header_table_size;
|
ssize_t header_table_size;
|
||||||
@@ -260,7 +260,7 @@ struct HttpClient {
|
|||||||
// true if the response message of HTTP Upgrade request is fully
|
// true if the response message of HTTP Upgrade request is fully
|
||||||
// received. It is not relevant the upgrade succeeds, or not.
|
// received. It is not relevant the upgrade succeeds, or not.
|
||||||
bool upgrade_response_complete;
|
bool upgrade_response_complete;
|
||||||
Buffer<65536> wb;
|
Buffer<64_k> wb;
|
||||||
// SETTINGS payload sent as token68 in HTTP Upgrade
|
// SETTINGS payload sent as token68 in HTTP Upgrade
|
||||||
std::array<uint8_t, 128> settings_payload;
|
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) {
|
if (auto_tls_ticket_key) {
|
||||||
// Renew ticket key every 12hrs
|
// Renew ticket key every 12hrs
|
||||||
ev_timer_init(&renew_ticket_key_timer, renew_ticket_key_cb, 0.,
|
ev_timer_init(&renew_ticket_key_timer, renew_ticket_key_cb, 0., 12_h);
|
||||||
12 * 3600.);
|
|
||||||
renew_ticket_key_timer.data = conn_handler.get();
|
renew_ticket_key_timer.data = conn_handler.get();
|
||||||
ev_timer_again(loop, &renew_ticket_key_timer);
|
ev_timer_again(loop, &renew_ticket_key_timer);
|
||||||
|
|
||||||
@@ -831,16 +830,16 @@ void fill_default_config() {
|
|||||||
mod_config()->cert_file = nullptr;
|
mod_config()->cert_file = nullptr;
|
||||||
|
|
||||||
// Read timeout for HTTP2 upstream connection
|
// 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
|
// 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
|
// Write timeout for HTTP2/non-HTTP2 upstream connection
|
||||||
mod_config()->upstream_write_timeout = 30.;
|
mod_config()->upstream_write_timeout = 30.;
|
||||||
|
|
||||||
// Read/Write timeouts for downstream connection
|
// 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.;
|
mod_config()->downstream_write_timeout = 30.;
|
||||||
|
|
||||||
// Read timeout for HTTP/2 stream
|
// 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_host = 8;
|
||||||
mod_config()->downstream_connections_per_frontend = 0;
|
mod_config()->downstream_connections_per_frontend = 0;
|
||||||
mod_config()->listener_disable_timeout = 0.;
|
mod_config()->listener_disable_timeout = 0.;
|
||||||
mod_config()->downstream_request_buffer_size = 16 * 1024;
|
mod_config()->downstream_request_buffer_size = 16_k;
|
||||||
mod_config()->downstream_response_buffer_size = 16 * 1024;
|
mod_config()->downstream_response_buffer_size = 16_k;
|
||||||
mod_config()->no_server_push = false;
|
mod_config()->no_server_push = false;
|
||||||
mod_config()->host_unix = false;
|
mod_config()->host_unix = false;
|
||||||
mod_config()->http2_downstream_connections_per_worker = 0;
|
mod_config()->http2_downstream_connections_per_worker = 0;
|
||||||
// ocsp update interval = 14400 secs = 4 hours, borrowed from h2o
|
// 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 =
|
mod_config()->fetch_ocsp_response_file =
|
||||||
strcopy(PKGDATADIR "/fetch-ocsp-response");
|
strcopy(PKGDATADIR "/fetch-ocsp-response");
|
||||||
mod_config()->no_ocsp = false;
|
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;
|
mod_config()->max_header_fields = 100;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
@@ -1075,9 +1074,11 @@ Performance:
|
|||||||
backend addresses specified by -b option.
|
backend addresses specified by -b option.
|
||||||
--backend-http1-connections-per-host=<N>
|
--backend-http1-connections-per-host=<N>
|
||||||
Set maximum number of backend concurrent HTTP/1
|
Set maximum number of backend concurrent HTTP/1
|
||||||
connections per host. This option is meaningful when -s
|
connections per origin host. This option is meaningful
|
||||||
option is used. To limit the number of connections per
|
when -s option is used. The origin host is determined
|
||||||
frontend for default mode, use
|
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.
|
--backend-http1-connections-per-frontend.
|
||||||
Default: )" << get_config()->downstream_connections_per_host
|
Default: )" << get_config()->downstream_connections_per_host
|
||||||
<< R"(
|
<< R"(
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ public:
|
|||||||
Worker *get_worker() const;
|
Worker *get_worker() const;
|
||||||
|
|
||||||
using WriteBuf = Buffer<32768>;
|
using WriteBuf = Buffer<32768>;
|
||||||
using ReadBuf = Buffer<8192>;
|
using ReadBuf = Buffer<8_k>;
|
||||||
|
|
||||||
WriteBuf *get_wb();
|
WriteBuf *get_wb();
|
||||||
ReadBuf *get_rb();
|
ReadBuf *get_rb();
|
||||||
|
|||||||
@@ -455,7 +455,7 @@ int ConnectionHandler::start_ocsp_update(const char *cert_file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionHandler::read_ocsp_chunk() {
|
void ConnectionHandler::read_ocsp_chunk() {
|
||||||
std::array<uint8_t, 4096> buf;
|
std::array<uint8_t, 4_k> buf;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
ssize_t n;
|
ssize_t n;
|
||||||
while ((n = read(ocsp_.fd, buf.data(), buf.size())) == -1 && errno == EINTR)
|
while ((n = read(ocsp_.fd, buf.data(), buf.size())) == -1 && errno == EINTR)
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ public:
|
|||||||
HostEntry();
|
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.
|
// conn_max_per_host == 0 means no limit for downstream connection.
|
||||||
DownstreamQueue(size_t conn_max_per_host = 0, bool unified_host = true);
|
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() +
|
nva.reserve(nheader + 8 + cookies.size() +
|
||||||
get_config()->add_request_headers.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(
|
nva.push_back(http2::make_nv_lc(
|
||||||
":method", http2::to_method_string(downstream_->get_request_method())));
|
":method", http2::to_method_string(downstream_->get_request_method())));
|
||||||
|
|
||||||
|
auto &scheme = downstream_->get_request_http2_scheme();
|
||||||
|
|
||||||
if (downstream_->get_request_method() == HTTP_CONNECT) {
|
if (downstream_->get_request_method() == HTTP_CONNECT) {
|
||||||
if (authority) {
|
if (authority) {
|
||||||
nva.push_back(http2::make_nv_lc(":authority", 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()));
|
http2::make_nv_ls(":authority", downstream_->get_request_path()));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(!downstream_->get_request_http2_scheme().empty());
|
assert(!scheme.empty());
|
||||||
nva.push_back(
|
nva.push_back(http2::make_nv_ls(":scheme", scheme));
|
||||||
http2::make_nv_ls(":scheme", downstream_->get_request_http2_scheme()));
|
|
||||||
|
|
||||||
if (authority) {
|
if (authority) {
|
||||||
nva.push_back(http2::make_nv_lc(":authority", 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));
|
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);
|
auto xff = downstream_->get_request_header(http2::HD_X_FORWARDED_FOR);
|
||||||
if (get_config()->add_x_forwarded_for) {
|
if (get_config()->add_x_forwarded_for) {
|
||||||
if (xff && !get_config()->strip_incoming_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 &&
|
if (!get_config()->http2_proxy && !get_config()->client_proxy &&
|
||||||
downstream_->get_request_method() != HTTP_CONNECT) {
|
downstream_->get_request_method() != HTTP_CONNECT) {
|
||||||
// We use same protocol with :scheme header field
|
// 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));
|
nva.push_back(http2::make_nv_ls("x-forwarded-proto", scheme));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
std::string via_value;
|
||||||
auto via = downstream_->get_request_header(http2::HD_VIA);
|
auto via = downstream_->get_request_header(http2::HD_VIA);
|
||||||
if (get_config()->no_via) {
|
if (get_config()->no_via) {
|
||||||
if (via) {
|
if (via) {
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ public:
|
|||||||
CONNECTION_CHECK_STARTED
|
CONNECTION_CHECK_STARTED
|
||||||
};
|
};
|
||||||
|
|
||||||
using ReadBuf = Buffer<8192>;
|
using ReadBuf = Buffer<8_k>;
|
||||||
using WriteBuf = Buffer<32768>;
|
using WriteBuf = Buffer<32768>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -251,6 +251,9 @@ int HttpDownstreamConnection::push_request_headers() {
|
|||||||
// Assume that method and request path do not contain \r\n.
|
// Assume that method and request path do not contain \r\n.
|
||||||
std::string hdrs = http2::to_method_string(downstream_->get_request_method());
|
std::string hdrs = http2::to_method_string(downstream_->get_request_method());
|
||||||
hdrs += ' ';
|
hdrs += ' ';
|
||||||
|
|
||||||
|
auto &scheme = downstream_->get_request_http2_scheme();
|
||||||
|
|
||||||
if (connect_method) {
|
if (connect_method) {
|
||||||
if (authority) {
|
if (authority) {
|
||||||
hdrs += authority;
|
hdrs += authority;
|
||||||
@@ -260,8 +263,8 @@ int HttpDownstreamConnection::push_request_headers() {
|
|||||||
} else if (get_config()->http2_proxy || get_config()->client_proxy) {
|
} else if (get_config()->http2_proxy || get_config()->client_proxy) {
|
||||||
// Construct absolute-form request target because we are going to
|
// Construct absolute-form request target because we are going to
|
||||||
// send a request to a HTTP/1 proxy.
|
// send a request to a HTTP/1 proxy.
|
||||||
assert(!downstream_->get_request_http2_scheme().empty());
|
assert(!scheme.empty());
|
||||||
hdrs += downstream_->get_request_http2_scheme();
|
hdrs += scheme;
|
||||||
hdrs += "://";
|
hdrs += "://";
|
||||||
|
|
||||||
if (authority) {
|
if (authority) {
|
||||||
@@ -344,8 +347,8 @@ int HttpDownstreamConnection::push_request_headers() {
|
|||||||
if (!get_config()->http2_proxy && !get_config()->client_proxy &&
|
if (!get_config()->http2_proxy && !get_config()->client_proxy &&
|
||||||
!connect_method) {
|
!connect_method) {
|
||||||
hdrs += "X-Forwarded-Proto: ";
|
hdrs += "X-Forwarded-Proto: ";
|
||||||
assert(!downstream_->get_request_http2_scheme().empty());
|
assert(!scheme.empty());
|
||||||
hdrs += downstream_->get_request_http2_scheme();
|
hdrs += scheme;
|
||||||
hdrs += "\r\n";
|
hdrs += "\r\n";
|
||||||
}
|
}
|
||||||
auto via = downstream_->get_request_header(http2::HD_VIA);
|
auto via = downstream_->get_request_header(http2::HD_VIA);
|
||||||
@@ -726,7 +729,7 @@ int HttpDownstreamConnection::on_read() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ev_timer_again(conn_.loop, &conn_.rt);
|
ev_timer_again(conn_.loop, &conn_.rt);
|
||||||
std::array<uint8_t, 8192> buf;
|
std::array<uint8_t, 8_k> buf;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
if (downstream_->get_upgraded()) {
|
if (downstream_->get_upgraded()) {
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ Log::~Log() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char buf[4096];
|
char buf[4_k];
|
||||||
auto tty = lgconf->errorlog_tty;
|
auto tty = lgconf->errorlog_tty;
|
||||||
|
|
||||||
lgconf->update_tstamp(std::chrono::system_clock::now());
|
lgconf->update_tstamp(std::chrono::system_clock::now());
|
||||||
@@ -172,7 +172,7 @@ void upstream_accesslog(const std::vector<LogFragment> &lfv,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char buf[4096];
|
char buf[4_k];
|
||||||
|
|
||||||
auto downstream = lgsp.downstream;
|
auto downstream = lgsp.downstream;
|
||||||
|
|
||||||
|
|||||||
@@ -215,6 +215,14 @@ void on_ctrl_recv_callback(spdylay_session *session, spdylay_frame_type type,
|
|||||||
return;
|
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);
|
downstream->set_request_method(method_token);
|
||||||
if (is_connect) {
|
if (is_connect) {
|
||||||
downstream->set_request_http2_authority(path->value);
|
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);
|
rv = spdylay_session_server_new(&session_, version, &callbacks, this);
|
||||||
assert(rv == 0);
|
assert(rv == 0);
|
||||||
|
|
||||||
uint32_t max_buffer = 65536;
|
uint32_t max_buffer = 64_k;
|
||||||
rv = spdylay_session_set_option(session_,
|
rv = spdylay_session_set_option(session_,
|
||||||
SPDYLAY_OPT_MAX_RECV_CTRL_FRAME_BUFFER,
|
SPDYLAY_OPT_MAX_RECV_CTRL_FRAME_BUFFER,
|
||||||
&max_buffer, sizeof(max_buffer));
|
&max_buffer, sizeof(max_buffer));
|
||||||
|
|||||||
@@ -338,12 +338,14 @@ SSL_CTX *create_ssl_context(const char *private_key_file,
|
|||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
|
|
||||||
SSL_CTX_set_options(
|
auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
|
||||||
ssl_ctx,
|
SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION |
|
||||||
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION |
|
|
||||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
|
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
|
||||||
SSL_OP_SINGLE_ECDH_USE | SSL_OP_SINGLE_DH_USE |
|
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";
|
const unsigned char sid_ctx[] = "shrpx";
|
||||||
SSL_CTX_set_session_id_context(ssl_ctx, sid_ctx, sizeof(sid_ctx) - 1);
|
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);
|
LOG(FATAL) << ERR_error_string(ERR_get_error(), nullptr);
|
||||||
DIE();
|
DIE();
|
||||||
}
|
}
|
||||||
SSL_CTX_set_options(ssl_ctx,
|
|
||||||
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
|
auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
|
||||||
SSL_OP_NO_COMPRESSION |
|
SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION |
|
||||||
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
|
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;
|
const char *ciphers;
|
||||||
if (get_config()->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
|
} // namespace nghttp2
|
||||||
|
|
||||||
#endif // TEMPLATE_H
|
#endif // TEMPLATE_H
|
||||||
|
|||||||
@@ -52,11 +52,11 @@ namespace nghttp2 {
|
|||||||
// The additional HTTP/2 protocol ALPN protocol identifier we also
|
// The additional HTTP/2 protocol ALPN protocol identifier we also
|
||||||
// supports for our applications to make smooth migration into final
|
// supports for our applications to make smooth migration into final
|
||||||
// h2 ALPN ID.
|
// h2 ALPN ID.
|
||||||
#define NGHTTP2_H2_16_ALPN "\x5h2-16"
|
constexpr const char NGHTTP2_H2_16_ALPN[] = "\x5h2-16";
|
||||||
#define NGHTTP2_H2_16 "h2-16"
|
constexpr const char NGHTTP2_H2_16[] = "h2-16";
|
||||||
|
|
||||||
#define NGHTTP2_H2_14_ALPN "\x5h2-14"
|
constexpr const char NGHTTP2_H2_14_ALPN[] = "\x5h2-14";
|
||||||
#define NGHTTP2_H2_14 "h2-14"
|
constexpr const char NGHTTP2_H2_14[] = "h2-14";
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
|
|
||||||
|
|||||||
@@ -266,6 +266,8 @@ int main(int argc _U_, char *argv[] _U_) {
|
|||||||
test_nghttp2_session_send_data_callback) ||
|
test_nghttp2_session_send_data_callback) ||
|
||||||
!CU_add_test(pSuite, "session_on_begin_headers_temporal_failure",
|
!CU_add_test(pSuite, "session_on_begin_headers_temporal_failure",
|
||||||
test_nghttp2_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",
|
!CU_add_test(pSuite, "http_mandatory_headers",
|
||||||
test_nghttp2_http_mandatory_headers) ||
|
test_nghttp2_http_mandatory_headers) ||
|
||||||
!CU_add_test(pSuite, "http_content_length",
|
!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_frame_priority_free(&frame.priority);
|
||||||
nghttp2_session_del(session);
|
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) {
|
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(a, NULL, b, NULL, NULL);
|
||||||
check_stream_dep_sib(b, a, NULL, NULL, c);
|
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);
|
check_stream_dep_sib(d, c, NULL, NULL, NULL);
|
||||||
|
|
||||||
CU_ASSERT(4 == session->roots.num_streams);
|
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(a, NULL, e, NULL, NULL);
|
||||||
check_stream_dep_sib(e, a, b, NULL, NULL);
|
check_stream_dep_sib(e, a, b, NULL, NULL);
|
||||||
check_stream_dep_sib(b, e, NULL, NULL, c);
|
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);
|
check_stream_dep_sib(d, c, NULL, NULL, NULL);
|
||||||
|
|
||||||
CU_ASSERT(5 == session->roots.num_streams);
|
CU_ASSERT(5 == session->roots.num_streams);
|
||||||
@@ -5621,7 +5637,7 @@ void test_nghttp2_session_stream_dep_remove(void) {
|
|||||||
|
|
||||||
nghttp2_session_del(session);
|
nghttp2_session_del(session);
|
||||||
|
|
||||||
/* Remove left most stream */
|
/* Remove right most stream */
|
||||||
nghttp2_session_server_new(&session, &callbacks, NULL);
|
nghttp2_session_server_new(&session, &callbacks, NULL);
|
||||||
|
|
||||||
a = open_stream(session, 1);
|
a = open_stream(session, 1);
|
||||||
@@ -5667,19 +5683,20 @@ void test_nghttp2_session_stream_dep_remove(void) {
|
|||||||
|
|
||||||
nghttp2_session_del(session);
|
nghttp2_session_del(session);
|
||||||
|
|
||||||
/* Remove right most stream */
|
/* Remove left most stream */
|
||||||
nghttp2_session_server_new(&session, &callbacks, NULL);
|
nghttp2_session_server_new(&session, &callbacks, NULL);
|
||||||
|
|
||||||
a = open_stream(session, 1);
|
a = open_stream(session, 1);
|
||||||
b = open_stream_with_dep(session, 3, a);
|
b = open_stream_with_dep(session, 3, a);
|
||||||
c = open_stream_with_dep(session, 5, a);
|
c = open_stream_with_dep(session, 5, a);
|
||||||
d = open_stream_with_dep(session, 7, c);
|
d = open_stream_with_dep(session, 7, c);
|
||||||
|
e = open_stream_with_dep(session, 9, c);
|
||||||
|
|
||||||
/* a
|
/* a
|
||||||
* |
|
* |
|
||||||
* c--b
|
* c--b
|
||||||
* |
|
* |
|
||||||
* d
|
* e--d
|
||||||
*/
|
*/
|
||||||
|
|
||||||
nghttp2_stream_dep_remove(c);
|
nghttp2_stream_dep_remove(c);
|
||||||
@@ -5687,23 +5704,26 @@ void test_nghttp2_session_stream_dep_remove(void) {
|
|||||||
/* becomes:
|
/* becomes:
|
||||||
* a
|
* 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 == b->num_substreams);
|
||||||
CU_ASSERT(1 == c->num_substreams);
|
CU_ASSERT(1 == c->num_substreams);
|
||||||
CU_ASSERT(1 == d->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(NGHTTP2_DEFAULT_WEIGHT * 2 == a->sum_dep_weight);
|
||||||
CU_ASSERT(0 == b->sum_dep_weight);
|
CU_ASSERT(0 == b->sum_dep_weight);
|
||||||
CU_ASSERT(0 == d->sum_dep_weight);
|
CU_ASSERT(0 == d->sum_dep_weight);
|
||||||
CU_ASSERT(0 == c->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(a, NULL, e, NULL, NULL);
|
||||||
check_stream_dep_sib(b, NULL, NULL, d, NULL);
|
check_stream_dep_sib(b, a, NULL, d, NULL);
|
||||||
check_stream_dep_sib(c, NULL, NULL, NULL, 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);
|
nghttp2_session_del(session);
|
||||||
|
|
||||||
@@ -5763,10 +5783,10 @@ void test_nghttp2_session_stream_dep_remove(void) {
|
|||||||
CU_ASSERT(0 == f->sum_dep_weight);
|
CU_ASSERT(0 == f->sum_dep_weight);
|
||||||
|
|
||||||
check_stream_dep_sib(a, NULL, d, NULL, NULL);
|
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(c, NULL, NULL, NULL, NULL);
|
||||||
check_stream_dep_sib(e, NULL, NULL, f, b);
|
check_stream_dep_sib(e, a, NULL, f, b);
|
||||||
check_stream_dep_sib(f, NULL, NULL, d, e);
|
check_stream_dep_sib(f, a, NULL, d, e);
|
||||||
check_stream_dep_sib(d, a, NULL, NULL, f);
|
check_stream_dep_sib(d, a, NULL, NULL, f);
|
||||||
|
|
||||||
nghttp2_session_del(session);
|
nghttp2_session_del(session);
|
||||||
@@ -5822,8 +5842,8 @@ void test_nghttp2_session_stream_dep_add_subtree(void) {
|
|||||||
CU_ASSERT(0 == f->sum_dep_weight);
|
CU_ASSERT(0 == f->sum_dep_weight);
|
||||||
|
|
||||||
check_stream_dep_sib(a, NULL, e, NULL, NULL);
|
check_stream_dep_sib(a, NULL, e, NULL, NULL);
|
||||||
check_stream_dep_sib(b, NULL, NULL, c, NULL);
|
check_stream_dep_sib(b, a, NULL, c, NULL);
|
||||||
check_stream_dep_sib(c, NULL, d, e, b);
|
check_stream_dep_sib(c, a, d, e, b);
|
||||||
check_stream_dep_sib(d, c, NULL, NULL, NULL);
|
check_stream_dep_sib(d, c, NULL, NULL, NULL);
|
||||||
check_stream_dep_sib(e, a, f, NULL, c);
|
check_stream_dep_sib(e, a, f, NULL, c);
|
||||||
check_stream_dep_sib(f, e, NULL, NULL, NULL);
|
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(a, NULL, e, NULL, NULL);
|
||||||
check_stream_dep_sib(e, a, f, NULL, NULL);
|
check_stream_dep_sib(e, a, f, NULL, NULL);
|
||||||
check_stream_dep_sib(f, e, NULL, NULL, c);
|
check_stream_dep_sib(f, e, NULL, NULL, c);
|
||||||
check_stream_dep_sib(b, NULL, NULL, c, NULL);
|
check_stream_dep_sib(b, e, NULL, c, NULL);
|
||||||
check_stream_dep_sib(c, NULL, d, f, b);
|
check_stream_dep_sib(c, e, d, f, b);
|
||||||
check_stream_dep_sib(d, c, NULL, NULL, NULL);
|
check_stream_dep_sib(d, c, NULL, NULL, NULL);
|
||||||
|
|
||||||
nghttp2_session_del(session);
|
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(a, NULL, b, NULL, NULL);
|
||||||
check_stream_dep_sib(b, a, NULL, NULL, e);
|
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(c, NULL, d, NULL, NULL);
|
||||||
check_stream_dep_sib(d, c, NULL, 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 *session;
|
||||||
nghttp2_session_callbacks callbacks;
|
nghttp2_session_callbacks callbacks;
|
||||||
nghttp2_stream *a, *b, *c, *d;
|
nghttp2_stream *a, *b, *c, *d;
|
||||||
|
nghttp2_outbound_item *db, *dc;
|
||||||
|
nghttp2_mem *mem;
|
||||||
|
|
||||||
|
mem = nghttp2_mem_default();
|
||||||
|
|
||||||
memset(&callbacks, 0, sizeof(callbacks));
|
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(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
|
||||||
CU_ASSERT(0 == b->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(c, NULL, a, NULL, NULL);
|
||||||
check_stream_dep_sib(a, c, b, NULL, NULL);
|
check_stream_dep_sib(a, c, b, NULL, NULL);
|
||||||
check_stream_dep_sib(b, a, NULL, 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);
|
nghttp2_session_server_new(&session, &callbacks, NULL);
|
||||||
|
|
||||||
a = open_stream(session, 1);
|
a = open_stream(session, 1);
|
||||||
|
|
||||||
b = open_stream(session, 3);
|
b = open_stream(session, 3);
|
||||||
|
|
||||||
c = open_stream(session, 5);
|
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 == b->sum_dep_weight);
|
||||||
CU_ASSERT(0 == a->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(c, NULL, b, NULL, NULL);
|
||||||
check_stream_dep_sib(b, c, NULL, NULL, a);
|
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);
|
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(NGHTTP2_DEFAULT_WEIGHT == a->sum_dep_weight);
|
||||||
CU_ASSERT(0 == b->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(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(a, c, b, NULL, d);
|
||||||
check_stream_dep_sib(b, a, NULL, NULL, NULL);
|
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) {
|
void test_nghttp2_session_stream_attach_item(void) {
|
||||||
nghttp2_session *session;
|
nghttp2_session *session;
|
||||||
nghttp2_session_callbacks callbacks;
|
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_outbound_item *da, *db, *dc, *dd;
|
||||||
nghttp2_mem *mem;
|
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 == c->dpri);
|
||||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->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);
|
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_TOP == c->dpri);
|
||||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
|
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
|
||||||
|
|
||||||
CU_ASSERT(16 * 16 / 32 == b->effective_weight);
|
CU_ASSERT(16 * 16 / 32 == nghttp2_stream_compute_effective_weight(b));
|
||||||
CU_ASSERT(16 * 16 / 32 == c->effective_weight);
|
CU_ASSERT(16 * 16 / 32 == nghttp2_stream_compute_effective_weight(c));
|
||||||
|
|
||||||
CU_ASSERT(32 == a->sum_norest_weight);
|
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_REST == c->dpri);
|
||||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->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);
|
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_TOP == c->dpri);
|
||||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
|
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == d->dpri);
|
||||||
|
|
||||||
CU_ASSERT(16 * 16 / 32 == b->effective_weight);
|
CU_ASSERT(16 * 16 / 32 == nghttp2_stream_compute_effective_weight(b));
|
||||||
CU_ASSERT(16 * 16 / 32 == c->effective_weight);
|
CU_ASSERT(16 * 16 / 32 == nghttp2_stream_compute_effective_weight(c));
|
||||||
|
|
||||||
dd = create_data_ob_item(mem);
|
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_TOP == c->dpri);
|
||||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == d->dpri);
|
CU_ASSERT(NGHTTP2_STREAM_DPRI_REST == d->dpri);
|
||||||
|
|
||||||
CU_ASSERT(16 * 16 / 32 == b->effective_weight);
|
CU_ASSERT(16 * 16 / 32 == nghttp2_stream_compute_effective_weight(b));
|
||||||
CU_ASSERT(16 * 16 / 32 == c->effective_weight);
|
CU_ASSERT(16 * 16 / 32 == nghttp2_stream_compute_effective_weight(c));
|
||||||
|
|
||||||
CU_ASSERT(0 == dd->queued);
|
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_NO_ITEM == c->dpri);
|
||||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == d->dpri);
|
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == d->dpri);
|
||||||
|
|
||||||
CU_ASSERT(16 * 16 / 32 == b->effective_weight);
|
CU_ASSERT(16 * 16 / 32 == nghttp2_stream_compute_effective_weight(b));
|
||||||
CU_ASSERT(16 * 16 / 32 == d->effective_weight);
|
CU_ASSERT(16 * 16 / 32 == nghttp2_stream_compute_effective_weight(d));
|
||||||
|
|
||||||
CU_ASSERT(1 == dd->queued);
|
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_NO_ITEM == c->dpri);
|
||||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_TOP == d->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);
|
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);
|
nghttp2_session_del(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6265,7 +6435,7 @@ void test_nghttp2_session_stream_attach_item_subtree(void) {
|
|||||||
nghttp2_session *session;
|
nghttp2_session *session;
|
||||||
nghttp2_session_callbacks callbacks;
|
nghttp2_session_callbacks callbacks;
|
||||||
nghttp2_stream *a, *b, *c, *d, *e, *f;
|
nghttp2_stream *a, *b, *c, *d, *e, *f;
|
||||||
nghttp2_outbound_item *db, *dd, *de;
|
nghttp2_outbound_item *da, *db, *dd, *de;
|
||||||
nghttp2_mem *mem;
|
nghttp2_mem *mem;
|
||||||
|
|
||||||
mem = nghttp2_mem_default();
|
mem = nghttp2_mem_default();
|
||||||
@@ -6281,6 +6451,8 @@ void test_nghttp2_session_stream_attach_item_subtree(void) {
|
|||||||
|
|
||||||
e = open_stream(session, 9);
|
e = open_stream(session, 9);
|
||||||
f = open_stream_with_dep(session, 11, e);
|
f = open_stream_with_dep(session, 11, e);
|
||||||
|
e->weight = 32;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* a e
|
* 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_TOP == e->dpri);
|
||||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->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 == e->effective_weight);
|
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 */
|
/* 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_TOP == e->dpri);
|
||||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->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 */
|
/* 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_TOP == e->dpri);
|
||||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->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 == e->effective_weight);
|
CU_ASSERT(16 == nghttp2_stream_compute_effective_weight(e));
|
||||||
|
|
||||||
/* Remove subtree a */
|
/* 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_TOP == e->dpri);
|
||||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->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);
|
dd = create_data_ob_item(mem);
|
||||||
|
|
||||||
nghttp2_stream_attach_item(d, dd, session);
|
nghttp2_stream_attach_item(d, dd, session);
|
||||||
|
|
||||||
|
CU_ASSERT(16 == c->sum_norest_weight);
|
||||||
|
|
||||||
/* Add subtree c to a */
|
/* Add subtree c to a */
|
||||||
|
|
||||||
nghttp2_stream_dep_remove_subtree(c);
|
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_TOP == e->dpri);
|
||||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->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 * 16 / 32 == e->effective_weight);
|
CU_ASSERT(16 * 16 / 48 == nghttp2_stream_compute_effective_weight(d));
|
||||||
CU_ASSERT(16 * 16 / 32 == e->effective_weight);
|
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);
|
CU_ASSERT(16 == c->sum_norest_weight);
|
||||||
|
|
||||||
/* Insert b under a */
|
/* 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_REST == e->dpri);
|
||||||
CU_ASSERT(NGHTTP2_STREAM_DPRI_NO_ITEM == f->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(16 == a->sum_norest_weight);
|
||||||
CU_ASSERT(0 == b->sum_norest_weight);
|
|
||||||
|
|
||||||
/* Remove subtree b */
|
/* 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(NGHTTP2_STREAM_DPRI_NO_ITEM == f->dpri);
|
||||||
|
|
||||||
CU_ASSERT(0 == a->sum_norest_weight);
|
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);
|
nghttp2_session_del(session);
|
||||||
}
|
}
|
||||||
@@ -7218,6 +7469,45 @@ void test_nghttp2_session_on_begin_headers_temporal_failure(void) {
|
|||||||
nghttp2_bufs_free(&bufs);
|
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(
|
static void check_nghttp2_http_recv_headers_fail(
|
||||||
nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
|
nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
|
||||||
int stream_state, const nghttp2_nv *nva, size_t nvlen) {
|
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_reset_pending_headers(void);
|
||||||
void test_nghttp2_session_send_data_callback(void);
|
void test_nghttp2_session_send_data_callback(void);
|
||||||
void test_nghttp2_session_on_begin_headers_temporal_failure(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_mandatory_headers(void);
|
||||||
void test_nghttp2_http_content_length(void);
|
void test_nghttp2_http_content_length(void);
|
||||||
void test_nghttp2_http_content_length_mismatch(void);
|
void test_nghttp2_http_content_length_mismatch(void);
|
||||||
|
|||||||
Reference in New Issue
Block a user