Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames M Snell <jasnell@gmail.com>2018-09-22 00:14:04 +0300
committerBeth Griggs <Bethany.Griggs@uk.ibm.com>2018-10-17 02:07:24 +0300
commit10576d6e772eb4a0002d63327563cfb0a09625e5 (patch)
tree9ab8d65c856345e8130dc9aed573e7d352abf8eb
parentca933ce5778364b46d6a8ad6dd4dca456119b948 (diff)
http2: add ping event
Add a `Http2Session` event whenever a non-ack `PING` is received. Fixes: https://github.com/nodejs/node/issues/18514 Backport-PR-URL: https://github.com/nodejs/node/pull/22850 PR-URL: https://github.com/nodejs/node/pull/23009 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Ujjwal Sharma <usharma1998@gmail.com> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com> Reviewed-By: Denys Otrishko <shishugi@gmail.com>
-rw-r--r--doc/api/http2.md10
-rw-r--r--lib/internal/http2/core.js10
-rw-r--r--src/env.h1
-rw-r--r--src/node_http2.cc22
-rw-r--r--test/parallel/test-http2-onping.js48
5 files changed, 82 insertions, 9 deletions
diff --git a/doc/api/http2.md b/doc/api/http2.md
index 349e2b9b710..ebb89c1bd4c 100644
--- a/doc/api/http2.md
+++ b/doc/api/http2.md
@@ -217,6 +217,16 @@ session.on('localSettings', (settings) => {
});
```
+#### Event: 'ping'
+<!-- YAML
+added: REPLACEME
+-->
+
+* `payload` {Buffer} The `PING` frame 8-byte payload
+
+The `'ping'` event is emitted whenever a `PING` frame is received from the
+connected peer.
+
#### Event: 'remoteSettings'
<!-- YAML
added: v8.4.0
diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js
index dadbaefa9ce..4c184fcfe18 100644
--- a/lib/internal/http2/core.js
+++ b/lib/internal/http2/core.js
@@ -287,6 +287,15 @@ function submitRstStream(code) {
}
}
+function onPing(payload) {
+ const session = this[kOwner];
+ if (session.destroyed)
+ return;
+ session[kUpdateTimer]();
+ debug(`Http2Session ${sessionName(session[kType])}: new ping received`);
+ session.emit('ping', payload);
+}
+
// Called when the stream is closed either by sending or receiving an
// RST_STREAM frame, or through a natural end-of-stream.
// If the writable and readable sides of the stream are still open at this
@@ -803,6 +812,7 @@ function setupHandle(socket, type, options) {
handle.error = onSessionInternalError;
handle.onpriority = onPriority;
handle.onsettings = onSettings;
+ handle.onping = onPing;
handle.onheaders = onSessionHeaders;
handle.onframeerror = onFrameError;
handle.ongoawaydata = onGoawayData;
diff --git a/src/env.h b/src/env.h
index 8afedb7044e..e378869b4cc 100644
--- a/src/env.h
+++ b/src/env.h
@@ -225,6 +225,7 @@ class ModuleWrap;
V(onreadstart_string, "onreadstart") \
V(onreadstop_string, "onreadstop") \
V(onselect_string, "onselect") \
+ V(onping_string, "onping") \
V(onsettings_string, "onsettings") \
V(onshutdown_string, "onshutdown") \
V(onsignal_string, "onsignal") \
diff --git a/src/node_http2.cc b/src/node_http2.cc
index 3dad804aa48..49238dcae2d 100644
--- a/src/node_http2.cc
+++ b/src/node_http2.cc
@@ -1468,6 +1468,11 @@ void Http2Session::HandleOriginFrame(const nghttp2_frame* frame) {
// Called by OnFrameReceived when a complete PING frame has been received.
inline void Http2Session::HandlePingFrame(const nghttp2_frame* frame) {
+ Isolate* isolate = env()->isolate();
+ HandleScope scope(isolate);
+ Local<Context> context = env()->context();
+ Context::Scope context_scope(context);
+ Local<Value> arg;
bool ack = frame->hd.flags & NGHTTP2_FLAG_ACK;
if (ack) {
Http2Ping* ping = PopPing();
@@ -1479,16 +1484,15 @@ inline void Http2Session::HandlePingFrame(const nghttp2_frame* frame) {
// receive an unsolicited PING ack on a connection. Either the peer
// is buggy or malicious, and we're not going to tolerate such
// nonsense.
- Isolate* isolate = env()->isolate();
- HandleScope scope(isolate);
- Local<Context> context = env()->context();
- Context::Scope context_scope(context);
-
- Local<Value> argv[1] = {
- Integer::New(isolate, NGHTTP2_ERR_PROTO),
- };
- MakeCallback(env()->error_string(), arraysize(argv), argv);
+ arg = Integer::New(isolate, NGHTTP2_ERR_PROTO);
+ MakeCallback(env()->error_string(), 1, &arg);
}
+ } else {
+ // Notify the session that a ping occurred
+ arg = Buffer::Copy(env(),
+ reinterpret_cast<const char*>(frame->ping.opaque_data),
+ 8).ToLocalChecked();
+ MakeCallback(env()->onping_string(), 1, &arg);
}
}
diff --git a/test/parallel/test-http2-onping.js b/test/parallel/test-http2-onping.js
new file mode 100644
index 00000000000..134a94ddb8f
--- /dev/null
+++ b/test/parallel/test-http2-onping.js
@@ -0,0 +1,48 @@
+'use strict';
+
+const {
+ hasCrypto,
+ mustCall,
+ skip
+} = require('../common');
+if (!hasCrypto)
+ skip('missing crypto');
+
+const {
+ deepStrictEqual
+} = require('assert');
+const {
+ createServer,
+ connect
+} = require('http2');
+
+const check = Buffer.from([ 1, 2, 3, 4, 5, 6, 7, 8 ]);
+
+const server = createServer();
+server.on('stream', mustCall((stream) => {
+ stream.respond();
+ stream.end('ok');
+}));
+server.on('session', mustCall((session) => {
+ session.on('ping', mustCall((payload) => {
+ deepStrictEqual(check, payload);
+ }));
+ session.ping(check, mustCall());
+}));
+server.listen(0, mustCall(() => {
+ const client = connect(`http://localhost:${server.address().port}`);
+
+ client.on('ping', mustCall((payload) => {
+ deepStrictEqual(check, payload);
+ }));
+ client.on('connect', mustCall(() => {
+ client.ping(check, mustCall());
+ }));
+
+ const req = client.request();
+ req.resume();
+ req.on('close', mustCall(() => {
+ client.close();
+ server.close();
+ }));
+}));