From 929f387cc8897a0589d6e83d2d9b994fc6249619 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Wed, 15 Nov 2017 10:55:31 -0800 Subject: [PATCH] http2: major update to internals 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: https://github.com/nodejs/node/pull/17105 Reviewed-By: Anna Henningsen Reviewed-By: Sebastiaan Deckers --- doc/api/errors.md | 10 + doc/api/http2.md | 94 +- lib/internal/errors.js | 2 + lib/internal/http2/core.js | 741 ++--- lib/internal/http2/util.js | 104 +- node.gyp | 2 - src/async-wrap.h | 3 +- src/env.h | 2 + src/node_http2.cc | 2503 +++++++++++------ src/node_http2.h | 671 ++++- src/node_http2_core-inl.h | 925 ------ src/node_http2_core.h | 516 ---- src/node_http2_state.h | 1 + test/parallel/test-http2-client-data-end.js | 2 +- test/parallel/test-http2-client-destroy.js | 3 - .../test-http2-client-http1-server.js | 27 + .../test-http2-client-onconnect-errors.js | 28 +- ...st-http2-client-priority-before-connect.js | 2 +- ...t-http2-client-rststream-before-connect.js | 10 +- .../test-http2-client-settings-errors.js | 84 - ...est-http2-compat-serverrequest-trailers.js | 2 +- test/parallel/test-http2-getpackedsettings.js | 3 +- .../test-http2-info-headers-errors.js | 22 +- .../test-http2-invalidargtypes-errors.js | 10 +- test/parallel/test-http2-no-more-streams.js | 53 + test/parallel/test-http2-ping.js | 87 + test/parallel/test-http2-pipe.js | 16 +- test/parallel/test-http2-priority-errors.js | 110 - test/parallel/test-http2-respond-errors.js | 21 +- .../test-http2-respond-with-fd-errors.js | 24 +- test/parallel/test-http2-rststream-errors.js | 22 +- .../test-http2-server-http1-client.js | 22 + .../test-http2-server-push-stream-errors.js | 17 +- ...est-http2-server-stream-session-destroy.js | 6 +- test/parallel/test-http2-shutdown-errors.js | 2 +- .../test-http2-util-update-options-buffer.js | 16 +- test/sequential/test-async-wrap-getasyncid.js | 3 +- 37 files changed, 2929 insertions(+), 3237 deletions(-) delete mode 100644 src/node_http2_core-inl.h delete mode 100644 src/node_http2_core.h create mode 100644 test/parallel/test-http2-client-http1-server.js delete mode 100644 test/parallel/test-http2-client-settings-errors.js create mode 100644 test/parallel/test-http2-no-more-streams.js create mode 100644 test/parallel/test-http2-ping.js delete mode 100644 test/parallel/test-http2-priority-errors.js create mode 100644 test/parallel/test-http2-server-http1-client.js diff --git a/doc/api/errors.md b/doc/api/errors.md index 4d28d4f1d13028..663d431398105b 100755 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -776,6 +776,16 @@ created. Used when a message payload is specified for an HTTP response code for which a payload is forbidden. + +### ERR_HTTP2_PING_CANCEL + +An HTTP/2 ping was cancelled. + + +### ERR_HTTP2_PING_LENGTH + +HTTP/2 ping payloads must be exactly 8 bytes in length. + ### ERR_HTTP2_PSEUDOHEADER_NOT_ALLOWED diff --git a/doc/api/http2.md b/doc/api/http2.md index 82eb9b9322d60b..356081fd78a48f 100644 --- a/doc/api/http2.md +++ b/doc/api/http2.md @@ -342,6 +342,44 @@ 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([payload, ]callback) + + +* `payload` {Buffer|TypedArray|DataView} Optional ping payload. +* `callback` {Function} +* Returns: {boolean} + +Sends a `PING` frame to the connected HTTP/2 peer. A `callback` function must +be provided. The method will return `true` if the `PING` was sent, `false` +otherwise. + +The maximum number of outstanding (unacknowledged) pings is determined by the +`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 +returned with the ping acknowledgement. + +The callback will be invoked with three arguments: an error argument that will +be `null` if the `PING` was successfully acknowledged, a `duration` argument +that reports the number of milliseconds elapsed since the ping was sent and the +acknowledgement was received, and a `Buffer` containing the 8-byte `PING` +payload. + +```js +session.ping(Buffer.from('abcdefgh'), (err, duration, payload) => { + if (!err) { + console.log(`Ping acknowledged in ${duration} milliseconds`); + console.log(`With payload '${payload.toString()}`); + } +}); +``` + +If the `payload` argument is not specified, the default payload will be the +64-bit timestamp (little endian) marking the start of the `PING` duration. + #### http2session.remoteSettings - -* stream {Http2Stream} -* code {number} Unsigned 32-bit integer identifying the error code. **Default:** - `http2.constant.NGHTTP2_NO_ERROR` (`0x00`) -* Returns: {undefined} - -Sends an `RST_STREAM` frame to the connected HTTP/2 peer, causing the given -`Http2Stream` to be closed on both sides using [error code][] `code`. - #### http2session.setTimeout(msecs, callback) - -* `stream` {Http2Stream} -* `options` {Object} - * `exclusive` {boolean} When `true` and `parent` identifies a parent Stream, - the given stream is made the sole direct dependency of the parent, with - all other existing dependents made a dependent of the given stream. **Default:** - `false` - * `parent` {number} Specifies the numeric identifier of a stream the given - stream is dependent on. - * `weight` {number} Specifies the relative dependency of a stream in relation - to other streams with the same `parent`. The value is a number between `1` - and `256` (inclusive). - * `silent` {boolean} When `true`, changes the priority locally without - sending a `PRIORITY` frame to the connected peer. -* Returns: {undefined} - -Updates the priority for the given `Http2Stream` instance. - #### http2session.settings(settings)