Compare commits

...

8 Commits

Author SHA1 Message Date
Tatsuhiro Tsujikawa d8e908286d Update authors 2016-04-03 10:26:39 +09:00
Tatsuhiro Tsujikawa 915e26b33d Update man pages 2016-04-03 10:22:40 +09:00
Tatsuhiro Tsujikawa 5ab05402e4 Bump up version number to 1.9.2 2016-04-03 10:20:38 +09:00
Tatsuhiro Tsujikawa 0af9629cc1 nghttpx: Fix crash with backend failure 2016-04-03 10:19:08 +09:00
Tatsuhiro Tsujikawa 53989dc70c nghttpx: Better distribute load to backend h2 servers 2016-04-03 10:19:02 +09:00
Tatsuhiro Tsujikawa 290a697bf9 Merge branch 'tsing-patch-1' 2016-04-03 10:18:47 +09:00
Tatsuhiro Tsujikawa b63c88aab7 nghttpx: Fix bug that logger wrote string which was not NULL-terminated 2016-04-03 09:59:44 +09:00
Tatsuhiro Tsujikawa 73e513601f nghttpx: Fix bug that proxy with HTTP/1.1 CONNECT did not work
This was a regression in 5fbe4cc225.
2016-04-03 09:59:33 +09:00
13 changed files with 61 additions and 30 deletions

View File

@ -34,6 +34,7 @@ Gabi Davar
Jan-E Jan-E
Janusz Dziemidowicz Janusz Dziemidowicz
Jay Satiro Jay Satiro
Jianqing Wang
Jim Morrison Jim Morrison
José F. Calcerrada José F. Calcerrada
Kamil Dudka Kamil Dudka

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.9.1) project(nghttp2 VERSION 1.9.2)
# 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

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.9.1], [t-tujikawa@users.sourceforge.net]) AC_INIT([nghttp2], [1.9.2], [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])

View File

@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText. .\" Man page generated from reStructuredText.
. .
.TH "H2LOAD" "1" "March 27, 2016" "1.9.1" "nghttp2" .TH "H2LOAD" "1" "April 03, 2016" "1.9.2" "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" "March 27, 2016" "1.9.1" "nghttp2" .TH "NGHTTP" "1" "April 03, 2016" "1.9.2" "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" "March 27, 2016" "1.9.1" "nghttp2" .TH "NGHTTPD" "1" "April 03, 2016" "1.9.2" "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" "March 27, 2016" "1.9.1" "nghttp2" .TH "NGHTTPX" "1" "April 03, 2016" "1.9.2" "nghttp2"
.SH NAME .SH NAME
nghttpx \- HTTP/2 proxy nghttpx \- HTTP/2 proxy
. .

View File

@ -737,6 +737,8 @@ ClientHandler::get_downstream_connection(Downstream *downstream) {
if (shared_addr->proto == PROTO_HTTP2) { if (shared_addr->proto == PROTO_HTTP2) {
auto &http2_freelist = shared_addr->http2_freelist; auto &http2_freelist = shared_addr->http2_freelist;
Http2Session *http2session;
if (http2_freelist.empty() || if (http2_freelist.empty() ||
http2_freelist.size() < shared_addr->addrs.size()) { http2_freelist.size() < shared_addr->addrs.size()) {
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
@ -749,21 +751,22 @@ ClientHandler::get_downstream_connection(Downstream *downstream) {
<< shared_addr->addrs.size(); << shared_addr->addrs.size();
} }
} }
auto session = make_unique<Http2Session>( http2session = new Http2Session(
conn_.loop, shared_addr->tls ? worker_->get_cl_ssl_ctx() : nullptr, conn_.loop, shared_addr->tls ? worker_->get_cl_ssl_ctx() : nullptr,
worker_, &group); worker_, &group);
http2_freelist.append(session.release()); } else {
http2session = http2_freelist.head;
http2_freelist.remove(http2session);
} }
auto http2session = http2_freelist.head;
if (http2session->max_concurrency_reached(1)) { if (http2session->max_concurrency_reached(1)) {
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
CLOG(INFO, this) << "Maximum streams are reached for Http2Session(" CLOG(INFO, this) << "Maximum streams are reached for Http2Session("
<< http2session << http2session
<< "). Remove Http2Session from http2_freelist"; << "). Remove Http2Session from http2_freelist";
} }
http2_freelist.remove(http2session); } else {
http2_freelist.append(http2session);
} }
dconn = make_unique<Http2DownstreamConnection>(http2session); dconn = make_unique<Http2DownstreamConnection>(http2session);

View File

@ -1870,12 +1870,14 @@ int parse_config(const StringRef &opt, const StringRef &optarg,
return 0; return 0;
case SHRPX_OPTID_HTTP2_BRIDGE: case SHRPX_OPTID_HTTP2_BRIDGE:
LOG(ERROR) << opt << ": deprecated. Use backend=<addr>,<port>;;proto=h2 " LOG(ERROR) << opt
"and backend-tls"; << ": deprecated. Use backend=<addr>,<port>;;proto=h2;tls";
return -1; return -1;
case SHRPX_OPTID_CLIENT_PROXY: case SHRPX_OPTID_CLIENT_PROXY:
LOG(ERROR) << opt << ": deprecated. Use http2-proxy, frontend-no-tls, " LOG(ERROR)
"backend=<addr>,<port>;;proto=h2 and backend-tls"; << opt
<< ": deprecated. Use http2-proxy, frontend=<addr>,<port>;no-tls "
"and backend=<addr>,<port>;;proto=h2;tls";
return -1; return -1;
case SHRPX_OPTID_ADD_X_FORWARDED_FOR: case SHRPX_OPTID_ADD_X_FORWARDED_FOR:
mod_config()->http.xff.add = util::strieq_l("yes", optarg); mod_config()->http.xff.add = util::strieq_l("yes", optarg);
@ -2120,8 +2122,8 @@ int parse_config(const StringRef &opt, const StringRef &optarg,
return 0; return 0;
case SHRPX_OPTID_CLIENT: case SHRPX_OPTID_CLIENT:
LOG(ERROR) << opt << ": deprecated. Use frontend-no-tls, " LOG(ERROR) << opt << ": deprecated. Use frontend=<addr>,<port>;no-tls, "
"backend=<addr>,<port>;;proto=h2 and backend-tls"; "backend=<addr>,<port>;;proto=h2;tls";
return -1; return -1;
case SHRPX_OPTID_INSECURE: case SHRPX_OPTID_INSECURE:
mod_config()->tls.insecure = util::strieq_l("yes", optarg); mod_config()->tls.insecure = util::strieq_l("yes", optarg);

View File

@ -97,9 +97,6 @@ int Http2DownstreamConnection::attach_downstream(Downstream *downstream) {
http2session_->add_downstream_connection(this); http2session_->add_downstream_connection(this);
if (http2session_->get_state() == Http2Session::DISCONNECTED) { if (http2session_->get_state() == Http2Session::DISCONNECTED) {
http2session_->signal_write(); http2session_->signal_write();
if (http2session_->get_state() == Http2Session::DISCONNECTED) {
return -1;
}
} }
downstream_ = downstream; downstream_ = downstream;
@ -108,7 +105,9 @@ int Http2DownstreamConnection::attach_downstream(Downstream *downstream) {
auto &req = downstream_->request(); auto &req = downstream_->request();
// HTTP/2 disables HTTP Upgrade. // HTTP/2 disables HTTP Upgrade.
req.upgrade_request = false; if (req.method != HTTP_CONNECT) {
req.upgrade_request = false;
}
return 0; return 0;
} }
@ -442,7 +441,8 @@ int Http2DownstreamConnection::push_request_headers() {
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
std::stringstream ss; std::stringstream ss;
for (auto &nv : nva) { for (auto &nv : nva) {
ss << TTY_HTTP_HD << nv.name << TTY_RST << ": " << nv.value << "\n"; ss << TTY_HTTP_HD << StringRef{nv.name, nv.namelen} << TTY_RST << ": "
<< StringRef{nv.value, nv.valuelen} << "\n";
} }
DCLOG(INFO, this) << "HTTP request headers\n" << ss.str(); DCLOG(INFO, this) << "HTTP request headers\n" << ss.str();
} }

View File

@ -165,6 +165,22 @@ void writecb(struct ev_loop *loop, ev_io *w, int revents) {
} }
} // namespace } // namespace
namespace {
void initiate_connection_cb(struct ev_loop *loop, ev_timer *w, int revents) {
auto http2session = static_cast<Http2Session *>(w->data);
ev_timer_stop(loop, w);
if (http2session->initiate_connection() != 0) {
if (LOG_ENABLED(INFO)) {
SSLOG(INFO, http2session) << "Could not initiate backend connection";
}
http2session->disconnect(true);
assert(http2session->get_num_dconns() == 0);
delete http2session;
return;
}
}
} // namespace
Http2Session::Http2Session(struct ev_loop *loop, SSL_CTX *ssl_ctx, Http2Session::Http2Session(struct ev_loop *loop, SSL_CTX *ssl_ctx,
Worker *worker, DownstreamAddrGroup *group) Worker *worker, DownstreamAddrGroup *group)
: dlnext(nullptr), : dlnext(nullptr),
@ -199,6 +215,9 @@ Http2Session::Http2Session(struct ev_loop *loop, SSL_CTX *ssl_ctx,
ev_timer_init(&settings_timer_, settings_timeout_cb, 0., 10.); ev_timer_init(&settings_timer_, settings_timeout_cb, 0., 10.);
settings_timer_.data = this; settings_timer_.data = this;
ev_timer_init(&initiate_connection_timer_, initiate_connection_cb, 0., 0.);
initiate_connection_timer_.data = this;
} }
Http2Session::~Http2Session() { Http2Session::~Http2Session() {
@ -224,6 +243,7 @@ int Http2Session::disconnect(bool hard) {
conn_.rlimit.stopw(); conn_.rlimit.stopw();
conn_.wlimit.stopw(); conn_.wlimit.stopw();
ev_timer_stop(conn_.loop, &initiate_connection_timer_);
ev_timer_stop(conn_.loop, &settings_timer_); ev_timer_stop(conn_.loop, &settings_timer_);
ev_timer_stop(conn_.loop, &connchk_timer_); ev_timer_stop(conn_.loop, &connchk_timer_);
@ -1600,14 +1620,15 @@ int Http2Session::downstream_write() {
void Http2Session::signal_write() { void Http2Session::signal_write() {
switch (state_) { switch (state_) {
case Http2Session::DISCONNECTED: case Http2Session::DISCONNECTED:
if (LOG_ENABLED(INFO)) { if (!ev_is_active(&initiate_connection_timer_)) {
LOG(INFO) << "Start connecting to backend server";
}
if (initiate_connection() != 0) {
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
SSLOG(INFO, this) << "Could not initiate backend connection"; LOG(INFO) << "Start connecting to backend server";
} }
disconnect(true); // Since the timer is set to 0., these will feed 2 events. We
// will stop the timer in the initiate_connection_timer_ to void
// 2nd event.
ev_timer_start(conn_.loop, &initiate_connection_timer_);
ev_feed_event(conn_.loop, &initiate_connection_timer_, 0);
} }
break; break;
case Http2Session::CONNECTED: case Http2Session::CONNECTED:

View File

@ -211,6 +211,8 @@ private:
// connection check has started, this timer is started again and // connection check has started, this timer is started again and
// traps PING ACK timeout. // traps PING ACK timeout.
ev_timer connchk_timer_; ev_timer connchk_timer_;
// timer to initiate connection. usually, this fires immediately.
ev_timer initiate_connection_timer_;
DList<Http2DownstreamConnection> dconns_; DList<Http2DownstreamConnection> dconns_;
DList<StreamData> streams_; DList<StreamData> streams_;
std::function<int(Http2Session &)> read_, write_; std::function<int(Http2Session &)> read_, write_;

View File

@ -1687,7 +1687,8 @@ void Http2Upstream::log_response_headers(
Downstream *downstream, const std::vector<nghttp2_nv> &nva) const { Downstream *downstream, const std::vector<nghttp2_nv> &nva) const {
std::stringstream ss; std::stringstream ss;
for (auto &nv : nva) { for (auto &nv : nva) {
ss << TTY_HTTP_HD << nv.name << TTY_RST << ": " << nv.value << "\n"; ss << TTY_HTTP_HD << StringRef{nv.name, nv.namelen} << TTY_RST << ": "
<< StringRef{nv.value, nv.valuelen} << "\n";
} }
ULOG(INFO, this) << "HTTP response headers. stream_id=" ULOG(INFO, this) << "HTTP response headers. stream_id="
<< downstream->get_stream_id() << "\n" << ss.str(); << downstream->get_stream_id() << "\n" << ss.str();
@ -1860,7 +1861,8 @@ int Http2Upstream::submit_push_promise(const StringRef &scheme,
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
std::stringstream ss; std::stringstream ss;
for (auto &nv : nva) { for (auto &nv : nva) {
ss << TTY_HTTP_HD << nv.name << TTY_RST << ": " << nv.value << "\n"; ss << TTY_HTTP_HD << StringRef{nv.name, nv.namelen} << TTY_RST << ": "
<< StringRef{nv.value, nv.valuelen} << "\n";
} }
ULOG(INFO, this) << "HTTP push request headers. promised_stream_id=" ULOG(INFO, this) << "HTTP push request headers. promised_stream_id="
<< promised_stream_id << "\n" << ss.str(); << promised_stream_id << "\n" << ss.str();