Compare commits
8 Commits
Author | SHA1 | Date |
---|---|---|
Tatsuhiro Tsujikawa | 5563a0bea6 | |
Tatsuhiro Tsujikawa | 5952f071da | |
Tatsuhiro Tsujikawa | 5a7486164f | |
Tatsuhiro Tsujikawa | c8395edfbe | |
Tatsuhiro Tsujikawa | 3bff503a16 | |
Tatsuhiro Tsujikawa | 7a0ab83107 | |
Tatsuhiro Tsujikawa | 026919b7ea | |
Tatsuhiro Tsujikawa | 64d7288428 |
|
@ -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.7.0], [t-tujikawa@users.sourceforge.net])
|
AC_INIT([nghttp2], [1.7.1], [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])
|
||||||
|
@ -185,8 +185,8 @@ if test "x$GCC" = "xyes" -o "x$CC" = "xclang" ; then
|
||||||
AC_DEFINE([_U_], [__attribute__((unused))], [Hint to the compiler that a function parameters is not used])
|
AC_DEFINE([_U_], [__attribute__((unused))], [Hint to the compiler that a function parameters is not used])
|
||||||
AC_DEFINE([NGHTTP2_NORETURN], [__attribute__((noreturn))], [Hint to the compiler that a function never return])
|
AC_DEFINE([NGHTTP2_NORETURN], [__attribute__((noreturn))], [Hint to the compiler that a function never return])
|
||||||
else
|
else
|
||||||
AC_DEFINE([_U_], , [Hint to the compiler that a function parameters is not use AC_DEFINE([NGHTTP2_NORETURN], , [Hint to the compiler that a function never return])
|
AC_DEFINE([_U_], , [Hint to the compiler that a function parameter is not used])
|
||||||
d])
|
AC_DEFINE([NGHTTP2_NORETURN], , [Hint to the compiler that a function never return])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AX_CXX_COMPILE_STDCXX_11([noext], [optional])
|
AX_CXX_COMPILE_STDCXX_11([noext], [optional])
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
.\" Man page generated from reStructuredText.
|
.\" Man page generated from reStructuredText.
|
||||||
.
|
.
|
||||||
.TH "H2LOAD" "1" "January 25, 2016" "1.7.0" "nghttp2"
|
.TH "H2LOAD" "1" "February 11, 2016" "1.7.1" "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" "January 25, 2016" "1.7.0" "nghttp2"
|
.TH "NGHTTP" "1" "February 11, 2016" "1.7.1" "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" "January 25, 2016" "1.7.0" "nghttp2"
|
.TH "NGHTTPD" "1" "February 11, 2016" "1.7.1" "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" "January 25, 2016" "1.7.0" "nghttp2"
|
.TH "NGHTTPX" "1" "February 11, 2016" "1.7.1" "nghttp2"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
nghttpx \- HTTP/2 proxy
|
nghttpx \- HTTP/2 proxy
|
||||||
.
|
.
|
||||||
|
|
|
@ -1608,6 +1608,14 @@ typedef int (*nghttp2_on_begin_headers_callback)(nghttp2_session *session,
|
||||||
*
|
*
|
||||||
* To set this callback to :type:`nghttp2_session_callbacks`, use
|
* To set this callback to :type:`nghttp2_session_callbacks`, use
|
||||||
* `nghttp2_session_callbacks_set_on_header_callback()`.
|
* `nghttp2_session_callbacks_set_on_header_callback()`.
|
||||||
|
*
|
||||||
|
* .. warning::
|
||||||
|
*
|
||||||
|
* Application should properly limit the total buffer size to store
|
||||||
|
* incoming header fields. Without it, peer may send large number
|
||||||
|
* of header fields or large header fields to cause out of memory in
|
||||||
|
* local endpoint. Due to how HPACK works, peer can do this
|
||||||
|
* effectively without using much memory on their own.
|
||||||
*/
|
*/
|
||||||
typedef int (*nghttp2_on_header_callback)(nghttp2_session *session,
|
typedef int (*nghttp2_on_header_callback)(nghttp2_session *session,
|
||||||
const nghttp2_frame *frame,
|
const nghttp2_frame *frame,
|
||||||
|
|
|
@ -425,7 +425,7 @@ void release_fd_cb(struct ev_loop *loop, ev_timer *w, int revents) {
|
||||||
|
|
||||||
Stream::Stream(Http2Handler *handler, int32_t stream_id)
|
Stream::Stream(Http2Handler *handler, int32_t stream_id)
|
||||||
: handler(handler), file_ent(nullptr), body_length(0), body_offset(0),
|
: handler(handler), file_ent(nullptr), body_length(0), body_offset(0),
|
||||||
stream_id(stream_id), echo_upload(false) {
|
header_buffer_size(0), stream_id(stream_id), echo_upload(false) {
|
||||||
auto config = handler->get_config();
|
auto config = handler->get_config();
|
||||||
ev_timer_init(&rtimer, stream_timeout_cb, 0., config->stream_read_timeout);
|
ev_timer_init(&rtimer, stream_timeout_cb, 0., config->stream_read_timeout);
|
||||||
ev_timer_init(&wtimer, stream_timeout_cb, 0., config->stream_write_timeout);
|
ev_timer_init(&wtimer, stream_timeout_cb, 0., config->stream_write_timeout);
|
||||||
|
@ -1316,6 +1316,13 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stream->header_buffer_size + namelen + valuelen > 64_k) {
|
||||||
|
hd->submit_rst_stream(stream, NGHTTP2_INTERNAL_ERROR);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream->header_buffer_size += namelen + valuelen;
|
||||||
|
|
||||||
auto token = http2::lookup_token(name, namelen);
|
auto token = http2::lookup_token(name, namelen);
|
||||||
|
|
||||||
http2::index_header(stream->hdidx, token, stream->headers.size());
|
http2::index_header(stream->hdidx, token, stream->headers.size());
|
||||||
|
|
|
@ -110,6 +110,9 @@ struct Stream {
|
||||||
ev_timer wtimer;
|
ev_timer wtimer;
|
||||||
int64_t body_length;
|
int64_t body_length;
|
||||||
int64_t body_offset;
|
int64_t body_offset;
|
||||||
|
// Total amount of bytes (sum of name and value length) used in
|
||||||
|
// headers.
|
||||||
|
size_t header_buffer_size;
|
||||||
int32_t stream_id;
|
int32_t stream_id;
|
||||||
http2::HeaderIndex hdidx;
|
http2::HeaderIndex hdidx;
|
||||||
bool echo_upload;
|
bool echo_upload;
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace nghttp2 {
|
||||||
namespace asio_http2 {
|
namespace asio_http2 {
|
||||||
namespace client {
|
namespace client {
|
||||||
|
|
||||||
request_impl::request_impl() : strm_(nullptr) {}
|
request_impl::request_impl() : strm_(nullptr), header_buffer_size_(0) {}
|
||||||
|
|
||||||
void request_impl::write_trailer(header_map h) {
|
void request_impl::write_trailer(header_map h) {
|
||||||
auto sess = strm_->session();
|
auto sess = strm_->session();
|
||||||
|
@ -105,6 +105,12 @@ void request_impl::method(std::string s) { method_ = std::move(s); }
|
||||||
|
|
||||||
const std::string &request_impl::method() const { return method_; }
|
const std::string &request_impl::method() const { return method_; }
|
||||||
|
|
||||||
|
size_t request_impl::header_buffer_size() const { return header_buffer_size_; }
|
||||||
|
|
||||||
|
void request_impl::update_header_buffer_size(size_t len) {
|
||||||
|
header_buffer_size_ += len;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace client
|
} // namespace client
|
||||||
} // namespace asio_http2
|
} // namespace asio_http2
|
||||||
} // namespace nghttp2
|
} // namespace nghttp2
|
||||||
|
|
|
@ -75,6 +75,9 @@ public:
|
||||||
void method(std::string s);
|
void method(std::string s);
|
||||||
const std::string &method() const;
|
const std::string &method() const;
|
||||||
|
|
||||||
|
size_t header_buffer_size() const;
|
||||||
|
void update_header_buffer_size(size_t len);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
header_map header_;
|
header_map header_;
|
||||||
response_cb response_cb_;
|
response_cb response_cb_;
|
||||||
|
@ -84,6 +87,7 @@ private:
|
||||||
class stream *strm_;
|
class stream *strm_;
|
||||||
uri_ref uri_;
|
uri_ref uri_;
|
||||||
std::string method_;
|
std::string method_;
|
||||||
|
size_t header_buffer_size_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace client
|
} // namespace client
|
||||||
|
|
|
@ -30,7 +30,8 @@ namespace nghttp2 {
|
||||||
namespace asio_http2 {
|
namespace asio_http2 {
|
||||||
namespace client {
|
namespace client {
|
||||||
|
|
||||||
response_impl::response_impl() : content_length_(-1), status_code_(0) {}
|
response_impl::response_impl()
|
||||||
|
: content_length_(-1), header_buffer_size_(0), status_code_(0) {}
|
||||||
|
|
||||||
void response_impl::on_data(data_cb cb) { data_cb_ = std::move(cb); }
|
void response_impl::on_data(data_cb cb) { data_cb_ = std::move(cb); }
|
||||||
|
|
||||||
|
@ -52,6 +53,12 @@ header_map &response_impl::header() { return header_; }
|
||||||
|
|
||||||
const header_map &response_impl::header() const { return header_; }
|
const header_map &response_impl::header() const { return header_; }
|
||||||
|
|
||||||
|
size_t response_impl::header_buffer_size() const { return header_buffer_size_; }
|
||||||
|
|
||||||
|
void response_impl::update_header_buffer_size(size_t len) {
|
||||||
|
header_buffer_size_ += len;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace client
|
} // namespace client
|
||||||
} // namespace asio_http2
|
} // namespace asio_http2
|
||||||
} // namespace nghttp2
|
} // namespace nghttp2
|
||||||
|
|
|
@ -53,12 +53,16 @@ public:
|
||||||
header_map &header();
|
header_map &header();
|
||||||
const header_map &header() const;
|
const header_map &header() const;
|
||||||
|
|
||||||
|
size_t header_buffer_size() const;
|
||||||
|
void update_header_buffer_size(size_t len);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
data_cb data_cb_;
|
data_cb data_cb_;
|
||||||
|
|
||||||
header_map header_;
|
header_map header_;
|
||||||
|
|
||||||
int64_t content_length_;
|
int64_t content_length_;
|
||||||
|
size_t header_buffer_size_;
|
||||||
int status_code_;
|
int status_code_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -174,6 +174,12 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
|
||||||
if (token == http2::HD__STATUS) {
|
if (token == http2::HD__STATUS) {
|
||||||
res.status_code(util::parse_uint(value, valuelen));
|
res.status_code(util::parse_uint(value, valuelen));
|
||||||
} else {
|
} else {
|
||||||
|
if (res.header_buffer_size() + namelen + valuelen > 64_k) {
|
||||||
|
nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
|
||||||
|
frame->hd.stream_id, NGHTTP2_INTERNAL_ERROR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
res.update_header_buffer_size(namelen + valuelen);
|
||||||
|
|
||||||
if (token == http2::HD_CONTENT_LENGTH) {
|
if (token == http2::HD_CONTENT_LENGTH) {
|
||||||
res.content_length(util::parse_uint(value, valuelen));
|
res.content_length(util::parse_uint(value, valuelen));
|
||||||
|
@ -214,6 +220,13 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
default:
|
default:
|
||||||
|
if (req.header_buffer_size() + namelen + valuelen > 64_k) {
|
||||||
|
nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
|
||||||
|
frame->hd.stream_id, NGHTTP2_INTERNAL_ERROR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
req.update_header_buffer_size(namelen + valuelen);
|
||||||
|
|
||||||
req.header().emplace(
|
req.header().emplace(
|
||||||
std::string(name, name + namelen),
|
std::string(name, name + namelen),
|
||||||
header_value{std::string(value, value + valuelen),
|
header_value{std::string(value, value + valuelen),
|
||||||
|
|
|
@ -105,6 +105,13 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
|
||||||
}
|
}
|
||||||
// fall through
|
// fall through
|
||||||
default:
|
default:
|
||||||
|
if (req.header_buffer_size() + namelen + valuelen > 64_k) {
|
||||||
|
nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, frame->hd.stream_id,
|
||||||
|
NGHTTP2_INTERNAL_ERROR);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
req.update_header_buffer_size(namelen + valuelen);
|
||||||
|
|
||||||
req.header().emplace(std::string(name, name + namelen),
|
req.header().emplace(std::string(name, name + namelen),
|
||||||
header_value{std::string(value, value + valuelen),
|
header_value{std::string(value, value + valuelen),
|
||||||
(flags & NGHTTP2_NV_FLAG_NO_INDEX) != 0});
|
(flags & NGHTTP2_NV_FLAG_NO_INDEX) != 0});
|
||||||
|
|
|
@ -28,7 +28,7 @@ namespace nghttp2 {
|
||||||
namespace asio_http2 {
|
namespace asio_http2 {
|
||||||
namespace server {
|
namespace server {
|
||||||
|
|
||||||
request_impl::request_impl() : strm_(nullptr) {}
|
request_impl::request_impl() : strm_(nullptr), header_buffer_size_(0) {}
|
||||||
|
|
||||||
const header_map &request_impl::header() const { return header_; }
|
const header_map &request_impl::header() const { return header_; }
|
||||||
|
|
||||||
|
@ -62,6 +62,12 @@ void request_impl::remote_endpoint(boost::asio::ip::tcp::endpoint ep) {
|
||||||
remote_ep_ = std::move(ep);
|
remote_ep_ = std::move(ep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t request_impl::header_buffer_size() const { return header_buffer_size_; }
|
||||||
|
|
||||||
|
void request_impl::update_header_buffer_size(size_t len) {
|
||||||
|
header_buffer_size_ += len;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace server
|
} // namespace server
|
||||||
} // namespace asio_http2
|
} // namespace asio_http2
|
||||||
} // namespace nghttp2
|
} // namespace nghttp2
|
||||||
|
|
|
@ -58,6 +58,9 @@ public:
|
||||||
const boost::asio::ip::tcp::endpoint &remote_endpoint() const;
|
const boost::asio::ip::tcp::endpoint &remote_endpoint() const;
|
||||||
void remote_endpoint(boost::asio::ip::tcp::endpoint ep);
|
void remote_endpoint(boost::asio::ip::tcp::endpoint ep);
|
||||||
|
|
||||||
|
size_t header_buffer_size() const;
|
||||||
|
void update_header_buffer_size(size_t len);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class stream *strm_;
|
class stream *strm_;
|
||||||
header_map header_;
|
header_map header_;
|
||||||
|
@ -65,6 +68,7 @@ private:
|
||||||
uri_ref uri_;
|
uri_ref uri_;
|
||||||
data_cb on_data_cb_;
|
data_cb on_data_cb_;
|
||||||
boost::asio::ip::tcp::endpoint remote_ep_;
|
boost::asio::ip::tcp::endpoint remote_ep_;
|
||||||
|
size_t header_buffer_size_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace server
|
} // namespace server
|
||||||
|
|
|
@ -135,8 +135,8 @@ Request::Request(const std::string &uri, const http_parser_url &u,
|
||||||
const nghttp2_priority_spec &pri_spec, int level)
|
const nghttp2_priority_spec &pri_spec, int level)
|
||||||
: uri(uri), u(u), pri_spec(pri_spec), data_length(data_length),
|
: uri(uri), u(u), pri_spec(pri_spec), data_length(data_length),
|
||||||
data_offset(0), response_len(0), inflater(nullptr), html_parser(nullptr),
|
data_offset(0), response_len(0), inflater(nullptr), html_parser(nullptr),
|
||||||
data_prd(data_prd), stream_id(-1), status(0), level(level),
|
data_prd(data_prd), header_buffer_size(0), stream_id(-1), status(0),
|
||||||
expect_final_response(false) {
|
level(level), expect_final_response(false) {
|
||||||
http2::init_hdidx(res_hdidx);
|
http2::init_hdidx(res_hdidx);
|
||||||
http2::init_hdidx(req_hdidx);
|
http2::init_hdidx(req_hdidx);
|
||||||
}
|
}
|
||||||
|
@ -1704,6 +1704,14 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (req->header_buffer_size + namelen + valuelen > 64_k) {
|
||||||
|
nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, frame->hd.stream_id,
|
||||||
|
NGHTTP2_INTERNAL_ERROR);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
req->header_buffer_size += namelen + valuelen;
|
||||||
|
|
||||||
auto token = http2::lookup_token(name, namelen);
|
auto token = http2::lookup_token(name, namelen);
|
||||||
|
|
||||||
http2::index_header(req->res_hdidx, token, req->res_nva.size());
|
http2::index_header(req->res_hdidx, token, req->res_nva.size());
|
||||||
|
@ -1719,6 +1727,15 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (req->header_buffer_size + namelen + valuelen > 64_k) {
|
||||||
|
nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
|
||||||
|
frame->push_promise.promised_stream_id,
|
||||||
|
NGHTTP2_INTERNAL_ERROR);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
req->header_buffer_size += namelen + valuelen;
|
||||||
|
|
||||||
auto token = http2::lookup_token(name, namelen);
|
auto token = http2::lookup_token(name, namelen);
|
||||||
|
|
||||||
http2::index_header(req->req_hdidx, token, req->req_nva.size());
|
http2::index_header(req->req_hdidx, token, req->req_nva.size());
|
||||||
|
@ -1806,6 +1823,10 @@ int on_frame_recv_callback2(nghttp2_session *session,
|
||||||
if (!req) {
|
if (!req) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset for response header field reception
|
||||||
|
req->header_buffer_size = 0;
|
||||||
|
|
||||||
auto scheme = req->get_req_header(http2::HD__SCHEME);
|
auto scheme = req->get_req_header(http2::HD__SCHEME);
|
||||||
auto authority = req->get_req_header(http2::HD__AUTHORITY);
|
auto authority = req->get_req_header(http2::HD__AUTHORITY);
|
||||||
auto path = req->get_req_header(http2::HD__PATH);
|
auto path = req->get_req_header(http2::HD__PATH);
|
||||||
|
|
|
@ -150,6 +150,7 @@ struct Request {
|
||||||
nghttp2_gzip *inflater;
|
nghttp2_gzip *inflater;
|
||||||
HtmlParser *html_parser;
|
HtmlParser *html_parser;
|
||||||
const nghttp2_data_provider *data_prd;
|
const nghttp2_data_provider *data_prd;
|
||||||
|
size_t header_buffer_size;
|
||||||
int32_t stream_id;
|
int32_t stream_id;
|
||||||
int status;
|
int status;
|
||||||
// Recursion level: 0: first entity, 1: entity linked from first entity
|
// Recursion level: 0: first entity, 1: entity linked from first entity
|
||||||
|
|
Loading…
Reference in New Issue