mirror of
https://github.com/nghttp2/nghttp2.git
synced 2025-12-08 02:58:53 +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:
|
env:
|
||||||
matrix:
|
matrix:
|
||||||
- CI_BUILD=cmake
|
- CI_BUILD=cmake
|
||||||
@@ -6,15 +7,13 @@ language: cpp
|
|||||||
compiler:
|
compiler:
|
||||||
- clang
|
- clang
|
||||||
- gcc
|
- gcc
|
||||||
sudo: false
|
sudo: required
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
- ubuntu-toolchain-r-test
|
- ubuntu-toolchain-r-test
|
||||||
- george-edison55-precise-backports
|
|
||||||
packages:
|
packages:
|
||||||
- g++-4.9
|
- g++-7
|
||||||
- libstdc++-4.9-dev
|
|
||||||
- autoconf
|
- autoconf
|
||||||
- automake
|
- automake
|
||||||
- autotools-dev
|
- autotools-dev
|
||||||
@@ -33,29 +32,18 @@ addons:
|
|||||||
- cmake-data
|
- cmake-data
|
||||||
before_install:
|
before_install:
|
||||||
- $CC --version
|
- $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
|
- $CC --version
|
||||||
- go version
|
- go version
|
||||||
- cmake --version
|
- cmake --version
|
||||||
before_script:
|
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
|
# Now build nghttp2
|
||||||
- if [ "$CI_BUILD" = "autotools" ]; then autoreconf -i; fi
|
- if [ "$CI_BUILD" = "autotools" ]; then autoreconf -i; fi
|
||||||
- git submodule update --init
|
- 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" = "autotools" ]; then ./configure --with-mruby; 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" = "cmake" ]; then cmake -DENABLE_WERROR=1 -DWITH_MRUBY=1 -DWITH_NEVERBLEED=1; fi
|
||||||
script:
|
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
|
- if [ "$CI_BUILD" = "cmake" ]; then make check; fi
|
||||||
# As of April, 23, 2016, golang http2 build fails, probably because
|
# As of April, 23, 2016, golang http2 build fails, probably because
|
||||||
# the default go version is too old.
|
# the default go version is too old.
|
||||||
|
|||||||
4
AUTHORS
4
AUTHORS
@@ -29,6 +29,7 @@ Benjamin Peterson
|
|||||||
Bernard Spil
|
Bernard Spil
|
||||||
Brian Card
|
Brian Card
|
||||||
Brian Suh
|
Brian Suh
|
||||||
|
Daniel Evers
|
||||||
Daniel Stenberg
|
Daniel Stenberg
|
||||||
Dave Reisner
|
Dave Reisner
|
||||||
David Beitey
|
David Beitey
|
||||||
@@ -53,6 +54,7 @@ Kenny (kang-yen) Peng
|
|||||||
Kenny Peng
|
Kenny Peng
|
||||||
Kit Chan
|
Kit Chan
|
||||||
Kyle Schomp
|
Kyle Schomp
|
||||||
|
LazyHamster
|
||||||
Lucas Pardue
|
Lucas Pardue
|
||||||
MATSUMOTO Ryosuke
|
MATSUMOTO Ryosuke
|
||||||
Marc Bachmann
|
Marc Bachmann
|
||||||
@@ -60,6 +62,7 @@ Matt Rudary
|
|||||||
Matt Way
|
Matt Way
|
||||||
Mike Conlen
|
Mike Conlen
|
||||||
Mike Frysinger
|
Mike Frysinger
|
||||||
|
Mike Lothian
|
||||||
Nicholas Hurley
|
Nicholas Hurley
|
||||||
Nora Shoemaker
|
Nora Shoemaker
|
||||||
Peeyush Aggarwal
|
Peeyush Aggarwal
|
||||||
@@ -82,6 +85,7 @@ Syohei YOSHIDA
|
|||||||
Tapanito
|
Tapanito
|
||||||
Tatsuhiko Kubo
|
Tatsuhiko Kubo
|
||||||
Tatsuhiro Tsujikawa
|
Tatsuhiro Tsujikawa
|
||||||
|
Tobias Geerinckx-Rice
|
||||||
Tom Harwood
|
Tom Harwood
|
||||||
Tomasz Buchert
|
Tomasz Buchert
|
||||||
Tomasz Torcz
|
Tomasz Torcz
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
cmake_minimum_required(VERSION 3.0)
|
cmake_minimum_required(VERSION 3.0)
|
||||||
# XXX using 1.8.90 instead of 1.9.0-DEV
|
# 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:
|
# See versioning rule:
|
||||||
# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
|
||||||
@@ -79,7 +79,7 @@ else()
|
|||||||
set(ENABLE_PYTHON_BINDINGS_DEFAULT OFF)
|
set(ENABLE_PYTHON_BINDINGS_DEFAULT OFF)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(LibXml2 2.7.7)
|
find_package(LibXml2 2.6.26)
|
||||||
set(WITH_LIBXML2_DEFAULT ${LIBXML2_FOUND})
|
set(WITH_LIBXML2_DEFAULT ${LIBXML2_FOUND})
|
||||||
find_package(Jemalloc)
|
find_package(Jemalloc)
|
||||||
set(WITH_JEMALLOC_DEFAULT ${JEMALLOC_FOUND})
|
set(WITH_JEMALLOC_DEFAULT ${JEMALLOC_FOUND})
|
||||||
@@ -106,7 +106,7 @@ endif()
|
|||||||
foreach(_build_type "Release" "MinSizeRel" "RelWithDebInfo")
|
foreach(_build_type "Release" "MinSizeRel" "RelWithDebInfo")
|
||||||
foreach(_lang C CXX)
|
foreach(_lang C CXX)
|
||||||
string(TOUPPER "CMAKE_${_lang}_FLAGS_${_build_type}" _var)
|
string(TOUPPER "CMAKE_${_lang}_FLAGS_${_build_type}" _var)
|
||||||
string(REGEX REPLACE "(^| )[/-]D *NDEBUG($| )" "" ${_var} "${${_var}}")
|
string(REGEX REPLACE "(^| )[/-]D *NDEBUG($| )" " " ${_var} "${${_var}}")
|
||||||
endforeach()
|
endforeach()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ enabled. SPDY support will be removed soon.
|
|||||||
To enable ``-a`` option (getting linked assets from the downloaded
|
To enable ``-a`` option (getting linked assets from the downloaded
|
||||||
resource) in ``nghttp``, the following package is required:
|
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
|
To enable systemd support in nghttpx, the following package is
|
||||||
required:
|
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
|
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.26.0], [t-tujikawa@users.sourceforge.net])
|
AC_INIT([nghttp2], [1.27.0], [t-tujikawa@users.sourceforge.net])
|
||||||
AC_CONFIG_AUX_DIR([.])
|
AC_CONFIG_AUX_DIR([.])
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
@@ -410,7 +410,7 @@ if test "x${request_systemd}" = "xyes" &&
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# libxml2 (for src/nghttp)
|
# 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])
|
[have_libxml2=yes], [have_libxml2=no])
|
||||||
if test "x${have_libxml2}" = "xyes"; then
|
if test "x${have_libxml2}" = "xyes"; then
|
||||||
AC_DEFINE([HAVE_LIBXML2], [1], [Define to 1 if you have `libxml2` library.])
|
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([-Werror], [CXXFLAGS="$CXXFLAGS -Werror"])
|
||||||
AX_CHECK_COMPILE_FLAG([-Wformat-security], [CXXFLAGS="$CXXFLAGS -Wformat-security"])
|
AX_CHECK_COMPILE_FLAG([-Wformat-security], [CXXFLAGS="$CXXFLAGS -Wformat-security"])
|
||||||
AX_CHECK_COMPILE_FLAG([-Wsometimes-uninitialized], [CXXFLAGS="$CXXFLAGS -Wsometimes-uninitialized"])
|
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()
|
AC_LANG_POP()
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import re
|
|||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
from docutils.parsers.rst import directives
|
from docutils.parsers.rst import directives
|
||||||
|
from docutils.parsers.rst import Directive
|
||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
from sphinx import version_info
|
from sphinx import version_info
|
||||||
@@ -21,10 +22,8 @@ from sphinx.locale import l_, _
|
|||||||
from sphinx.domains import Domain, ObjType, Index
|
from sphinx.domains import Domain, ObjType, Index
|
||||||
from sphinx.directives import ObjectDescription
|
from sphinx.directives import ObjectDescription
|
||||||
from sphinx.util.nodes import make_refnode
|
from sphinx.util.nodes import make_refnode
|
||||||
from sphinx.util.compat import Directive
|
|
||||||
from sphinx.util.docfields import Field, GroupedField, TypedField
|
from sphinx.util.docfields import Field, GroupedField, TypedField
|
||||||
|
|
||||||
|
|
||||||
# REs for Ruby signatures
|
# REs for Ruby signatures
|
||||||
rb_sig_re = re.compile(
|
rb_sig_re = re.compile(
|
||||||
r'''^ ([\w.]*\.)? # class name(s)
|
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
|
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||||
# typographically correct entities.
|
# typographically correct entities.
|
||||||
html_use_smartypants = False
|
#html_use_smartypants = False
|
||||||
|
|
||||||
# Custom sidebar templates, maps document names to template names.
|
# Custom sidebar templates, maps document names to template names.
|
||||||
html_sidebars = {
|
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.
|
.\" 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
|
.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" "Sep 20, 2017" "1.26.0" "nghttp2"
|
.TH "NGHTTP" "1" "Oct 24, 2017" "1.27.0" "nghttp2"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
nghttp \- HTTP/2 client
|
nghttp \- HTTP/2 client
|
||||||
.
|
.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.\" Man page generated from reStructuredText.
|
.\" 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
|
.SH NAME
|
||||||
nghttpd \- HTTP/2 server
|
nghttpd \- HTTP/2 server
|
||||||
.
|
.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.\" Man page generated from reStructuredText.
|
.\" 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
|
.SH NAME
|
||||||
nghttpx \- HTTP/2 proxy
|
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
|
See the h2load manual page :ref:`h2load-1-output` section for the
|
||||||
explanation of the above numbers.
|
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
|
Flow Control
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ following compiler/linker flags:
|
|||||||
|
|
||||||
.. code-block:: text
|
.. code-block:: text
|
||||||
|
|
||||||
CPPFLAGS="-fsanitize-coverage=edge -fsanitize=addres"
|
CPPFLAGS="-fsanitize-coverage=edge -fsanitize=address"
|
||||||
LDFLAGS="-fsanitize-coverage=edge -fsanitize=addres"
|
LDFLAGS="-fsanitize-coverage=edge -fsanitize=address"
|
||||||
|
|
||||||
Then, fuzz_target.cc can be built using the following command:
|
Then, fuzz_target.cc can be built using the following command:
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,9 @@
|
|||||||
|
|
||||||
#include "nghttp2_config.h"
|
#include "nghttp2_config.h"
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
|
#endif // !_WIN32
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "asio_common.h"
|
#include "asio_common.h"
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "h2load.h"
|
#include "h2load.h"
|
||||||
#include "util.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->on_header(frame->hd.stream_id, name, namelen, value, valuelen);
|
||||||
client->worker->stats.bytes_head_decomp += namelen + 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;
|
return 0;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@@ -28,7 +28,15 @@
|
|||||||
#include "nghttp2_config.h"
|
#include "nghttp2_config.h"
|
||||||
|
|
||||||
#include <limits.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>
|
#include <sys/uio.h>
|
||||||
|
#endif // !_WIN32
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|||||||
@@ -33,7 +33,11 @@
|
|||||||
#ifdef HAVE_SYS_SOCKET_H
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#endif // HAVE_SYS_SOCKET_H
|
#endif // HAVE_SYS_SOCKET_H
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <ws2tcpip.h>
|
||||||
|
#else // !_WIN32
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
#endif // !_WIN32
|
||||||
#ifdef HAVE_NETINET_IN_H
|
#ifdef HAVE_NETINET_IN_H
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#endif // HAVE_NETINET_IN_H
|
#endif // HAVE_NETINET_IN_H
|
||||||
@@ -48,7 +52,9 @@ union sockaddr_union {
|
|||||||
sockaddr sa;
|
sockaddr sa;
|
||||||
sockaddr_in6 in6;
|
sockaddr_in6 in6;
|
||||||
sockaddr_in in;
|
sockaddr_in in;
|
||||||
|
#ifndef _WIN32
|
||||||
sockaddr_un un;
|
sockaddr_un un;
|
||||||
|
#endif // !_WIN32
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Address {
|
struct Address {
|
||||||
|
|||||||
@@ -115,6 +115,8 @@ int main(int argc, char *argv[]) {
|
|||||||
shrpx::test_downstream_assemble_request_cookie) ||
|
shrpx::test_downstream_assemble_request_cookie) ||
|
||||||
!CU_add_test(pSuite, "downstream_rewrite_location_response_header",
|
!CU_add_test(pSuite, "downstream_rewrite_location_response_header",
|
||||||
shrpx::test_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",
|
!CU_add_test(pSuite, "config_parse_header",
|
||||||
shrpx::test_shrpx_config_parse_header) ||
|
shrpx::test_shrpx_config_parse_header) ||
|
||||||
!CU_add_test(pSuite, "config_parse_log_format",
|
!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(
|
Http2Session *ClientHandler::select_http2_session(
|
||||||
const std::shared_ptr<DownstreamAddrGroup> &group) {
|
const std::shared_ptr<DownstreamAddrGroup> &group) {
|
||||||
auto &shared_addr = group->shared_addr;
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
++min;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (min == 0) {
|
|
||||||
if (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
CLOG(INFO, this) << "No working backend address found";
|
CLOG(INFO, this) << "Use Http2Session " << session
|
||||||
|
<< " from http2_avail_freelist";
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
if (session->max_concurrency_reached(1)) {
|
||||||
}
|
|
||||||
|
|
||||||
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 (LOG_ENABLED(INFO)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
CLOG(INFO, this) << "Use Http2Session " << session
|
CLOG(INFO, this) << "Maximum streams are reached for Http2Session("
|
||||||
<< " from http2_avail_freelist";
|
<< session << ").";
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
if (session->max_concurrency_reached(1)) {
|
session->add_to_avail_freelist();
|
||||||
if (LOG_ENABLED(INFO)) {
|
|
||||||
CLOG(INFO, this) << "Maximum streams are reached for Http2Session("
|
|
||||||
<< session << ").";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
session->add_to_avail_freelist();
|
|
||||||
}
|
|
||||||
return session;
|
|
||||||
}
|
}
|
||||||
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
DownstreamAddr *selected_addr = nullptr;
|
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)) {
|
if (LOG_ENABLED(INFO)) {
|
||||||
CLOG(INFO, this) << "Selected DownstreamAddr=" << selected_addr
|
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;
|
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_upgraded() const { return upgraded_; }
|
||||||
|
|
||||||
bool Downstream::get_http2_upgrade_request() const {
|
bool Downstream::get_http2_upgrade_request() const {
|
||||||
|
|||||||
@@ -348,6 +348,9 @@ public:
|
|||||||
// True if the response is non-final (1xx status code). Note that
|
// True if the response is non-final (1xx status code). Note that
|
||||||
// if connection was upgraded, 101 status code is treated as final.
|
// if connection was upgraded, 101 status code is treated as final.
|
||||||
bool get_non_final_response() const;
|
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);
|
void set_expect_final_response(bool f);
|
||||||
bool get_expect_final_response() const;
|
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);
|
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
|
} // namespace shrpx
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ void test_downstream_field_store_header(void);
|
|||||||
void test_downstream_crumble_request_cookie(void);
|
void test_downstream_crumble_request_cookie(void);
|
||||||
void test_downstream_assemble_request_cookie(void);
|
void test_downstream_assemble_request_cookie(void);
|
||||||
void test_downstream_rewrite_location_response_header(void);
|
void test_downstream_rewrite_location_response_header(void);
|
||||||
|
void test_downstream_supports_non_final_response(void);
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ int exec_read_command(Process &proc, char *const argv[]) {
|
|||||||
|
|
||||||
rv = shrpx_signal_unblock_all();
|
rv = shrpx_signal_unblock_all();
|
||||||
if (rv != 0) {
|
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)
|
while (write(STDERR_FILENO, msg, str_size(msg)) == -1 && errno == EINTR)
|
||||||
;
|
;
|
||||||
nghttp2_Exit(EXIT_FAILURE);
|
nghttp2_Exit(EXIT_FAILURE);
|
||||||
@@ -95,7 +95,7 @@ int exec_read_command(Process &proc, char *const argv[]) {
|
|||||||
|
|
||||||
rv = execv(argv[0], argv);
|
rv = execv(argv[0], argv);
|
||||||
if (rv == -1) {
|
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)
|
while (write(STDERR_FILENO, msg, str_size(msg)) == -1 && errno == EINTR)
|
||||||
;
|
;
|
||||||
nghttp2_Exit(EXIT_FAILURE);
|
nghttp2_Exit(EXIT_FAILURE);
|
||||||
|
|||||||
@@ -1022,6 +1022,12 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
|
|||||||
auto &resp = downstream->response();
|
auto &resp = downstream->response();
|
||||||
auto &balloc = downstream->get_block_allocator();
|
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
|
#ifdef HAVE_MRUBY
|
||||||
if (!downstream->get_non_final_response()) {
|
if (!downstream->get_non_final_response()) {
|
||||||
auto worker = handler_->get_worker();
|
auto worker = handler_->get_worker();
|
||||||
|
|||||||
@@ -558,6 +558,8 @@ int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
|
|||||||
} // namespace
|
} // namespace
|
||||||
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||||
|
|
||||||
|
#if !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||||
|
|
||||||
#ifndef TLSEXT_TYPE_signed_certificate_timestamp
|
#ifndef TLSEXT_TYPE_signed_certificate_timestamp
|
||||||
#define TLSEXT_TYPE_signed_certificate_timestamp 18
|
#define TLSEXT_TYPE_signed_certificate_timestamp 18
|
||||||
#endif // !TLSEXT_TYPE_signed_certificate_timestamp
|
#endif // !TLSEXT_TYPE_signed_certificate_timestamp
|
||||||
@@ -620,8 +622,7 @@ int sct_parse_cb(SSL *ssl, unsigned int ext_type, unsigned int context,
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
#if !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L && \
|
#if !OPENSSL_1_1_1_API
|
||||||
!OPENSSL_1_1_1_API
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
int legacy_sct_add_cb(SSL *ssl, unsigned int ext_type,
|
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
|
} // namespace
|
||||||
|
|
||||||
#endif // !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L &&
|
#endif // !OPENSSL_1_1_1_API
|
||||||
// !OPENSSL_1_1_1_API
|
#endif // !LIBRESSL_IN_USE && OPENSSL_VERSION_NUMBER >= 0x10002000L
|
||||||
|
|
||||||
#if !LIBRESSL_IN_USE
|
#if !LIBRESSL_IN_USE
|
||||||
namespace {
|
namespace {
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ void test_shrpx_tls_create_lookup_tree(void) {
|
|||||||
CU_ASSERT(-1 == tree->lookup(StringRef{}));
|
CU_ASSERT(-1 == tree->lookup(StringRef{}));
|
||||||
CU_ASSERT(5 == tree->lookup(hostnames[5]));
|
CU_ASSERT(5 == tree->lookup(hostnames[5]));
|
||||||
CU_ASSERT(6 == tree->lookup(hostnames[6]));
|
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) {
|
for (int i = 0; i < 7; ++i) {
|
||||||
CU_ASSERT(-1 == tree->lookup(StringRef{h6 + i, str_size(h6) - 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) {
|
void test_shrpx_tls_cert_lookup_tree_add_ssl_ctx(void) {
|
||||||
int rv;
|
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 = SSL_CTX_new(SSLv23_server_method());
|
||||||
auto nghttp2_ssl_ctx_del = defer(SSL_CTX_free, nghttp2_ssl_ctx);
|
auto nghttp2_ssl_ctx_del = defer(SSL_CTX_free, nghttp2_ssl_ctx);
|
||||||
auto nghttp2_tls_ctx_data = make_unique<tls::TLSContextData>();
|
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);
|
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 = SSL_CTX_new(SSLv23_server_method());
|
||||||
auto examples_ssl_ctx_del = defer(SSL_CTX_free, examples_ssl_ctx);
|
auto examples_ssl_ctx_del = defer(SSL_CTX_free, examples_ssl_ctx);
|
||||||
auto examples_tls_ctx_data = make_unique<tls::TLSContextData>();
|
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
|
#ifdef HAVE_NETINET_IN_H
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#endif // HAVE_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>
|
#include <netinet/tcp.h>
|
||||||
|
#endif // !_WIN32
|
||||||
#ifdef HAVE_ARPA_INET_H
|
#ifdef HAVE_ARPA_INET_H
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#endif // HAVE_ARPA_INET_H
|
#endif // HAVE_ARPA_INET_H
|
||||||
@@ -65,6 +70,26 @@ namespace nghttp2 {
|
|||||||
|
|
||||||
namespace util {
|
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";
|
const char UPPER_XDIGITS[] = "0123456789ABCDEF";
|
||||||
|
|
||||||
bool in_rfc3986_unreserved_chars(const char c) {
|
bool in_rfc3986_unreserved_chars(const char c) {
|
||||||
@@ -352,13 +377,34 @@ char *iso8601_date(char *res, int64_t ms) {
|
|||||||
return p;
|
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) {
|
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{};
|
tm tm{};
|
||||||
char *r = strptime(s.c_str(), "%a, %d %b %Y %H:%M:%S GMT", &tm);
|
char *r = strptime(s.c_str(), "%a, %d %b %Y %H:%M:%S GMT", &tm);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return nghttp2_timegm_without_yday(&tm);
|
return nghttp2_timegm_without_yday(&tm);
|
||||||
|
#endif // !_WIN32
|
||||||
}
|
}
|
||||||
|
|
||||||
char upcase(char c) {
|
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) {
|
std::string to_numeric_addr(const Address *addr) {
|
||||||
auto family = addr->su.storage.ss_family;
|
auto family = addr->su.storage.ss_family;
|
||||||
|
#ifndef _WIN32
|
||||||
if (family == AF_UNIX) {
|
if (family == AF_UNIX) {
|
||||||
return addr->su.un.sun_path;
|
return addr->su.un.sun_path;
|
||||||
}
|
}
|
||||||
|
#endif // !_WIN32
|
||||||
|
|
||||||
std::array<char, NI_MAXHOST> host;
|
std::array<char, NI_MAXHOST> host;
|
||||||
std::array<char, NI_MAXSERV> serv;
|
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) {
|
int make_socket_closeonexec(int fd) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
(void)fd;
|
||||||
|
return 0;
|
||||||
|
#else // !_WIN32
|
||||||
int flags;
|
int flags;
|
||||||
int rv;
|
int rv;
|
||||||
while ((flags = fcntl(fd, F_GETFD)) == -1 && errno == EINTR)
|
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)
|
while ((rv = fcntl(fd, F_SETFD, flags | FD_CLOEXEC)) == -1 && errno == EINTR)
|
||||||
;
|
;
|
||||||
return rv;
|
return rv;
|
||||||
|
#endif // !_WIN32
|
||||||
}
|
}
|
||||||
|
|
||||||
int make_socket_nonblocking(int fd) {
|
int make_socket_nonblocking(int fd) {
|
||||||
int flags;
|
|
||||||
int rv;
|
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 ((flags = fcntl(fd, F_GETFL, 0)) == -1 && errno == EINTR)
|
||||||
;
|
;
|
||||||
while ((rv = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR)
|
while ((rv = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR)
|
||||||
;
|
;
|
||||||
|
#endif // !_WIN32
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -874,7 +935,7 @@ int create_nonblock_socket(int family) {
|
|||||||
bool check_socket_connected(int fd) {
|
bool check_socket_connected(int fd) {
|
||||||
int error;
|
int error;
|
||||||
socklen_t len = sizeof(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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -884,7 +945,7 @@ bool check_socket_connected(int fd) {
|
|||||||
int get_socket_error(int fd) {
|
int get_socket_error(int fd) {
|
||||||
int error;
|
int error;
|
||||||
socklen_t len = sizeof(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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -716,7 +716,7 @@ template <typename OutputIt, typename Generator>
|
|||||||
OutputIt random_alpha_digit(OutputIt first, OutputIt last, Generator &gen) {
|
OutputIt random_alpha_digit(OutputIt first, OutputIt last, Generator &gen) {
|
||||||
// If we use uint8_t instead char, gcc 6.2.0 complains by shouting
|
// If we use uint8_t instead char, gcc 6.2.0 complains by shouting
|
||||||
// char-array initialized from wide string.
|
// char-array initialized from wide string.
|
||||||
constexpr char s[] =
|
static constexpr char s[] =
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
std::uniform_int_distribution<> dis(0, 26 * 2 + 10 - 1);
|
std::uniform_int_distribution<> dis(0, 26 * 2 + 10 - 1);
|
||||||
for (; first != last; ++first) {
|
for (; first != last; ++first) {
|
||||||
|
|||||||
@@ -473,6 +473,7 @@ void test_util_localtime_date(void) {
|
|||||||
|
|
||||||
if (tz) {
|
if (tz) {
|
||||||
setenv("TZ", tz, 1);
|
setenv("TZ", tz, 1);
|
||||||
|
free(tz);
|
||||||
} else {
|
} else {
|
||||||
unsetenv("TZ");
|
unsetenv("TZ");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user