|
|
@ -7,10 +7,12 @@ namespace node { |
|
|
|
using v8::ArrayBuffer; |
|
|
|
using v8::Boolean; |
|
|
|
using v8::Context; |
|
|
|
using v8::Float64Array; |
|
|
|
using v8::Function; |
|
|
|
using v8::Integer; |
|
|
|
using v8::String; |
|
|
|
using v8::Uint32; |
|
|
|
using v8::Uint32Array; |
|
|
|
using v8::Undefined; |
|
|
|
|
|
|
|
namespace http2 { |
|
|
@ -57,27 +59,18 @@ enum Http2OptionsIndex { |
|
|
|
IDX_OPTIONS_FLAGS |
|
|
|
}; |
|
|
|
|
|
|
|
static uint32_t http2_padding_buffer[3]; |
|
|
|
static uint32_t http2_options_buffer[IDX_OPTIONS_FLAGS + 1]; |
|
|
|
static uint32_t http2_settings_buffer[IDX_SETTINGS_COUNT + 1]; |
|
|
|
static double http2_session_state_buffer[IDX_SESSION_STATE_COUNT]; |
|
|
|
static double http2_stream_state_buffer[IDX_STREAM_STATE_COUNT]; |
|
|
|
|
|
|
|
static const size_t http2_options_buffer_byte_length = |
|
|
|
sizeof(http2_options_buffer) * (IDX_OPTIONS_FLAGS + 1); |
|
|
|
static const size_t http2_settings_buffer_byte_length = |
|
|
|
sizeof(http2_settings_buffer) * (IDX_SETTINGS_COUNT + 1); |
|
|
|
static const size_t http2_padding_buffer_byte_length = |
|
|
|
sizeof(http2_padding_buffer) * 3; |
|
|
|
static const size_t http2_stream_state_buffer_byte_length = |
|
|
|
sizeof(http2_stream_state_buffer) * IDX_STREAM_STATE_COUNT; |
|
|
|
static const size_t http2_session_state_buffer_byte_length = |
|
|
|
sizeof(http2_session_state_buffer) * IDX_SESSION_STATE_COUNT; |
|
|
|
struct http2_state { |
|
|
|
uint32_t padding_buffer[3]; |
|
|
|
uint32_t options_buffer[IDX_OPTIONS_FLAGS + 1]; |
|
|
|
uint32_t settings_buffer[IDX_SETTINGS_COUNT + 1]; |
|
|
|
double session_state_buffer[IDX_SESSION_STATE_COUNT]; |
|
|
|
double stream_state_buffer[IDX_STREAM_STATE_COUNT]; |
|
|
|
}; |
|
|
|
|
|
|
|
Http2Options::Http2Options(Environment* env) { |
|
|
|
nghttp2_option_new(&options_); |
|
|
|
|
|
|
|
uint32_t* buffer = http2_options_buffer; |
|
|
|
uint32_t* buffer = env->http2_state_buffer()->options_buffer; |
|
|
|
uint32_t flags = buffer[IDX_OPTIONS_FLAGS]; |
|
|
|
|
|
|
|
if (flags & (1 << IDX_OPTIONS_MAX_DEFLATE_DYNAMIC_TABLE_SIZE)) { |
|
|
@ -126,7 +119,7 @@ ssize_t Http2Session::OnCallbackPadding(size_t frameLen, |
|
|
|
Context::Scope context_scope(context); |
|
|
|
|
|
|
|
if (object()->Has(context, env()->ongetpadding_string()).FromJust()) { |
|
|
|
uint32_t* buffer = http2_padding_buffer; |
|
|
|
uint32_t* buffer = env()->http2_state_buffer()->padding_buffer; |
|
|
|
buffer[0] = frameLen; |
|
|
|
buffer[1] = maxPayloadLen; |
|
|
|
MakeCallback(env()->ongetpadding_string(), 0, nullptr); |
|
|
@ -167,7 +160,7 @@ void PackSettings(const FunctionCallbackInfo<Value>& args) { |
|
|
|
std::vector<nghttp2_settings_entry> entries; |
|
|
|
entries.reserve(6); |
|
|
|
|
|
|
|
uint32_t* buffer = http2_settings_buffer; |
|
|
|
uint32_t* buffer = env->http2_state_buffer()->settings_buffer; |
|
|
|
uint32_t flags = buffer[IDX_SETTINGS_COUNT]; |
|
|
|
|
|
|
|
if (flags & (1 << IDX_SETTINGS_HEADER_TABLE_SIZE)) { |
|
|
@ -226,7 +219,8 @@ void PackSettings(const FunctionCallbackInfo<Value>& args) { |
|
|
|
// Used to fill in the spec defined initial values for each setting.
|
|
|
|
void RefreshDefaultSettings(const FunctionCallbackInfo<Value>& args) { |
|
|
|
DEBUG_HTTP2("Http2Session: refreshing default settings\n"); |
|
|
|
uint32_t* buffer = http2_settings_buffer; |
|
|
|
Environment* env = Environment::GetCurrent(args); |
|
|
|
uint32_t* buffer = env->http2_state_buffer()->settings_buffer; |
|
|
|
buffer[IDX_SETTINGS_HEADER_TABLE_SIZE] = |
|
|
|
DEFAULT_SETTINGS_HEADER_TABLE_SIZE; |
|
|
|
buffer[IDX_SETTINGS_ENABLE_PUSH] = |
|
|
@ -245,13 +239,14 @@ void RefreshDefaultSettings(const FunctionCallbackInfo<Value>& args) { |
|
|
|
template <get_setting fn> |
|
|
|
void RefreshSettings(const FunctionCallbackInfo<Value>& args) { |
|
|
|
DEBUG_HTTP2("Http2Session: refreshing settings for session\n"); |
|
|
|
Environment* env = Environment::GetCurrent(args); |
|
|
|
CHECK_EQ(args.Length(), 1); |
|
|
|
CHECK(args[0]->IsObject()); |
|
|
|
Http2Session* session; |
|
|
|
ASSIGN_OR_RETURN_UNWRAP(&session, args[0].As<Object>()); |
|
|
|
nghttp2_session* s = session->session(); |
|
|
|
|
|
|
|
uint32_t* buffer = http2_settings_buffer; |
|
|
|
uint32_t* buffer = env->http2_state_buffer()->settings_buffer; |
|
|
|
buffer[IDX_SETTINGS_HEADER_TABLE_SIZE] = |
|
|
|
fn(s, NGHTTP2_SETTINGS_HEADER_TABLE_SIZE); |
|
|
|
buffer[IDX_SETTINGS_MAX_CONCURRENT_STREAMS] = |
|
|
@ -269,9 +264,10 @@ void RefreshSettings(const FunctionCallbackInfo<Value>& args) { |
|
|
|
// Used to fill in the spec defined initial values for each setting.
|
|
|
|
void RefreshSessionState(const FunctionCallbackInfo<Value>& args) { |
|
|
|
DEBUG_HTTP2("Http2Session: refreshing session state\n"); |
|
|
|
Environment* env = Environment::GetCurrent(args); |
|
|
|
CHECK_EQ(args.Length(), 1); |
|
|
|
CHECK(args[0]->IsObject()); |
|
|
|
double* buffer = http2_session_state_buffer; |
|
|
|
double* buffer = env->http2_state_buffer()->session_state_buffer; |
|
|
|
Http2Session* session; |
|
|
|
ASSIGN_OR_RETURN_UNWRAP(&session, args[0].As<Object>()); |
|
|
|
nghttp2_session* s = session->session(); |
|
|
@ -308,7 +304,7 @@ void RefreshStreamState(const FunctionCallbackInfo<Value>& args) { |
|
|
|
nghttp2_session* s = session->session(); |
|
|
|
Nghttp2Stream* stream; |
|
|
|
|
|
|
|
double* buffer = http2_stream_state_buffer; |
|
|
|
double* buffer = env->http2_state_buffer()->stream_state_buffer; |
|
|
|
|
|
|
|
if ((stream = session->FindStream(id)) == nullptr) { |
|
|
|
buffer[IDX_STREAM_STATE] = NGHTTP2_STREAM_STATE_IDLE; |
|
|
@ -418,8 +414,9 @@ void Http2Session::SubmitPriority(const FunctionCallbackInfo<Value>& args) { |
|
|
|
void Http2Session::SubmitSettings(const FunctionCallbackInfo<Value>& args) { |
|
|
|
Http2Session* session; |
|
|
|
ASSIGN_OR_RETURN_UNWRAP(&session, args.Holder()); |
|
|
|
Environment* env = session->env(); |
|
|
|
|
|
|
|
uint32_t* buffer = http2_settings_buffer; |
|
|
|
uint32_t* buffer = env->http2_state_buffer()->settings_buffer; |
|
|
|
uint32_t flags = buffer[IDX_SETTINGS_COUNT]; |
|
|
|
|
|
|
|
std::vector<nghttp2_settings_entry> entries; |
|
|
@ -1148,43 +1145,27 @@ void Initialize(Local<Object> target, |
|
|
|
Isolate* isolate = env->isolate(); |
|
|
|
HandleScope scope(isolate); |
|
|
|
|
|
|
|
// Initialize the buffer used for padding callbacks
|
|
|
|
target->Set(context, |
|
|
|
FIXED_ONE_BYTE_STRING(isolate, "paddingArrayBuffer"), |
|
|
|
ArrayBuffer::New(isolate, |
|
|
|
&http2_padding_buffer, |
|
|
|
http2_padding_buffer_byte_length)) |
|
|
|
.FromJust(); |
|
|
|
http2_state* state = Calloc<http2_state>(1); |
|
|
|
env->set_http2_state_buffer(state); |
|
|
|
auto state_ab = ArrayBuffer::New(isolate, state, sizeof(*state)); |
|
|
|
|
|
|
|
// Initialize the buffer used to store the session state
|
|
|
|
target->Set(context, |
|
|
|
FIXED_ONE_BYTE_STRING(isolate, "sessionStateArrayBuffer"), |
|
|
|
ArrayBuffer::New(isolate, |
|
|
|
&http2_session_state_buffer, |
|
|
|
http2_session_state_buffer_byte_length)) |
|
|
|
.FromJust(); |
|
|
|
#define SET_STATE_TYPEDARRAY(name, type, field) \ |
|
|
|
target->Set(context, \ |
|
|
|
FIXED_ONE_BYTE_STRING(isolate, (name)), \ |
|
|
|
type::New(state_ab, \ |
|
|
|
offsetof(http2_state, field), \ |
|
|
|
arraysize(state->field))) \ |
|
|
|
.FromJust() |
|
|
|
|
|
|
|
// Initialize the buffer used for padding callbacks
|
|
|
|
SET_STATE_TYPEDARRAY("paddingBuffer", Uint32Array, padding_buffer); |
|
|
|
// Initialize the buffer used to store the session state
|
|
|
|
SET_STATE_TYPEDARRAY("sessionState", Float64Array, session_state_buffer); |
|
|
|
// Initialize the buffer used to store the stream state
|
|
|
|
target->Set(context, |
|
|
|
FIXED_ONE_BYTE_STRING(isolate, "streamStateArrayBuffer"), |
|
|
|
ArrayBuffer::New(isolate, |
|
|
|
&http2_stream_state_buffer, |
|
|
|
http2_stream_state_buffer_byte_length)) |
|
|
|
.FromJust(); |
|
|
|
|
|
|
|
target->Set(context, |
|
|
|
FIXED_ONE_BYTE_STRING(isolate, "settingsArrayBuffer"), |
|
|
|
ArrayBuffer::New(isolate, |
|
|
|
&http2_settings_buffer, |
|
|
|
http2_settings_buffer_byte_length)) |
|
|
|
.FromJust(); |
|
|
|
|
|
|
|
target->Set(context, |
|
|
|
FIXED_ONE_BYTE_STRING(isolate, "optionsArrayBuffer"), |
|
|
|
ArrayBuffer::New(isolate, |
|
|
|
&http2_options_buffer, |
|
|
|
http2_options_buffer_byte_length)) |
|
|
|
.FromJust(); |
|
|
|
SET_STATE_TYPEDARRAY("streamState", Float64Array, stream_state_buffer); |
|
|
|
SET_STATE_TYPEDARRAY("settingsBuffer", Uint32Array, settings_buffer); |
|
|
|
SET_STATE_TYPEDARRAY("optionsBuffer", Uint32Array, options_buffer); |
|
|
|
#undef SET_STATE_TYPEDARRAY |
|
|
|
|
|
|
|
// Method to fetch the nghttp2 string description of an nghttp2 error code
|
|
|
|
env->SetMethod(target, "nghttp2ErrorString", HttpErrorString); |
|
|
|