Merge branch 'master' into http2-debug-state-api

This commit is contained in:
Tatsuhiro Tsujikawa 2016-08-26 22:54:59 +09:00
commit 69aa70086a
27 changed files with 173 additions and 54 deletions

View File

@ -71,6 +71,7 @@ Tomasz Buchert
Vernon Tang Vernon Tang
Viacheslav Biriukov Viacheslav Biriukov
Viktor Szépe Viktor Szépe
Wenfeng Liu
Xiaoguang Sun Xiaoguang Sun
Zhuoyun Wei Zhuoyun Wei
acesso acesso

View File

@ -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.13.90) project(nghttp2 VERSION 1.14.90)
# 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

52
author.py Executable file
View File

@ -0,0 +1,52 @@
#!/usr/bin/env python
# script to extract commit author's name from standard input. The
# input should be <AUTHOR>:<EMAIL>, one per line.
# This script expects the input is created by git-log command:
#
# git log --format=%aN:%aE
#
# This script removes duplicates based on email address, breaking a
# tie with longer author name. Among the all author names extract the
# previous step, we remove duplicate by case-insensitive match.
#
# So we can do this in one line:
#
# git log --format=%aN:%aE | sort | uniq | ./author.py > authors
import sys
edict = {}
for line in sys.stdin:
author, email = line.strip().split(':', 1)
if email in edict:
an = edict[email]
if len(an) < len(author) or an > author:
sys.stderr.write(
'eliminated {} in favor of {}\n'.format(an, author))
edict[email] = author
else:
sys.stderr.write(
'eliminated {} in favor of {}\n'.format(author, an))
else:
edict[email] = author
names = list(sorted(edict.values()))
ndict = {}
for name in names:
lowname = name.lower()
if lowname in ndict:
an = ndict[lowname]
if an > name:
sys.stderr.write('eliminated {} in favor of {}\n'.format(an, name))
ndict[lowname] = name
else:
sys.stderr.write('eliminated {} in favor of {}\n'.format(name, an))
else:
ndict[lowname] = name
for name in sorted(ndict.values()):
print name

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 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.14.0-DEV], [t-tujikawa@users.sourceforge.net]) AC_INIT([nghttp2], [1.15.0-DEV], [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])
@ -44,9 +44,9 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
dnl See versioning rule: dnl See versioning rule:
dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html dnl http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
AC_SUBST(LT_CURRENT, 23) AC_SUBST(LT_CURRENT, 24)
AC_SUBST(LT_REVISION, 0) AC_SUBST(LT_REVISION, 0)
AC_SUBST(LT_AGE, 9) AC_SUBST(LT_AGE, 10)
major=`echo $PACKAGE_VERSION |cut -d. -f1 | sed -e "s/[^0-9]//g"` major=`echo $PACKAGE_VERSION |cut -d. -f1 | sed -e "s/[^0-9]//g"`
minor=`echo $PACKAGE_VERSION |cut -d. -f2 | sed -e "s/[^0-9]//g"` minor=`echo $PACKAGE_VERSION |cut -d. -f2 | sed -e "s/[^0-9]//g"`

View File

@ -37,6 +37,7 @@ APIDOCS= \
nghttp2_hd_deflate_get_num_table_entries.rst \ nghttp2_hd_deflate_get_num_table_entries.rst \
nghttp2_hd_deflate_get_table_entry.rst \ nghttp2_hd_deflate_get_table_entry.rst \
nghttp2_hd_deflate_hd.rst \ nghttp2_hd_deflate_hd.rst \
nghttp2_hd_deflate_hd_vec.rst \
nghttp2_hd_deflate_new.rst \ nghttp2_hd_deflate_new.rst \
nghttp2_hd_deflate_new2.rst \ nghttp2_hd_deflate_new2.rst \
nghttp2_hd_inflate_change_table_size.rst \ nghttp2_hd_inflate_change_table_size.rst \

View File

@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText. .\" Man page generated from reStructuredText.
. .
.TH "H2LOAD" "1" "Jul 31, 2016" "1.14.0-DEV" "nghttp2" .TH "H2LOAD" "1" "Aug 25, 2016" "1.14.0" "nghttp2"
.SH NAME .SH NAME
h2load \- HTTP/2 benchmarking tool h2load \- HTTP/2 benchmarking tool
. .

View File

@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText. .\" Man page generated from reStructuredText.
. .
.TH "NGHTTP" "1" "Jul 31, 2016" "1.14.0-DEV" "nghttp2" .TH "NGHTTP" "1" "Aug 25, 2016" "1.14.0" "nghttp2"
.SH NAME .SH NAME
nghttp \- HTTP/2 client nghttp \- HTTP/2 client
. .

View File

@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText. .\" Man page generated from reStructuredText.
. .
.TH "NGHTTPD" "1" "Jul 31, 2016" "1.14.0-DEV" "nghttp2" .TH "NGHTTPD" "1" "Aug 25, 2016" "1.14.0" "nghttp2"
.SH NAME .SH NAME
nghttpd \- HTTP/2 server nghttpd \- HTTP/2 server
. .

View File

@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText. .\" Man page generated from reStructuredText.
. .
.TH "NGHTTPX" "1" "Jul 31, 2016" "1.14.0-DEV" "nghttp2" .TH "NGHTTPX" "1" "Aug 25, 2016" "1.14.0" "nghttp2"
.SH NAME .SH NAME
nghttpx \- HTTP/2 proxy nghttpx \- HTTP/2 proxy
. .
@ -938,6 +938,12 @@ $ssl_session_id: session ID for SSL/TLS connection.
.IP \(bu 2 .IP \(bu 2
$ssl_session_reused: "r" if SSL/TLS session was $ssl_session_reused: "r" if SSL/TLS session was
reused. Otherwise, "." reused. Otherwise, "."
.IP \(bu 2
$backend_host: backend host used to fulfill the
request. "\-" if backend host is not available.
.IP \(bu 2
$backend_port: backend port used to fulfill the
request. "\-" if backend host is not available.
.UNINDENT .UNINDENT
.sp .sp
The variable can be enclosed by "{" and "}" for The variable can be enclosed by "{" and "}" for

View File

@ -847,6 +847,10 @@ Logging
* $ssl_session_id: session ID for SSL/TLS connection. * $ssl_session_id: session ID for SSL/TLS connection.
* $ssl_session_reused: "r" if SSL/TLS session was * $ssl_session_reused: "r" if SSL/TLS session was
reused. Otherwise, "." reused. Otherwise, "."
* $backend_host: backend host used to fulfill the
request. "-" if backend host is not available.
* $backend_port: backend port used to fulfill the
request. "-" if backend host is not available.
The variable can be enclosed by "{" and "}" for The variable can be enclosed by "{" and "}" for
disambiguation (e.g., ${remote_addr}). disambiguation (e.g., ${remote_addr}).

View File

@ -134,6 +134,7 @@ OPTIONS = [
"backend-http2-settings-timeout", "backend-http2-settings-timeout",
"api-max-request-body", "api-max-request-body",
"backend-max-backoff", "backend-max-backoff",
"server-name",
] ]
LOGVARS = [ LOGVARS = [

View File

@ -768,14 +768,12 @@ static size_t entry_room(size_t namelen, size_t valuelen) {
return NGHTTP2_HD_ENTRY_OVERHEAD + namelen + valuelen; return NGHTTP2_HD_ENTRY_OVERHEAD + namelen + valuelen;
} }
static int emit_header(nghttp2_hd_nv *nv_out, nghttp2_hd_nv *nv) { static void emit_header(nghttp2_hd_nv *nv_out, nghttp2_hd_nv *nv) {
DEBUGF(fprintf(stderr, "inflatehd: header emission: %s: %s\n", nv->name->base, DEBUGF(fprintf(stderr, "inflatehd: header emission: %s: %s\n", nv->name->base,
nv->value->base)); nv->value->base));
/* ent->ref may be 0. This happens if the encoder emits literal /* ent->ref may be 0. This happens if the encoder emits literal
block larger than header table capacity with indexing. */ block larger than header table capacity with indexing. */
*nv_out = *nv; *nv_out = *nv;
return 0;
} }
static size_t count_encoded_length(size_t n, size_t prefix) { static size_t count_encoded_length(size_t n, size_t prefix) {

View File

@ -503,7 +503,7 @@ const request *session_impl::submit(boost::system::error_code &ec,
} }
auto nva = std::vector<nghttp2_nv>(); auto nva = std::vector<nghttp2_nv>();
nva.reserve(3 + h.size()); nva.reserve(4 + h.size());
nva.push_back(http2::make_nv_ls(":method", method)); nva.push_back(http2::make_nv_ls(":method", method));
nva.push_back(http2::make_nv_ls(":scheme", uref.scheme)); nva.push_back(http2::make_nv_ls(":scheme", uref.scheme));
nva.push_back(http2::make_nv_ls(":path", path)); nva.push_back(http2::make_nv_ls(":path", path));

View File

@ -178,6 +178,9 @@ template <typename Memchunk> struct Memchunks {
} }
size_t append(const std::string &s) { return append(s.c_str(), s.size()); } size_t append(const std::string &s) { return append(s.c_str(), s.size()); }
size_t append(const StringRef &s) { return append(s.c_str(), s.size()); } size_t append(const StringRef &s) { return append(s.c_str(), s.size()); }
size_t append(const ImmutableString &s) {
return append(s.c_str(), s.size());
}
size_t remove(void *dest, size_t count) { size_t remove(void *dest, size_t count) {
if (!tail || count == 0) { if (!tail || count == 0) {
return 0; return 0;

View File

@ -574,7 +574,7 @@ int create_unix_domain_server_socket(UpstreamAddr &faddr,
<< (faddr.tls ? ", tls" : ""); << (faddr.tls ? ", tls" : "");
(*found).used = true; (*found).used = true;
faddr.fd = (*found).fd; faddr.fd = (*found).fd;
faddr.hostport = "localhost"; faddr.hostport = ImmutableString::from_lit("localhost");
return 0; return 0;
} }
@ -639,7 +639,7 @@ int create_unix_domain_server_socket(UpstreamAddr &faddr,
<< (faddr.tls ? ", tls" : ""); << (faddr.tls ? ", tls" : "");
faddr.fd = fd; faddr.fd = fd;
faddr.hostport = "localhost"; faddr.hostport = ImmutableString::from_lit("localhost");
return 0; return 0;
} }
@ -791,7 +791,8 @@ int create_tcp_server_socket(UpstreamAddr &faddr,
} }
faddr.fd = fd; faddr.fd = fd;
faddr.hostport = util::make_http_hostport(StringRef{host.data()}, faddr.port); faddr.hostport = ImmutableString{
util::make_http_hostport(StringRef{host.data()}, faddr.port)};
LOG(NOTICE) << "Listening on " << faddr.hostport LOG(NOTICE) << "Listening on " << faddr.hostport
<< (faddr.tls ? ", tls" : ""); << (faddr.tls ? ", tls" : "");
@ -855,7 +856,7 @@ get_inherited_addr_from_config(const Config *config) {
continue; continue;
} }
iaddr.host = host.data(); iaddr.host = ImmutableString{host.data()};
} }
return iaddrs; return iaddrs;
@ -947,7 +948,7 @@ std::vector<InheritedAddr> get_inherited_addr_from_env() {
} }
InheritedAddr addr{}; InheritedAddr addr{};
addr.host = path; addr.host = ImmutableString{path};
addr.host_unix = true; addr.host_unix = true;
addr.fd = static_cast<int>(fd); addr.fd = static_cast<int>(fd);
iaddrs.push_back(std::move(addr)); iaddrs.push_back(std::move(addr));
@ -1001,7 +1002,7 @@ std::vector<InheritedAddr> get_inherited_addr_from_env() {
} }
InheritedAddr addr{}; InheritedAddr addr{};
addr.host = host.data(); addr.host = ImmutableString{host.data()};
addr.port = static_cast<uint16_t>(port); addr.port = static_cast<uint16_t>(port);
addr.fd = static_cast<int>(fd); addr.fd = static_cast<int>(fd);
iaddrs.push_back(std::move(addr)); iaddrs.push_back(std::move(addr));
@ -1272,10 +1273,8 @@ constexpr auto DEFAULT_ACCESSLOG_FORMAT = StringRef::from_lit(
namespace { namespace {
void fill_default_config(Config *config) { void fill_default_config(Config *config) {
*config = {};
config->num_worker = 1; config->num_worker = 1;
config->conf_path = "/etc/nghttpx/nghttpx.conf"; config->conf_path = ImmutableString::from_lit("/etc/nghttpx/nghttpx.conf");
config->pid = getpid(); config->pid = getpid();
if (ev_supported_backends() & ~ev_recommended_backends() & EVBACKEND_KQUEUE) { if (ev_supported_backends() & ~ev_recommended_backends() & EVBACKEND_KQUEUE) {
@ -1306,7 +1305,8 @@ void fill_default_config(Config *config) {
auto &ocspconf = tlsconf.ocsp; auto &ocspconf = tlsconf.ocsp;
// ocsp update interval = 14400 secs = 4 hours, borrowed from h2o // ocsp update interval = 14400 secs = 4 hours, borrowed from h2o
ocspconf.update_interval = 4_h; ocspconf.update_interval = 4_h;
ocspconf.fetch_ocsp_response_file = PKGDATADIR "/fetch-ocsp-response"; ocspconf.fetch_ocsp_response_file =
ImmutableString::from_lit(PKGDATADIR "/fetch-ocsp-response");
} }
{ {
@ -1319,7 +1319,7 @@ void fill_default_config(Config *config) {
auto &httpconf = config->http; auto &httpconf = config->http;
httpconf.server_name = httpconf.server_name =
StringRef::from_lit("nghttpx nghttp2/" NGHTTP2_VERSION); ImmutableString::from_lit("nghttpx nghttp2/" NGHTTP2_VERSION);
httpconf.no_host_rewrite = true; httpconf.no_host_rewrite = true;
httpconf.request_header_field_buffer = 64_k; httpconf.request_header_field_buffer = 64_k;
httpconf.max_request_header_fields = 100; httpconf.max_request_header_fields = 100;
@ -1377,7 +1377,7 @@ void fill_default_config(Config *config) {
accessconf.format = parse_log_format(DEFAULT_ACCESSLOG_FORMAT); accessconf.format = parse_log_format(DEFAULT_ACCESSLOG_FORMAT);
auto &errorconf = loggingconf.error; auto &errorconf = loggingconf.error;
errorconf.file = "/dev/stderr"; errorconf.file = ImmutableString::from_lit("/dev/stderr");
} }
loggingconf.syslog_facility = LOG_DAEMON; loggingconf.syslog_facility = LOG_DAEMON;
@ -2205,6 +2205,9 @@ HTTP:
599. If "*" is used instead of <CODE>, it matches all 599. If "*" is used instead of <CODE>, it matches all
HTTP status code. If error status code comes from HTTP status code. If error status code comes from
backend server, the custom error pages are not used. backend server, the custom error pages are not used.
--server-name=<NAME>
Change server response header field value to <NAME>.
Default: )" << get_config()->http.server_name << R"(
API: API:
--api-max-request-body=<SIZE> --api-max-request-body=<SIZE>
@ -2396,7 +2399,7 @@ int process_options(Config *config,
if (listenerconf.addrs.empty()) { if (listenerconf.addrs.empty()) {
UpstreamAddr addr{}; UpstreamAddr addr{};
addr.host = "*"; addr.host = ImmutableString::from_lit("*");
addr.port = 3000; addr.port = 3000;
addr.tls = true; addr.tls = true;
addr.family = AF_INET; addr.family = AF_INET;
@ -2833,6 +2836,7 @@ int main(int argc, char **argv) {
&flag, 125}, &flag, 125},
{SHRPX_OPT_API_MAX_REQUEST_BODY.c_str(), required_argument, &flag, 126}, {SHRPX_OPT_API_MAX_REQUEST_BODY.c_str(), required_argument, &flag, 126},
{SHRPX_OPT_BACKEND_MAX_BACKOFF.c_str(), required_argument, &flag, 127}, {SHRPX_OPT_BACKEND_MAX_BACKOFF.c_str(), required_argument, &flag, 127},
{SHRPX_OPT_SERVER_NAME.c_str(), required_argument, &flag, 128},
{nullptr, 0, nullptr, 0}}; {nullptr, 0, nullptr, 0}};
int option_index = 0; int option_index = 0;
@ -2935,7 +2939,7 @@ int main(int argc, char **argv) {
break; break;
case 12: case 12:
// --conf // --conf
mod_config()->conf_path = optarg; mod_config()->conf_path = ImmutableString{optarg};
break; break;
case 14: case 14:
// --syslog-facility // --syslog-facility
@ -3430,6 +3434,10 @@ int main(int argc, char **argv) {
// --backend-max-backoff // --backend-max-backoff
cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_MAX_BACKOFF, StringRef{optarg}); cmdcfgs.emplace_back(SHRPX_OPT_BACKEND_MAX_BACKOFF, StringRef{optarg});
break; break;
case 128:
// --server-name
cmdcfgs.emplace_back(SHRPX_OPT_SERVER_NAME, StringRef{optarg});
break;
default: default:
break; break;
} }

View File

@ -1127,6 +1127,11 @@ int option_lookup_token(const char *name, size_t namelen) {
break; break;
case 11: case 11:
switch (name[10]) { switch (name[10]) {
case 'e':
if (util::strieq_l("server-nam", name, 10)) {
return SHRPX_OPTID_SERVER_NAME;
}
break;
case 's': case 's':
if (util::strieq_l("backend-tl", name, 10)) { if (util::strieq_l("backend-tl", name, 10)) {
return SHRPX_OPTID_BACKEND_TLS; return SHRPX_OPTID_BACKEND_TLS;
@ -2027,7 +2032,7 @@ int parse_config(Config *config, int optid, const StringRef &opt,
<< strerror(errno); << strerror(errno);
return -1; return -1;
} }
config->user = pwd->pw_name; config->user = ImmutableString{pwd->pw_name};
config->uid = pwd->pw_uid; config->uid = pwd->pw_uid;
config->gid = pwd->pw_gid; config->gid = pwd->pw_gid;
@ -2044,7 +2049,7 @@ int parse_config(Config *config, int optid, const StringRef &opt,
LOG(ERROR) << opt << ": Couldn't read key file's passwd from " << optarg; LOG(ERROR) << opt << ": Couldn't read key file's passwd from " << optarg;
return -1; return -1;
} }
config->tls.private_key_passwd = passwd; config->tls.private_key_passwd = ImmutableString{passwd};
return 0; return 0;
} }
@ -2479,14 +2484,14 @@ int parse_config(Config *config, int optid, const StringRef &opt,
switch (optid) { switch (optid) {
case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED: { case SHRPX_OPTID_TLS_SESSION_CACHE_MEMCACHED: {
auto &memcachedconf = config->tls.session_cache.memcached; auto &memcachedconf = config->tls.session_cache.memcached;
memcachedconf.host = host; memcachedconf.host = ImmutableString{host};
memcachedconf.port = port; memcachedconf.port = port;
memcachedconf.tls = params.tls; memcachedconf.tls = params.tls;
break; break;
} }
case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED: { case SHRPX_OPTID_TLS_TICKET_KEY_MEMCACHED: {
auto &memcachedconf = config->tls.ticket.memcached; auto &memcachedconf = config->tls.ticket.memcached;
memcachedconf.host = host; memcachedconf.host = ImmutableString{host};
memcachedconf.port = port; memcachedconf.port = port;
memcachedconf.tls = params.tls; memcachedconf.tls = params.tls;
break; break;
@ -2673,6 +2678,11 @@ int parse_config(Config *config, int optid, const StringRef &opt,
case SHRPX_OPTID_BACKEND_MAX_BACKOFF: case SHRPX_OPTID_BACKEND_MAX_BACKOFF:
return parse_duration(&config->conn.downstream->timeout.max_backoff, opt, return parse_duration(&config->conn.downstream->timeout.max_backoff, opt,
optarg); optarg);
case SHRPX_OPTID_SERVER_NAME:
config->http.server_name =
ImmutableString{std::begin(optarg), std::end(optarg)};
return 0;
case SHRPX_OPTID_CONF: case SHRPX_OPTID_CONF:
LOG(WARN) << "conf: ignored"; LOG(WARN) << "conf: ignored";
@ -2948,7 +2958,7 @@ int configure_downstream_group(Config *config, bool http2_proxy,
auto &sni = tlsconf.backend_sni_name; auto &sni = tlsconf.backend_sni_name;
for (auto &addr_group : addr_groups) { for (auto &addr_group : addr_groups) {
for (auto &addr : addr_group.addrs) { for (auto &addr : addr_group.addrs) {
addr.sni = sni; addr.sni = ImmutableString{sni};
} }
} }
} }
@ -2995,7 +3005,7 @@ int configure_downstream_group(Config *config, bool http2_proxy,
// for AF_UNIX socket, we use "localhost" as host for backend // for AF_UNIX socket, we use "localhost" as host for backend
// hostport. This is used as Host header field to backend and // hostport. This is used as Host header field to backend and
// not going to be passed to any syscalls. // not going to be passed to any syscalls.
addr.hostport = "localhost"; addr.hostport = ImmutableString::from_lit("localhost");
auto path = addr.host.c_str(); auto path = addr.host.c_str();
auto pathlen = addr.host.size(); auto pathlen = addr.host.size();

View File

@ -284,6 +284,7 @@ constexpr auto SHRPX_OPT_API_MAX_REQUEST_BODY =
StringRef::from_lit("api-max-request-body"); StringRef::from_lit("api-max-request-body");
constexpr auto SHRPX_OPT_BACKEND_MAX_BACKOFF = constexpr auto SHRPX_OPT_BACKEND_MAX_BACKOFF =
StringRef::from_lit("backend-max-backoff"); StringRef::from_lit("backend-max-backoff");
constexpr auto SHRPX_OPT_SERVER_NAME = StringRef::from_lit("server-name");
constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8; constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8;
@ -552,7 +553,7 @@ struct HttpConfig {
std::vector<ErrorPage> error_pages; std::vector<ErrorPage> error_pages;
Headers add_request_headers; Headers add_request_headers;
Headers add_response_headers; Headers add_response_headers;
StringRef server_name; ImmutableString server_name;
size_t request_header_field_buffer; size_t request_header_field_buffer;
size_t max_request_header_fields; size_t max_request_header_fields;
size_t response_header_field_buffer; size_t response_header_field_buffer;
@ -706,8 +707,14 @@ struct APIConfig {
}; };
struct Config { struct Config {
Config() = default;
~Config(); ~Config();
Config(Config &&) = delete;
Config(const Config &&) = delete;
Config &operator=(Config &&) = delete;
Config &operator=(const Config &&) = delete;
HttpProxy downstream_http_proxy; HttpProxy downstream_http_proxy;
HttpConfig http; HttpConfig http;
Http2Config http2; Http2Config http2;
@ -837,6 +844,7 @@ enum {
SHRPX_OPTID_REQUEST_HEADER_FIELD_BUFFER, SHRPX_OPTID_REQUEST_HEADER_FIELD_BUFFER,
SHRPX_OPTID_RESPONSE_HEADER_FIELD_BUFFER, SHRPX_OPTID_RESPONSE_HEADER_FIELD_BUFFER,
SHRPX_OPTID_RLIMIT_NOFILE, SHRPX_OPTID_RLIMIT_NOFILE,
SHRPX_OPTID_SERVER_NAME,
SHRPX_OPTID_STREAM_READ_TIMEOUT, SHRPX_OPTID_STREAM_READ_TIMEOUT,
SHRPX_OPTID_STREAM_WRITE_TIMEOUT, SHRPX_OPTID_STREAM_WRITE_TIMEOUT,
SHRPX_OPTID_STRIP_INCOMING_FORWARDED, SHRPX_OPTID_STRIP_INCOMING_FORWARDED,

View File

@ -51,7 +51,7 @@ StringRef create_error_html(BlockAllocator &balloc, unsigned int http_status) {
return concat_string_ref( return concat_string_ref(
balloc, StringRef::from_lit(R"(<!DOCTYPE html><html lang="en"><title>)"), balloc, StringRef::from_lit(R"(<!DOCTYPE html><html lang="en"><title>)"),
status_string, StringRef::from_lit("</title><body><h1>"), status_string, status_string, StringRef::from_lit("</title><body><h1>"), status_string,
StringRef::from_lit("</h1><footer>"), server_name, StringRef::from_lit("</h1><footer>"), StringRef{server_name},
StringRef::from_lit("</footer></body></html>")); StringRef::from_lit("</footer></body></html>"));
} }

View File

@ -1806,9 +1806,11 @@ int Http2Session::read_noop(const uint8_t *data, size_t datalen) { return 0; }
int Http2Session::write_noop() { return 0; } int Http2Session::write_noop() { return 0; }
int Http2Session::connected() { int Http2Session::connected() {
if (!util::check_socket_connected(conn_.fd)) { auto sock_error = util::get_socket_error(conn_.fd);
if (sock_error != 0) {
SSLOG(WARN, this) << "Backend connect failed; addr=" SSLOG(WARN, this) << "Backend connect failed; addr="
<< util::to_numeric_addr(&addr_->addr); << util::to_numeric_addr(&addr_->addr)
<< ": errno=" << sock_error;
downstream_failure(addr_); downstream_failure(addr_);

View File

@ -1307,8 +1307,8 @@ int Http2Upstream::send_reply(Downstream *downstream, const uint8_t *body,
} }
if (!resp.fs.header(http2::HD_SERVER)) { if (!resp.fs.header(http2::HD_SERVER)) {
nva.push_back( nva.push_back(http2::make_nv_ls_nocopy(
http2::make_nv_ls_nocopy("server", get_config()->http.server_name)); "server", StringRef{get_config()->http.server_name}));
} }
for (auto &p : httpconf.add_response_headers) { for (auto &p : httpconf.add_response_headers) {
@ -1359,7 +1359,8 @@ int Http2Upstream::error_reply(Downstream *downstream,
auto nva = std::array<nghttp2_nv, 5>{ auto nva = std::array<nghttp2_nv, 5>{
{http2::make_nv_ls_nocopy(":status", response_status), {http2::make_nv_ls_nocopy(":status", response_status),
http2::make_nv_ll("content-type", "text/html; charset=UTF-8"), http2::make_nv_ll("content-type", "text/html; charset=UTF-8"),
http2::make_nv_ls_nocopy("server", get_config()->http.server_name), http2::make_nv_ls_nocopy("server",
StringRef{get_config()->http.server_name}),
http2::make_nv_ls_nocopy("content-length", content_length), http2::make_nv_ls_nocopy("content-length", content_length),
http2::make_nv_ls_nocopy("date", date)}}; http2::make_nv_ls_nocopy("date", date)}};
@ -1506,7 +1507,8 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
http2::copy_headers_to_nva_nocopy(nva, resp.fs.headers()); http2::copy_headers_to_nva_nocopy(nva, resp.fs.headers());
if (!get_config()->http2_proxy) { if (!get_config()->http2_proxy) {
nva.push_back(http2::make_nv_ls_nocopy("server", httpconf.server_name)); nva.push_back(
http2::make_nv_ls_nocopy("server", StringRef{httpconf.server_name}));
} else { } else {
auto server = resp.fs.header(http2::HD_SERVER); auto server = resp.fs.header(http2::HD_SERVER);
if (server) { if (server) {

View File

@ -994,6 +994,8 @@ int HttpDownstreamConnection::tls_handshake() {
auto &connect_blocker = addr_->connect_blocker; auto &connect_blocker = addr_->connect_blocker;
do_signal_write_ = &HttpDownstreamConnection::actual_signal_write;
connect_blocker->on_success(); connect_blocker->on_success();
ev_set_cb(&conn_.rt, timeoutcb); ev_set_cb(&conn_.rt, timeoutcb);
@ -1141,11 +1143,13 @@ int HttpDownstreamConnection::process_input(const uint8_t *data,
int HttpDownstreamConnection::connected() { int HttpDownstreamConnection::connected() {
auto &connect_blocker = addr_->connect_blocker; auto &connect_blocker = addr_->connect_blocker;
if (!util::check_socket_connected(conn_.fd)) { auto sock_error = util::get_socket_error(conn_.fd);
if (sock_error != 0) {
conn_.wlimit.stopw(); conn_.wlimit.stopw();
DCLOG(WARN, this) << "Backend connect failed; addr=" DCLOG(WARN, this) << "Backend connect failed; addr="
<< util::to_numeric_addr(&addr_->addr); << util::to_numeric_addr(&addr_->addr)
<< ": errno=" << sock_error;
downstream_failure(addr_); downstream_failure(addr_);
@ -1160,8 +1164,6 @@ int HttpDownstreamConnection::connected() {
ev_set_cb(&conn_.wev, writecb); ev_set_cb(&conn_.wev, writecb);
do_signal_write_ = &HttpDownstreamConnection::actual_signal_write;
if (conn_.tls.ssl) { if (conn_.tls.ssl) {
do_read_ = &HttpDownstreamConnection::tls_handshake; do_read_ = &HttpDownstreamConnection::tls_handshake;
do_write_ = &HttpDownstreamConnection::tls_handshake; do_write_ = &HttpDownstreamConnection::tls_handshake;
@ -1169,6 +1171,8 @@ int HttpDownstreamConnection::connected() {
return 0; return 0;
} }
do_signal_write_ = &HttpDownstreamConnection::actual_signal_write;
connect_blocker->on_success(); connect_blocker->on_success();
ev_set_cb(&conn_.rt, timeoutcb); ev_set_cb(&conn_.rt, timeoutcb);

View File

@ -259,10 +259,12 @@ int LiveCheck::initiate_connection() {
} }
int LiveCheck::connected() { int LiveCheck::connected() {
if (!util::check_socket_connected(conn_.fd)) { auto sock_error = util::get_socket_error(conn_.fd);
if (sock_error != 0) {
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
LOG(INFO) << "Backend connect failed; addr=" LOG(INFO) << "Backend connect failed; addr="
<< util::to_numeric_addr(&addr_->addr); << util::to_numeric_addr(&addr_->addr)
<< ": errno=" << sock_error;
} }
return -1; return -1;

View File

@ -203,15 +203,16 @@ int MemcachedConnection::initiate_connection() {
} }
int MemcachedConnection::connected() { int MemcachedConnection::connected() {
if (!util::check_socket_connected(conn_.fd)) { auto sock_error = util::get_socket_error(conn_.fd);
if (sock_error != 0) {
MCLOG(WARN, this) << "memcached connect failed; addr="
<< util::to_numeric_addr(addr_)
<< ": errno=" << sock_error;
connect_blocker_.on_failure(); connect_blocker_.on_failure();
conn_.wlimit.stopw(); conn_.wlimit.stopw();
if (LOG_ENABLED(INFO)) {
MCLOG(INFO, this) << "memcached connect failed";
}
return -1; return -1;
} }

View File

@ -255,8 +255,9 @@ public:
ImmutableString() : len(0), base("") {} ImmutableString() : len(0), base("") {}
ImmutableString(const char *s, size_t slen) ImmutableString(const char *s, size_t slen)
: len(slen), base(copystr(s, s + len)) {} : len(slen), base(copystr(s, s + len)) {}
ImmutableString(const char *s) : len(strlen(s)), base(copystr(s, s + len)) {} explicit ImmutableString(const char *s)
ImmutableString(const std::string &s) : len(strlen(s)), base(copystr(s, s + len)) {}
explicit ImmutableString(const std::string &s)
: len(s.size()), base(copystr(std::begin(s), std::end(s))) {} : len(s.size()), base(copystr(std::begin(s), std::end(s))) {}
template <typename InputIt> template <typename InputIt>
ImmutableString(InputIt first, InputIt last) ImmutableString(InputIt first, InputIt last)

View File

@ -156,7 +156,7 @@ void test_template_string_ref(void) {
CU_ASSERT(5 == from_lit.size()); CU_ASSERT(5 == from_lit.size());
// from ImmutableString // from ImmutableString
ImmutableString im = "bravo"; auto im = ImmutableString::from_lit("bravo");
StringRef imref(im); StringRef imref(im);

View File

@ -893,6 +893,16 @@ bool check_socket_connected(int fd) {
return error == 0; return error == 0;
} }
int get_socket_error(int fd) {
int error;
socklen_t len = sizeof(error);
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) != 0) {
return -1;
}
return error;
}
bool ipv6_numeric_addr(const char *host) { bool ipv6_numeric_addr(const char *host) {
uint8_t dst[16]; uint8_t dst[16];
return inet_pton(AF_INET6, host, dst) == 1; return inet_pton(AF_INET6, host, dst) == 1;

View File

@ -574,6 +574,11 @@ int create_nonblock_socket(int family);
bool check_socket_connected(int fd); bool check_socket_connected(int fd);
// Returns the error code (errno) by inspecting SO_ERROR of given
// |fd|. This function returns the error code if it succeeds, or -1.
// Returning 0 means no error.
int get_socket_error(int fd);
// Returns true if |host| is IPv6 numeric address (e.g., ::1) // Returns true if |host| is IPv6 numeric address (e.g., ::1)
bool ipv6_numeric_addr(const char *host); bool ipv6_numeric_addr(const char *host);