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
committerJames M Snell <jasnell@gmail.com>2018-09-24 02:36:24 +0300
commita0c1326257b9679b056d8611ccdee2d6757b0bf0 (patch)
tree4914f6072d5b6b4365cda762114c25923f22145c
parentc67d3d0c3caf74795871f813dbef2ec3fc196e58 (diff)
http2: add ping event
Add a `Http2Session` event whenever a non-ack `PING` is received. Fixes: https://github.com/nodejs/node/issues/18514 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.cc17
-rw-r--r--test/parallel/test-http2-onping.js48
5 files changed, 81 insertions, 5 deletions
diff --git a/doc/api/http2.md b/doc/api/http2.md
index 205c0dc85b8..698f1bf2d87 100644
--- a/doc/api/http2.md
+++ b/doc/api/http2.md
@@ -222,6 +222,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 9cfa2fe4ccf..d5ea26374fc 100644
--- a/lib/internal/http2/core.js
+++ b/lib/internal/http2/core.js
@@ -346,6 +346,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
@@ -821,6 +830,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 aafb3f6e0c7..504bb5db2f4 100644
--- a/src/env.h
+++ b/src/env.h
@@ -229,6 +229,7 @@ struct PackageConfig {
V(onread_string, "onread") \
V(onreadstart_string, "onreadstart") \
V(onreadstop_string, "onreadstop") \
+ 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 837d58c81cb..7dc695ba797 100644
--- a/src/node_http2.cc
+++ b/src/node_http2.cc
@@ -1457,6 +1457,11 @@ void Http2Session::HandleOriginFrame(const nghttp2_frame* frame) {
// Called by OnFrameReceived when a complete PING frame has been received.
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();
@@ -1468,13 +1473,15 @@ 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> arg = Integer::New(isolate, NGHTTP2_ERR_PROTO);
+ 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();
+ }));
+}));