Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames M Snell <jasnell@gmail.com>2020-03-29 19:06:57 +0300
committerMichaƫl Zasso <targos@protonmail.com>2020-04-11 11:05:39 +0300
commitafc6a25f42a6e41a8bcc5a80eebd9c3973c45daa (patch)
tree0095988a25c8d7a66e62c5c72b1fbcb39b79b88c /src/node_http2.cc
parent4df3ac2a639ecdb08e9dbe48c2a4b40d6d3ae3ab (diff)
src: use smart pointers for nghttp2 objects
Signed-off-by: James M Snell <jasnell@gmail.com> PR-URL: https://github.com/nodejs/node/pull/32551 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Rich Trott <rtrott@gmail.com>
Diffstat (limited to 'src/node_http2.cc')
-rw-r--r--src/node_http2.cc117
1 files changed, 61 insertions, 56 deletions
diff --git a/src/node_http2.cc b/src/node_http2.cc
index e4b24b74341..9ffc72ff9ab 100644
--- a/src/node_http2.cc
+++ b/src/node_http2.cc
@@ -113,11 +113,14 @@ Http2Scope::~Http2Scope() {
// uses a single TypedArray instance that is shared with the JavaScript side
// to more efficiently pass values back and forth.
Http2Options::Http2Options(Environment* env, nghttp2_session_type type) {
- nghttp2_option_new(&options_);
+ nghttp2_option* option;
+ CHECK_EQ(nghttp2_option_new(&option), 0);
+ CHECK_NOT_NULL(option);
+ options_.reset(option);
// Make sure closed connections aren't kept around, taking up memory.
// Note that this breaks the priority tree, which we don't use.
- nghttp2_option_set_no_closed_streams(options_, 1);
+ nghttp2_option_set_no_closed_streams(option, 1);
// We manually handle flow control within a session in order to
// implement backpressure -- that is, we only send WINDOW_UPDATE
@@ -125,13 +128,13 @@ Http2Options::Http2Options(Environment* env, nghttp2_session_type type) {
// code. This ensures that the flow of data over the connection
// does not move too quickly and limits the amount of data we
// are required to buffer.
- nghttp2_option_set_no_auto_window_update(options_, 1);
+ nghttp2_option_set_no_auto_window_update(option, 1);
// Enable built in support for receiving ALTSVC and ORIGIN frames (but
// only on client side sessions
if (type == NGHTTP2_SESSION_CLIENT) {
- nghttp2_option_set_builtin_recv_extension_type(options_, NGHTTP2_ALTSVC);
- nghttp2_option_set_builtin_recv_extension_type(options_, NGHTTP2_ORIGIN);
+ nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ALTSVC);
+ nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ORIGIN);
}
AliasedUint32Array& buffer = env->http2_state()->options_buffer;
@@ -139,27 +142,27 @@ Http2Options::Http2Options(Environment* env, nghttp2_session_type type) {
if (flags & (1 << IDX_OPTIONS_MAX_DEFLATE_DYNAMIC_TABLE_SIZE)) {
nghttp2_option_set_max_deflate_dynamic_table_size(
- options_,
+ option,
buffer[IDX_OPTIONS_MAX_DEFLATE_DYNAMIC_TABLE_SIZE]);
}
if (flags & (1 << IDX_OPTIONS_MAX_RESERVED_REMOTE_STREAMS)) {
nghttp2_option_set_max_reserved_remote_streams(
- options_,
+ option,
buffer[IDX_OPTIONS_MAX_RESERVED_REMOTE_STREAMS]);
}
if (flags & (1 << IDX_OPTIONS_MAX_SEND_HEADER_BLOCK_LENGTH)) {
nghttp2_option_set_max_send_header_block_length(
- options_,
+ option,
buffer[IDX_OPTIONS_MAX_SEND_HEADER_BLOCK_LENGTH]);
}
// Recommended default
- nghttp2_option_set_peer_max_concurrent_streams(options_, 100);
+ nghttp2_option_set_peer_max_concurrent_streams(option, 100);
if (flags & (1 << IDX_OPTIONS_PEER_MAX_CONCURRENT_STREAMS)) {
nghttp2_option_set_peer_max_concurrent_streams(
- options_,
+ option,
buffer[IDX_OPTIONS_PEER_MAX_CONCURRENT_STREAMS]);
}
@@ -178,27 +181,24 @@ Http2Options::Http2Options(Environment* env, nghttp2_session_type type) {
// header pairs the session may accept. This is a hard limit.. that is,
// if the remote peer sends more than this amount, the stream will be
// automatically closed with an RST_STREAM.
- if (flags & (1 << IDX_OPTIONS_MAX_HEADER_LIST_PAIRS)) {
+ if (flags & (1 << IDX_OPTIONS_MAX_HEADER_LIST_PAIRS))
SetMaxHeaderPairs(buffer[IDX_OPTIONS_MAX_HEADER_LIST_PAIRS]);
- }
// The HTTP2 specification places no limits on the number of HTTP2
// PING frames that can be sent. In order to prevent PINGS from being
// abused as an attack vector, however, we place a strict upper limit
// on the number of unacknowledged PINGS that can be sent at any given
// time.
- if (flags & (1 << IDX_OPTIONS_MAX_OUTSTANDING_PINGS)) {
+ if (flags & (1 << IDX_OPTIONS_MAX_OUTSTANDING_PINGS))
SetMaxOutstandingPings(buffer[IDX_OPTIONS_MAX_OUTSTANDING_PINGS]);
- }
// The HTTP2 specification places no limits on the number of HTTP2
// SETTINGS frames that can be sent. In order to prevent PINGS from being
// abused as an attack vector, however, we place a strict upper limit
// on the number of unacknowledged SETTINGS that can be sent at any given
// time.
- if (flags & (1 << IDX_OPTIONS_MAX_OUTSTANDING_SETTINGS)) {
+ if (flags & (1 << IDX_OPTIONS_MAX_OUTSTANDING_SETTINGS))
SetMaxOutstandingSettings(buffer[IDX_OPTIONS_MAX_OUTSTANDING_SETTINGS]);
- }
// The HTTP2 specification places no limits on the amount of memory
// that a session can consume. In order to prevent abuse, we place a
@@ -208,9 +208,8 @@ Http2Options::Http2Options(Environment* env, nghttp2_session_type type) {
// created.
// Important: The maxSessionMemory option in javascript is expressed in
// terms of MB increments (i.e. the value 1 == 1 MB)
- if (flags & (1 << IDX_OPTIONS_MAX_SESSION_MEMORY)) {
+ if (flags & (1 << IDX_OPTIONS_MAX_SESSION_MEMORY))
SetMaxSessionMemory(buffer[IDX_OPTIONS_MAX_SESSION_MEMORY] * 1e6);
- }
}
void Http2Session::Http2Settings::Init() {
@@ -420,42 +419,39 @@ Origins::Origins(Isolate* isolate,
// Sets the various callback functions that nghttp2 will use to notify us
// about significant events while processing http2 stuff.
Http2Session::Callbacks::Callbacks(bool kHasGetPaddingCallback) {
- CHECK_EQ(nghttp2_session_callbacks_new(&callbacks), 0);
+ nghttp2_session_callbacks* callbacks_;
+ CHECK_EQ(nghttp2_session_callbacks_new(&callbacks_), 0);
+ callbacks.reset(callbacks_);
nghttp2_session_callbacks_set_on_begin_headers_callback(
- callbacks, OnBeginHeadersCallback);
+ callbacks_, OnBeginHeadersCallback);
nghttp2_session_callbacks_set_on_header_callback2(
- callbacks, OnHeaderCallback);
+ callbacks_, OnHeaderCallback);
nghttp2_session_callbacks_set_on_frame_recv_callback(
- callbacks, OnFrameReceive);
+ callbacks_, OnFrameReceive);
nghttp2_session_callbacks_set_on_stream_close_callback(
- callbacks, OnStreamClose);
+ callbacks_, OnStreamClose);
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
- callbacks, OnDataChunkReceived);
+ callbacks_, OnDataChunkReceived);
nghttp2_session_callbacks_set_on_frame_not_send_callback(
- callbacks, OnFrameNotSent);
+ callbacks_, OnFrameNotSent);
nghttp2_session_callbacks_set_on_invalid_header_callback2(
- callbacks, OnInvalidHeader);
+ callbacks_, OnInvalidHeader);
nghttp2_session_callbacks_set_error_callback(
- callbacks, OnNghttpError);
+ callbacks_, OnNghttpError);
nghttp2_session_callbacks_set_send_data_callback(
- callbacks, OnSendData);
+ callbacks_, OnSendData);
nghttp2_session_callbacks_set_on_invalid_frame_recv_callback(
- callbacks, OnInvalidFrame);
+ callbacks_, OnInvalidFrame);
nghttp2_session_callbacks_set_on_frame_send_callback(
- callbacks, OnFrameSent);
+ callbacks_, OnFrameSent);
if (kHasGetPaddingCallback) {
nghttp2_session_callbacks_set_select_padding_callback(
- callbacks, OnSelectPadding);
+ callbacks_, OnSelectPadding);
}
}
-
-Http2Session::Callbacks::~Callbacks() {
- nghttp2_session_callbacks_del(callbacks);
-}
-
void Http2Session::StopTrackingRcbuf(nghttp2_rcbuf* buf) {
StopTrackingMemory(buf);
}
@@ -499,9 +495,6 @@ Http2Session::Http2Session(Environment* env,
bool hasGetPaddingCallback =
padding_strategy_ != PADDING_STRATEGY_NONE;
- nghttp2_session_callbacks* callbacks
- = callback_struct_saved[hasGetPaddingCallback ? 1 : 0].callbacks;
-
auto fn = type == NGHTTP2_SESSION_SERVER ?
nghttp2_session_server_new3 :
nghttp2_session_client_new3;
@@ -513,7 +506,14 @@ Http2Session::Http2Session(Environment* env,
// of the options are out of acceptable range, which we should
// be catching before it gets this far. Either way, crash if this
// fails.
- CHECK_EQ(fn(&session_, callbacks, this, *opts, &alloc_info), 0);
+ nghttp2_session* session;
+ CHECK_EQ(fn(
+ &session,
+ callback_struct_saved[hasGetPaddingCallback ? 1 : 0].callbacks.get(),
+ this,
+ *opts,
+ &alloc_info), 0);
+ session_.reset(session);
outgoing_storage_.reserve(1024);
outgoing_buffers_.reserve(32);
@@ -533,7 +533,9 @@ Http2Session::Http2Session(Environment* env,
Http2Session::~Http2Session() {
CHECK_EQ(flags_ & SESSION_STATE_HAS_SCOPE, 0);
Debug(this, "freeing nghttp2 session");
- nghttp2_session_del(session_);
+ // Explicitly reset session_ so the subsequent
+ // current_nghttp2_memory_ check passes.
+ session_.reset();
CHECK_EQ(current_nghttp2_memory_, 0);
}
@@ -629,7 +631,7 @@ void Http2Session::Close(uint32_t code, bool socket_closed) {
// make a best effort.
if (!socket_closed) {
Debug(this, "terminating session with code %d", code);
- CHECK_EQ(nghttp2_session_terminate_session(session_, code), 0);
+ CHECK_EQ(nghttp2_session_terminate_session(session_.get(), code), 0);
SendPendingData();
} else if (stream_ != nullptr) {
stream_->RemoveStreamListener(this);
@@ -669,7 +671,7 @@ inline Http2Stream* Http2Session::FindStream(int32_t id) {
inline bool Http2Session::CanAddStream() {
uint32_t maxConcurrentStreams =
nghttp2_session_get_local_settings(
- session_, NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
+ session_.get(), NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS);
size_t maxSize =
std::min(streams_.max_size(), static_cast<size_t>(maxConcurrentStreams));
// We can add a new stream so long as we are less than the current
@@ -735,10 +737,10 @@ ssize_t Http2Session::ConsumeHTTP2Data() {
// multiple side effects.
Debug(this, "receiving %d bytes [wants data? %d]",
read_len,
- nghttp2_session_want_read(session_));
+ nghttp2_session_want_read(session_.get()));
flags_ &= ~SESSION_STATE_NGHTTP2_RECV_PAUSED;
ssize_t ret =
- nghttp2_session_mem_recv(session_,
+ nghttp2_session_mem_recv(session_.get(),
reinterpret_cast<uint8_t*>(stream_buf_.base) +
stream_buf_offset_,
read_len);
@@ -1437,7 +1439,7 @@ void Http2Session::OnStreamAfterWrite(WriteWrap* w, int status) {
if ((flags_ & SESSION_STATE_READING_STOPPED) &&
!(flags_ & SESSION_STATE_WRITE_IN_PROGRESS) &&
- nghttp2_session_want_read(session_)) {
+ nghttp2_session_want_read(session_.get())) {
flags_ &= ~SESSION_STATE_READING_STOPPED;
stream_->ReadStart();
}
@@ -1465,16 +1467,16 @@ void Http2Session::OnStreamAfterWrite(WriteWrap* w, int status) {
// queue), but only if a write has not already been scheduled.
void Http2Session::MaybeScheduleWrite() {
CHECK_EQ(flags_ & SESSION_STATE_WRITE_SCHEDULED, 0);
- if (UNLIKELY(session_ == nullptr))
+ if (UNLIKELY(!session_))
return;
- if (nghttp2_session_want_write(session_)) {
+ if (nghttp2_session_want_write(session_.get())) {
HandleScope handle_scope(env()->isolate());
Debug(this, "scheduling write");
flags_ |= SESSION_STATE_WRITE_SCHEDULED;
BaseObjectPtr<Http2Session> strong_ref{this};
env()->SetImmediate([this, strong_ref](Environment* env) {
- if (session_ == nullptr || !(flags_ & SESSION_STATE_WRITE_SCHEDULED)) {
+ if (!session_ || !(flags_ & SESSION_STATE_WRITE_SCHEDULED)) {
// This can happen e.g. when a stream was reset before this turn
// of the event loop, in which case SendPendingData() is called early,
// or the session was destroyed in the meantime.
@@ -1492,7 +1494,7 @@ void Http2Session::MaybeScheduleWrite() {
void Http2Session::MaybeStopReading() {
if (flags_ & SESSION_STATE_READING_STOPPED) return;
- int want_read = nghttp2_session_want_read(session_);
+ int want_read = nghttp2_session_want_read(session_.get());
Debug(this, "wants read? %d", want_read);
if (want_read == 0 || (flags_ & SESSION_STATE_WRITE_IN_PROGRESS)) {
flags_ |= SESSION_STATE_READING_STOPPED;
@@ -1590,7 +1592,7 @@ uint8_t Http2Session::SendPendingData() {
// Part One: Gather data from nghttp2
- while ((src_length = nghttp2_session_mem_send(session_, &src)) > 0) {
+ while ((src_length = nghttp2_session_mem_send(session_.get(), &src)) > 0) {
Debug(this, "nghttp2 has %d bytes to send", src_length);
CopyDataIntoOutgoing(src, src_length);
}
@@ -1715,7 +1717,7 @@ Http2Stream* Http2Session::SubmitRequest(
Http2Stream* stream = nullptr;
Http2Stream::Provider::Stream prov(options);
*ret = nghttp2_submit_request(
- session_,
+ session_.get(),
prispec,
headers.data(),
headers.length(),
@@ -2485,9 +2487,9 @@ void Http2Session::Goaway(uint32_t code,
Http2Scope h2scope(this);
// the last proc stream id is the most recently created Http2Stream.
if (lastStreamID <= 0)
- lastStreamID = nghttp2_session_get_last_proc_stream_id(session_);
+ lastStreamID = nghttp2_session_get_last_proc_stream_id(session_.get());
Debug(this, "submitting goaway");
- nghttp2_submit_goaway(session_, NGHTTP2_FLAG_NONE,
+ nghttp2_submit_goaway(session_.get(), NGHTTP2_FLAG_NONE,
lastStreamID, code, data, len);
}
@@ -2676,13 +2678,16 @@ void Http2Session::AltSvc(int32_t id,
uint8_t* value,
size_t value_len) {
Http2Scope h2scope(this);
- CHECK_EQ(nghttp2_submit_altsvc(session_, NGHTTP2_FLAG_NONE, id,
+ CHECK_EQ(nghttp2_submit_altsvc(session_.get(), NGHTTP2_FLAG_NONE, id,
origin, origin_len, value, value_len), 0);
}
void Http2Session::Origin(nghttp2_origin_entry* ov, size_t count) {
Http2Scope h2scope(this);
- CHECK_EQ(nghttp2_submit_origin(session_, NGHTTP2_FLAG_NONE, ov, count), 0);
+ CHECK_EQ(nghttp2_submit_origin(
+ session_.get(),
+ NGHTTP2_FLAG_NONE,
+ ov, count), 0);
}
// Submits an AltSvc frame to be sent to the connected peer.