Skip to content

Commit 788c847

Browse files
committed
http2: convert Http2Settings to an AsyncWrap
1 parent 0b0a4fc commit 788c847

11 files changed

+269
-164
lines changed

lib/internal/http2/core.js

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -324,23 +324,14 @@ function onStreamRead(nread, buf, handle) {
324324

325325
// Called when the remote peer settings have been updated.
326326
// Resets the cached settings.
327-
function onSettings(ack) {
327+
function onSettings() {
328328
const session = this[kOwner];
329329
if (session.destroyed)
330330
return;
331331
session[kUpdateTimer]();
332-
let event = 'remoteSettings';
333-
if (ack) {
334-
debug(`Http2Session ${sessionName(session[kType])}: settings acknowledged`);
335-
if (session[kState].pendingAck > 0)
336-
session[kState].pendingAck--;
337-
session[kLocalSettings] = undefined;
338-
event = 'localSettings';
339-
} else {
340-
debug(`Http2Session ${sessionName(session[kType])}: new settings received`);
341-
session[kRemoteSettings] = undefined;
342-
}
343-
process.nextTick(emit, session, event, session[event]);
332+
debug(`Http2Session ${sessionName(session[kType])}: new settings received`);
333+
session[kRemoteSettings] = undefined;
334+
process.nextTick(emit, session, 'remoteSettings', session.remoteSettings);
344335
}
345336

346337
// If the stream exists, an attempt will be made to emit an event
@@ -540,15 +531,32 @@ function onSessionInternalError(code) {
540531
this[kOwner].destroy(new NghttpError(code));
541532
}
542533

534+
function settingsCallback(cb, ack, duration) {
535+
this[kState].pendingAck--;
536+
this[kLocalSettings] = undefined;
537+
if (ack) {
538+
debug(`Http2Session ${sessionName(this[kType])}: settings received`);
539+
const settings = this.localSettings;
540+
if (typeof cb === 'function')
541+
cb(null, settings, duration);
542+
this.emit('localSettings', settings);
543+
} else {
544+
debug(`Http2Session ${sessionName(this[kType])}: settings canceled`);
545+
if (typeof cb === 'function')
546+
cb(new errors.Error('ERR_HTTP2_SETTINGS_CANCEL'));
547+
}
548+
}
549+
543550
// Submits a SETTINGS frame to be sent to the remote peer.
544-
function submitSettings(settings) {
551+
function submitSettings(settings, callback) {
545552
if (this.destroyed)
546553
return;
547554
debug(`Http2Session ${sessionName(this[kType])}: submitting settings`);
548555
this[kUpdateTimer]();
549-
this[kLocalSettings] = undefined;
550556
updateSettingsBuffer(settings);
551-
this[kHandle].settings();
557+
if (!this[kHandle].settings(settingsCallback.bind(this, callback))) {
558+
this.destroy(new errors.Error('ERR_HTTP2_MAX_PENDING_SETTINGS_ACK'));
559+
}
552560
}
553561

554562
// Submits a PRIORITY frame to be sent to the remote peer
@@ -783,7 +791,6 @@ class Http2Session extends EventEmitter {
783791
streams: new Map(),
784792
pendingStreams: new Set(),
785793
pendingAck: 0,
786-
maxPendingAck: Math.max(1, (options.maxPendingAck | 0) || 10),
787794
writeQueueSize: 0
788795
};
789796

@@ -951,21 +958,19 @@ class Http2Session extends EventEmitter {
951958
}
952959

953960
// Submits a SETTINGS frame to be sent to the remote peer.
954-
settings(settings) {
961+
settings(settings, callback) {
955962
if (this.destroyed)
956963
throw new errors.Error('ERR_HTTP2_INVALID_SESSION');
957-
958964
assertIsObject(settings, 'settings');
959965
settings = validateSettings(settings);
960-
const state = this[kState];
961-
if (state.pendingAck === state.maxPendingAck) {
962-
throw new errors.Error('ERR_HTTP2_MAX_PENDING_SETTINGS_ACK',
963-
this[kState].pendingAck);
964-
}
966+
967+
if (callback && typeof callback !== 'function')
968+
throw new errors.TypeError('ERR_INVALID_CALLBACK');
965969
debug(`Http2Session ${sessionName(this[kType])}: sending settings`);
966970

967-
state.pendingAck++;
968-
const settingsFn = submitSettings.bind(this, settings);
971+
this[kState].pendingAck++;
972+
973+
const settingsFn = submitSettings.bind(this, settings, callback);
969974
if (this.connecting) {
970975
this.once('connect', settingsFn);
971976
return;

lib/internal/http2/util.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,8 @@ const IDX_OPTIONS_PEER_MAX_CONCURRENT_STREAMS = 3;
174174
const IDX_OPTIONS_PADDING_STRATEGY = 4;
175175
const IDX_OPTIONS_MAX_HEADER_LIST_PAIRS = 5;
176176
const IDX_OPTIONS_MAX_OUTSTANDING_PINGS = 6;
177-
const IDX_OPTIONS_FLAGS = 7;
177+
const IDX_OPTIONS_MAX_OUTSTANDING_SETTINGS = 7;
178+
const IDX_OPTIONS_FLAGS = 8;
178179

179180
function updateOptionsBuffer(options) {
180181
var flags = 0;
@@ -213,6 +214,11 @@ function updateOptionsBuffer(options) {
213214
optionsBuffer[IDX_OPTIONS_MAX_OUTSTANDING_PINGS] =
214215
options.maxOutstandingPings;
215216
}
217+
if (typeof options.maxOutstandingSettings === 'number') {
218+
flags |= (1 << IDX_OPTIONS_MAX_OUTSTANDING_SETTINGS);
219+
optionsBuffer[IDX_OPTIONS_MAX_OUTSTANDING_SETTINGS] =
220+
Math.max(1, options.maxOutstandingSettings);
221+
}
216222
optionsBuffer[IDX_OPTIONS_FLAGS] = flags;
217223
}
218224

src/async_wrap.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ namespace node {
4343
V(HTTP2SESSION) \
4444
V(HTTP2STREAM) \
4545
V(HTTP2PING) \
46+
V(HTTP2SETTINGS) \
4647
V(HTTPPARSER) \
4748
V(JSSTREAM) \
4849
V(PIPECONNECTWRAP) \

src/env.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,7 @@ class ModuleWrap;
288288
V(host_import_module_dynamically_callback, v8::Function) \
289289
V(http2ping_constructor_template, v8::ObjectTemplate) \
290290
V(http2stream_constructor_template, v8::ObjectTemplate) \
291+
V(http2settings_constructor_template, v8::ObjectTemplate) \
291292
V(inspector_console_api_object, v8::Object) \
292293
V(module_load_list_array, v8::Array) \
293294
V(pbkdf2_constructor_template, v8::ObjectTemplate) \

0 commit comments

Comments
 (0)