-
Notifications
You must be signed in to change notification settings - Fork 30.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
http2: major update to internals #17105
Conversation
Yay for that!
Tbh, I did like the distinction between the C++ wrapper for nghttp2 and our own Node code… I guess this is okay tho. Also, the moving-code-around bits folded in with the rest of the changes into a single huge commit makes reviewing a bit harder than it could be ;) |
src/node_http2.cc
Outdated
using v8::String; | ||
using v8::Uint32; | ||
using v8::Uint32Array; | ||
using v8::Undefined; | ||
|
||
namespace http2 { | ||
|
||
Nghttp2Session::Callbacks Nghttp2Session::callback_struct_saved[2] = { | ||
Http2Session::Callbacks Http2Session::callback_struct_saved[2] = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While you’re at it, could you make these const
? Otherwise it’s technically global mutable state…
c43fa6b
to
e1542d0
Compare
@jasnell To prepare for an eventual QUIC layer, I had thought the "folding" of these classes would happen the other way around, i.e. retaining only the Nghttp2 classes and dropping the generic Http2Session/Http2Stream. I don't mean to bikeshed, the changes LGTM. Merely wondering if you had other future plans and considerations here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I only reviewed changes on the JS side.
test/parallel/test-http2-ping.js
Outdated
assert(ack); | ||
assert.strictEqual(typeof duration, 'number'); | ||
}))); | ||
// Only one ping at a time |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why only one ping at a time? I see no such limitation in the http2 spec.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The protocol doesn't limit it, but PING is a potential DOS vector. The one at a time limit is intended to avoid the possibility of abuse.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What risk does PING pose over sending any other outgoing REQUEST/SETTINGS/PRIORITY frame?
Multiple outstanding PINGs could occur as keepalive heartbeat messages under high RTT conditions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We also currently limit SETTINGS frame too, just not as strictly. The risk is in allowing node.js to be used inappropriately as an attack tool. It may be ok tho
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could allow a configurable upper limit on the number of outstanding pings, allowing more than one to be sent at a time, and using a stack for the Http2Ping callbacks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The FIFO approach should generally work, though, if I understand the spec correctly, there is a potential case where outstanding PING are not ACKed in the same order as the outgoing sequence. Methods for dealing with this would be limiting concurrency to 1, or matching the ACKed payload (assuming unique bytes).
doc/api/http2.md
Outdated
@@ -342,6 +342,31 @@ acknowledgement for a sent SETTINGS frame. Will be `true` after calling the | |||
`http2session.settings()` method. Will be `false` once all sent SETTINGS | |||
frames have been acknowledged. | |||
|
|||
#### http2session.ping(callback) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could ping expose an (optional) 8-octet payload
param?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'm considering that, just not sure how useful it's going to be if we stick with the one at a time limit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some considerations:
- Analysis/performance tools might want to send PING floods.
- When RTT exceeds keepalive interval. (Ouch! 😵)
- Avoid global state. Or at least do not expose it to the user.
- Follow what the spec says. Implementation is no place for protocol design.
@@ -29,7 +29,7 @@ const tests = Object.getOwnPropertyNames(constants) | |||
let currentError; | |||
|
|||
// mock submitGoaway because we only care about testing error handling | |||
Http2Session.prototype.submitGoaway = () => currentError.ngError; | |||
Http2Session.prototype.goaway = () => currentError.ngError; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: goAway
to be consistent with pushPromise
, rstStream
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The spec treats it as GOAWAY
and PUSH_PROMISE
/ RST_STREAM
, I was segmenting based on the presence of the _
@@ -9,7 +9,8 @@ const server = http2.createServer(); | |||
|
|||
server.on('stream', common.mustNotCall()); | |||
|
|||
const count = 32; | |||
//const count = 32; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Heh, yup
@@ -67,29 +56,21 @@ const genericTests = Object.getOwnPropertyNames(constants) | |||
type: 'session' | |||
})); | |||
|
|||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: does ESLint not complain about this extra blank line?
lib/internal/http2/core.js
Outdated
setNextStreamID(id) { | ||
if (typeof id !== 'number') | ||
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'id', 'number'); | ||
if (id <= 0 || id > 2 ** 31 - 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extract 0b111111...
trick to a const
to avoid repetitive calculation, or does V8 optimise that automatically?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe v8 optimizes these but it's still worthwhile avoid repetition
@@ -844,7 +778,7 @@ class Http2Session extends EventEmitter { | |||
|
|||
const handle = this[kHandle]; | |||
if (handle === undefined) | |||
return Object.create(null); | |||
return {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Q: Why is this preferred? (IIRC we discussed this before so I'm curious why change it now.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Under turbofan using the literal is more performant it turns out, and after evaluating, there's no real benefit to making these particular objects have that null prototype
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC, since about the time of TF being enabled (not sure it’s related), Object.create(null)
acts as a hint to the engine that the object is in dictionary mode, i.e. kind of acts like a Map.
So not using a null-prototype object here seems like a good idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TIL 🌈✨ Thanks!
Additional notable changelog:
Do we need to worry about deprecating this API? |
While the code is still in experimental status, we shouldn't need to sorry about deprecating those, although we'll want to call it out as a notable change. As for the possibility of introducing something like quic, we'd have to step back later and evaluate that. These changes shouldn't make it more difficult tho. |
doc/api/http2.md
Outdated
acknowledgement was received. | ||
|
||
```js | ||
session.ping((ack, duration) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want to deviate from errback style, it might be a good idea to add a custom util.promisify
variant (or stick with errback)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'm debating back and forth on this one
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternatively, this could accept a payload
argument and simply send out a PING
frame. Any received PING
frames would emit a ping
event with the payload
as argument. That avoids state (leaking memory) and allows users to implement promises or callbacks as well as limit or allow parallel PINGs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing! 🥇 A lot here so will need to go through this in stages, but had a few nits/questions to start.
// then, on flip of the event loop, do the actual shutdown | ||
setImmediate(doShutdown, this, options); | ||
setImmediate(doShutdown.bind(this), options); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a particular reason we do this? It's definitely faster without the bind
& call
. We could potentially rename self
to something better if that's not very readable (like stream
or session
depending on the context). Especially since these are one-time use only, we're not storing the bound version or anything.
(There are a few other places this is the case.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More of a preference than anything. Not opposed to switching it back
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm fine with it either way. It's a super minor thing. Wanted to make sure I wasn't missing anything.
Can always open my own PR if it really bugs me one day... 😆
@@ -40,7 +29,7 @@ const specificTests = [ | |||
message: 'No stream ID is available because ' + | |||
'maximum stream ID has been reached' | |||
}, | |||
type: 'session' | |||
type: 'stream' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you elaborate on this change? Maximum stream ID being reached means the whole session is probably in trouble, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More of an ergonomics thing, really. Yes it affects the session but it feels more natural to watch for the error on the steam itself. May be revisiting that tho
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense 👍 I can definitely see arguments both ways.
lib/internal/http2/core.js
Outdated
default: | ||
if (ret <= 0) { | ||
if (typeof ret === 'number') { | ||
let target = session; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like we could just not set the target
by default since each case
branch redefines it, including default
.
Or if we don't anticipate it changing, maybe just remove target
altogether and replace it with hard-coded this
. Can always change later if a session error comes to exist in this branch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
self.emit('destroy'); | ||
function finishStreamDestroy() { | ||
const id = this[kID]; | ||
this[kSession][kState].streams.delete(id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Complete nit, but since id
is now used only once, can we delete(this[kID]);
instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I’m missing context, but delete
is always going to change the map of the object whose property is being delete, so you don’t usually want that for performance reasons if it’s not necessary.
(And if you delete anything but the most recently added property, you’re going to switch the object into dictionary mode, which is even worse.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, to be clear I just mean this: this[kSession][kState].streams.delete(this[kID]);
. Avoid the unnecessary const
declaration (which was there because id was reused in the earlier version).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@addaleax ... Keep in mind that this is Map, not a regular object.
Are there any performance implications to this many changes? If any, hopefully all good ones ;) |
I benchmarked carefully as I went through to make sure there were no regressions with perf. It's partly what took so long to get this going (change, bench, change, bench, change,... Lol). The most significant impact is on the Http2Stream class becoming the StreamBase and the change there was negligible. |
Quick note: there are a number of more substantial changes that need to be made to the Closing/Error state handling for both Http2Session and Http2Stream that will need to build on top of these changes. They are rather large and significant changes that I'd much prefer doing in a separate PR once this lands. |
9c649e2
to
4c229db
Compare
Failed on one of the windows variants... passed on everything else... trying one more time: |
Ok, CI appears to be good on all platforms now (there are still a handful running at the moment but they passed on the previous run) |
CI is good. Will squash the commits. @nodejs/http2 ... there are some other large changes that need to build on top of this so I'd appreciate some sign offs so I can get this landed :-) |
This update does several significant things: 1. It eliminates the base Nghttp2* classes and folds those in to node::http2::Http2Session and node::http2::Http2Stream 2. It makes node::http2::Http2Stream a StreamBase instance and sends that out to JS-land to act as the [kHandle] for the JavaScript Http2Stream class. 3. It shifts some of the callbacks from C++ off of the JavaScript Http2Session class to the Http2Stream class. 4. It refactors the data provider structure for FD and Stream based sending to help encapsulate those functions easier 5. It streamlines some of the functions at the C++ layer to eliminate now unnecessary redirections 6. It cleans up node_http2.cc for better readability and maintainability 7. It refactors some of the debug output 8. Because Http2Stream instances are now StreamBases, they are now also trackable using async-hooks 9. The Stream::OnRead algorithm has been simplified with a couple bugs fixed. 10. I've eliminated node_http2_core.h and node_http2_core-inl.h 11. Detect invalid handshake a report protocol error to session 12. Refactor out of memory error, improve other errors 13. Add Http2Session.prototype.ping
72ec460
to
a21dca0
Compare
@jasnell Do you think you could split the commits so that moving code around is its separate thing? I know that’s quite a task, but it would really help a lot… |
umm... at this point, that would be extremely difficult to do, as moving the code around was not done as a separate task. It was done all at once while making the specific individual changes. |
doc/api/errors.md
Outdated
<a id="ERR_HTTP2_PING_LENGTH"></a> | ||
### ERR_HTTP2_PING_LENGTH | ||
|
||
HTTP/2 ping payloads must be exactly 8-bytes in length. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: 8 bytes
doc/api/http2.md
Outdated
`maxOutstandingPings` configuration option. The default maximum is 10. | ||
|
||
If provided, the `payload` must be a `Buffer`, `TypedArray`, or `DataView` | ||
containing 8-bytes of data that will be transmitted with the `PING` and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: 8 bytes
src/node_http2.cc
Outdated
max_header_pairs_ = | ||
type == NGHTTP2_SESSION_SERVER | ||
? std::max(maxHeaderPairs, 4) // minimum # of request headers | ||
: std::max(maxHeaderPairs, 1); // minumum # of response headers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: minumum
src/node_http2.cc
Outdated
const nghttp2_session_callbacks* callbacks, | ||
void* user_data, | ||
const nghttp2_option* options); | ||
init_fn fn = type == NGHTTP2_SESSION_SERVER ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mhhhhh… auto
? 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah yeah... ;-) I haven't quite managed to get used to using auto
too much. I'm working on it, I swear ;-)
// TODO(jasnell): Currently, this creates one uv_prepare_t per Http2Session, | ||
// we should investigate to see if it's faster to create a | ||
// single uv_prepare_t for all Http2Sessions, then iterate | ||
// over each. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just so you know what I’m having in mind for this: I’d keep a boolean flag on a each session that keeps track of whether a send callback is scheduled to be executed, and use the SetImmediate()
from #17117 to schedule it once it becomes necessary (if that flag is not already set).
In particular I’d really like to avoid iterating over all sessions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
whether or not there is data to send is not always easily visible. nghttp has a want_write
function that can be checked to see if a particular session has data to send.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nghttp2 doesn't do it's own I/O so it's always something that we do that makes it want to write something, right? We should use want_write
after such an action to check.
(Fwiw, I would be up for trying to do this myself once this PR is merged, and if I prove myself wrong, so be it. ;))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not saying it's a bad idea :-) ... just saying that it's not always immediately visible.
Btw... Currently, we are already calling SendPendingData()
immediately after receiving and processing data on a socket. It's entirely possible that we could eliminate the prep_t call entirely, I just haven't worked on that yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To expand a bit... the underlying nghttp2_session will have data to write to the output stream in one of two cases:
-
We receive data from the socket and pass it in to nghttp2_session. This will trigger a series of synchronous callbacks to user code. In some cases, nghttp2 will push it's own data onto the send queue during this time, in other cases user code will push it's own data onto the send queue. Either way, when we're doing receiving the chunk of data, we call
SendPendingData()
to push out whatever was sent. -
User-code takes other actions independent of receiving data from the socket. The
uv_prep_t
is really in place to handle this second set of actions. Rather than callingSendPendingData()
multiple times, once after each action, the data is allowed to batch up in nghttp2 internal queue and is sent on each tick of the event loop.
So what you're suggesting is absolutely doable. First, keep the SendPendingData()
in place for 1, then for 2, if any action occurring outside of the receive callback cycle puts data into the queue, schedule an env->SetImmediate()
to call SendPendingData()
on the next tick.
src/node_http2.cc
Outdated
Local<Array> headers = args[2].As<Array>(); | ||
Local<Context> context = env()->context(); | ||
Isolate* isolate = env()->isolate(); | ||
HandleScope scope(isolate); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
src/node_http2.cc
Outdated
Local<Array> headers = args[1].As<Array>(); | ||
Local<Context> context = env()->context(); | ||
Isolate* isolate = env()->isolate(); | ||
HandleScope scope(isolate); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
src/node_http2.cc
Outdated
inline void Http2Session::HandleSettingsFrame(const nghttp2_frame* frame) { | ||
Local<Context> context = env()->context(); | ||
Isolate* isolate = env()->isolate(); | ||
HandleScope scope(isolate); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
src/node_http2.cc
Outdated
Environment* env = Environment::GetCurrent(args); | ||
uint32_t val = args[0]->Uint32Value(env->context()).ToChecked(); | ||
args.GetReturnValue().Set( | ||
OneByteString(env->isolate(), nghttp2_strerror(val))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OneByteString()
uses v8::NewStringType::kNormal
– can you use kInternalized
, since these are static strings (i.e. call NewFromOneByte
directly with that flag)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call :)
src/node_http2.h
Outdated
public: | ||
Provider(Http2Stream* stream, int options); | ||
explicit Provider(int options); | ||
~Provider(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not making a base class destructor virtual is kind of dangerous… The small overhead might be worth avoiding the surprise of future crashes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, good point :)
that was the result of an over-zealous and lazy replace ;-) |
6a7ca53
to
b05f1dc
Compare
Landed in 69e6c5a Added |
This update does several significant things: 1. It eliminates the base Nghttp2* classes and folds those in to node::http2::Http2Session and node::http2::Http2Stream 2. It makes node::http2::Http2Stream a StreamBase instance and sends that out to JS-land to act as the [kHandle] for the JavaScript Http2Stream class. 3. It shifts some of the callbacks from C++ off of the JavaScript Http2Session class to the Http2Stream class. 4. It refactors the data provider structure for FD and Stream based sending to help encapsulate those functions easier 5. It streamlines some of the functions at the C++ layer to eliminate now unnecessary redirections 6. It cleans up node_http2.cc for better readability and maintainability 7. It refactors some of the debug output 8. Because Http2Stream instances are now StreamBases, they are now also trackable using async-hooks 9. The Stream::OnRead algorithm has been simplified with a couple bugs fixed. 10. I've eliminated node_http2_core.h and node_http2_core-inl.h 11. Detect invalid handshake a report protocol error to session 12. Refactor out of memory error, improve other errors 13. Add Http2Session.prototype.ping PR-URL: #17105 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Sebastiaan Deckers <[email protected]>
This update does several significant things: 1. It eliminates the base Nghttp2* classes and folds those in to node::http2::Http2Session and node::http2::Http2Stream 2. It makes node::http2::Http2Stream a StreamBase instance and sends that out to JS-land to act as the [kHandle] for the JavaScript Http2Stream class. 3. It shifts some of the callbacks from C++ off of the JavaScript Http2Session class to the Http2Stream class. 4. It refactors the data provider structure for FD and Stream based sending to help encapsulate those functions easier 5. It streamlines some of the functions at the C++ layer to eliminate now unnecessary redirections 6. It cleans up node_http2.cc for better readability and maintainability 7. It refactors some of the debug output 8. Because Http2Stream instances are now StreamBases, they are now also trackable using async-hooks 9. The Stream::OnRead algorithm has been simplified with a couple bugs fixed. 10. I've eliminated node_http2_core.h and node_http2_core-inl.h 11. Detect invalid handshake a report protocol error to session 12. Refactor out of memory error, improve other errors 13. Add Http2Session.prototype.ping PR-URL: #17105 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Sebastiaan Deckers <[email protected]>
This update does several significant things: 1. It eliminates the base Nghttp2* classes and folds those in to node::http2::Http2Session and node::http2::Http2Stream 2. It makes node::http2::Http2Stream a StreamBase instance and sends that out to JS-land to act as the [kHandle] for the JavaScript Http2Stream class. 3. It shifts some of the callbacks from C++ off of the JavaScript Http2Session class to the Http2Stream class. 4. It refactors the data provider structure for FD and Stream based sending to help encapsulate those functions easier 5. It streamlines some of the functions at the C++ layer to eliminate now unnecessary redirections 6. It cleans up node_http2.cc for better readability and maintainability 7. It refactors some of the debug output 8. Because Http2Stream instances are now StreamBases, they are now also trackable using async-hooks 9. The Stream::OnRead algorithm has been simplified with a couple bugs fixed. 10. I've eliminated node_http2_core.h and node_http2_core-inl.h 11. Detect invalid handshake a report protocol error to session 12. Refactor out of memory error, improve other errors 13. Add Http2Session.prototype.ping PR-URL: #17105 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Sebastiaan Deckers <[email protected]>
This update does several significant things: 1. It eliminates the base Nghttp2* classes and folds those in to node::http2::Http2Session and node::http2::Http2Stream 2. It makes node::http2::Http2Stream a StreamBase instance and sends that out to JS-land to act as the [kHandle] for the JavaScript Http2Stream class. 3. It shifts some of the callbacks from C++ off of the JavaScript Http2Session class to the Http2Stream class. 4. It refactors the data provider structure for FD and Stream based sending to help encapsulate those functions easier 5. It streamlines some of the functions at the C++ layer to eliminate now unnecessary redirections 6. It cleans up node_http2.cc for better readability and maintainability 7. It refactors some of the debug output 8. Because Http2Stream instances are now StreamBases, they are now also trackable using async-hooks 9. The Stream::OnRead algorithm has been simplified with a couple bugs fixed. 10. I've eliminated node_http2_core.h and node_http2_core-inl.h 11. Detect invalid handshake a report protocol error to session 12. Refactor out of memory error, improve other errors 13. Add Http2Session.prototype.ping PR-URL: #17105 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Sebastiaan Deckers <[email protected]>
This update does several significant things: 1. It eliminates the base Nghttp2* classes and folds those in to node::http2::Http2Session and node::http2::Http2Stream 2. It makes node::http2::Http2Stream a StreamBase instance and sends that out to JS-land to act as the [kHandle] for the JavaScript Http2Stream class. 3. It shifts some of the callbacks from C++ off of the JavaScript Http2Session class to the Http2Stream class. 4. It refactors the data provider structure for FD and Stream based sending to help encapsulate those functions easier 5. It streamlines some of the functions at the C++ layer to eliminate now unnecessary redirections 6. It cleans up node_http2.cc for better readability and maintainability 7. It refactors some of the debug output 8. Because Http2Stream instances are now StreamBases, they are now also trackable using async-hooks 9. The Stream::OnRead algorithm has been simplified with a couple bugs fixed. 10. I've eliminated node_http2_core.h and node_http2_core-inl.h 11. Detect invalid handshake a report protocol error to session 12. Refactor out of memory error, improve other errors 13. Add Http2Session.prototype.ping PR-URL: #17105 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Sebastiaan Deckers <[email protected]>
This update does several significant things:
in to node::http2::Http2Session and node::http2::Http2Stream
sends that out to JS-land to act as the [kHandle] for the
JavaScript Http2Stream class.
Http2Session class to the Http2Stream class.
based sending to help encapsulate those functions easier
eliminate now unnecessary redirections
maintainability
now also trackable using async-hooks
couple bugs fixed.
@mcollina @apapirovski @addaleax @sebdeckers @nodejs/http2
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)
http2