Compare commits

...

35 Commits

Author SHA1 Message Date
Tatsuhiro Tsujikawa
4c76aaeea4 Update manual pages 2018-08-25 16:46:19 +09:00
Tatsuhiro Tsujikawa
2b51ad67d3 Bump up version number to 1.32.1, LT revision to 30:3:16 2018-08-25 16:43:47 +09:00
Tatsuhiro Tsujikawa
708379dcab Tweak nghttp2_session_set_stream_user_data
nghttp2_session_set_stream_user_data now works for a stream which is
not created yet, but the request which creates the stream is queued.
2018-08-25 16:43:47 +09:00
Tatsuhiro Tsujikawa
73106b0d0d Compile with clang-6.0 2018-08-25 16:43:47 +09:00
Tatsuhiro Tsujikawa
572735e496 Update manual pages 2018-05-08 22:18:42 +09:00
Tatsuhiro Tsujikawa
e8d693c395 Bump up version number to 1.32.0, LT revision to 30:2:16 2018-05-08 22:12:43 +09:00
Tatsuhiro Tsujikawa
f44dfcd9dc Update AUTHORS 2018-05-08 22:11:06 +09:00
Tatsuhiro Tsujikawa
1f1b0d93d4 Update manual pages 2018-05-07 21:43:13 +09:00
Tatsuhiro Tsujikawa
ce8c749b77 Merge pull request #1173 from nghttp2/asio-client-sni
asio: Support client side SNI
2018-05-04 10:26:31 +09:00
Tatsuhiro Tsujikawa
3e4f257b91 asio: Support client side SNI 2018-05-03 20:29:16 +09:00
Tatsuhiro Tsujikawa
86fab997b4 Upgrade neverbleed to the latest master 2018-05-03 14:51:59 +09:00
Tatsuhiro Tsujikawa
c3ecd44592 Merge pull request #1171 from nghttp2/h2load-rate-and-duration
h2load: -r and --duration are mutually exclusive
2018-04-28 01:23:22 +09:00
Tatsuhiro Tsujikawa
c65ca20a49 h2load: -r and --duration are mutually exclusive 2018-04-28 00:30:43 +09:00
Tatsuhiro Tsujikawa
a5c408c5e3 Ignore all input after calling session_terminate_session 2018-04-22 14:42:28 +09:00
Tatsuhiro Tsujikawa
06379b2861 Fix treatment of padding 2018-04-22 14:42:28 +09:00
Tatsuhiro Tsujikawa
e04de48ed9 Merge pull request #1162 from nghttp2/libressl
Libressl
2018-04-14 23:57:20 +09:00
Tatsuhiro Tsujikawa
009646421c Use LIBRESSL_IN_USE instead of defined(LIBRESSL_VERSION_NUMBER) 2018-04-14 18:31:57 +09:00
Tatsuhiro Tsujikawa
8d0b4544f8 libressl 2.7 has X509_VERIFY_PARAM_* 2018-04-14 18:31:57 +09:00
Tatsuhiro Tsujikawa
d8a34131e1 libressl 2.7 has SSL_CTX_get0_certificate 2018-04-14 18:31:57 +09:00
Tatsuhiro Tsujikawa
5db17d0af9 Compile with libressl 2.7.2 2018-04-14 18:09:47 +09:00
Tatsuhiro Tsujikawa
1bf69b5662 Define LIBRESSL_LEGACY_API and LIBRESSL_2_7_API
LIBRESSL_LEGACY_API is drop-in replacement for LIBRESSL_IN_USE.  In
the upcoming commits, we will add changes to support libressl 2.7.
2018-04-14 18:09:47 +09:00
Tatsuhiro Tsujikawa
3febaef1fa Bump up LT revision to 30:1:16 due to v1.31.1 release 2018-04-13 00:24:13 +09:00
Tatsuhiro Tsujikawa
b1bd6035e8 Fix frame handling 2018-04-07 00:27:55 +09:00
Tatsuhiro Tsujikawa
b48bcb214a examples: Use C style comment in .c files 2018-04-03 22:08:24 +09:00
Tatsuhiro Tsujikawa
6f3ce2c72d examples: Remove unused lambda capture 2018-04-03 22:07:02 +09:00
Tatsuhiro Tsujikawa
2f9121cf44 Merge branch 'Sp1l-Sp1l/allow-no-npn' 2018-04-03 21:42:17 +09:00
Tatsuhiro Tsujikawa
e65e7711ca Add comment on #endif 2018-04-03 21:39:44 +09:00
Tatsuhiro Tsujikawa
636ef51b0f Fix compile error with -Wunused-function 2018-04-03 21:33:09 +09:00
Bernard Spil
400934e5a3 [PATCH] Allow building without NPN
NPN has been superseeded by ALPN. OpenSSL provides a configure
option to disable npn (no-npn) which results in an OpenSSL
installation that defines OPENSSL_NO_NEXTPROTONEG in opensslconf.h

The #ifdef's look safe here (as the next_proto is initialized as
nullptr). Alteratively, macros could be defined for the used npn
methods that return a 0 for next_proto.

Signed-off-by: Bernard Spil <brnrd@FreeBSD.org>
2018-03-25 18:27:23 +02:00
Tatsuhiro Tsujikawa
4c3a3acf9b Merge pull request #1146 from vszakats/cmakestaticlib
cmake: add ENABLE_STATIC_LIB option to build static lib
2018-03-13 23:06:29 +09:00
Tatsuhiro Tsujikawa
9aa6002c37 Merge pull request #1144 from hellojaewon/master
Fix typo
2018-03-13 23:04:05 +09:00
Viktor Szakats
f342260bfe cmake: add ENABLE_STATIC_LIB option to build static lib
When using the ENABLE_LIB_ONLY option, only the shared
library was built. This new option allows to build the
static library as well.
2018-03-12 22:41:37 +00:00
jwchoi
a6dd497016 Fix typo 2018-03-12 09:19:19 +09:00
Tatsuhiro Tsujikawa
842509dab6 Don't allow 101 HTTP status code because HTTP/2 removes HTTP Upgrade 2018-03-11 15:37:30 +09:00
Tatsuhiro Tsujikawa
4add618a3f Bump up version number to 1.32.0-DEV 2018-02-27 22:32:00 +09:00
39 changed files with 465 additions and 136 deletions

View File

@@ -92,6 +92,7 @@ Tomasz Buchert
Tomasz Torcz
Vernon Tang
Viacheslav Biriukov
Viktor Szakats
Viktor Szépe
Wenfeng Liu
Xiaoguang Sun
@@ -103,6 +104,7 @@ clemahieu
dalf
es
fangdingjun
jwchoi
kumagi
lstefani
makovich

View File

@@ -24,12 +24,12 @@
cmake_minimum_required(VERSION 3.0)
# XXX using 1.8.90 instead of 1.9.0-DEV
project(nghttp2 VERSION 1.31.0)
project(nghttp2 VERSION 1.32.1)
# See versioning rule:
# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
set(LT_CURRENT 30)
set(LT_REVISION 0)
set(LT_REVISION 3)
set(LT_AGE 16)
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})

View File

@@ -14,6 +14,7 @@ option(ENABLE_PYTHON_BINDINGS "Build Python bindings"
${ENABLE_PYTHON_BINDINGS_DEFAULT})
option(ENABLE_FAILMALLOC "Build failmalloc test program" ON)
option(ENABLE_LIB_ONLY "Build libnghttp2 only. This is a short hand for -DENABLE_APP=0 -DENABLE_EXAMPLES=0 -DENABLE_HPACK_TOOLS=0 -DENABLE_PYTHON_BINDINGS=0")
option(ENABLE_STATIC_LIB "Build libnghttp2 in static mode also")
option(WITH_LIBXML2 "Use libxml2"
${WITH_LIBXML2_DEFAULT})

View File

@@ -951,7 +951,7 @@ output_length
The length of the compressed header block.
percentage_of_original_size
``input_length`` / ``output_length`` * 100
``output_length`` / ``input_length`` * 100
wire
The compressed header block as a hex string.

View File

@@ -25,7 +25,7 @@ dnl Do not change user variables!
dnl http://www.gnu.org/software/automake/manual/html_node/Flag-Variables-Ordering.html
AC_PREREQ(2.61)
AC_INIT([nghttp2], [1.31.0], [t-tujikawa@users.sourceforge.net])
AC_INIT([nghttp2], [1.32.1], [t-tujikawa@users.sourceforge.net])
AC_CONFIG_AUX_DIR([.])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h])
@@ -45,7 +45,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
dnl See versioning rule:
dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
AC_SUBST(LT_CURRENT, 30)
AC_SUBST(LT_REVISION, 0)
AC_SUBST(LT_REVISION, 3)
AC_SUBST(LT_AGE, 16)
major=`echo $PACKAGE_VERSION |cut -d. -f1 | sed -e "s/[^0-9]//g"`

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "H2LOAD" "1" "Feb 27, 2018" "1.31.0" "nghttp2"
.TH "H2LOAD" "1" "Aug 25, 2018" "1.32.1" "nghttp2"
.SH NAME
h2load \- HTTP/2 benchmarking tool
.
@@ -155,7 +155,7 @@ example, with \fI\%\-t\fP2 and \fI\%\-r\fP4, each thread gets 2
connections per period. When the rate is 0, the program
will run as it normally does, creating connections at
whatever variable rate it wants. The default value for
this option is 0.
this option is 0. \fI\%\-r\fP and \fI\%\-D\fP are mutually exclusive.
.UNINDENT
.INDENT 0.0
.TP
@@ -170,7 +170,8 @@ option is 1s.
.TP
.B \-D, \-\-duration=<N>
Specifies the main duration for the measurements in case
of timing\-based benchmarking.
of timing\-based benchmarking. \fI\%\-D\fP and \fI\%\-r\fP are mutually
exclusive.
.UNINDENT
.INDENT 0.0
.TP

View File

@@ -124,7 +124,7 @@ OPTIONS
connections per period. When the rate is 0, the program
will run as it normally does, creating connections at
whatever variable rate it wants. The default value for
this option is 0.
this option is 0. :option:`-r` and :option:`\-D` are mutually exclusive.
.. option:: --rate-period=<DURATION>
@@ -137,7 +137,8 @@ OPTIONS
.. option:: -D, --duration=<N>
Specifies the main duration for the measurements in case
of timing-based benchmarking.
of timing-based benchmarking. :option:`-D` and :option:`\-r` are mutually
exclusive.
.. option:: --warm-up-time=<DURATION>

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "NGHTTP" "1" "Feb 27, 2018" "1.31.0" "nghttp2"
.TH "NGHTTP" "1" "Aug 25, 2018" "1.32.1" "nghttp2"
.SH NAME
nghttp \- HTTP/2 client
.

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "NGHTTPD" "1" "Feb 27, 2018" "1.31.0" "nghttp2"
.TH "NGHTTPD" "1" "Aug 25, 2018" "1.32.1" "nghttp2"
.SH NAME
nghttpd \- HTTP/2 server
.

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "NGHTTPX" "1" "Feb 27, 2018" "1.31.0" "nghttp2"
.TH "NGHTTPX" "1" "Aug 25, 2018" "1.32.1" "nghttp2"
.SH NAME
nghttpx \- HTTP/2 proxy
.

View File

@@ -67,14 +67,14 @@ int main(int argc, char *argv[]) {
return;
}
req->on_response([&sess](const response &res) {
req->on_response([](const response &res) {
std::cerr << "HTTP/2 " << res.status_code() << std::endl;
for (auto &kv : res.header()) {
std::cerr << kv.first << ": " << kv.second.value << "\n";
}
std::cerr << std::endl;
res.on_data([&sess](const uint8_t *data, std::size_t len) {
res.on_data([](const uint8_t *data, std::size_t len) {
std::cerr.write(reinterpret_cast<const char *>(data), len);
std::cerr << std::endl;
});

View File

@@ -91,17 +91,17 @@ int main(int argc, char *argv[]) {
return;
}
req->on_response([&sess, req](const response &res) {
req->on_response([](const response &res) {
std::cerr << "response header was received" << std::endl;
print_header(res);
res.on_data([&sess](const uint8_t *data, std::size_t len) {
res.on_data([](const uint8_t *data, std::size_t len) {
std::cerr.write(reinterpret_cast<const char *>(data), len);
std::cerr << std::endl;
});
});
req->on_close([&sess](uint32_t error_code) {
req->on_close([](uint32_t error_code) {
std::cerr << "request done with error_code=" << error_code << std::endl;
});

View File

@@ -345,6 +345,7 @@ static void setup_nghttp2_callbacks(nghttp2_session_callbacks *callbacks) {
callbacks, on_data_chunk_recv_callback);
}
#ifndef OPENSSL_NO_NEXTPROTONEG
/*
* Callback function for TLS NPN. Since this program only supports
* HTTP/2 protocol, if server does not offer HTTP/2 the nghttp2
@@ -365,6 +366,7 @@ static int select_next_proto_cb(SSL *ssl, unsigned char **out,
}
return SSL_TLSEXT_ERR_OK;
}
#endif /* !OPENSSL_NO_NEXTPROTONEG */
/*
* Setup SSL/TLS context.
@@ -375,7 +377,9 @@ static void init_ssl_ctx(SSL_CTX *ssl_ctx) {
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
/* Set NPN callback */
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
#endif /* !OPENSSL_NO_NEXTPROTONEG */
}
static void ssl_handshake(SSL *ssl, int fd) {

View File

@@ -308,6 +308,7 @@ static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
return 0;
}
#ifndef OPENSSL_NO_NEXTPROTONEG
/* NPN TLS extension client callback. We check that server advertised
the HTTP/2 protocol the nghttp2 library supports. If not, exit
the program. */
@@ -322,6 +323,7 @@ static int select_next_proto_cb(SSL *ssl, unsigned char **out,
}
return SSL_TLSEXT_ERR_OK;
}
#endif /* !OPENSSL_NO_NEXTPROTONEG */
/* Create SSL_CTX. */
static SSL_CTX *create_ssl_ctx(void) {
@@ -335,11 +337,13 @@ static SSL_CTX *create_ssl_ctx(void) {
SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 |
SSL_OP_NO_COMPRESSION |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_CTX_set_next_proto_select_cb(ssl_ctx, select_next_proto_cb, NULL);
#endif /* !OPENSSL_NO_NEXTPROTONEG */
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
SSL_CTX_set_alpn_protos(ssl_ctx, (const unsigned char *)"\x02h2", 3);
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
return ssl_ctx;
}
@@ -504,12 +508,14 @@ static void eventcb(struct bufferevent *bev, short events, void *ptr) {
ssl = bufferevent_openssl_get_ssl(session_data->bev);
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen);
#endif /* !OPENSSL_NO_NEXTPROTONEG */
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
if (alpn == NULL) {
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
}
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
fprintf(stderr, "h2 is not negotiated\n");

View File

@@ -109,6 +109,7 @@ struct app_context {
static unsigned char next_proto_list[256];
static size_t next_proto_list_len;
#ifndef OPENSSL_NO_NEXTPROTONEG
static int next_proto_cb(SSL *ssl, const unsigned char **data,
unsigned int *len, void *arg) {
(void)ssl;
@@ -118,6 +119,7 @@ static int next_proto_cb(SSL *ssl, const unsigned char **data,
*len = (unsigned int)next_proto_list_len;
return SSL_TLSEXT_ERR_OK;
}
#endif /* !OPENSSL_NO_NEXTPROTONEG */
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
static int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
@@ -135,7 +137,7 @@ static int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
return SSL_TLSEXT_ERR_OK;
}
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
/* Create SSL_CTX. */
static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) {
@@ -172,11 +174,13 @@ static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) {
NGHTTP2_PROTO_VERSION_ID_LEN);
next_proto_list_len = 1 + NGHTTP2_PROTO_VERSION_ID_LEN;
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, NULL);
#endif /* !OPENSSL_NO_NEXTPROTONEG */
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, NULL);
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
return ssl_ctx;
}
@@ -690,12 +694,14 @@ static void eventcb(struct bufferevent *bev, short events, void *ptr) {
ssl = bufferevent_openssl_get_ssl(session_data->bev);
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen);
#endif /* !OPENSSL_NO_NEXTPROTONEG */
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
if (alpn == NULL) {
SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
}
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
#endif /* OPENSSL_VERSION_NUMBER >= 0x10002000L */
if (alpn == NULL || alpnlen != 2 || memcmp("h2", alpn, 2) != 0) {
fprintf(stderr, "%s h2 is not negotiated\n", session_data->client_addr);

View File

@@ -49,7 +49,7 @@ target_include_directories(nghttp2 INTERFACE
"${CMAKE_CURRENT_SOURCE_DIR}/includes"
)
if(HAVE_CUNIT)
if(HAVE_CUNIT OR ENABLE_STATIC_LIB)
# Static library (for unittests because of symbol visibility)
add_library(nghttp2_static STATIC ${NGHTTP2_SOURCES})
set_target_properties(nghttp2_static PROPERTIES
@@ -58,6 +58,10 @@ if(HAVE_CUNIT)
ARCHIVE_OUTPUT_NAME nghttp2
)
target_compile_definitions(nghttp2_static PUBLIC "-DNGHTTP2_STATICLIB")
if(ENABLE_STATIC_LIB)
install(TARGETS nghttp2_static
DESTINATION "${CMAKE_INSTALL_LIBDIR}")
endif()
endif()
install(TARGETS nghttp2

View File

@@ -3797,10 +3797,13 @@ nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec);
* .. warning::
*
* This function returns assigned stream ID if it succeeds. But
* that stream is not opened yet. The application must not submit
* that stream is not created yet. The application must not submit
* frame to that stream ID before
* :type:`nghttp2_before_frame_send_callback` is called for this
* frame.
* frame. This means `nghttp2_session_get_stream_user_data()` does
* not work before the callback. But
* `nghttp2_session_set_stream_user_data()` handles this situation
* specially, and it can set data to a stream during this period.
*
*/
NGHTTP2_EXTERN int32_t nghttp2_submit_request(

View File

@@ -215,6 +215,9 @@ void nghttp2_frame_altsvc_free(nghttp2_extension *frame, nghttp2_mem *mem) {
nghttp2_ext_altsvc *altsvc;
altsvc = frame->payload;
if (altsvc == NULL) {
return;
}
/* We use the same buffer for altsvc->origin and
altsvc->field_value. */
nghttp2_mem_free(mem, altsvc->origin);

View File

@@ -244,7 +244,7 @@ static int http_response_on_header(nghttp2_stream *stream, nghttp2_hd_nv *nv,
return NGHTTP2_ERR_HTTP_HEADER;
}
stream->status_code = (int16_t)parse_uint(nv->value->base, nv->value->len);
if (stream->status_code == -1) {
if (stream->status_code == -1 || stream->status_code == 101) {
return NGHTTP2_ERR_HTTP_HEADER;
}
break;

View File

@@ -219,6 +219,10 @@ static int session_terminate_session(nghttp2_session *session,
return 0;
}
/* Ignore all incoming frames because we are going to tear down the
session. */
session->iframe.state = NGHTTP2_IB_IGN_ALL;
if (reason == NULL) {
debug_data = NULL;
debug_datalen = 0;
@@ -5346,9 +5350,6 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
if (iframe->sbuf.pos[3] != NGHTTP2_SETTINGS ||
(iframe->sbuf.pos[4] & NGHTTP2_FLAG_ACK)) {
iframe->state = NGHTTP2_IB_IGN_ALL;
rv = session_call_error_callback(
session, NGHTTP2_ERR_SETTINGS_EXPECTED,
"Remote peer returned unexpected data while we expected "
@@ -5395,10 +5396,6 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
DEBUGF("recv: length is too large %zu > %u\n", iframe->frame.hd.length,
session->local_settings.max_frame_size);
busy = 1;
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
rv = nghttp2_session_terminate_session_with_reason(
session, NGHTTP2_FRAME_SIZE_ERROR, "too large frame size");
@@ -5406,7 +5403,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
return rv;
}
break;
return (ssize_t)inlen;
}
switch (iframe->frame.hd.type) {
@@ -5420,6 +5417,9 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
busy = 1;
rv = session_on_data_received_fail_fast(session);
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (ssize_t)inlen;
}
if (rv == NGHTTP2_ERR_IGN_PAYLOAD) {
DEBUGF("recv: DATA not allowed stream_id=%d\n",
iframe->frame.hd.stream_id);
@@ -5433,7 +5433,6 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd);
if (rv < 0) {
iframe->state = NGHTTP2_IB_IGN_DATA;
rv = nghttp2_session_terminate_session_with_reason(
session, NGHTTP2_PROTOCOL_ERROR,
"DATA: insufficient padding space");
@@ -5441,7 +5440,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
if (nghttp2_is_fatal(rv)) {
return rv;
}
break;
return (ssize_t)inlen;
}
if (rv == 1) {
@@ -5462,17 +5461,13 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd);
if (rv < 0) {
busy = 1;
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
rv = nghttp2_session_terminate_session_with_reason(
session, NGHTTP2_PROTOCOL_ERROR,
"HEADERS: insufficient padding space");
if (nghttp2_is_fatal(rv)) {
return rv;
}
break;
return (ssize_t)inlen;
}
if (rv == 1) {
@@ -5514,6 +5509,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
busy = 1;
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (ssize_t)inlen;
}
if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
rv = nghttp2_session_add_rst_stream(
session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR);
@@ -5628,15 +5627,13 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
rv = inbound_frame_handle_pad(iframe, &iframe->frame.hd);
if (rv < 0) {
busy = 1;
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
rv = nghttp2_session_terminate_session_with_reason(
session, NGHTTP2_PROTOCOL_ERROR,
"PUSH_PROMISE: insufficient padding space");
if (nghttp2_is_fatal(rv)) {
return rv;
}
break;
return (ssize_t)inlen;
}
if (rv == 1) {
@@ -5696,11 +5693,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
return rv;
}
busy = 1;
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
break;
return (ssize_t)inlen;
default:
DEBUGF("recv: extension frame\n");
@@ -5770,6 +5763,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
case NGHTTP2_IB_IGN_PAYLOAD:
case NGHTTP2_IB_FRAME_SIZE_ERROR:
case NGHTTP2_IB_IGN_DATA:
case NGHTTP2_IB_IGN_ALL:
break;
default:
rv = session_call_on_begin_frame(session, &iframe->frame.hd);
@@ -5800,21 +5794,19 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
case NGHTTP2_HEADERS:
if (iframe->padlen == 0 &&
(iframe->frame.hd.flags & NGHTTP2_FLAG_PADDED)) {
pri_fieldlen = nghttp2_frame_priority_len(iframe->frame.hd.flags);
padlen = inbound_frame_compute_pad(iframe);
if (padlen < 0) {
busy = 1;
if (padlen < 0 ||
(size_t)padlen + pri_fieldlen > 1 + iframe->payloadleft) {
rv = nghttp2_session_terminate_session_with_reason(
session, NGHTTP2_PROTOCOL_ERROR, "HEADERS: invalid padding");
if (nghttp2_is_fatal(rv)) {
return rv;
}
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
break;
return (ssize_t)inlen;
}
iframe->frame.headers.padlen = (size_t)padlen;
pri_fieldlen = nghttp2_frame_priority_len(iframe->frame.hd.flags);
if (pri_fieldlen > 0) {
if (iframe->payloadleft < pri_fieldlen) {
busy = 1;
@@ -5837,6 +5829,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
busy = 1;
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (ssize_t)inlen;
}
if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
rv = nghttp2_session_add_rst_stream(
session, iframe->frame.hd.stream_id, NGHTTP2_INTERNAL_ERROR);
@@ -5861,6 +5857,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
return rv;
}
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (ssize_t)inlen;
}
session_inbound_frame_reset(session);
break;
@@ -5870,6 +5870,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
return rv;
}
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (ssize_t)inlen;
}
session_inbound_frame_reset(session);
break;
@@ -5877,16 +5881,15 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
if (iframe->padlen == 0 &&
(iframe->frame.hd.flags & NGHTTP2_FLAG_PADDED)) {
padlen = inbound_frame_compute_pad(iframe);
if (padlen < 0) {
busy = 1;
if (padlen < 0 || (size_t)padlen + 4 /* promised stream id */
> 1 + iframe->payloadleft) {
rv = nghttp2_session_terminate_session_with_reason(
session, NGHTTP2_PROTOCOL_ERROR,
"PUSH_PROMISE: invalid padding");
if (nghttp2_is_fatal(rv)) {
return rv;
}
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
break;
return (ssize_t)inlen;
}
iframe->frame.push_promise.padlen = (size_t)padlen;
@@ -5911,6 +5914,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
busy = 1;
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (ssize_t)inlen;
}
if (rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
rv = nghttp2_session_add_rst_stream(
session, iframe->frame.push_promise.promised_stream_id,
@@ -5936,6 +5943,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
return rv;
}
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (ssize_t)inlen;
}
session_inbound_frame_reset(session);
break;
@@ -5967,6 +5978,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
return rv;
}
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (ssize_t)inlen;
}
session_inbound_frame_reset(session);
break;
@@ -6028,6 +6043,12 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
data_readlen = inbound_frame_effective_readlen(
iframe, iframe->payloadleft - readlen, readlen);
if (data_readlen == -1) {
/* everything is padding */
data_readlen = 0;
}
trail_padlen = nghttp2_frame_trail_padlen(&iframe->frame, iframe->padlen);
final = (iframe->frame.hd.flags & NGHTTP2_FLAG_END_HEADERS) &&
@@ -6047,6 +6068,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
return rv;
}
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (ssize_t)inlen;
}
if (rv == NGHTTP2_ERR_PAUSE) {
in += hd_proclen;
iframe->payloadleft -= hd_proclen;
@@ -6156,11 +6181,9 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
return rv;
}
busy = 1;
assert(iframe->state == NGHTTP2_IB_IGN_ALL);
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
break;
return (ssize_t)inlen;
case NGHTTP2_IB_READ_SETTINGS:
DEBUGF("recv: [IB_READ_SETTINGS]\n");
@@ -6189,6 +6212,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
return rv;
}
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (ssize_t)inlen;
}
session_inbound_frame_reset(session);
break;
@@ -6219,6 +6246,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
return rv;
}
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (ssize_t)inlen;
}
session_inbound_frame_reset(session);
break;
@@ -6258,11 +6289,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
return rv;
}
busy = 1;
iframe->state = NGHTTP2_IB_IGN_PAYLOAD;
break;
return (ssize_t)inlen;
}
/* CONTINUATION won't bear NGHTTP2_PADDED flag */
@@ -6306,6 +6333,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
return rv;
}
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (ssize_t)inlen;
}
/* Pad Length field is consumed immediately */
rv =
nghttp2_session_consume(session, iframe->frame.hd.stream_id, readlen);
@@ -6314,6 +6345,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
return rv;
}
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (ssize_t)inlen;
}
stream = nghttp2_session_get_stream(session, iframe->frame.hd.stream_id);
if (stream) {
rv = session_update_recv_stream_window_size(
@@ -6334,8 +6369,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
if (nghttp2_is_fatal(rv)) {
return rv;
}
iframe->state = NGHTTP2_IB_IGN_DATA;
break;
return (ssize_t)inlen;
}
iframe->frame.data.padlen = (size_t)padlen;
@@ -6369,6 +6403,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
return rv;
}
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (ssize_t)inlen;
}
rv = session_update_recv_stream_window_size(
session, stream, readlen,
iframe->payloadleft ||
@@ -6395,6 +6433,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
if (nghttp2_is_fatal(rv)) {
return rv;
}
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (ssize_t)inlen;
}
}
DEBUGF("recv: data_readlen=%zd\n", data_readlen);
@@ -6410,6 +6452,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
if (nghttp2_is_fatal(rv)) {
return rv;
}
if (iframe->state == NGHTTP2_IB_IGN_DATA) {
return (ssize_t)inlen;
}
}
rv = nghttp2_session_add_rst_stream(
@@ -6467,6 +6513,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
return rv;
}
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (ssize_t)inlen;
}
if (session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE) {
/* Ignored DATA is considered as "consumed" immediately. */
@@ -6475,6 +6525,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session, const uint8_t *in,
if (nghttp2_is_fatal(rv)) {
return rv;
}
if (iframe->state == NGHTTP2_IB_IGN_ALL) {
return (ssize_t)inlen;
}
}
}
@@ -7031,12 +7085,42 @@ int nghttp2_session_set_stream_user_data(nghttp2_session *session,
int32_t stream_id,
void *stream_user_data) {
nghttp2_stream *stream;
nghttp2_frame *frame;
nghttp2_outbound_item *item;
stream = nghttp2_session_get_stream(session, stream_id);
if (!stream) {
if (stream) {
stream->stream_user_data = stream_user_data;
return 0;
}
if (session->server || !nghttp2_session_is_my_stream_id(session, stream_id) ||
!nghttp2_outbound_queue_top(&session->ob_syn)) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
stream->stream_user_data = stream_user_data;
return 0;
frame = &nghttp2_outbound_queue_top(&session->ob_syn)->frame;
assert(frame->hd.type == NGHTTP2_HEADERS);
if (frame->hd.stream_id > stream_id ||
(uint32_t)stream_id >= session->next_stream_id) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
for (item = session->ob_syn.head; item; item = item->qnext) {
if (item->frame.hd.stream_id < stream_id) {
continue;
}
if (item->frame.hd.stream_id > stream_id) {
break;
}
item->aux_data.headers.stream_user_data = stream_user_data;
return 0;
}
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
int nghttp2_session_resume_data(nghttp2_session *session, int32_t stream_id) {

View File

@@ -888,7 +888,9 @@ int Http2Handler::verify_npn_result() {
const unsigned char *next_proto = nullptr;
unsigned int next_proto_len;
// Check the negotiated protocol in NPN or ALPN
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_get0_next_proto_negotiated(ssl_, &next_proto, &next_proto_len);
#endif // !OPENSSL_NO_NEXTPROTONEG
for (int i = 0; i < 2; ++i) {
if (next_proto) {
auto proto = StringRef{next_proto, next_proto_len};
@@ -1982,6 +1984,7 @@ HttpServer::HttpServer(const Config *config) : config_(config) {
};
}
#ifndef OPENSSL_NO_NEXTPROTONEG
namespace {
int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
void *arg) {
@@ -1991,6 +1994,7 @@ int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
return SSL_TLSEXT_ERR_OK;
}
} // namespace
#endif // !OPENSSL_NO_NEXTPROTONEG
namespace {
int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
@@ -2205,7 +2209,9 @@ int HttpServer::run() {
next_proto = util::get_default_alpn();
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, &next_proto);
#endif // !OPENSSL_NO_NEXTPROTONEG
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
// ALPN selection callback
SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, this);

View File

@@ -38,6 +38,10 @@ session_tls_impl::session_tls_impl(
// ssl::context::set_verify_mode(boost::asio::ssl::verify_peer) is
// not used, which is what we want.
socket_.set_verify_callback(boost::asio::ssl::rfc2818_verification(host));
auto ssl = socket_.native_handle();
if (!util::numeric_host(host.c_str())) {
SSL_set_tlsext_host_name(ssl, host.c_str());
}
}
session_tls_impl::~session_tls_impl() {}

View File

@@ -35,6 +35,7 @@ namespace nghttp2 {
namespace asio_http2 {
namespace client {
#ifndef OPENSSL_NO_NEXTPROTONEG
namespace {
int client_select_next_proto_cb(SSL *ssl, unsigned char **out,
unsigned char *outlen, const unsigned char *in,
@@ -46,6 +47,7 @@ int client_select_next_proto_cb(SSL *ssl, unsigned char **out,
return SSL_TLSEXT_ERR_OK;
}
} // namespace
#endif // !OPENSSL_NO_NEXTPROTONEG
boost::system::error_code
configure_tls_context(boost::system::error_code &ec,
@@ -54,7 +56,9 @@ configure_tls_context(boost::system::error_code &ec,
auto ctx = tls_ctx.native_handle();
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_CTX_set_next_proto_select_cb(ctx, client_select_next_proto_cb, nullptr);
#endif // !OPENSSL_NO_NEXTPROTONEG
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
auto proto_list = util::get_default_alpn();

View File

@@ -177,7 +177,9 @@ bool tls_h2_negotiated(ssl_socket &socket) {
const unsigned char *next_proto = nullptr;
unsigned int next_proto_len = 0;
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len);
#endif // !OPENSSL_NO_NEXTPROTONEG
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
if (next_proto == nullptr) {
SSL_get0_alpn_selected(ssl, &next_proto, &next_proto_len);

View File

@@ -35,12 +35,14 @@ namespace nghttp2 {
namespace asio_http2 {
namespace server {
#ifndef OPENSSL_NO_NEXTPROTONEG
namespace {
std::vector<unsigned char> &get_alpn_token() {
static auto alpn_token = util::get_default_alpn();
return alpn_token;
}
} // namespace
#endif // !OPENSSL_NO_NEXTPROTONEG
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
namespace {
@@ -82,6 +84,7 @@ configure_tls_context_easy(boost::system::error_code &ec,
}
#endif /* OPENSSL_NO_EC */
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_CTX_set_next_protos_advertised_cb(
ctx,
[](SSL *s, const unsigned char **data, unsigned int *len, void *arg) {
@@ -93,6 +96,7 @@ configure_tls_context_easy(boost::system::error_code &ec,
return SSL_TLSEXT_ERR_OK;
},
nullptr);
#endif // !OPENSSL_NO_NEXTPROTONEG
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
// ALPN selection callback

View File

@@ -857,7 +857,9 @@ int Client::connection_made() {
const unsigned char *next_proto = nullptr;
unsigned int next_proto_len;
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len);
#endif // !OPENSSL_NO_NEXTPROTONEG
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
if (next_proto == nullptr) {
SSL_get0_alpn_selected(ssl, &next_proto, &next_proto_len);
@@ -1563,6 +1565,7 @@ std::string get_reqline(const char *uri, const http_parser_url &u) {
}
} // namespace
#ifndef OPENSSL_NO_NEXTPROTONEG
namespace {
int client_select_next_proto_cb(SSL *ssl, unsigned char **out,
unsigned char *outlen, const unsigned char *in,
@@ -1577,6 +1580,7 @@ int client_select_next_proto_cb(SSL *ssl, unsigned char **out,
return SSL_TLSEXT_ERR_NOACK;
}
} // namespace
#endif // !OPENSSL_NO_NEXTPROTONEG
namespace {
constexpr char UNIX_PATH_PREFIX[] = "unix:";
@@ -1852,7 +1856,7 @@ Options:
connections per period. When the rate is 0, the program
will run as it normally does, creating connections at
whatever variable rate it wants. The default value for
this option is 0.
this option is 0. -r and -D are mutually exclusive.
--rate-period=<DURATION>
Specifies the time period between creating connections.
The period must be a positive number, representing the
@@ -1861,7 +1865,8 @@ Options:
option is 1s.
-D, --duration=<N>
Specifies the main duration for the measurements in case
of timing-based benchmarking.
of timing-based benchmarking. -D and -r are mutually
exclusive.
--warm-up-time=<DURATION>
Specifies the time period before starting the actual
measurements, in case of timing-based benchmarking.
@@ -2294,6 +2299,11 @@ int main(int argc, char **argv) {
exit(EXIT_FAILURE);
}
if (config.is_timing_based_mode() && config.is_rate_mode()) {
std::cerr << "-r, -D: they are mutually exclusive." << std::endl;
exit(EXIT_FAILURE);
}
if (config.nreqs == 0 && !config.is_timing_based_mode()) {
std::cerr << "-n: the number of requests must be strictly greater than 0 "
"if timing-based test is not being run."
@@ -2399,8 +2409,10 @@ int main(int argc, char **argv) {
exit(EXIT_FAILURE);
}
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_CTX_set_next_proto_select_cb(ssl_ctx, client_select_next_proto_cb,
nullptr);
#endif // !OPENSSL_NO_NEXTPROTONEG
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
std::vector<unsigned char> proto_list;

View File

@@ -59,6 +59,7 @@
#include "base64.h"
#include "tls.h"
#include "template.h"
#include "ssl_compat.h"
#ifndef O_BINARY
#define O_BINARY (0)
@@ -680,15 +681,16 @@ int HttpClient::initiate_connection() {
const auto &host_string =
config.host_override.empty() ? host : config.host_override;
#if (!defined(LIBRESSL_VERSION_NUMBER) && \
OPENSSL_VERSION_NUMBER >= 0x10002000L) || \
#if LIBRESSL_2_7_API || \
(!LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L) || \
defined(OPENSSL_IS_BORINGSSL)
auto param = SSL_get0_param(ssl);
X509_VERIFY_PARAM_set_hostflags(param, 0);
X509_VERIFY_PARAM_set1_host(param, host_string.c_str(),
host_string.size());
#endif // (!defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >=
// 0x10002000L) || defined(OPENSSL_IS_BORINGSSL)
#endif // LIBRESSL_2_7_API || (!LIBRESSL_IN_USE &&
// OPENSSL_VERSION_NUMBER >= 0x10002000L) ||
// defined(OPENSSL_IS_BORINGSSL)
SSL_set_verify(ssl, SSL_VERIFY_PEER, verify_cb);
if (!util::numeric_host(host_string.c_str())) {
@@ -1095,7 +1097,9 @@ int HttpClient::connection_made() {
// Check NPN or ALPN result
const unsigned char *next_proto = nullptr;
unsigned int next_proto_len;
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len);
#endif // !OPENSSL_NO_NEXTPROTONEG
for (int i = 0; i < 2; ++i) {
if (next_proto) {
auto proto = StringRef{next_proto, next_proto_len};
@@ -2220,6 +2224,7 @@ id responseEnd requestStart process code size request path)"
}
} // namespace
#ifndef OPENSSL_NO_NEXTPROTONEG
namespace {
int client_select_next_proto_cb(SSL *ssl, unsigned char **out,
unsigned char *outlen, const unsigned char *in,
@@ -2243,6 +2248,7 @@ int client_select_next_proto_cb(SSL *ssl, unsigned char **out,
return SSL_TLSEXT_ERR_OK;
}
} // namespace
#endif // !OPENSSL_NO_NEXTPROTONEG
namespace {
int communicate(
@@ -2308,8 +2314,10 @@ int communicate(
goto fin;
}
}
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_CTX_set_next_proto_select_cb(ssl_ctx, client_select_next_proto_cb,
nullptr);
#endif // !OPENSSL_NO_NEXTPROTONEG
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
auto proto_list = util::get_default_alpn();

View File

@@ -549,7 +549,9 @@ int ClientHandler::validate_next_proto() {
// First set callback for catch all cases
on_read_ = &ClientHandler::upstream_read;
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_get0_next_proto_negotiated(conn_.tls.ssl, &next_proto, &next_proto_len);
#endif // !OPENSSL_NO_NEXTPROTONEG
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
if (next_proto == nullptr) {
SSL_get0_alpn_selected(conn_.tls.ssl, &next_proto, &next_proto_len);

View File

@@ -1222,7 +1222,7 @@ int parse_subcert_params(SubcertParams &out, const StringRef &src_params) {
auto param = StringRef{first, end};
if (util::istarts_with_l(param, "sct-dir=")) {
#if !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L
#if !LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L
auto sct_dir =
StringRef{std::begin(param) + str_size("sct-dir="), std::end(param)};
if (sct_dir.empty()) {
@@ -1230,9 +1230,9 @@ int parse_subcert_params(SubcertParams &out, const StringRef &src_params) {
return -1;
}
out.sct_dir = sct_dir;
#else // !(!LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L)
#else // !(!LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L)
LOG(WARN) << "subcert: sct-dir requires OpenSSL >= 1.0.2";
#endif // !(!LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L)
#endif // !(!LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L)
} else if (!param.empty()) {
LOG(ERROR) << "subcert: " << param << ": unknown keyword";
return -1;
@@ -1364,7 +1364,7 @@ int read_tls_sct_from_dir(std::vector<uint8_t> &dst, const StringRef &opt,
}
} // namespace
#if !LIBRESSL_IN_USE
#if !LIBRESSL_LEGACY_API
namespace {
// Reads PSK secrets from path, and parses each line. The result is
// directly stored into config->tls.psk_secrets. This function
@@ -1428,9 +1428,9 @@ int parse_psk_secrets(Config *config, const StringRef &path) {
return 0;
}
} // namespace
#endif // !LIBRESSL_IN_USE
#endif // !LIBRESSL_LEGACY_API
#if !LIBRESSL_IN_USE
#if !LIBRESSL_LEGACY_API
namespace {
// Reads PSK secrets from path, and parses each line. The result is
// directly stored into config->tls.client.psk. This function returns
@@ -1490,7 +1490,7 @@ int parse_client_psk_secrets(Config *config, const StringRef &path) {
return 0;
}
} // namespace
#endif // !LIBRESSL_IN_USE
#endif // !LIBRESSL_LEGACY_API
// generated by gennghttpxfun.py
int option_lookup_token(const char *name, size_t namelen) {
@@ -3454,19 +3454,19 @@ int parse_config(Config *config, int optid, const StringRef &opt,
return parse_uint_with_unit(
&config->http2.downstream.decoder_dynamic_table_size, opt, optarg);
case SHRPX_OPTID_ECDH_CURVES:
#if !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L
#if !LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L
config->tls.ecdh_curves = make_string_ref(config->balloc, optarg);
#else // !(!LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L)
#else // !(!LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L)
LOG(WARN) << opt << ": This option requires OpenSSL >= 1.0.2";
#endif // !(!LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L)
#endif // !(!LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L)
return 0;
case SHRPX_OPTID_TLS_SCT_DIR:
#if !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L
#if !LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L
return read_tls_sct_from_dir(config->tls.sct_data, opt, optarg);
#else // !(!LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L)
#else // !(!LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L)
LOG(WARN) << opt << ": This option requires OpenSSL >= 1.0.2";
return 0;
#endif // !(!LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L)
#endif // !(!LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L)
case SHRPX_OPTID_DNS_CACHE_TIMEOUT:
return parse_duration(&config->dns.timeout.cache, opt, optarg);
case SHRPX_OPTID_DNS_LOOKUP_TIMEOUT:
@@ -3489,23 +3489,23 @@ int parse_config(Config *config, int optid, const StringRef &opt,
return parse_duration(&config->conn.upstream.timeout.idle_read, opt,
optarg);
case SHRPX_OPTID_PSK_SECRETS:
#if !LIBRESSL_IN_USE
#if !LIBRESSL_LEGACY_API
return parse_psk_secrets(config, optarg);
#else // LIBRESSL_IN_USE
#else // LIBRESSL_LEGACY_API
LOG(WARN)
<< opt
<< ": ignored because underlying TLS library does not support PSK";
return 0;
#endif // LIBRESSL_IN_USE
#endif // LIBRESSL_LEGACY_API
case SHRPX_OPTID_CLIENT_PSK_SECRETS:
#if !LIBRESSL_IN_USE
#if !LIBRESSL_LEGACY_API
return parse_client_psk_secrets(config, optarg);
#else // LIBRESSL_IN_USE
#else // LIBRESSL_LEGACY_API
LOG(WARN)
<< opt
<< ": ignored because underlying TLS library does not support PSK";
return 0;
#endif // LIBRESSL_IN_USE
#endif // LIBRESSL_LEGACY_API
case SHRPX_OPTID_CLIENT_NO_HTTP2_CIPHER_BLACK_LIST:
config->tls.client.no_http2_cipher_black_list =
util::strieq_l("yes", optarg);

View File

@@ -44,13 +44,13 @@ using namespace nghttp2;
namespace shrpx {
#if !OPENSSL_1_1_API
#if !LIBRESSL_2_7_API && !OPENSSL_1_1_API
void *BIO_get_data(BIO *bio) { return bio->ptr; }
void BIO_set_data(BIO *bio, void *ptr) { bio->ptr = ptr; }
void BIO_set_init(BIO *bio, int init) { bio->init = init; }
#endif // !OPENSSL_1_1_API
#endif // !LIBRESSL_2_7_API && !OPENSSL_1_1_API
Connection::Connection(struct ev_loop *loop, int fd, SSL *ssl,
MemchunkPool *mcpool, ev_tstamp write_timeout,
@@ -523,7 +523,9 @@ int Connection::check_http2_requirement() {
const unsigned char *next_proto = nullptr;
unsigned int next_proto_len;
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_get0_next_proto_negotiated(tls.ssl, &next_proto, &next_proto_len);
#endif // !OPENSSL_NO_NEXTPROTONEG
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
if (next_proto == nullptr) {
SSL_get0_alpn_selected(tls.ssl, &next_proto, &next_proto_len);

View File

@@ -1649,7 +1649,9 @@ int Http2Session::connection_made() {
const unsigned char *next_proto = nullptr;
unsigned int next_proto_len = 0;
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_get0_next_proto_negotiated(conn_.tls.ssl, &next_proto, &next_proto_len);
#endif // !OPENSSL_NO_NEXTPROTONEG
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
if (!next_proto) {
SSL_get0_alpn_selected(conn_.tls.ssl, &next_proto, &next_proto_len);

View File

@@ -406,7 +406,9 @@ int LiveCheck::tls_handshake() {
const unsigned char *next_proto = nullptr;
unsigned int next_proto_len = 0;
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_get0_next_proto_negotiated(conn_.tls.ssl, &next_proto, &next_proto_len);
#endif // !OPENSSL_NO_NEXTPROTONEG
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
if (next_proto == nullptr) {
SSL_get0_alpn_selected(conn_.tls.ssl, &next_proto, &next_proto_len);

View File

@@ -80,6 +80,7 @@ const unsigned char *ASN1_STRING_get0_data(ASN1_STRING *x) {
} // namespace
#endif // !OPENSSL_1_1_API
#ifndef OPENSSL_NO_NEXTPROTONEG
namespace {
int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
void *arg) {
@@ -89,6 +90,7 @@ int next_proto_cb(SSL *s, const unsigned char **data, unsigned int *len,
return SSL_TLSEXT_ERR_OK;
}
} // namespace
#endif // !OPENSSL_NO_NEXTPROTONEG
namespace {
int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
@@ -192,7 +194,7 @@ int servername_callback(SSL *ssl, int *al, void *arg) {
const auto &ssl_ctx_list = conn_handler->get_indexed_ssl_ctx(idx);
assert(!ssl_ctx_list.empty());
#if !defined(OPENSSL_IS_BORINGSSL) && !defined(LIBRESSL_VERSION_NUMBER) && \
#if !defined(OPENSSL_IS_BORINGSSL) && !LIBRESSL_IN_USE && \
OPENSSL_VERSION_NUMBER >= 0x10002000L
auto num_shared_curves = SSL_get_shared_curve(ssl, -1);
@@ -236,7 +238,7 @@ int servername_callback(SSL *ssl, int *al, void *arg) {
}
}
}
#endif // !defined(OPENSSL_IS_BORINGSSL) && !defined(LIBRESSL_VERSION_NUMBER) &&
#endif // !defined(OPENSSL_IS_BORINGSSL) && !LIBRESSL_IN_USE &&
// OPENSSL_VERSION_NUMBER >= 0x10002000L
SSL_set_SSL_CTX(ssl, ssl_ctx_list[0]);
@@ -655,7 +657,7 @@ int legacy_sct_parse_cb(SSL *ssl, unsigned int ext_type,
#endif // !OPENSSL_1_1_1_API
#endif // !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L
#if !LIBRESSL_IN_USE
#ifndef OPENSSL_NO_PSK
namespace {
unsigned int psk_server_cb(SSL *ssl, const char *identity, unsigned char *psk,
unsigned int max_psk_len) {
@@ -679,9 +681,9 @@ unsigned int psk_server_cb(SSL *ssl, const char *identity, unsigned char *psk,
return static_cast<unsigned int>(secret.size());
}
} // namespace
#endif // !LIBRESSL_IN_USE
#endif // !OPENSSL_NO_PSK
#if !LIBRESSL_IN_USE
#ifndef OPENSSL_NO_PSK
namespace {
unsigned int psk_client_cb(SSL *ssl, const char *hint, char *identity_out,
unsigned int max_identity_len, unsigned char *psk,
@@ -714,7 +716,7 @@ unsigned int psk_client_cb(SSL *ssl, const char *hint, char *identity_out,
return static_cast<unsigned int>(secret.size());
}
} // namespace
#endif // !LIBRESSL_IN_USE
#endif // !OPENSSL_NO_PSK
struct TLSProtocol {
StringRef name;
@@ -792,7 +794,7 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file,
}
#ifndef OPENSSL_NO_EC
#if !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L
#if !LIBRESSL_LEGACY_API && OPENSSL_VERSION_NUMBER >= 0x10002000L
if (SSL_CTX_set1_curves_list(ssl_ctx, tlsconf.ecdh_curves.c_str()) != 1) {
LOG(FATAL) << "SSL_CTX_set1_curves_list " << tlsconf.ecdh_curves
<< " failed";
@@ -803,7 +805,7 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file,
// function was deprecated in OpenSSL 1.1.0 and BoringSSL.
SSL_CTX_set_ecdh_auto(ssl_ctx, 1);
#endif // !defined(OPENSSL_IS_BORINGSSL) && !OPENSSL_1_1_API
#else // LIBRESSL_IN_USE || OPENSSL_VERSION_NUBMER < 0x10002000L
#else // LIBRESSL_LEGACY_API || OPENSSL_VERSION_NUBMER < 0x10002000L
// Use P-256, which is sufficiently secure at the time of this
// writing.
auto ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
@@ -814,7 +816,7 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file,
}
SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh);
EC_KEY_free(ecdh);
#endif // LIBRESSL_IN_USE || OPENSSL_VERSION_NUBMER < 0x10002000L
#endif // LIBRESSL_LEGACY_API || OPENSSL_VERSION_NUBMER < 0x10002000L
#endif // OPENSSL_NO_EC
if (!tlsconf.dh_param_file.empty()) {
@@ -923,7 +925,9 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file,
#endif // OPENSSL_IS_BORINGSSL
// NPN advertisement
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, nullptr);
#endif // !OPENSSL_NO_NEXTPROTONEG
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
// ALPN selection callback
SSL_CTX_set_alpn_select_cb(ssl_ctx, alpn_select_proto_cb, nullptr);
@@ -962,9 +966,9 @@ SSL_CTX *create_ssl_context(const char *private_key_file, const char *cert_file,
}
#endif // !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L
#if !LIBRESSL_IN_USE
#ifndef OPENSSL_NO_PSK
SSL_CTX_set_psk_server_callback(ssl_ctx, psk_server_cb);
#endif // !LIBRESSL_IN_USE
#endif // !LIBRESSL_NO_PSK
auto tls_ctx_data = new TLSContextData();
tls_ctx_data->cert_file = cert_file;
@@ -1112,13 +1116,15 @@ SSL_CTX *create_ssl_client_context(
#endif // HAVE_NEVERBLEED
}
#if !LIBRESSL_IN_USE
#ifndef OPENSSL_NO_PSK
SSL_CTX_set_psk_client_callback(ssl_ctx, psk_client_cb);
#endif // !LIBRESSL_IN_USE
#endif // !OPENSSL_NO_PSK
// NPN selection callback. This is required to set SSL_CTX because
// OpenSSL does not offer SSL_set_next_proto_select_cb.
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_CTX_set_next_proto_select_cb(ssl_ctx, next_proto_select_cb, nullptr);
#endif // !OPENSSL_NO_NEXTPROTONEG
return ssl_ctx;
}
@@ -1549,16 +1555,15 @@ int cert_lookup_tree_add_ssl_ctx(
SSL_CTX *ssl_ctx) {
std::array<uint8_t, NI_MAXHOST> buf;
#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10002000L
#if LIBRESSL_2_7_API || \
(!LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L)
auto cert = SSL_CTX_get0_certificate(ssl_ctx);
#else // defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER <
// 0x10002000L
#else // !LIBRESSL_2_7_API && OPENSSL_VERSION_NUMBER < 0x10002000L
auto tls_ctx_data =
static_cast<TLSContextData *>(SSL_CTX_get_app_data(ssl_ctx));
auto cert = load_certificate(tls_ctx_data->cert_file);
auto cert_deleter = defer(X509_free, cert);
#endif // defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER <
// 0x10002000L
#endif // !LIBRESSL_2_7_API && OPENSSL_VERSION_NUMBER < 0x10002000L
auto altnames = static_cast<GENERAL_NAMES *>(
X509_get_ext_d2i(cert, NID_subject_alt_name, nullptr, nullptr));
@@ -1846,7 +1851,7 @@ int proto_version_from_string(const StringRef &v) {
int verify_ocsp_response(SSL_CTX *ssl_ctx, const uint8_t *ocsp_resp,
size_t ocsp_resplen) {
#if !defined(OPENSSL_NO_OCSP) && !defined(LIBRESSL_VERSION_NUMBER) && \
#if !defined(OPENSSL_NO_OCSP) && !LIBRESSL_IN_USE && \
OPENSSL_VERSION_NUMBER >= 0x10002000L
int rv;
@@ -1919,7 +1924,7 @@ int verify_ocsp_response(SSL_CTX *ssl_ctx, const uint8_t *ocsp_resp,
if (LOG_ENABLED(INFO)) {
LOG(INFO) << "OCSP verification succeeded";
}
#endif // !defined(OPENSSL_NO_OCSP) && !defined(LIBRESSL_VERSION_NUMBER)
#endif // !defined(OPENSSL_NO_OCSP) && !LIBRESSL_IN_USE
// && OPENSSL_VERSION_NUMBER >= 0x10002000L
return 0;

View File

@@ -27,15 +27,17 @@
#include <openssl/opensslv.h>
#if defined(LIBRESSL_VERSION_NUMBER)
#define OPENSSL_1_1_API 0
#define OPENSSL_1_1_1_API 0
#define LIBRESSL_IN_USE 1
#define LIBRESSL_LEGACY_API (LIBRESSL_VERSION_NUMBER < 0x20700000L)
#define LIBRESSL_2_7_API (LIBRESSL_VERSION_NUMBER >= 0x20700000L)
#else // !defined(LIBRESSL_VERSION_NUMBER)
#define OPENSSL_1_1_API (OPENSSL_VERSION_NUMBER >= 0x1010000fL)
#define OPENSSL_1_1_1_API (OPENSSL_VERSION_NUMBER >= 0x10101000L)
#define LIBRESSL_IN_USE 0
#define LIBRESSL_LEGACY_API 0
#define LIBRESSL_2_7_API 0
#endif // !defined(LIBRESSL_VERSION_NUMBER)
#define OPENSSL_1_1_API \
(!LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x1010000fL)
#define OPENSSL_1_1_1_API \
(!LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10101000L)
#endif // OPENSSL_COMPAT_H

View File

@@ -43,13 +43,13 @@ int main() {
/* initialize the CUnit test registry */
if (CUE_SUCCESS != CU_initialize_registry())
return CU_get_error();
return (int)CU_get_error();
/* add a suite to the registry */
pSuite = CU_add_suite("libnghttp2_TestSuite", init_suite1, clean_suite1);
if (NULL == pSuite) {
CU_cleanup_registry();
return CU_get_error();
return (int)CU_get_error();
}
/* add the tests to the suite */
@@ -62,7 +62,7 @@ int main() {
!CU_add_test(pSuite, "failmalloc_frame", test_nghttp2_frame) ||
!CU_add_test(pSuite, "failmalloc_hd", test_nghttp2_hd)) {
CU_cleanup_registry();
return CU_get_error();
return (int)CU_get_error();
}
/* Run all tests using the CUnit Basic interface */
@@ -74,6 +74,6 @@ int main() {
return (int)num_tests_failed;
} else {
printf("CUnit Error: %s\n", CU_get_error_msg());
return CU_get_error();
return (int)CU_get_error();
}
}

View File

@@ -55,13 +55,13 @@ int main() {
/* initialize the CUnit test registry */
if (CUE_SUCCESS != CU_initialize_registry())
return CU_get_error();
return (int)CU_get_error();
/* add a suite to the registry */
pSuite = CU_add_suite("libnghttp2_TestSuite", init_suite1, clean_suite1);
if (NULL == pSuite) {
CU_cleanup_registry();
return CU_get_error();
return (int)CU_get_error();
}
/* add the tests to the suite */
@@ -87,6 +87,8 @@ int main() {
test_nghttp2_session_recv_continuation) ||
!CU_add_test(pSuite, "session_recv_headers_with_priority",
test_nghttp2_session_recv_headers_with_priority) ||
!CU_add_test(pSuite, "session_recv_headers_with_padding",
test_nghttp2_session_recv_headers_with_padding) ||
!CU_add_test(pSuite, "session_recv_headers_early_response",
test_nghttp2_session_recv_headers_early_response) ||
!CU_add_test(pSuite, "session_server_recv_push_response",
@@ -314,6 +316,8 @@ int main() {
test_nghttp2_session_pause_data) ||
!CU_add_test(pSuite, "session_no_closed_streams",
test_nghttp2_session_no_closed_streams) ||
!CU_add_test(pSuite, "session_set_stream_user_data",
test_nghttp2_session_set_stream_user_data) ||
!CU_add_test(pSuite, "http_mandatory_headers",
test_nghttp2_http_mandatory_headers) ||
!CU_add_test(pSuite, "http_content_length",
@@ -409,7 +413,7 @@ int main() {
test_nghttp2_bufs_next_present) ||
!CU_add_test(pSuite, "bufs_realloc", test_nghttp2_bufs_realloc)) {
CU_cleanup_registry();
return CU_get_error();
return (int)CU_get_error();
}
/* Run all tests using the CUnit Basic interface */
@@ -421,6 +425,6 @@ int main() {
return (int)num_tests_failed;
} else {
printf("CUnit Error: %s\n", CU_get_error_msg());
return CU_get_error();
return (int)CU_get_error();
}
}

View File

@@ -1575,6 +1575,94 @@ void test_nghttp2_session_recv_headers_with_priority(void) {
nghttp2_session_del(session);
}
void test_nghttp2_session_recv_headers_with_padding(void) {
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
nghttp2_bufs bufs;
nghttp2_buf *buf;
nghttp2_frame_hd hd;
nghttp2_outbound_item *item;
my_user_data ud;
ssize_t rv;
frame_pack_bufs_init(&bufs);
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
callbacks.on_frame_recv_callback = on_frame_recv_callback;
callbacks.send_callback = null_send_callback;
/* HEADERS: Wrong padding length */
nghttp2_session_server_new(&session, &callbacks, &ud);
nghttp2_session_send(session);
nghttp2_frame_hd_init(&hd, 10, NGHTTP2_HEADERS,
NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY |
NGHTTP2_FLAG_PADDED,
1);
buf = &bufs.head->buf;
nghttp2_frame_pack_frame_hd(buf->last, &hd);
buf->last += NGHTTP2_FRAME_HDLEN;
/* padding is 6 bytes */
*buf->last++ = 5;
/* priority field */
nghttp2_put_uint32be(buf->last, 3);
buf->last += sizeof(uint32_t);
*buf->last++ = 1;
/* rest is garbage */
memset(buf->last, 0, 4);
buf->last += 4;
ud.frame_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
CU_ASSERT(0 == ud.frame_recv_cb_called);
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NULL != item);
CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
nghttp2_bufs_reset(&bufs);
nghttp2_session_del(session);
/* PUSH_PROMISE: Wrong padding length */
nghttp2_session_client_new(&session, &callbacks, &ud);
nghttp2_session_send(session);
open_sent_stream(session, 1);
nghttp2_frame_hd_init(&hd, 9, NGHTTP2_PUSH_PROMISE,
NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PADDED, 1);
buf = &bufs.head->buf;
nghttp2_frame_pack_frame_hd(buf->last, &hd);
buf->last += NGHTTP2_FRAME_HDLEN;
/* padding is 6 bytes */
*buf->last++ = 5;
/* promised stream ID field */
nghttp2_put_uint32be(buf->last, 2);
buf->last += sizeof(uint32_t);
/* rest is garbage */
memset(buf->last, 0, 4);
buf->last += 4;
ud.frame_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf));
CU_ASSERT((ssize_t)nghttp2_buf_len(buf) == rv);
CU_ASSERT(0 == ud.frame_recv_cb_called);
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NULL != item);
CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
nghttp2_bufs_free(&bufs);
nghttp2_session_del(session);
}
static int response_on_begin_frame_callback(nghttp2_session *session,
const nghttp2_frame_hd *hd,
void *user_data) {
@@ -2297,6 +2385,31 @@ void test_nghttp2_session_recv_altsvc(void) {
nghttp2_session_del(session);
/* send too large frame */
nghttp2_buf_reset(&buf);
nghttp2_session_client_new2(&session, &callbacks, &ud, option);
session->local_settings.max_frame_size = NGHTTP2_MAX_FRAME_SIZE_MIN - 1;
nghttp2_frame_hd_init(&hd, NGHTTP2_MAX_FRAME_SIZE_MIN + 1, NGHTTP2_ALTSVC,
NGHTTP2_FLAG_NONE, 0);
nghttp2_frame_pack_frame_hd(buf.last, &hd);
buf.last += NGHTTP2_FRAME_HDLEN;
nghttp2_put_uint16be(buf.last, sizeof(origin) - 1);
buf.last += 2;
buf.last = nghttp2_cpymem(buf.last, origin, sizeof(origin) - 1);
memset(buf.last, 0, nghttp2_buf_avail(&buf));
buf.last += nghttp2_buf_avail(&buf);
ud.frame_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf));
CU_ASSERT((ssize_t)nghttp2_buf_len(&buf) == rv);
CU_ASSERT(0 == ud.frame_recv_cb_called);
nghttp2_session_del(session);
/* received by server */
nghttp2_buf_reset(&buf);
@@ -10329,6 +10442,39 @@ void test_nghttp2_session_no_closed_streams(void) {
nghttp2_option_del(option);
}
void test_nghttp2_session_set_stream_user_data(void) {
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
int32_t stream_id;
int user_data1, user_data2;
int rv;
const uint8_t *datap;
ssize_t datalen;
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
nghttp2_session_client_new(&session, &callbacks, NULL);
stream_id = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL,
&user_data1);
rv = nghttp2_session_set_stream_user_data(session, stream_id, &user_data2);
CU_ASSERT(0 == rv);
datalen = nghttp2_session_mem_send(session, &datap);
CU_ASSERT(datalen > 0);
CU_ASSERT(&user_data2 ==
nghttp2_session_get_stream_user_data(session, stream_id));
CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT ==
nghttp2_session_set_stream_user_data(session, 2, NULL));
nghttp2_session_del(session);
}
static void check_nghttp2_http_recv_headers_fail(
nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
int stream_state, const nghttp2_nv *nva, size_t nvlen) {
@@ -10437,6 +10583,7 @@ void test_nghttp2_http_mandatory_headers(void) {
MAKE_NV("content-length", "0")};
const nghttp2_nv clnonzero204_resnv[] = {MAKE_NV(":status", "204"),
MAKE_NV("content-length", "100")};
const nghttp2_nv status101_resnv[] = {MAKE_NV(":status", "101")};
/* test case for request */
const nghttp2_nv nopath_reqnv[] = {MAKE_NV(":scheme", "https"),
@@ -10551,6 +10698,12 @@ void test_nghttp2_http_mandatory_headers(void) {
session, &deflater, 21, NGHTTP2_STREAM_OPENING, clnonzero204_resnv,
ARRLEN(clnonzero204_resnv));
/* status code 101 should not be used in HTTP/2 because it is used
for HTTP Upgrade which HTTP/2 removes. */
check_nghttp2_http_recv_headers_fail(session, &deflater, 23,
NGHTTP2_STREAM_OPENING, status101_resnv,
ARRLEN(status101_resnv));
nghttp2_hd_deflate_free(&deflater);
nghttp2_session_del(session);

View File

@@ -37,6 +37,7 @@ void test_nghttp2_session_recv_data(void);
void test_nghttp2_session_recv_data_no_auto_flow_control(void);
void test_nghttp2_session_recv_continuation(void);
void test_nghttp2_session_recv_headers_with_priority(void);
void test_nghttp2_session_recv_headers_with_padding(void);
void test_nghttp2_session_recv_headers_early_response(void);
void test_nghttp2_session_server_recv_push_response(void);
void test_nghttp2_session_recv_premature_headers(void);
@@ -155,6 +156,7 @@ void test_nghttp2_session_cancel_from_before_frame_send(void);
void test_nghttp2_session_removed_closed_stream(void);
void test_nghttp2_session_pause_data(void);
void test_nghttp2_session_no_closed_streams(void);
void test_nghttp2_session_set_stream_user_data(void);
void test_nghttp2_http_mandatory_headers(void);
void test_nghttp2_http_content_length(void);
void test_nghttp2_http_content_length_mismatch(void);