Skip to content
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

Closed
wants to merge 2 commits into from

Conversation

jasnell
Copy link
Member

@jasnell jasnell commented Nov 17, 2017

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. Add Http2Session.prototype.ping

@mcollina @apapirovski @addaleax @sebdeckers @nodejs/http2

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines
Affected core subsystem(s)

http2

@nodejs-github-bot nodejs-github-bot added the lib / src Issues and PRs related to general changes in the lib or src directory. label Nov 17, 2017
@addaleax
Copy link
Member

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.

Yay for that!

It eliminates the base Nghttp2* classes and folds those in to node::http2::Http2Session and node::http2::Http2Stream

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 ;)

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] = {
Copy link
Member

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…

@mscdex mscdex added the http2 Issues or PRs related to the http2 subsystem. label Nov 18, 2017
@sebdeckers
Copy link
Contributor

@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.

Copy link
Contributor

@sebdeckers sebdeckers left a 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.

assert(ack);
assert.strictEqual(typeof duration, 'number');
})));
// Only one ping at a time
Copy link
Contributor

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.

Copy link
Member Author

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.

Copy link
Contributor

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.

Copy link
Member Author

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

Copy link
Member Author

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

Copy link
Contributor

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)
Copy link
Contributor

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?

Copy link
Member Author

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.

Copy link
Contributor

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;
Copy link
Contributor

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.

Copy link
Member Author

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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops?

Copy link
Member Author

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'
}));


Copy link
Contributor

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?

setNextStreamID(id) {
if (typeof id !== 'number')
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'id', 'number');
if (id <= 0 || id > 2 ** 31 - 1)
Copy link
Contributor

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?

Copy link
Member Author

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 {};
Copy link
Contributor

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.)

Copy link
Member Author

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

Copy link
Member

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.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL 🌈✨ Thanks!

@sebdeckers
Copy link
Contributor

Additional notable changelog:

  • Http2Session.priority() is removed. Only use Http2Stream.priority().

Do we need to worry about deprecating this API?

@jasnell
Copy link
Member Author

jasnell commented Nov 18, 2017

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) => {
Copy link
Member

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)

Copy link
Member Author

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

Copy link
Contributor

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.

Copy link
Member

@apapirovski apapirovski left a 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);
Copy link
Member

@apapirovski apapirovski Nov 17, 2017

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.)

Copy link
Member Author

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

Copy link
Member

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'
Copy link
Member

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?

Copy link
Member Author

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

Copy link
Member

@apapirovski apapirovski Nov 18, 2017

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.

default:
if (ret <= 0) {
if (typeof ret === 'number') {
let target = session;
Copy link
Member

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.

Copy link
Member Author

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);
Copy link
Member

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?

Copy link
Member

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.)

Copy link
Member

@apapirovski apapirovski Nov 18, 2017

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).

Copy link
Member Author

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.

@ronkorving
Copy link
Contributor

Are there any performance implications to this many changes? If any, hopefully all good ones ;)

@jasnell
Copy link
Member Author

jasnell commented Nov 20, 2017

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.

@jasnell
Copy link
Member Author

jasnell commented Nov 20, 2017

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.

@jasnell
Copy link
Member Author

jasnell commented Nov 20, 2017

@jasnell
Copy link
Member Author

jasnell commented Nov 20, 2017

Failed on one of the windows variants... passed on everything else... trying one more time:

CI: https://ci.nodejs.org/job/node-test-pull-request/11565/

@jasnell
Copy link
Member Author

jasnell commented Nov 20, 2017

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)

@jasnell
Copy link
Member Author

jasnell commented Nov 20, 2017

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
@addaleax
Copy link
Member

@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…

@jasnell
Copy link
Member Author

jasnell commented Nov 21, 2017

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.

<a id="ERR_HTTP2_PING_LENGTH"></a>
### ERR_HTTP2_PING_LENGTH

HTTP/2 ping payloads must be exactly 8-bytes in length.
Copy link
Member

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: 8 bytes

max_header_pairs_ =
type == NGHTTP2_SESSION_SERVER
? std::max(maxHeaderPairs, 4) // minimum # of request headers
: std::max(maxHeaderPairs, 1); // minumum # of response headers
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: minumum

const nghttp2_session_callbacks* callbacks,
void* user_data,
const nghttp2_option* options);
init_fn fn = type == NGHTTP2_SESSION_SERVER ?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mhhhhh… auto? 😄

Copy link
Member Author

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.
Copy link
Member

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.

Copy link
Member Author

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.

Copy link
Member

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. ;))

Copy link
Member Author

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.

Copy link
Member Author

@jasnell jasnell Nov 21, 2017

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:

  1. 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.

  2. 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 calling SendPendingData() 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.

Local<Array> headers = args[2].As<Array>();
Local<Context> context = env()->context();
Isolate* isolate = env()->isolate();
HandleScope scope(isolate);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Local<Array> headers = args[1].As<Array>();
Local<Context> context = env()->context();
Isolate* isolate = env()->isolate();
HandleScope scope(isolate);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

inline void Http2Session::HandleSettingsFrame(const nghttp2_frame* frame) {
Local<Context> context = env()->context();
Isolate* isolate = env()->isolate();
HandleScope scope(isolate);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Environment* env = Environment::GetCurrent(args);
uint32_t val = args[0]->Uint32Value(env->context()).ToChecked();
args.GetReturnValue().Set(
OneByteString(env->isolate(), nghttp2_strerror(val)));
Copy link
Member

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)?

Copy link
Member Author

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();
Copy link
Member

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?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, good point :)

@jasnell
Copy link
Member Author

jasnell commented Nov 21, 2017

that was the result of an over-zealous and lazy replace ;-)

@jasnell
Copy link
Member Author

jasnell commented Nov 21, 2017

@addaleax addaleax added author ready PRs that have at least one approval, no pending requests for changes, and a CI started. semver-minor PRs that contain new features and should be released in the next minor version. and removed author ready PRs that have at least one approval, no pending requests for changes, and a CI started. labels Nov 21, 2017
@addaleax
Copy link
Member

Landed in 69e6c5a

Added semver-minor label for the new ping methods

@addaleax addaleax closed this Nov 21, 2017
addaleax pushed a commit that referenced this pull request Nov 21, 2017
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 <anna@addaleax.net>
Reviewed-By: Sebastiaan Deckers <sebdeckers83@gmail.com>
MylesBorins pushed a commit that referenced this pull request Dec 7, 2017
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 <anna@addaleax.net>
Reviewed-By: Sebastiaan Deckers <sebdeckers83@gmail.com>
MylesBorins pushed a commit that referenced this pull request Dec 7, 2017
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 <anna@addaleax.net>
Reviewed-By: Sebastiaan Deckers <sebdeckers83@gmail.com>
@MylesBorins MylesBorins mentioned this pull request Dec 7, 2017
MylesBorins pushed a commit that referenced this pull request Dec 8, 2017
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 <anna@addaleax.net>
Reviewed-By: Sebastiaan Deckers <sebdeckers83@gmail.com>
MylesBorins pushed a commit that referenced this pull request Dec 8, 2017
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 <anna@addaleax.net>
Reviewed-By: Sebastiaan Deckers <sebdeckers83@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
http2 Issues or PRs related to the http2 subsystem. lib / src Issues and PRs related to general changes in the lib or src directory. semver-minor PRs that contain new features and should be released in the next minor version.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants