Skip to content

Commit f54b5b2

Browse files
committed
src: move HTTP/2 state out of Environment
Moves state that is specific to HTTP/2 into the HTTP/2 implementation as a cleanup. PR-URL: #32538 Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 6576b9b commit f54b5b2

7 files changed

+119
-109
lines changed

src/env-inl.h

-10
Original file line numberDiff line numberDiff line change
@@ -630,16 +630,6 @@ inline void Environment::set_http_parser_buffer_in_use(bool in_use) {
630630
http_parser_buffer_in_use_ = in_use;
631631
}
632632

633-
inline http2::Http2State* Environment::http2_state() const {
634-
return http2_state_.get();
635-
}
636-
637-
inline void Environment::set_http2_state(
638-
std::unique_ptr<http2::Http2State> buffer) {
639-
CHECK(!http2_state_); // Should be set only once.
640-
http2_state_ = std::move(buffer);
641-
}
642-
643633
inline AliasedFloat64Array* Environment::fs_stats_field_array() {
644634
return &fs_stats_field_array_;
645635
}

src/env.h

+2-8
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
#include "handle_wrap.h"
3434
#include "node.h"
3535
#include "node_binding.h"
36-
#include "node_http2_state.h"
3736
#include "node_main_instance.h"
3837
#include "node_options.h"
3938
#include "req_wrap.h"
@@ -50,8 +49,6 @@
5049
#include <unordered_set>
5150
#include <vector>
5251

53-
struct nghttp2_rcbuf;
54-
5552
namespace node {
5653

5754
namespace contextify {
@@ -515,7 +512,8 @@ class IsolateData : public MemoryRetainer {
515512
#undef VP
516513
inline v8::Local<v8::String> async_wrap_provider(int index) const;
517514

518-
std::unordered_map<const char*, v8::Eternal<v8::String>> http_static_strs;
515+
std::unordered_map<const char*, v8::Eternal<v8::String>> static_str_map;
516+
519517
inline v8::Isolate* isolate() const;
520518
IsolateData(const IsolateData&) = delete;
521519
IsolateData& operator=(const IsolateData&) = delete;
@@ -1026,9 +1024,6 @@ class Environment : public MemoryRetainer {
10261024
inline bool http_parser_buffer_in_use() const;
10271025
inline void set_http_parser_buffer_in_use(bool in_use);
10281026

1029-
inline http2::Http2State* http2_state() const;
1030-
inline void set_http2_state(std::unique_ptr<http2::Http2State> state);
1031-
10321027
EnabledDebugList* enabled_debug_list() { return &enabled_debug_list_; }
10331028

10341029
inline AliasedFloat64Array* fs_stats_field_array();
@@ -1391,7 +1386,6 @@ class Environment : public MemoryRetainer {
13911386

13921387
char* http_parser_buffer_ = nullptr;
13931388
bool http_parser_buffer_in_use_ = false;
1394-
std::unique_ptr<http2::Http2State> http2_state_;
13951389

13961390
EnabledDebugList enabled_debug_list_;
13971391
AliasedFloat64Array fs_stats_field_array_;

src/node_http2.cc

+48-41
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
#include "node.h"
55
#include "node_buffer.h"
66
#include "node_http2.h"
7-
#include "node_http2_state.h"
87
#include "node_http_common-inl.h"
98
#include "node_mem-inl.h"
109
#include "node_perf.h"
@@ -113,7 +112,7 @@ Http2Scope::~Http2Scope() {
113112
// instances to configure an appropriate nghttp2_options struct. The class
114113
// uses a single TypedArray instance that is shared with the JavaScript side
115114
// to more efficiently pass values back and forth.
116-
Http2Options::Http2Options(Environment* env, nghttp2_session_type type) {
115+
Http2Options::Http2Options(Http2State* http2_state, nghttp2_session_type type) {
117116
nghttp2_option* option;
118117
CHECK_EQ(nghttp2_option_new(&option), 0);
119118
CHECK_NOT_NULL(option);
@@ -138,7 +137,7 @@ Http2Options::Http2Options(Environment* env, nghttp2_session_type type) {
138137
nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ORIGIN);
139138
}
140139

141-
AliasedUint32Array& buffer = env->http2_state()->options_buffer;
140+
AliasedUint32Array& buffer = http2_state->options_buffer;
142141
uint32_t flags = buffer[IDX_OPTIONS_FLAGS];
143142

144143
if (flags & (1 << IDX_OPTIONS_MAX_DEFLATE_DYNAMIC_TABLE_SIZE)) {
@@ -213,8 +212,8 @@ Http2Options::Http2Options(Environment* env, nghttp2_session_type type) {
213212
SetMaxSessionMemory(buffer[IDX_OPTIONS_MAX_SESSION_MEMORY] * 1000000);
214213
}
215214

216-
void Http2Session::Http2Settings::Init() {
217-
AliasedUint32Array& buffer = env()->http2_state()->settings_buffer;
215+
void Http2Session::Http2Settings::Init(Http2State* http2_state) {
216+
AliasedUint32Array& buffer = http2_state->settings_buffer;
218217
uint32_t flags = buffer[IDX_SETTINGS_COUNT];
219218

220219
size_t n = 0;
@@ -244,14 +243,14 @@ void Http2Session::Http2Settings::Init() {
244243
// The Http2Settings class is used to configure a SETTINGS frame that is
245244
// to be sent to the connected peer. The settings are set using a TypedArray
246245
// that is shared with the JavaScript side.
247-
Http2Session::Http2Settings::Http2Settings(Environment* env,
246+
Http2Session::Http2Settings::Http2Settings(Http2State* http2_state,
248247
Http2Session* session,
249248
Local<Object> obj,
250249
uint64_t start_time)
251-
: AsyncWrap(env, obj, PROVIDER_HTTP2SETTINGS),
250+
: AsyncWrap(http2_state->env(), obj, PROVIDER_HTTP2SETTINGS),
252251
session_(session),
253252
startTime_(start_time) {
254-
Init();
253+
Init(http2_state);
255254
}
256255

257256
// Generates a Buffer that contains the serialized payload of a SETTINGS
@@ -272,10 +271,9 @@ Local<Value> Http2Session::Http2Settings::Pack() {
272271

273272
// Updates the shared TypedArray with the current remote or local settings for
274273
// the session.
275-
void Http2Session::Http2Settings::Update(Environment* env,
276-
Http2Session* session,
274+
void Http2Session::Http2Settings::Update(Http2Session* session,
277275
get_setting fn) {
278-
AliasedUint32Array& buffer = env->http2_state()->settings_buffer;
276+
AliasedUint32Array& buffer = session->http2_state()->settings_buffer;
279277
buffer[IDX_SETTINGS_HEADER_TABLE_SIZE] =
280278
fn(**session, NGHTTP2_SETTINGS_HEADER_TABLE_SIZE);
281279
buffer[IDX_SETTINGS_MAX_CONCURRENT_STREAMS] =
@@ -293,8 +291,8 @@ void Http2Session::Http2Settings::Update(Environment* env,
293291
}
294292

295293
// Initializes the shared TypedArray with the default settings values.
296-
void Http2Session::Http2Settings::RefreshDefaults(Environment* env) {
297-
AliasedUint32Array& buffer = env->http2_state()->settings_buffer;
294+
void Http2Session::Http2Settings::RefreshDefaults(Http2State* http2_state) {
295+
AliasedUint32Array& buffer = http2_state->settings_buffer;
298296

299297
buffer[IDX_SETTINGS_HEADER_TABLE_SIZE] =
300298
DEFAULT_SETTINGS_HEADER_TABLE_SIZE;
@@ -469,16 +467,17 @@ void Http2Session::DecreaseAllocatedSize(size_t size) {
469467
current_nghttp2_memory_ -= size;
470468
}
471469

472-
Http2Session::Http2Session(Environment* env,
470+
Http2Session::Http2Session(Http2State* http2_state,
473471
Local<Object> wrap,
474472
nghttp2_session_type type)
475-
: AsyncWrap(env, wrap, AsyncWrap::PROVIDER_HTTP2SESSION),
476-
session_type_(type) {
473+
: AsyncWrap(http2_state->env(), wrap, AsyncWrap::PROVIDER_HTTP2SESSION),
474+
session_type_(type),
475+
http2_state_(http2_state) {
477476
MakeWeak();
478477
statistics_.start_time = uv_hrtime();
479478

480479
// Capture the configuration options for this session
481-
Http2Options opts(env, type);
480+
Http2Options opts(http2_state, type);
482481

483482
max_session_memory_ = opts.GetMaxSessionMemory();
484483

@@ -521,13 +520,13 @@ Http2Session::Http2Session(Environment* env,
521520

522521
// Make the js_fields_ property accessible to JS land.
523522
js_fields_store_ =
524-
ArrayBuffer::NewBackingStore(env->isolate(), sizeof(SessionJSFields));
523+
ArrayBuffer::NewBackingStore(env()->isolate(), sizeof(SessionJSFields));
525524
js_fields_ = new(js_fields_store_->Data()) SessionJSFields;
526525

527-
Local<ArrayBuffer> ab = ArrayBuffer::New(env->isolate(), js_fields_store_);
526+
Local<ArrayBuffer> ab = ArrayBuffer::New(env()->isolate(), js_fields_store_);
528527
Local<Uint8Array> uint8_arr =
529528
Uint8Array::New(ab, 0, kSessionUint8FieldCount);
530-
USE(wrap->Set(env->context(), env->fields_string(), uint8_arr));
529+
USE(wrap->Set(env()->context(), env()->fields_string(), uint8_arr));
531530
}
532531

533532
Http2Session::~Http2Session() {
@@ -551,15 +550,17 @@ inline bool HasHttp2Observer(Environment* env) {
551550
}
552551

553552
void Http2Stream::EmitStatistics() {
553+
CHECK_NOT_NULL(session());
554554
if (!HasHttp2Observer(env()))
555555
return;
556556
auto entry =
557-
std::make_unique<Http2StreamPerformanceEntry>(env(), id_, statistics_);
557+
std::make_unique<Http2StreamPerformanceEntry>(
558+
session()->http2_state(), id_, statistics_);
558559
env()->SetImmediate([entry = move(entry)](Environment* env) {
559560
if (!HasHttp2Observer(env))
560561
return;
561562
HandleScope handle_scope(env->isolate());
562-
AliasedFloat64Array& buffer = env->http2_state()->stream_stats_buffer;
563+
AliasedFloat64Array& buffer = entry->http2_state()->stream_stats_buffer;
563564
buffer[IDX_STREAM_STATS_ID] = entry->id();
564565
if (entry->first_byte() != 0) {
565566
buffer[IDX_STREAM_STATS_TIMETOFIRSTBYTE] =
@@ -592,12 +593,12 @@ void Http2Session::EmitStatistics() {
592593
if (!HasHttp2Observer(env()))
593594
return;
594595
auto entry = std::make_unique<Http2SessionPerformanceEntry>(
595-
env(), statistics_, session_type_);
596+
http2_state(), statistics_, session_type_);
596597
env()->SetImmediate([entry = std::move(entry)](Environment* env) {
597598
if (!HasHttp2Observer(env))
598599
return;
599600
HandleScope handle_scope(env->isolate());
600-
AliasedFloat64Array& buffer = env->http2_state()->session_stats_buffer;
601+
AliasedFloat64Array& buffer = entry->http2_state()->session_stats_buffer;
601602
buffer[IDX_SESSION_STATS_TYPE] = entry->type();
602603
buffer[IDX_SESSION_STATS_PINGRTT] = entry->ping_rtt() / 1e6;
603604
buffer[IDX_SESSION_STATS_FRAMESRECEIVED] = entry->frame_count();
@@ -2334,24 +2335,25 @@ void HttpErrorString(const FunctionCallbackInfo<Value>& args) {
23342335
// would be suitable, for instance, for creating the Base64
23352336
// output for an HTTP2-Settings header field.
23362337
void PackSettings(const FunctionCallbackInfo<Value>& args) {
2337-
Environment* env = Environment::GetCurrent(args);
2338+
Http2State* state = Unwrap<Http2State>(args.Data());
2339+
Environment* env = state->env();
23382340
// TODO(addaleax): We should not be creating a full AsyncWrap for this.
23392341
Local<Object> obj;
23402342
if (!env->http2settings_constructor_template()
23412343
->NewInstance(env->context())
23422344
.ToLocal(&obj)) {
23432345
return;
23442346
}
2345-
Http2Session::Http2Settings settings(env, nullptr, obj);
2347+
Http2Session::Http2Settings settings(state, nullptr, obj);
23462348
args.GetReturnValue().Set(settings.Pack());
23472349
}
23482350

23492351
// A TypedArray instance is shared between C++ and JS land to contain the
23502352
// default SETTINGS. RefreshDefaultSettings updates that TypedArray with the
23512353
// default values.
23522354
void RefreshDefaultSettings(const FunctionCallbackInfo<Value>& args) {
2353-
Environment* env = Environment::GetCurrent(args);
2354-
Http2Session::Http2Settings::RefreshDefaults(env);
2355+
Http2State* state = Unwrap<Http2State>(args.Data());
2356+
Http2Session::Http2Settings::RefreshDefaults(state);
23552357
}
23562358

23572359
// Sets the next stream ID the Http2Session. If successful, returns true.
@@ -2373,23 +2375,21 @@ void Http2Session::SetNextStreamID(const FunctionCallbackInfo<Value>& args) {
23732375
// values established for each of the settings so those can be read in JS land.
23742376
template <get_setting fn>
23752377
void Http2Session::RefreshSettings(const FunctionCallbackInfo<Value>& args) {
2376-
Environment* env = Environment::GetCurrent(args);
23772378
Http2Session* session;
23782379
ASSIGN_OR_RETURN_UNWRAP(&session, args.Holder());
2379-
Http2Settings::Update(env, session, fn);
2380+
Http2Settings::Update(session, fn);
23802381
Debug(session, "settings refreshed for session");
23812382
}
23822383

23832384
// A TypedArray instance is shared between C++ and JS land to contain state
23842385
// information of the current Http2Session. This updates the values in the
23852386
// TypedArray so those can be read in JS land.
23862387
void Http2Session::RefreshState(const FunctionCallbackInfo<Value>& args) {
2387-
Environment* env = Environment::GetCurrent(args);
23882388
Http2Session* session;
23892389
ASSIGN_OR_RETURN_UNWRAP(&session, args.Holder());
23902390
Debug(session, "refreshing state");
23912391

2392-
AliasedFloat64Array& buffer = env->http2_state()->session_state_buffer;
2392+
AliasedFloat64Array& buffer = session->http2_state()->session_state_buffer;
23932393

23942394
nghttp2_session* s = **session;
23952395

@@ -2416,11 +2416,12 @@ void Http2Session::RefreshState(const FunctionCallbackInfo<Value>& args) {
24162416

24172417
// Constructor for new Http2Session instances.
24182418
void Http2Session::New(const FunctionCallbackInfo<Value>& args) {
2419-
Environment* env = Environment::GetCurrent(args);
2419+
Http2State* state = Unwrap<Http2State>(args.Data());
2420+
Environment* env = state->env();
24202421
CHECK(args.IsConstructCall());
24212422
int32_t val = args[0]->Int32Value(env->context()).ToChecked();
24222423
nghttp2_session_type type = static_cast<nghttp2_session_type>(val);
2423-
Http2Session* session = new Http2Session(env, args.This(), type);
2424+
Http2Session* session = new Http2Session(state, args.This(), type);
24242425
session->get_async_id(); // avoid compiler warning
24252426
Debug(session, "session created");
24262427
}
@@ -2645,13 +2646,14 @@ void Http2Stream::Priority(const FunctionCallbackInfo<Value>& args) {
26452646
// information about the Http2Stream. This updates the values in that
26462647
// TypedArray so that the state can be read by JS.
26472648
void Http2Stream::RefreshState(const FunctionCallbackInfo<Value>& args) {
2648-
Environment* env = Environment::GetCurrent(args);
26492649
Http2Stream* stream;
26502650
ASSIGN_OR_RETURN_UNWRAP(&stream, args.Holder());
26512651

26522652
Debug(stream, "refreshing state");
26532653

2654-
AliasedFloat64Array& buffer = env->http2_state()->stream_state_buffer;
2654+
CHECK_NOT_NULL(stream->session());
2655+
AliasedFloat64Array& buffer =
2656+
stream->session()->http2_state()->stream_state_buffer;
26552657

26562658
nghttp2_stream* str = **stream;
26572659
nghttp2_session* s = **(stream->session());
@@ -2797,7 +2799,8 @@ void Http2Session::Settings(const FunctionCallbackInfo<Value>& args) {
27972799
return;
27982800

27992801
Http2Settings* settings = session->AddSettings(
2800-
MakeDetachedBaseObject<Http2Settings>(session->env(), session, obj, 0));
2802+
MakeDetachedBaseObject<Http2Settings>(
2803+
session->http2_state(), session, obj, 0));
28012804
if (settings == nullptr) return args.GetReturnValue().Set(false);
28022805

28032806
settings->Send();
@@ -2921,16 +2924,22 @@ void SetCallbackFunctions(const FunctionCallbackInfo<Value>& args) {
29212924
#undef SET_FUNCTION
29222925
}
29232926

2927+
void Http2State::MemoryInfo(MemoryTracker* tracker) const {
2928+
tracker->TrackField("root_buffer", root_buffer);
2929+
}
2930+
29242931
// Set up the process.binding('http2') binding.
29252932
void Initialize(Local<Object> target,
29262933
Local<Value> unused,
29272934
Local<Context> context,
29282935
void* priv) {
29292936
Environment* env = Environment::GetCurrent(context);
29302937
Isolate* isolate = env->isolate();
2931-
HandleScope scope(isolate);
2938+
HandleScope handle_scope(isolate);
29322939

2933-
std::unique_ptr<Http2State> state(new Http2State(isolate));
2940+
Environment::BindingScope<Http2State> binding_scope(env);
2941+
if (!binding_scope) return;
2942+
Http2State* state = binding_scope.data;
29342943

29352944
#define SET_STATE_TYPEDARRAY(name, field) \
29362945
target->Set(context, \
@@ -2953,8 +2962,6 @@ void Initialize(Local<Object> target,
29532962
"sessionStats", state->session_stats_buffer.GetJSArray());
29542963
#undef SET_STATE_TYPEDARRAY
29552964

2956-
env->set_http2_state(std::move(state));
2957-
29582965
NODE_DEFINE_CONSTANT(target, kBitfield);
29592966
NODE_DEFINE_CONSTANT(target, kSessionPriorityListenerCount);
29602967
NODE_DEFINE_CONSTANT(target, kSessionFrameErrorListenerCount);

0 commit comments

Comments
 (0)