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
|
||||
|
||||
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_MACRO_DIR([m4])
|
||||
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([NGHTTP2_NORETURN], [__attribute__((noreturn))], [Hint to the compiler that a function never return])
|
||||
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])
|
||||
d])
|
||||
AC_DEFINE([_U_], , [Hint to the compiler that a function parameter is not used])
|
||||
AC_DEFINE([NGHTTP2_NORETURN], , [Hint to the compiler that a function never return])
|
||||
fi
|
||||
|
||||
AX_CXX_COMPILE_STDCXX_11([noext], [optional])
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" 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
|
||||
h2load \- HTTP/2 benchmarking tool
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" 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
|
||||
nghttp \- HTTP/2 client
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" 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
|
||||
nghttpd \- HTTP/2 server
|
||||
.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.\" 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
|
||||
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
|
||||
* `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,
|
||||
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)
|
||||
: 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();
|
||||
ev_timer_init(&rtimer, stream_timeout_cb, 0., config->stream_read_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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
http2::index_header(stream->hdidx, token, stream->headers.size());
|
||||
|
|
|
@ -110,6 +110,9 @@ struct Stream {
|
|||
ev_timer wtimer;
|
||||
int64_t body_length;
|
||||
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;
|
||||
http2::HeaderIndex hdidx;
|
||||
bool echo_upload;
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace nghttp2 {
|
|||
namespace asio_http2 {
|
||||
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) {
|
||||
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_; }
|
||||
|
||||
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 asio_http2
|
||||
} // namespace nghttp2
|
||||
|
|
|
@ -75,6 +75,9 @@ public:
|
|||
void method(std::string s);
|
||||
const std::string &method() const;
|
||||
|
||||
size_t header_buffer_size() const;
|
||||
void update_header_buffer_size(size_t len);
|
||||
|
||||
private:
|
||||
header_map header_;
|
||||
response_cb response_cb_;
|
||||
|
@ -84,6 +87,7 @@ private:
|
|||
class stream *strm_;
|
||||
uri_ref uri_;
|
||||
std::string method_;
|
||||
size_t header_buffer_size_;
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
|
|
@ -30,7 +30,8 @@ namespace nghttp2 {
|
|||
namespace asio_http2 {
|
||||
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); }
|
||||
|
||||
|
@ -52,6 +53,12 @@ header_map &response_impl::header() { 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 asio_http2
|
||||
} // namespace nghttp2
|
||||
|
|
|
@ -53,12 +53,16 @@ public:
|
|||
header_map &header();
|
||||
const header_map &header() const;
|
||||
|
||||
size_t header_buffer_size() const;
|
||||
void update_header_buffer_size(size_t len);
|
||||
|
||||
private:
|
||||
data_cb data_cb_;
|
||||
|
||||
header_map header_;
|
||||
|
||||
int64_t content_length_;
|
||||
size_t header_buffer_size_;
|
||||
int status_code_;
|
||||
};
|
||||
|
||||
|
|
|
@ -174,6 +174,12 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
|
|||
if (token == http2::HD__STATUS) {
|
||||
res.status_code(util::parse_uint(value, valuelen));
|
||||
} 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) {
|
||||
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
|
||||
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),
|
||||
header_value{std::string(value, value + valuelen),
|
||||
|
|
|
@ -105,6 +105,13 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
|
|||
}
|
||||
// fall through
|
||||
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),
|
||||
header_value{std::string(value, value + valuelen),
|
||||
(flags & NGHTTP2_NV_FLAG_NO_INDEX) != 0});
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace nghttp2 {
|
|||
namespace asio_http2 {
|
||||
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_; }
|
||||
|
||||
|
@ -62,6 +62,12 @@ void request_impl::remote_endpoint(boost::asio::ip::tcp::endpoint 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 asio_http2
|
||||
} // namespace nghttp2
|
||||
|
|
|
@ -58,6 +58,9 @@ public:
|
|||
const boost::asio::ip::tcp::endpoint &remote_endpoint() const;
|
||||
void remote_endpoint(boost::asio::ip::tcp::endpoint ep);
|
||||
|
||||
size_t header_buffer_size() const;
|
||||
void update_header_buffer_size(size_t len);
|
||||
|
||||
private:
|
||||
class stream *strm_;
|
||||
header_map header_;
|
||||
|
@ -65,6 +68,7 @@ private:
|
|||
uri_ref uri_;
|
||||
data_cb on_data_cb_;
|
||||
boost::asio::ip::tcp::endpoint remote_ep_;
|
||||
size_t header_buffer_size_;
|
||||
};
|
||||
|
||||
} // 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)
|
||||
: uri(uri), u(u), pri_spec(pri_spec), data_length(data_length),
|
||||
data_offset(0), response_len(0), inflater(nullptr), html_parser(nullptr),
|
||||
data_prd(data_prd), stream_id(-1), status(0), level(level),
|
||||
expect_final_response(false) {
|
||||
data_prd(data_prd), header_buffer_size(0), stream_id(-1), status(0),
|
||||
level(level), expect_final_response(false) {
|
||||
http2::init_hdidx(res_hdidx);
|
||||
http2::init_hdidx(req_hdidx);
|
||||
}
|
||||
|
@ -1704,6 +1704,14 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
|
|||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Reset for response header field reception
|
||||
req->header_buffer_size = 0;
|
||||
|
||||
auto scheme = req->get_req_header(http2::HD__SCHEME);
|
||||
auto authority = req->get_req_header(http2::HD__AUTHORITY);
|
||||
auto path = req->get_req_header(http2::HD__PATH);
|
||||
|
|
|
@ -150,6 +150,7 @@ struct Request {
|
|||
nghttp2_gzip *inflater;
|
||||
HtmlParser *html_parser;
|
||||
const nghttp2_data_provider *data_prd;
|
||||
size_t header_buffer_size;
|
||||
int32_t stream_id;
|
||||
int status;
|
||||
// Recursion level: 0: first entity, 1: entity linked from first entity
|
||||
|
|
Loading…
Reference in New Issue