mirror of
https://github.com/nghttp2/nghttp2.git
synced 2025-12-07 18:48:54 +08:00
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e8907a073f | ||
|
|
9656ac0254 | ||
|
|
75624617ce | ||
|
|
1a8f6578b3 | ||
|
|
4f0548b018 | ||
|
|
5119e82b93 | ||
|
|
3be5856c82 | ||
|
|
a319143901 | ||
|
|
17c88d60c7 | ||
|
|
7601511fdf | ||
|
|
f507b5eee4 | ||
|
|
93821165be | ||
|
|
aaa0b858e4 | ||
|
|
5fa1938691 | ||
|
|
56ee3d4820 | ||
|
|
c2d9a1ed6f | ||
|
|
fcf9ab2798 | ||
|
|
35e445bd04 | ||
|
|
88ce3c31b7 | ||
|
|
16320a0f81 | ||
|
|
8c72fb3539 | ||
|
|
8ffe389daa | ||
|
|
189a4516a1 | ||
|
|
2576855ded | ||
|
|
7d4d48a35e | ||
|
|
cc6f759190 | ||
|
|
c23fc86a23 |
26
.travis.yml
26
.travis.yml
@@ -1,3 +1,4 @@
|
||||
dist: trusty
|
||||
env:
|
||||
matrix:
|
||||
- CI_BUILD=cmake
|
||||
@@ -6,15 +7,13 @@ language: cpp
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
sudo: false
|
||||
sudo: required
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- george-edison55-precise-backports
|
||||
packages:
|
||||
- g++-4.9
|
||||
- libstdc++-4.9-dev
|
||||
- g++-7
|
||||
- autoconf
|
||||
- automake
|
||||
- autotools-dev
|
||||
@@ -33,29 +32,18 @@ addons:
|
||||
- cmake-data
|
||||
before_install:
|
||||
- $CC --version
|
||||
- if [ "$CXX" = "g++" ]; then export CXX="g++-4.9" CC="gcc-4.9"; fi
|
||||
- if [ "$CXX" = "g++" ]; then export CXX="g++-7" CC="gcc-7"; fi
|
||||
- $CC --version
|
||||
- go version
|
||||
- cmake --version
|
||||
before_script:
|
||||
# First build spdylay, since integration tests require it.
|
||||
# spdylay is going to be built under third-party/spdylay
|
||||
- cd third-party
|
||||
- git clone https://github.com/tatsuhiro-t/spdylay.git
|
||||
- cd spdylay
|
||||
- autoreconf -i
|
||||
# Don't use ASAN for spdylay since failmalloc does not work with it.
|
||||
- ./configure --disable-src --disable-examples
|
||||
- make check
|
||||
- export SPDYLAY_HOME=$PWD
|
||||
- cd ../..
|
||||
# Now build nghttp2
|
||||
- if [ "$CI_BUILD" = "autotools" ]; then autoreconf -i; fi
|
||||
- git submodule update --init
|
||||
- if [ "$CI_BUILD" = "autotools" ]; then ./configure --enable-werror --with-mruby --with-neverbleed LIBSPDYLAY_CFLAGS="-I$SPDYLAY_HOME/lib/includes" LIBSPDYLAY_LIBS="-L$SPDYLAY_HOME/lib/.libs -lspdylay" CPPFLAGS=-fsanitize=address LDFLAGS=-fsanitize=address; fi
|
||||
- if [ "$CI_BUILD" = "cmake" ]; then cmake -DENABLE_WERROR=1 -DWITH_MRUBY=1 -DWITH_NEVERBLEED=1 -DSPDYLAY_INCLUDE_DIR="$SPDYLAY_HOME/lib/includes" -DSPDYLAY_LIBRARY="$SPDYLAY_HOME/lib/.libs/libspdylay.so"; fi
|
||||
- if [ "$CI_BUILD" = "autotools" ]; then ./configure --with-mruby; fi
|
||||
- if [ "$CI_BUILD" = "cmake" ]; then cmake -DENABLE_WERROR=1 -DWITH_MRUBY=1 -DWITH_NEVERBLEED=1; fi
|
||||
script:
|
||||
- if [ "$CI_BUILD" = "autotools" ]; then make distcheck; fi
|
||||
- if [ "$CI_BUILD" = "autotools" ]; then make distcheck DISTCHECK_CONFIGURE_FLAGS="--with-mruby --with-neverbleed --enable-werror CPPFLAGS=-fsanitize=address LDFLAGS=\"-fsanitize=address -fuse-ld=gold\""; fi
|
||||
- if [ "$CI_BUILD" = "cmake" ]; then make check; fi
|
||||
# As of April, 23, 2016, golang http2 build fails, probably because
|
||||
# the default go version is too old.
|
||||
|
||||
4
AUTHORS
4
AUTHORS
@@ -29,6 +29,7 @@ Benjamin Peterson
|
||||
Bernard Spil
|
||||
Brian Card
|
||||
Brian Suh
|
||||
Daniel Evers
|
||||
Daniel Stenberg
|
||||
Dave Reisner
|
||||
David Beitey
|
||||
@@ -53,6 +54,7 @@ Kenny (kang-yen) Peng
|
||||
Kenny Peng
|
||||
Kit Chan
|
||||
Kyle Schomp
|
||||
LazyHamster
|
||||
Lucas Pardue
|
||||
MATSUMOTO Ryosuke
|
||||
Marc Bachmann
|
||||
@@ -60,6 +62,7 @@ Matt Rudary
|
||||
Matt Way
|
||||
Mike Conlen
|
||||
Mike Frysinger
|
||||
Mike Lothian
|
||||
Nicholas Hurley
|
||||
Nora Shoemaker
|
||||
Peeyush Aggarwal
|
||||
@@ -82,6 +85,7 @@ Syohei YOSHIDA
|
||||
Tapanito
|
||||
Tatsuhiko Kubo
|
||||
Tatsuhiro Tsujikawa
|
||||
Tobias Geerinckx-Rice
|
||||
Tom Harwood
|
||||
Tomasz Buchert
|
||||
Tomasz Torcz
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
# XXX using 1.8.90 instead of 1.9.0-DEV
|
||||
project(nghttp2 VERSION 1.26.0)
|
||||
project(nghttp2 VERSION 1.27.0)
|
||||
|
||||
# See versioning rule:
|
||||
# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||
@@ -79,7 +79,7 @@ else()
|
||||
set(ENABLE_PYTHON_BINDINGS_DEFAULT OFF)
|
||||
endif()
|
||||
|
||||
find_package(LibXml2 2.7.7)
|
||||
find_package(LibXml2 2.6.26)
|
||||
set(WITH_LIBXML2_DEFAULT ${LIBXML2_FOUND})
|
||||
find_package(Jemalloc)
|
||||
set(WITH_JEMALLOC_DEFAULT ${JEMALLOC_FOUND})
|
||||
@@ -106,7 +106,7 @@ endif()
|
||||
foreach(_build_type "Release" "MinSizeRel" "RelWithDebInfo")
|
||||
foreach(_lang C CXX)
|
||||
string(TOUPPER "CMAKE_${_lang}_FLAGS_${_build_type}" _var)
|
||||
string(REGEX REPLACE "(^| )[/-]D *NDEBUG($| )" "" ${_var} "${${_var}}")
|
||||
string(REGEX REPLACE "(^| )[/-]D *NDEBUG($| )" " " ${_var} "${${_var}}")
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ enabled. SPDY support will be removed soon.
|
||||
To enable ``-a`` option (getting linked assets from the downloaded
|
||||
resource) in ``nghttp``, the following package is required:
|
||||
|
||||
* libxml2 >= 2.7.7
|
||||
* libxml2 >= 2.6.26
|
||||
|
||||
To enable systemd support in nghttpx, the following package is
|
||||
required:
|
||||
|
||||
@@ -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.26.0], [t-tujikawa@users.sourceforge.net])
|
||||
AC_INIT([nghttp2], [1.27.0], [t-tujikawa@users.sourceforge.net])
|
||||
AC_CONFIG_AUX_DIR([.])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
@@ -410,7 +410,7 @@ if test "x${request_systemd}" = "xyes" &&
|
||||
fi
|
||||
|
||||
# libxml2 (for src/nghttp)
|
||||
PKG_CHECK_MODULES([LIBXML2], [libxml-2.0 >= 2.7.7],
|
||||
PKG_CHECK_MODULES([LIBXML2], [libxml-2.0 >= 2.6.26],
|
||||
[have_libxml2=yes], [have_libxml2=no])
|
||||
if test "x${have_libxml2}" = "xyes"; then
|
||||
AC_DEFINE([HAVE_LIBXML2], [1], [Define to 1 if you have `libxml2` library.])
|
||||
@@ -804,6 +804,9 @@ if test "x$werror" != "xno"; then
|
||||
AX_CHECK_COMPILE_FLAG([-Werror], [CXXFLAGS="$CXXFLAGS -Werror"])
|
||||
AX_CHECK_COMPILE_FLAG([-Wformat-security], [CXXFLAGS="$CXXFLAGS -Wformat-security"])
|
||||
AX_CHECK_COMPILE_FLAG([-Wsometimes-uninitialized], [CXXFLAGS="$CXXFLAGS -Wsometimes-uninitialized"])
|
||||
# Disable noexcept-type warning of g++-7. This is not harmful as
|
||||
# long as all source files are compiled with the same compiler.
|
||||
AX_CHECK_COMPILE_FLAG([-Wno-noexcept-type], [CXXFLAGS="$CXXFLAGS -Wno-noexcept-type"])
|
||||
AC_LANG_POP()
|
||||
fi
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import re
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers.rst import directives
|
||||
from docutils.parsers.rst import Directive
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx import version_info
|
||||
@@ -21,10 +22,8 @@ from sphinx.locale import l_, _
|
||||
from sphinx.domains import Domain, ObjType, Index
|
||||
from sphinx.directives import ObjectDescription
|
||||
from sphinx.util.nodes import make_refnode
|
||||
from sphinx.util.compat import Directive
|
||||
from sphinx.util.docfields import Field, GroupedField, TypedField
|
||||
|
||||
|
||||
# REs for Ruby signatures
|
||||
rb_sig_re = re.compile(
|
||||
r'''^ ([\w.]*\.)? # class name(s)
|
||||
|
||||
@@ -157,7 +157,7 @@ html_theme_path = ['@top_srcdir@/doc/_themes']
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
html_use_smartypants = False
|
||||
#html_use_smartypants = False
|
||||
|
||||
# Custom sidebar templates, maps document names to template names.
|
||||
html_sidebars = {
|
||||
|
||||
2
doc/docutils.conf
Normal file
2
doc/docutils.conf
Normal file
@@ -0,0 +1,2 @@
|
||||
[parsers]
|
||||
smart_quotes=no
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "H2LOAD" "1" "Sep 20, 2017" "1.26.0" "nghttp2"
|
||||
.TH "H2LOAD" "1" "Oct 24, 2017" "1.27.0" "nghttp2"
|
||||
.SH NAME
|
||||
h2load \- HTTP/2 benchmarking tool
|
||||
.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "NGHTTP" "1" "Sep 20, 2017" "1.26.0" "nghttp2"
|
||||
.TH "NGHTTP" "1" "Oct 24, 2017" "1.27.0" "nghttp2"
|
||||
.SH NAME
|
||||
nghttp \- HTTP/2 client
|
||||
.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "NGHTTPD" "1" "Sep 20, 2017" "1.26.0" "nghttp2"
|
||||
.TH "NGHTTPD" "1" "Oct 24, 2017" "1.27.0" "nghttp2"
|
||||
.SH NAME
|
||||
nghttpd \- HTTP/2 server
|
||||
.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Man page generated from reStructuredText.
|
||||
.
|
||||
.TH "NGHTTPX" "1" "Sep 20, 2017" "1.26.0" "nghttp2"
|
||||
.TH "NGHTTPX" "1" "Oct 24, 2017" "1.27.0" "nghttp2"
|
||||
.SH NAME
|
||||
nghttpx \- HTTP/2 proxy
|
||||
.
|
||||
|
||||
@@ -64,6 +64,25 @@ The benchmarking result looks like this:
|
||||
See the h2load manual page :ref:`h2load-1-output` section for the
|
||||
explanation of the above numbers.
|
||||
|
||||
Timing-based load-testing
|
||||
-------------------------
|
||||
|
||||
As of v1.26.0, h2load supports timing-based load-testing. This method
|
||||
performs load-testing in terms of a given duration instead of a
|
||||
pre-defined number of requests. The new option :option:`--duration`
|
||||
specifies how long the load-testing takes. For example,
|
||||
``--duration=10`` makes h2load perform load-testing against a server
|
||||
for 10 seconds. You can also specify a “warming-up” period with
|
||||
:option:`--warm-up-time`. If :option:`--duration` is used,
|
||||
:option:`-n` option is ignored.
|
||||
|
||||
The following command performs load-testing for 10 seconds after 5
|
||||
seconds warming up period:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
$ h2load -c100 -m100 --duration=10 --warm-up-time=5 https://localhost
|
||||
|
||||
Flow Control
|
||||
------------
|
||||
|
||||
|
||||
@@ -23,8 +23,8 @@ following compiler/linker flags:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
CPPFLAGS="-fsanitize-coverage=edge -fsanitize=addres"
|
||||
LDFLAGS="-fsanitize-coverage=edge -fsanitize=addres"
|
||||
CPPFLAGS="-fsanitize-coverage=edge -fsanitize=address"
|
||||
LDFLAGS="-fsanitize-coverage=edge -fsanitize=address"
|
||||
|
||||
Then, fuzz_target.cc can be built using the following command:
|
||||
|
||||
|
||||
@@ -27,7 +27,9 @@
|
||||
|
||||
#include "nghttp2_config.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/uio.h>
|
||||
#endif // !_WIN32
|
||||
|
||||
#include <cassert>
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
*/
|
||||
#include "asio_common.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <memory>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <cassert>
|
||||
#include <cerrno>
|
||||
#include <iostream>
|
||||
|
||||
#include "h2load.h"
|
||||
#include "util.h"
|
||||
@@ -52,6 +53,15 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
|
||||
}
|
||||
client->on_header(frame->hd.stream_id, name, namelen, value, valuelen);
|
||||
client->worker->stats.bytes_head_decomp += namelen + valuelen;
|
||||
|
||||
if (client->worker->config->verbose) {
|
||||
std::cout << "[stream_id=" << frame->hd.stream_id << "] ";
|
||||
std::cout.write(reinterpret_cast<const char *>(name), namelen);
|
||||
std::cout << ": ";
|
||||
std::cout.write(reinterpret_cast<const char *>(value), valuelen);
|
||||
std::cout << "\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -28,7 +28,15 @@
|
||||
#include "nghttp2_config.h"
|
||||
|
||||
#include <limits.h>
|
||||
#ifdef _WIN32
|
||||
/* Structure for scatter/gather I/O. */
|
||||
struct iovec {
|
||||
void *iov_base; /* Pointer to data. */
|
||||
size_t iov_len; /* Length of data. */
|
||||
};
|
||||
#else // !_WIN32
|
||||
#include <sys/uio.h>
|
||||
#endif // !_WIN32
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
@@ -33,7 +33,11 @@
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
#include <sys/socket.h>
|
||||
#endif // HAVE_SYS_SOCKET_H
|
||||
#ifdef _WIN32
|
||||
#include <ws2tcpip.h>
|
||||
#else // !_WIN32
|
||||
#include <sys/un.h>
|
||||
#endif // !_WIN32
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif // HAVE_NETINET_IN_H
|
||||
@@ -48,7 +52,9 @@ union sockaddr_union {
|
||||
sockaddr sa;
|
||||
sockaddr_in6 in6;
|
||||
sockaddr_in in;
|
||||
#ifndef _WIN32
|
||||
sockaddr_un un;
|
||||
#endif // !_WIN32
|
||||
};
|
||||
|
||||
struct Address {
|
||||
|
||||
@@ -115,6 +115,8 @@ int main(int argc, char *argv[]) {
|
||||
shrpx::test_downstream_assemble_request_cookie) ||
|
||||
!CU_add_test(pSuite, "downstream_rewrite_location_response_header",
|
||||
shrpx::test_downstream_rewrite_location_response_header) ||
|
||||
!CU_add_test(pSuite, "downstream_supports_non_final_response",
|
||||
shrpx::test_downstream_supports_non_final_response) ||
|
||||
!CU_add_test(pSuite, "config_parse_header",
|
||||
shrpx::test_shrpx_config_parse_header) ||
|
||||
!CU_add_test(pSuite, "config_parse_log_format",
|
||||
|
||||
@@ -804,61 +804,40 @@ bool load_lighter(const DownstreamAddr *lhs, const DownstreamAddr *rhs) {
|
||||
Http2Session *ClientHandler::select_http2_session(
|
||||
const std::shared_ptr<DownstreamAddrGroup> &group) {
|
||||
auto &shared_addr = group->shared_addr;
|
||||
auto &http2_avail_freelist = shared_addr->http2_avail_freelist;
|
||||
|
||||
for (auto session = http2_avail_freelist.head; session;) {
|
||||
auto next = session->dlnext;
|
||||
|
||||
session->remove_from_freelist();
|
||||
|
||||
// session may be in graceful shutdown period now.
|
||||
if (session->max_concurrency_reached(0)) {
|
||||
if (LOG_ENABLED(INFO)) {
|
||||
CLOG(INFO, this)
|
||||
<< "Maximum streams have been reached for Http2Session(" << session
|
||||
<< "). Skip it";
|
||||
}
|
||||
|
||||
session = next;
|
||||
|
||||
// First count the working backend addresses.
|
||||
size_t min = 0;
|
||||
for (const auto &addr : shared_addr->addrs) {
|
||||
if (addr.proto != PROTO_HTTP2 || addr.connect_blocker->blocked()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
++min;
|
||||
}
|
||||
|
||||
if (min == 0) {
|
||||
if (LOG_ENABLED(INFO)) {
|
||||
CLOG(INFO, this) << "No working backend address found";
|
||||
CLOG(INFO, this) << "Use Http2Session " << session
|
||||
<< " from http2_avail_freelist";
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto &http2_avail_freelist = shared_addr->http2_avail_freelist;
|
||||
|
||||
if (http2_avail_freelist.size() >= min) {
|
||||
for (auto session = http2_avail_freelist.head; session;) {
|
||||
auto next = session->dlnext;
|
||||
|
||||
session->remove_from_freelist();
|
||||
|
||||
// session may be in graceful shutdown period now.
|
||||
if (session->max_concurrency_reached(0)) {
|
||||
if (LOG_ENABLED(INFO)) {
|
||||
CLOG(INFO, this)
|
||||
<< "Maximum streams have been reached for Http2Session("
|
||||
<< session << "). Skip it";
|
||||
}
|
||||
|
||||
session = next;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (session->max_concurrency_reached(1)) {
|
||||
if (LOG_ENABLED(INFO)) {
|
||||
CLOG(INFO, this) << "Use Http2Session " << session
|
||||
<< " from http2_avail_freelist";
|
||||
CLOG(INFO, this) << "Maximum streams are reached for Http2Session("
|
||||
<< session << ").";
|
||||
}
|
||||
|
||||
if (session->max_concurrency_reached(1)) {
|
||||
if (LOG_ENABLED(INFO)) {
|
||||
CLOG(INFO, this) << "Maximum streams are reached for Http2Session("
|
||||
<< session << ").";
|
||||
}
|
||||
} else {
|
||||
session->add_to_avail_freelist();
|
||||
}
|
||||
return session;
|
||||
} else {
|
||||
session->add_to_avail_freelist();
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
DownstreamAddr *selected_addr = nullptr;
|
||||
@@ -901,7 +880,12 @@ Http2Session *ClientHandler::select_http2_session(
|
||||
}
|
||||
}
|
||||
|
||||
assert(selected_addr);
|
||||
if (selected_addr == nullptr) {
|
||||
if (LOG_ENABLED(INFO)) {
|
||||
CLOG(INFO, this) << "No working backend address found";
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (LOG_ENABLED(INFO)) {
|
||||
CLOG(INFO, this) << "Selected DownstreamAddr=" << selected_addr
|
||||
|
||||
@@ -743,6 +743,10 @@ bool Downstream::get_non_final_response() const {
|
||||
return !upgraded_ && resp_.http_status / 100 == 1;
|
||||
}
|
||||
|
||||
bool Downstream::supports_non_final_response() const {
|
||||
return req_.http_major == 2 || (req_.http_major == 1 && req_.http_minor == 1);
|
||||
}
|
||||
|
||||
bool Downstream::get_upgraded() const { return upgraded_; }
|
||||
|
||||
bool Downstream::get_http2_upgrade_request() const {
|
||||
|
||||
@@ -348,6 +348,9 @@ public:
|
||||
// True if the response is non-final (1xx status code). Note that
|
||||
// if connection was upgraded, 101 status code is treated as final.
|
||||
bool get_non_final_response() const;
|
||||
// True if protocol version used by client supports non final
|
||||
// response. Only HTTP/1.1 and HTTP/2 clients support it.
|
||||
bool supports_non_final_response() const;
|
||||
void set_expect_final_response(bool f);
|
||||
bool get_expect_final_response() const;
|
||||
|
||||
|
||||
@@ -164,4 +164,29 @@ void test_downstream_rewrite_location_response_header(void) {
|
||||
CU_ASSERT("https://localhost:8443/" == (*location).value);
|
||||
}
|
||||
|
||||
void test_downstream_supports_non_final_response(void) {
|
||||
Downstream d(nullptr, nullptr, 0);
|
||||
auto &req = d.request();
|
||||
|
||||
req.http_major = 2;
|
||||
req.http_minor = 0;
|
||||
|
||||
CU_ASSERT(d.supports_non_final_response());
|
||||
|
||||
req.http_major = 1;
|
||||
req.http_minor = 1;
|
||||
|
||||
CU_ASSERT(d.supports_non_final_response());
|
||||
|
||||
req.http_major = 1;
|
||||
req.http_minor = 0;
|
||||
|
||||
CU_ASSERT(!d.supports_non_final_response());
|
||||
|
||||
req.http_major = 0;
|
||||
req.http_minor = 9;
|
||||
|
||||
CU_ASSERT(!d.supports_non_final_response());
|
||||
}
|
||||
|
||||
} // namespace shrpx
|
||||
|
||||
@@ -36,6 +36,7 @@ void test_downstream_field_store_header(void);
|
||||
void test_downstream_crumble_request_cookie(void);
|
||||
void test_downstream_assemble_request_cookie(void);
|
||||
void test_downstream_rewrite_location_response_header(void);
|
||||
void test_downstream_supports_non_final_response(void);
|
||||
|
||||
} // namespace shrpx
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ int exec_read_command(Process &proc, char *const argv[]) {
|
||||
|
||||
rv = shrpx_signal_unblock_all();
|
||||
if (rv != 0) {
|
||||
constexpr char msg[] = "Unblocking all signals failed\n";
|
||||
static constexpr char msg[] = "Unblocking all signals failed\n";
|
||||
while (write(STDERR_FILENO, msg, str_size(msg)) == -1 && errno == EINTR)
|
||||
;
|
||||
nghttp2_Exit(EXIT_FAILURE);
|
||||
@@ -95,7 +95,7 @@ int exec_read_command(Process &proc, char *const argv[]) {
|
||||
|
||||
rv = execv(argv[0], argv);
|
||||
if (rv == -1) {
|
||||
constexpr char msg[] = "Could not execute command\n";
|
||||
static constexpr char msg[] = "Could not execute command\n";
|
||||
while (write(STDERR_FILENO, msg, str_size(msg)) == -1 && errno == EINTR)
|
||||
;
|
||||
nghttp2_Exit(EXIT_FAILURE);
|
||||
|
||||
@@ -1022,6 +1022,12 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
|
||||
auto &resp = downstream->response();
|
||||
auto &balloc = downstream->get_block_allocator();
|
||||
|
||||
if (downstream->get_non_final_response() &&
|
||||
!downstream->supports_non_final_response()) {
|
||||
resp.fs.clear_headers();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MRUBY
|
||||
if (!downstream->get_non_final_response()) {
|
||||
auto worker = handler_->get_worker();
|
||||
|
||||
@@ -558,6 +558,8 @@ int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
|
||||
} // namespace
|
||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
|
||||
#if !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
|
||||
#ifndef TLSEXT_TYPE_signed_certificate_timestamp
|
||||
#define TLSEXT_TYPE_signed_certificate_timestamp 18
|
||||
#endif // !TLSEXT_TYPE_signed_certificate_timestamp
|
||||
@@ -620,8 +622,7 @@ int sct_parse_cb(SSL *ssl, unsigned int ext_type, unsigned int context,
|
||||
}
|
||||
} // namespace
|
||||
|
||||
#if !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L && \
|
||||
!OPENSSL_1_1_1_API
|
||||
#if !OPENSSL_1_1_1_API
|
||||
|
||||
namespace {
|
||||
int legacy_sct_add_cb(SSL *ssl, unsigned int ext_type,
|
||||
@@ -646,8 +647,8 @@ int legacy_sct_parse_cb(SSL *ssl, unsigned int ext_type,
|
||||
}
|
||||
} // namespace
|
||||
|
||||
#endif // !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L &&
|
||||
// !OPENSSL_1_1_1_API
|
||||
#endif // !OPENSSL_1_1_1_API
|
||||
#endif // !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||
|
||||
#if !LIBRESSL_IN_USE
|
||||
namespace {
|
||||
|
||||
@@ -70,7 +70,7 @@ void test_shrpx_tls_create_lookup_tree(void) {
|
||||
CU_ASSERT(-1 == tree->lookup(StringRef{}));
|
||||
CU_ASSERT(5 == tree->lookup(hostnames[5]));
|
||||
CU_ASSERT(6 == tree->lookup(hostnames[6]));
|
||||
constexpr char h6[] = "pdylay.sourceforge.net";
|
||||
static constexpr char h6[] = "pdylay.sourceforge.net";
|
||||
for (int i = 0; i < 7; ++i) {
|
||||
CU_ASSERT(-1 == tree->lookup(StringRef{h6 + i, str_size(h6) - i}));
|
||||
}
|
||||
@@ -119,7 +119,8 @@ void test_shrpx_tls_create_lookup_tree(void) {
|
||||
void test_shrpx_tls_cert_lookup_tree_add_ssl_ctx(void) {
|
||||
int rv;
|
||||
|
||||
constexpr char nghttp2_certfile[] = NGHTTP2_SRC_DIR "/test.nghttp2.org.pem";
|
||||
static constexpr char nghttp2_certfile[] =
|
||||
NGHTTP2_SRC_DIR "/test.nghttp2.org.pem";
|
||||
auto nghttp2_ssl_ctx = SSL_CTX_new(SSLv23_server_method());
|
||||
auto nghttp2_ssl_ctx_del = defer(SSL_CTX_free, nghttp2_ssl_ctx);
|
||||
auto nghttp2_tls_ctx_data = make_unique<tls::TLSContextData>();
|
||||
@@ -129,7 +130,8 @@ void test_shrpx_tls_cert_lookup_tree_add_ssl_ctx(void) {
|
||||
|
||||
CU_ASSERT(1 == rv);
|
||||
|
||||
constexpr char examples_certfile[] = NGHTTP2_SRC_DIR "/test.example.com.pem";
|
||||
static constexpr char examples_certfile[] =
|
||||
NGHTTP2_SRC_DIR "/test.example.com.pem";
|
||||
auto examples_ssl_ctx = SSL_CTX_new(SSLv23_server_method());
|
||||
auto examples_ssl_ctx_del = defer(SSL_CTX_free, examples_ssl_ctx);
|
||||
auto examples_tls_ctx_data = make_unique<tls::TLSContextData>();
|
||||
|
||||
67
src/util.cc
67
src/util.cc
@@ -41,7 +41,12 @@
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
#include <netinet/in.h>
|
||||
#endif // HAVE_NETINET_IN_H
|
||||
#ifdef _WIN32
|
||||
#include <ws2tcpip.h>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#else // !_WIN32
|
||||
#include <netinet/tcp.h>
|
||||
#endif // !_WIN32
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
#include <arpa/inet.h>
|
||||
#endif // HAVE_ARPA_INET_H
|
||||
@@ -65,6 +70,26 @@ namespace nghttp2 {
|
||||
|
||||
namespace util {
|
||||
|
||||
#ifdef _WIN32
|
||||
// inet_pton-wrapper for Windows
|
||||
static int inet_pton(int af, const char *src, void *dst) {
|
||||
#if _WIN32_WINNT >= 0x0600
|
||||
return InetPtonA(af, src, dst);
|
||||
#else
|
||||
// the function takes a 'char*', so we need to make a copy
|
||||
char addr[INET6_ADDRSTRLEN + 1];
|
||||
strncpy(addr, src, sizeof(addr));
|
||||
addr[sizeof(addr) - 1] = 0;
|
||||
|
||||
int size = sizeof(struct in6_addr);
|
||||
|
||||
if (WSAStringToAddress(addr, af, NULL, (LPSOCKADDR)dst, &size) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
#endif // _WIN32
|
||||
|
||||
const char UPPER_XDIGITS[] = "0123456789ABCDEF";
|
||||
|
||||
bool in_rfc3986_unreserved_chars(const char c) {
|
||||
@@ -352,13 +377,34 @@ char *iso8601_date(char *res, int64_t ms) {
|
||||
return p;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
namespace bt = boost::posix_time;
|
||||
// one-time definition of the locale that is used to parse UTC strings
|
||||
// (note that the time_input_facet is ref-counted and deleted automatically)
|
||||
static const std::locale
|
||||
ptime_locale(std::locale::classic(),
|
||||
new bt::time_input_facet("%a, %d %b %Y %H:%M:%S GMT"));
|
||||
#endif //_WIN32
|
||||
|
||||
time_t parse_http_date(const StringRef &s) {
|
||||
#ifdef _WIN32
|
||||
// there is no strptime - use boost
|
||||
std::stringstream sstr(s.str());
|
||||
sstr.imbue(ptime_locale);
|
||||
bt::ptime ltime;
|
||||
sstr >> ltime;
|
||||
if (!sstr)
|
||||
return 0;
|
||||
|
||||
return boost::posix_time::to_time_t(ltime);
|
||||
#else // !_WIN32
|
||||
tm tm{};
|
||||
char *r = strptime(s.c_str(), "%a, %d %b %Y %H:%M:%S GMT", &tm);
|
||||
if (r == 0) {
|
||||
return 0;
|
||||
}
|
||||
return nghttp2_timegm_without_yday(&tm);
|
||||
#endif // !_WIN32
|
||||
}
|
||||
|
||||
char upcase(char c) {
|
||||
@@ -628,9 +674,11 @@ std::string numeric_name(const struct sockaddr *sa, socklen_t salen) {
|
||||
|
||||
std::string to_numeric_addr(const Address *addr) {
|
||||
auto family = addr->su.storage.ss_family;
|
||||
#ifndef _WIN32
|
||||
if (family == AF_UNIX) {
|
||||
return addr->su.un.sun_path;
|
||||
}
|
||||
#endif // !_WIN32
|
||||
|
||||
std::array<char, NI_MAXHOST> host;
|
||||
std::array<char, NI_MAXSERV> serv;
|
||||
@@ -818,6 +866,10 @@ std::vector<std::string> parse_config_str_list(const StringRef &s, char delim) {
|
||||
}
|
||||
|
||||
int make_socket_closeonexec(int fd) {
|
||||
#ifdef _WIN32
|
||||
(void)fd;
|
||||
return 0;
|
||||
#else // !_WIN32
|
||||
int flags;
|
||||
int rv;
|
||||
while ((flags = fcntl(fd, F_GETFD)) == -1 && errno == EINTR)
|
||||
@@ -825,15 +877,24 @@ int make_socket_closeonexec(int fd) {
|
||||
while ((rv = fcntl(fd, F_SETFD, flags | FD_CLOEXEC)) == -1 && errno == EINTR)
|
||||
;
|
||||
return rv;
|
||||
#endif // !_WIN32
|
||||
}
|
||||
|
||||
int make_socket_nonblocking(int fd) {
|
||||
int flags;
|
||||
int rv;
|
||||
|
||||
#ifdef _WIN32
|
||||
u_long mode = 1;
|
||||
|
||||
rv = ioctlsocket(fd, FIONBIO, &mode);
|
||||
#else // !_WIN32
|
||||
int flags;
|
||||
while ((flags = fcntl(fd, F_GETFL, 0)) == -1 && errno == EINTR)
|
||||
;
|
||||
while ((rv = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR)
|
||||
;
|
||||
#endif // !_WIN32
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -874,7 +935,7 @@ int create_nonblock_socket(int family) {
|
||||
bool check_socket_connected(int fd) {
|
||||
int error;
|
||||
socklen_t len = sizeof(error);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) != 0) {
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char *)&error, &len) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -884,7 +945,7 @@ bool check_socket_connected(int fd) {
|
||||
int get_socket_error(int fd) {
|
||||
int error;
|
||||
socklen_t len = sizeof(error);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) != 0) {
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char *)&error, &len) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -716,7 +716,7 @@ template <typename OutputIt, typename Generator>
|
||||
OutputIt random_alpha_digit(OutputIt first, OutputIt last, Generator &gen) {
|
||||
// If we use uint8_t instead char, gcc 6.2.0 complains by shouting
|
||||
// char-array initialized from wide string.
|
||||
constexpr char s[] =
|
||||
static constexpr char s[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
std::uniform_int_distribution<> dis(0, 26 * 2 + 10 - 1);
|
||||
for (; first != last; ++first) {
|
||||
|
||||
@@ -473,6 +473,7 @@ void test_util_localtime_date(void) {
|
||||
|
||||
if (tz) {
|
||||
setenv("TZ", tz, 1);
|
||||
free(tz);
|
||||
} else {
|
||||
unsetenv("TZ");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user