Skip to content

Commit b0b8d7a

Browse files
committed
AssertionError: false == true in lib/protocol/connection.js
from molnarg#239
1 parent 2c4c310 commit b0b8d7a

File tree

3 files changed

+69
-23
lines changed

3 files changed

+69
-23
lines changed

lib/protocol/connection.js

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -214,15 +214,18 @@ Connection.prototype._insert = function _insert(stream, priority) {
214214
};
215215

216216
Connection.prototype._reprioritize = function _reprioritize(stream, priority) {
217+
this._removePrioritisedStream(stream);
218+
this._insert(stream, priority);
219+
};
220+
221+
Connection.prototype._removePrioritisedStream = function _removePrioritisedStream(stream) {
217222
var bucket = this._streamPriorities[stream._priority];
218223
var index = bucket.indexOf(stream);
219224
assert(index !== -1);
220225
bucket.splice(index, 1);
221226
if (bucket.length === 0) {
222227
delete this._streamPriorities[stream._priority];
223228
}
224-
225-
this._insert(stream, priority);
226229
};
227230

228231
// Creating an *inbound* stream with the given ID. It is called when there's an incoming frame to
@@ -246,9 +249,17 @@ Connection.prototype.createStream = function createStream() {
246249
var stream = new Stream(this._log, this);
247250
this._allocatePriority(stream);
248251

252+
stream.on('end', this._removeStream.bind(this, stream));
253+
249254
return stream;
250255
};
251256

257+
Connection.prototype._removeStream = function _removeStream(stream) {
258+
this._log.trace('Removing outbound stream.');
259+
delete this._streamIds[stream.id];
260+
this._removePrioritisedStream(stream);
261+
};
262+
252263
// Multiplexing
253264
// ------------
254265

@@ -290,7 +301,7 @@ priority_loop:
290301
// 2. if there's no frame, skip this stream
291302
// 3. if forwarding this frame would make `streamCount` greater than `streamLimit`, skip
292303
// this stream
293-
// 4. adding stream to the bucket of the next round
304+
// 4. adding stream to the bucket of the next round unless it has ended
294305
// 5. assigning an ID to the frame (allocating an ID to the stream if there isn't already)
295306
// 6. if forwarding a PUSH_PROMISE, allocate ID to the promised stream
296307
// 7. forwarding the frame, changing `streamCount` as appropriate
@@ -299,6 +310,7 @@ priority_loop:
299310
while (bucket.length > 0) {
300311
for (var index = 0; index < bucket.length; index++) {
301312
var stream = bucket[index];
313+
if(!stream || !stream.upstream) continue;
302314
var frame = stream.upstream.read((this._window > 0) ? this._window : -1);
303315

304316
if (!frame) {
@@ -307,8 +319,11 @@ priority_loop:
307319
stream.upstream.unshift(frame);
308320
continue;
309321
}
310-
311-
nextBucket.push(stream);
322+
if (!stream._ended) {
323+
nextBucket.push(stream);
324+
} else {
325+
delete this._streamIds[stream.id];
326+
}
312327

313328
if (frame.stream === undefined) {
314329
frame.stream = stream.id || this._allocateId(stream);
@@ -323,8 +338,12 @@ priority_loop:
323338
var moreNeeded = this.push(frame);
324339
this._changeStreamCount(frame.count_change);
325340

326-
assert(moreNeeded !== null); // The frame shouldn't be unforwarded
327-
if (moreNeeded === false) {
341+
//assert(moreNeeded !== null); // The frame shouldn't be unforwarded
342+
if (moreNeeded === null) {
343+
this._log.error('The frame shouldn\'t be unforwarded');
344+
}
345+
346+
if (!moreNeeded) {
328347
break priority_loop;
329348
}
330349
}
@@ -577,7 +596,8 @@ Connection.prototype.close = function close(error) {
577596
};
578597

579598
Connection.prototype._receiveGoaway = function _receiveGoaway(frame) {
580-
this._log.debug({ error: frame.error }, 'Other end closed the connection');
599+
// this._log.debug({ error: frame.error }, 'Other end closed the connection');
600+
this._log.error({ frame: frame }, '_receiveGoaway, Other end closed the connection');
581601
this.push(null);
582602
this._closed = true;
583603
if (frame.error !== 'NO_ERROR') {

lib/protocol/framer.js

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,11 @@ Deserializer.prototype._transform = function _transform(chunk, encoding, done) {
111111
// If it's header then the parsed data is stored in a temporary variable and then the
112112
// deserializer waits for the specified length payload.
113113
if ((this._cursor === this._buffer.length) && this._waitingForHeader) {
114-
var payloadSize = Deserializer.commonHeader(this._buffer, this._frame);
114+
var payloadSize = Deserializer.commonHeader(this._buffer, this._frame, this._log);
115115
if (payloadSize <= MAX_PAYLOAD_SIZE) {
116116
this._next(payloadSize);
117117
} else {
118-
this.emit('error', 'FRAME_SIZE_ERROR');
118+
this._log.error({ payloadSize: payloadSize, max: MAX_PAYLOAD_SIZE }, 'FRAME_SIZE_ERROR, _transform');
119119
return;
120120
}
121121
}
@@ -127,7 +127,7 @@ Deserializer.prototype._transform = function _transform(chunk, encoding, done) {
127127
// will also run.
128128
if ((this._cursor === this._buffer.length) && !this._waitingForHeader) {
129129
if (this._frame.type) {
130-
var error = Deserializer[this._frame.type](this._buffer, this._frame, this._role);
130+
var error = Deserializer[this._frame.type](this._buffer, this._frame, this._role, this._log);
131131
if (error) {
132132
this._log.error('Incoming frame parsing error: ' + error);
133133
this.emit('error', error);
@@ -234,8 +234,9 @@ Serializer.commonHeader = function writeCommonHeader(frame, buffers) {
234234
return size;
235235
};
236236

237-
Deserializer.commonHeader = function readCommonHeader(buffer, frame) {
237+
Deserializer.commonHeader = function readCommonHeader(buffer, frame, logger) {
238238
if (buffer.length < 9) {
239+
logger.error({ buffer: buffer }, 'FRAME_SIZE_ERROR, readCommonHeader, buffer.length: ' + buffer.length);
239240
return 'FRAME_SIZE_ERROR';
240241
}
241242

@@ -297,12 +298,13 @@ Serializer.DATA = function writeData(frame, buffers) {
297298
buffers.push(frame.data);
298299
};
299300

300-
Deserializer.DATA = function readData(buffer, frame) {
301+
Deserializer.DATA = function readData(buffer, frame, role, logger) {
301302
var dataOffset = 0;
302303
var paddingLength = 0;
303304
if (frame.flags.PADDED) {
304305
if (buffer.length < 1) {
305306
// We must have at least one byte for padding control, but we don't. Bad peer!
307+
logger.error({ buffer: buffer }, 'FRAME_SIZE_ERROR, readData, buffer.length: ' + buffer.length);
306308
return 'FRAME_SIZE_ERROR';
307309
}
308310
paddingLength = (buffer.readUInt8(dataOffset) & 0xff);
@@ -376,7 +378,7 @@ Serializer.HEADERS = function writeHeadersPriority(frame, buffers) {
376378
buffers.push(frame.data);
377379
};
378380

379-
Deserializer.HEADERS = function readHeadersPriority(buffer, frame) {
381+
Deserializer.HEADERS = function readHeadersPriority(buffer, frame, role, logger) {
380382
var minFrameLength = 0;
381383
if (frame.flags.PADDED) {
382384
minFrameLength += 1;
@@ -386,6 +388,8 @@ Deserializer.HEADERS = function readHeadersPriority(buffer, frame) {
386388
}
387389
if (buffer.length < minFrameLength) {
388390
// Peer didn't send enough data - bad peer!
391+
logger.error({ buffer: buffer }, 'FRAME_SIZE_ERROR, readHeadersPriority, buffer.length: '
392+
+ buffer.length + ' minFrameLength: ' + minFrameLength);
389393
return 'FRAME_SIZE_ERROR';
390394
}
391395

@@ -410,6 +414,8 @@ Deserializer.HEADERS = function readHeadersPriority(buffer, frame) {
410414
if (paddingLength) {
411415
if ((buffer.length - dataOffset) < paddingLength) {
412416
// Not enough data left to satisfy the advertised padding - bad peer!
417+
logger.error({ buffer: buffer }, 'FRAME_SIZE_ERROR, readHeadersPriority, buffer.length: ' + buffer.length
418+
+ ' dataOffset: ' + dataOffset + ' paddingLength: ' + paddingLength);
413419
return 'FRAME_SIZE_ERROR';
414420
}
415421
frame.data = buffer.slice(dataOffset, -1 * paddingLength);
@@ -454,9 +460,10 @@ Serializer.PRIORITY = function writePriority(frame, buffers) {
454460
buffers.push(buffer);
455461
};
456462

457-
Deserializer.PRIORITY = function readPriority(buffer, frame) {
463+
Deserializer.PRIORITY = function readPriority(buffer, frame, role, logger) {
458464
if (buffer.length < 5) {
459465
// PRIORITY frames are 5 bytes long. Bad peer!
466+
logger.error({ buffer: buffer }, 'FRAME_SIZE_ERROR, readPriority, buffer.length: ' + buffer.length);
460467
return 'FRAME_SIZE_ERROR';
461468
}
462469
var dependencyData = new Buffer(4);
@@ -497,9 +504,10 @@ Serializer.RST_STREAM = function writeRstStream(frame, buffers) {
497504
buffers.push(buffer);
498505
};
499506

500-
Deserializer.RST_STREAM = function readRstStream(buffer, frame) {
507+
Deserializer.RST_STREAM = function readRstStream(buffer, frame, role, logger) {
501508
if (buffer.length < 4) {
502509
// RST_STREAM is 4 bytes long. Bad peer!
510+
logger.error({ buffer: buffer }, 'FRAME_SIZE_ERROR, readRstStream, buffer.length: ' + buffer.length);
503511
return 'FRAME_SIZE_ERROR';
504512
}
505513
frame.error = errorCodes[buffer.readUInt32BE(0)];
@@ -564,13 +572,14 @@ Serializer.SETTINGS = function writeSettings(frame, buffers) {
564572
buffers.push(buffer);
565573
};
566574

567-
Deserializer.SETTINGS = function readSettings(buffer, frame, role) {
575+
Deserializer.SETTINGS = function readSettings(buffer, frame, role, logger) {
568576
frame.settings = {};
569577

570578
// Receipt of a SETTINGS frame with the ACK flag set and a length
571579
// field value other than 0 MUST be treated as a connection error
572580
// (Section 5.4.1) of type FRAME_SIZE_ERROR.
573581
if(frame.flags.ACK && buffer.length != 0) {
582+
logger.error({ buffer: buffer }, 'FRAME_SIZE_ERROR, readSettings, buffer.length: ' + buffer.length);
574583
return 'FRAME_SIZE_ERROR';
575584
}
576585

@@ -661,14 +670,16 @@ Serializer.PUSH_PROMISE = function writePushPromise(frame, buffers) {
661670
buffers.push(frame.data);
662671
};
663672

664-
Deserializer.PUSH_PROMISE = function readPushPromise(buffer, frame) {
673+
Deserializer.PUSH_PROMISE = function readPushPromise(buffer, frame, role, logger) {
665674
if (buffer.length < 4) {
675+
logger.error({ buffer: buffer }, 'FRAME_SIZE_ERROR, readPushPromise, buffer.length: ' + buffer.length);
666676
return 'FRAME_SIZE_ERROR';
667677
}
668678
var dataOffset = 0;
669679
var paddingLength = 0;
670680
if (frame.flags.PADDED) {
671681
if (buffer.length < 5) {
682+
logger.error({ buffer: buffer }, 'FRAME_SIZE_ERROR, readPushPromise PADDED, buffer.length: ' + buffer.length);
672683
return 'FRAME_SIZE_ERROR';
673684
}
674685
paddingLength = (buffer.readUInt8(dataOffset) & 0xff);
@@ -678,6 +689,8 @@ Deserializer.PUSH_PROMISE = function readPushPromise(buffer, frame) {
678689
dataOffset += 4;
679690
if (paddingLength) {
680691
if ((buffer.length - dataOffset) < paddingLength) {
692+
logger.error({ buffer: buffer }, 'FRAME_SIZE_ERROR, readPushPromise, buffer.length: ' + buffer.length
693+
+ ' dataOffset: ' + dataOffset + ' paddingLength: ' + paddingLength);
681694
return 'FRAME_SIZE_ERROR';
682695
}
683696
frame.data = buffer.slice(dataOffset, -1 * paddingLength);
@@ -709,8 +722,9 @@ Serializer.PING = function writePing(frame, buffers) {
709722
buffers.push(frame.data);
710723
};
711724

712-
Deserializer.PING = function readPing(buffer, frame) {
725+
Deserializer.PING = function readPing(buffer, frame, role, logger) {
713726
if (buffer.length !== 8) {
727+
logger.error({ buffer: buffer }, 'FRAME_SIZE_ERROR, readPing, buffer.length: ' + buffer.length);
714728
return 'FRAME_SIZE_ERROR';
715729
}
716730
frame.data = buffer;
@@ -758,9 +772,10 @@ Serializer.GOAWAY = function writeGoaway(frame, buffers) {
758772
buffers.push(buffer);
759773
};
760774

761-
Deserializer.GOAWAY = function readGoaway(buffer, frame) {
762-
if (buffer.length !== 8) {
775+
Deserializer.GOAWAY = function readGoaway(buffer, frame, role, logger) {
776+
if (buffer.length < 8) {
763777
// GOAWAY must have 8 bytes
778+
logger.error({ frame: frame }, 'FRAME_SIZE_ERROR, readGoAway, buffer.length: ' + buffer.length);
764779
return 'FRAME_SIZE_ERROR';
765780
}
766781
frame.last_stream = buffer.readUInt32BE(0) & 0x7fffffff;
@@ -769,6 +784,13 @@ Deserializer.GOAWAY = function readGoaway(buffer, frame) {
769784
// Unknown error types are to be considered equivalent to INTERNAL ERROR
770785
frame.error = 'INTERNAL_ERROR';
771786
}
787+
// Read remaining data into "debug_data"
788+
// https://http2.github.io/http2-spec/#GOAWAY
789+
// Endpoints MAY append opaque data to the payload of any GOAWAY frame
790+
if (buffer.length > 8) {
791+
logger.error({ frame: frame }, 'readGoAway debug_data, buffer.length: ' + buffer.length);
792+
frame.debug_data = buffer.slice(8);
793+
}
772794
};
773795

774796
// [WINDOW_UPDATE](https://tools.ietf.org/html/rfc7540#section-6.9)
@@ -799,8 +821,9 @@ Serializer.WINDOW_UPDATE = function writeWindowUpdate(frame, buffers) {
799821
buffers.push(buffer);
800822
};
801823

802-
Deserializer.WINDOW_UPDATE = function readWindowUpdate(buffer, frame) {
824+
Deserializer.WINDOW_UPDATE = function readWindowUpdate(buffer, frame, role, logger) {
803825
if (buffer.length !== WINDOW_UPDATE_PAYLOAD_SIZE) {
826+
logger.error({ frame: frame }, 'FRAME_SIZE_ERROR, readWindowUpdate, buffer.length: ' + buffer.length);
804827
return 'FRAME_SIZE_ERROR';
805828
}
806829
frame.window_size = buffer.readUInt32BE(0) & 0x7fffffff;
@@ -1034,12 +1057,14 @@ function unescape(s) {
10341057
return t;
10351058
}
10361059

1037-
Deserializer.ALTSVC = function readAltSvc(buffer, frame) {
1060+
Deserializer.ALTSVC = function readAltSvc(buffer, frame, role, logger) {
10381061
if (buffer.length < 2) {
1062+
logger.error({ buffer: buffer }, 'FRAME_SIZE_ERROR, readAltSvc, buffer.length: ' + buffer.length);
10391063
return 'FRAME_SIZE_ERROR';
10401064
}
10411065
var originLength = buffer.readUInt16BE(0);
10421066
if ((buffer.length - 2) < originLength) {
1067+
logger.error({ buffer: buffer }, 'FRAME_SIZE_ERROR, readAltSvc 2, buffer.length: ' + buffer.length);
10431068
return 'FRAME_SIZE_ERROR';
10441069
}
10451070
frame.origin = buffer.toString('ascii', 2, 2 + originLength);

lib/protocol/stream.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ Stream.prototype._write = function _write(buffer, encoding, ready) {
313313

314314
// * Call ready when upstream is ready to receive more frames.
315315
if (moreNeeded) {
316+
this._log.error('Stream._write moreNeeded');
316317
ready();
317318
} else {
318319
this._sendMore = ready;

0 commit comments

Comments
 (0)