Compare commits

..

12 Commits

Author SHA1 Message Date
Tatsuhiro Tsujikawa
8585599b4b nghttpx: Add doc 2015-07-16 00:03:34 +09:00
Tatsuhiro Tsujikawa
2bac00ea5f nghttpx: Add additional assert just in case 2015-07-16 00:01:26 +09:00
Tatsuhiro Tsujikawa
3396c71c3c Update man pages 2015-07-15 23:48:41 +09:00
Tatsuhiro Tsujikawa
f821f6bd80 Bump up version number to 1.1.1 2015-07-15 23:46:22 +09:00
Tatsuhiro Tsujikawa
7a3012cc1b src: Rename timegm as nghttp2_timegm 2015-07-15 23:44:24 +09:00
Tatsuhiro Tsujikawa
ba31b990a2 nghttpx: Remove dead handling of Downstream::STREAM_CLOSED 2015-07-15 23:33:44 +09:00
Tatsuhiro Tsujikawa
fc062976a1 nghttpx: Delete DownstreamConnection from Downstream explicitly 2015-07-15 23:31:32 +09:00
Tatsuhiro Tsujikawa
20e63151a5 nghttpx: Fix bug that idle timer is used after reuse 2015-07-15 23:18:32 +09:00
Tatsuhiro Tsujikawa
e63e775fea nghttpx: Simplify BlockedLink management 2015-07-15 20:44:44 +09:00
Tatsuhiro Tsujikawa
031fb31248 nghttpx: Fix memory leak, and blocked stream dispatch 2015-07-15 19:47:15 +09:00
Tatsuhiro Tsujikawa
6d10799301 nghttpx: Don't pool failed HTTP/1 backend connection 2015-07-15 19:46:48 +09:00
Tatsuhiro Tsujikawa
f54745fe4c Bump up version number to 1.1.1-DEV 2015-07-15 01:29:57 +09:00
15 changed files with 48 additions and 107 deletions

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.1.0], [t-tujikawa@users.sourceforge.net]) AC_INIT([nghttp2], [1.1.1], [t-tujikawa@users.sourceforge.net])
AC_USE_SYSTEM_EXTENSIONS AC_USE_SYSTEM_EXTENSIONS
LT_PREREQ([2.2.6]) LT_PREREQ([2.2.6])

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText. .\" Man page generated from reStructuredText.
. .
.TH "H2LOAD" "1" "July 15, 2015" "1.1.0" "nghttp2" .TH "H2LOAD" "1" "July 15, 2015" "1.1.1" "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" "July 15, 2015" "1.1.0" "nghttp2" .TH "NGHTTP" "1" "July 15, 2015" "1.1.1" "nghttp2"
.SH NAME .SH NAME
nghttp \- HTTP/2 experimental client nghttp \- HTTP/2 experimental client
. .

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText. .\" Man page generated from reStructuredText.
. .
.TH "NGHTTPD" "1" "July 15, 2015" "1.1.0" "nghttp2" .TH "NGHTTPD" "1" "July 15, 2015" "1.1.1" "nghttp2"
.SH NAME .SH NAME
nghttpd \- HTTP/2 experimental server nghttpd \- HTTP/2 experimental server
. .

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText. .\" Man page generated from reStructuredText.
. .
.TH "NGHTTPX" "1" "July 15, 2015" "1.1.0" "nghttp2" .TH "NGHTTPX" "1" "July 15, 2015" "1.1.1" "nghttp2"
.SH NAME .SH NAME
nghttpx \- HTTP/2 experimental proxy nghttpx \- HTTP/2 experimental proxy
. .

View File

@@ -152,10 +152,6 @@ Downstream::~Downstream() {
DLOG(INFO, this) << "Deleting"; DLOG(INFO, this) << "Deleting";
} }
if (blocked_link_) {
detach_blocked_link(blocked_link_);
}
// check nullptr for unittest // check nullptr for unittest
if (upstream_) { if (upstream_) {
auto loop = upstream_->get_client_handler()->get_loop(); auto loop = upstream_->get_client_handler()->get_loop();
@@ -166,6 +162,10 @@ Downstream::~Downstream() {
ev_timer_stop(loop, &downstream_wtimer_); ev_timer_stop(loop, &downstream_wtimer_);
} }
// DownstreamConnection may refer to this object. Delete it now
// explicitly.
dconn_.reset();
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
DLOG(INFO, this) << "Deleted"; DLOG(INFO, this) << "Deleted";
} }
@@ -195,8 +195,6 @@ void Downstream::detach_downstream_connection() {
std::unique_ptr<DownstreamConnection>(dconn_.release())); std::unique_ptr<DownstreamConnection>(dconn_.release()));
} }
void Downstream::release_downstream_connection() { dconn_.release(); }
DownstreamConnection *Downstream::get_downstream_connection() { DownstreamConnection *Downstream::get_downstream_connection() {
return dconn_.get(); return dconn_.get();
} }
@@ -1200,12 +1198,10 @@ void Downstream::attach_blocked_link(BlockedLink *l) {
blocked_link_ = l; blocked_link_ = l;
} }
void Downstream::detach_blocked_link(BlockedLink *l) { BlockedLink *Downstream::detach_blocked_link() {
assert(blocked_link_); auto link = blocked_link_;
assert(l->downstream == this);
l->downstream = nullptr;
blocked_link_ = nullptr; blocked_link_ = nullptr;
return link;
} }
void Downstream::add_request_headers_sum(size_t amount) { void Downstream::add_request_headers_sum(size_t amount) {

View File

@@ -69,8 +69,6 @@ public:
int attach_downstream_connection(std::unique_ptr<DownstreamConnection> dconn); int attach_downstream_connection(std::unique_ptr<DownstreamConnection> dconn);
void detach_downstream_connection(); void detach_downstream_connection();
// Releases dconn_, without freeing it.
void release_downstream_connection();
DownstreamConnection *get_downstream_connection(); DownstreamConnection *get_downstream_connection();
// Returns dconn_ and nullifies dconn_. // Returns dconn_ and nullifies dconn_.
std::unique_ptr<DownstreamConnection> pop_downstream_connection(); std::unique_ptr<DownstreamConnection> pop_downstream_connection();
@@ -332,7 +330,7 @@ public:
void set_dispatch_state(int s); void set_dispatch_state(int s);
void attach_blocked_link(BlockedLink *l); void attach_blocked_link(BlockedLink *l);
void detach_blocked_link(BlockedLink *l); BlockedLink *detach_blocked_link();
enum { enum {
EVENT_ERROR = 0x1, EVENT_ERROR = 0x1,

View File

@@ -124,17 +124,21 @@ Downstream *DownstreamQueue::remove_and_get_blocked(Downstream *downstream) {
// Delete downstream when this function returns. // Delete downstream when this function returns.
auto delptr = std::unique_ptr<Downstream>(downstream); auto delptr = std::unique_ptr<Downstream>(downstream);
if (downstream->get_dispatch_state() != Downstream::DISPATCH_ACTIVE) {
assert(downstream->get_dispatch_state() != Downstream::DISPATCH_NONE);
downstreams_.remove(downstream);
return nullptr;
}
downstreams_.remove(downstream); downstreams_.remove(downstream);
auto &host = make_host_key(downstream); auto &host = make_host_key(downstream);
auto &ent = find_host_entry(host); auto &ent = find_host_entry(host);
--ent.num_active;
if (downstream->get_dispatch_state() == Downstream::DISPATCH_ACTIVE) {
--ent.num_active;
} else {
// For those downstreams deleted while in blocked state
auto link = downstream->detach_blocked_link();
if (link) {
ent.blocked.remove(link);
delete link;
}
}
if (remove_host_entry_if_empty(ent, host_entries_, host)) { if (remove_host_entry_if_empty(ent, host_entries_, host)) {
return nullptr; return nullptr;
@@ -144,21 +148,20 @@ Downstream *DownstreamQueue::remove_and_get_blocked(Downstream *downstream) {
return nullptr; return nullptr;
} }
for (auto link = ent.blocked.head; link;) { auto link = ent.blocked.head;
auto next = link->dlnext;
if (!link->downstream) { if (!link) {
ent.blocked.remove(link); return nullptr;
link = next;
continue;
}
auto next_downstream = link->downstream;
next_downstream->detach_blocked_link(link);
ent.blocked.remove(link);
delete link;
remove_host_entry_if_empty(ent, host_entries_, host);
return next_downstream;
} }
return nullptr;
auto next_downstream = link->downstream;
auto link2 = next_downstream->detach_blocked_link();
assert(link2 == link);
ent.blocked.remove(link);
delete link;
remove_host_entry_if_empty(ent, host_entries_, host);
return next_downstream;
} }
Downstream *DownstreamQueue::get_downstreams() const { Downstream *DownstreamQueue::get_downstreams() const {

View File

@@ -86,11 +86,7 @@ Http2DownstreamConnection::~Http2DownstreamConnection() {
} }
} }
http2session_->remove_downstream_connection(this); http2session_->remove_downstream_connection(this);
// Downstream and DownstreamConnection may be deleted
// asynchronously.
if (downstream_) {
downstream_->release_downstream_connection();
}
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
DCLOG(INFO, this) << "Deleted"; DCLOG(INFO, this) << "Deleted";
} }

View File

@@ -884,16 +884,6 @@ ClientHandler *Http2Upstream::get_client_handler() const { return handler_; }
int Http2Upstream::downstream_read(DownstreamConnection *dconn) { int Http2Upstream::downstream_read(DownstreamConnection *dconn) {
auto downstream = dconn->get_downstream(); auto downstream = dconn->get_downstream();
if (downstream->get_request_state() == Downstream::STREAM_CLOSED) {
// If upstream HTTP2 stream was closed, we just close downstream,
// because there is no consumer now. Downstream connection is also
// closed in this case.
remove_downstream(downstream);
// downstream was deleted
return 0;
}
if (downstream->get_response_state() == Downstream::MSG_RESET) { if (downstream->get_response_state() == Downstream::MSG_RESET) {
// The downstream stream was reset (canceled). In this case, // The downstream stream was reset (canceled). In this case,
// RST_STREAM to the upstream and delete downstream connection // RST_STREAM to the upstream and delete downstream connection
@@ -959,14 +949,6 @@ int Http2Upstream::downstream_eof(DownstreamConnection *dconn) {
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
DCLOG(INFO, dconn) << "EOF. stream_id=" << downstream->get_stream_id(); DCLOG(INFO, dconn) << "EOF. stream_id=" << downstream->get_stream_id();
} }
if (downstream->get_request_state() == Downstream::STREAM_CLOSED) {
// If stream was closed already, we don't need to send reply at
// the first place. We can delete downstream.
remove_downstream(downstream);
// downstream was deleted
return 0;
}
// Delete downstream connection. If we don't delete it here, it will // Delete downstream connection. If we don't delete it here, it will
// be pooled in on_stream_close_callback. // be pooled in on_stream_close_callback.
@@ -1012,13 +994,6 @@ int Http2Upstream::downstream_error(DownstreamConnection *dconn, int events) {
} }
} }
if (downstream->get_request_state() == Downstream::STREAM_CLOSED) {
remove_downstream(downstream);
// downstream was deleted
return 0;
}
// Delete downstream connection. If we don't delete it here, it will // Delete downstream connection. If we don't delete it here, it will
// be pooled in on_stream_close_callback. // be pooled in on_stream_close_callback.
downstream->pop_downstream_connection(); downstream->pop_downstream_connection();

View File

@@ -118,13 +118,7 @@ HttpDownstreamConnection::HttpDownstreamConnection(
ioctrl_(&conn_.rlimit), response_htp_{0}, group_(group), addr_idx_(0), ioctrl_(&conn_.rlimit), response_htp_{0}, group_(group), addr_idx_(0),
connected_(false) {} connected_(false) {}
HttpDownstreamConnection::~HttpDownstreamConnection() { HttpDownstreamConnection::~HttpDownstreamConnection() {}
// Downstream and DownstreamConnection may be deleted
// asynchronously.
if (downstream_) {
downstream_->release_downstream_connection();
}
}
int HttpDownstreamConnection::attach_downstream(Downstream *downstream) { int HttpDownstreamConnection::attach_downstream(Downstream *downstream) {
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
@@ -205,6 +199,8 @@ int HttpDownstreamConnection::attach_downstream(Downstream *downstream) {
ev_set_cb(&conn_.rev, readcb); ev_set_cb(&conn_.rev, readcb);
conn_.rt.repeat = get_config()->downstream_read_timeout; conn_.rt.repeat = get_config()->downstream_read_timeout;
// we may set read timer cb to idle_timeoutcb. Reset again.
ev_set_cb(&conn_.rt, timeoutcb);
ev_timer_again(conn_.loop, &conn_.rt); ev_timer_again(conn_.loop, &conn_.rt);
// TODO we should have timeout for connection establishment // TODO we should have timeout for connection establishment
ev_timer_again(conn_.loop, &conn_.wt); ev_timer_again(conn_.loop, &conn_.wt);
@@ -864,6 +860,8 @@ int HttpDownstreamConnection::on_connect() {
DLOG(INFO, this) << "downstream connect failed"; DLOG(INFO, this) << "downstream connect failed";
} }
downstream_->set_request_state(Downstream::CONNECT_FAIL);
return -1; return -1;
} }

View File

@@ -560,16 +560,6 @@ ClientHandler *SpdyUpstream::get_client_handler() const { return handler_; }
int SpdyUpstream::downstream_read(DownstreamConnection *dconn) { int SpdyUpstream::downstream_read(DownstreamConnection *dconn) {
auto downstream = dconn->get_downstream(); auto downstream = dconn->get_downstream();
if (downstream->get_request_state() == Downstream::STREAM_CLOSED) {
// If upstream SPDY stream was closed, we just close downstream,
// because there is no consumer now. Downstream connection is also
// closed in this case.
remove_downstream(downstream);
// downstrea was deleted
return 0;
}
if (downstream->get_response_state() == Downstream::MSG_RESET) { if (downstream->get_response_state() == Downstream::MSG_RESET) {
// The downstream stream was reset (canceled). In this case, // The downstream stream was reset (canceled). In this case,
// RST_STREAM to the upstream and delete downstream connection // RST_STREAM to the upstream and delete downstream connection
@@ -633,14 +623,6 @@ int SpdyUpstream::downstream_eof(DownstreamConnection *dconn) {
if (LOG_ENABLED(INFO)) { if (LOG_ENABLED(INFO)) {
DCLOG(INFO, dconn) << "EOF. stream_id=" << downstream->get_stream_id(); DCLOG(INFO, dconn) << "EOF. stream_id=" << downstream->get_stream_id();
} }
if (downstream->get_request_state() == Downstream::STREAM_CLOSED) {
// If stream was closed already, we don't need to send reply at
// the first place. We can delete downstream.
remove_downstream(downstream);
// downstream was deleted
return 0;
}
// Delete downstream connection. If we don't delete it here, it will // Delete downstream connection. If we don't delete it here, it will
// be pooled in on_stream_close_callback. // be pooled in on_stream_close_callback.
@@ -686,13 +668,6 @@ int SpdyUpstream::downstream_error(DownstreamConnection *dconn, int events) {
} }
} }
if (downstream->get_request_state() == Downstream::STREAM_CLOSED) {
remove_downstream(downstream);
// downstream was deleted
return 0;
}
// Delete downstream connection. If we don't delete it here, it will // Delete downstream connection. If we don't delete it here, it will
// be pooled in on_stream_close_callback. // be pooled in on_stream_close_callback.
downstream->pop_downstream_connection(); downstream->pop_downstream_connection();

View File

@@ -34,7 +34,7 @@ static int count_leap_year(int y) {
} }
/* Based on the algorithm of Python 2.7 calendar.timegm. */ /* Based on the algorithm of Python 2.7 calendar.timegm. */
time_t timegm(struct tm *tm) { time_t nghttp2_timegm(struct tm *tm) {
int days; int days;
int num_leap_year; int num_leap_year;
int64_t t; int64_t t;

View File

@@ -37,7 +37,7 @@ extern "C" {
#include <time.h> #include <time.h>
#endif // HAVE_TIME_H #endif // HAVE_TIME_H
time_t timegm(struct tm *tm); time_t nghttp2_timegm(struct tm *tm);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -278,7 +278,7 @@ std::string common_log_date(time_t t) {
#ifdef HAVE_STRUCT_TM_TM_GMTOFF #ifdef HAVE_STRUCT_TM_TM_GMTOFF
auto gmtoff = tms.tm_gmtoff; auto gmtoff = tms.tm_gmtoff;
#else // !HAVE_STRUCT_TM_TM_GMTOFF #else // !HAVE_STRUCT_TM_TM_GMTOFF
auto gmtoff = timegm(&tms) - t; auto gmtoff = nghttp2_timegm(&tms) - t;
#endif // !HAVE_STRUCT_TM_TM_GMTOFF #endif // !HAVE_STRUCT_TM_TM_GMTOFF
if (gmtoff >= 0) { if (gmtoff >= 0) {
*p++ = '+'; *p++ = '+';
@@ -326,7 +326,7 @@ std::string iso8601_date(int64_t ms) {
#ifdef HAVE_STRUCT_TM_TM_GMTOFF #ifdef HAVE_STRUCT_TM_TM_GMTOFF
auto gmtoff = tms.tm_gmtoff; auto gmtoff = tms.tm_gmtoff;
#else // !HAVE_STRUCT_TM_TM_GMTOFF #else // !HAVE_STRUCT_TM_TM_GMTOFF
auto gmtoff = timegm(&tms) - sec; auto gmtoff = nghttp2_timegm(&tms) - sec;
#endif // !HAVE_STRUCT_TM_TM_GMTOFF #endif // !HAVE_STRUCT_TM_TM_GMTOFF
if (gmtoff == 0) { if (gmtoff == 0) {
*p++ = 'Z'; *p++ = 'Z';
@@ -354,7 +354,7 @@ time_t parse_http_date(const std::string &s) {
if (r == 0) { if (r == 0) {
return 0; return 0;
} }
return timegm(&tm); return nghttp2_timegm(&tm);
} }
namespace { namespace {