Bug 1246761 - Properly handle non-terminal 0-length DATA frames. r=mcmanus

This commit is contained in:
Nicholas Hurley 2016-03-01 16:28:39 -08:00
parent d0da0f7767
commit 89c248fae8
3 changed files with 45 additions and 0 deletions

View File

@ -2410,6 +2410,12 @@ Http2Session::ReadyToProcessDataFrame(enum internalStateType newState)
if (mInputFrameDataStream->RecvdFin() || mInputFrameDataStream->RecvdReset())
GenerateRstStream(STREAM_CLOSED_ERROR, mInputFrameID);
ChangeDownstreamState(DISCARDING_DATA_FRAME);
} else if (mInputFrameDataSize == 0 && !mInputFrameFinal) {
// Only if non-final because the stream properly handles final frames of any
// size, and we want the stream to be able to notice its own end flag.
LOG3(("Http2Session::ReadyToProcessDataFrame %p streamID 0x%X "
"Ignoring 0-length non-terminal data frame.", this, mInputFrameID));
ChangeDownstreamState(DISCARDING_DATA_FRAME);
}
LOG3(("Start Processing Data Frame. "

View File

@ -871,6 +871,12 @@ function test_http2_folded_header() {
chan.asyncOpen2(listener);
}
function test_http2_empty_data() {
var chan = makeChan("https://localhost:" + serverPort + "/emptydata");
var listener = new Http2CheckListener();
chan.asyncOpen2(listener);
}
function test_complete() {
resetPrefs();
do_test_pending();
@ -915,6 +921,7 @@ var tests = [ test_http2_post_big
, test_http2_illegalhpacksoft
, test_http2_illegalhpackhard
, test_http2_folded_header
, test_http2_empty_data
// Add new tests above here - best to add new tests before h1
// streams get too involved
// These next two must always come in this order

View File

@ -45,6 +45,31 @@ Connection.prototype.close = function (error, lastId) {
originalClose.apply(this, arguments);
}
var framer_module = node_http2_root + "/lib/protocol/framer";
var http2_framer = require(framer_module);
var Serializer = http2_framer.Serializer;
var originalTransform = Serializer.prototype._transform;
var newTransform = function (frame, encoding, done) {
if (frame.type == 'DATA') {
// Insert our empty DATA frame
emptyFrame = {};
emptyFrame.type = 'DATA';
emptyFrame.data = new Buffer(0);
emptyFrame.flags = [];
emptyFrame.stream = frame.stream;
var buffers = [];
Serializer['DATA'](emptyFrame, buffers);
Serializer.commonHeader(emptyFrame, buffers);
for (var i = 0; i < buffers.length; i++) {
this.push(buffers[i]);
}
// Reset to the original version for later uses
Serializer.prototype._transform = originalTransform;
}
originalTransform.apply(this, arguments);
};
function getHttpContent(path) {
var content = '<!doctype html>' +
'<html>' +
@ -663,6 +688,13 @@ function handleRequest(req, res) {
// Fall through to the default response behavior
}
else if (u.pathname === "/emptydata") {
// Overwrite the original transform with our version that will insert an
// empty DATA frame at the beginning of the stream response, then fall
// through to the default response behavior.
Serializer.prototype._transform = newTransform;
}
res.setHeader('Content-Type', 'text/html');
if (req.httpVersionMajor != 2) {
res.setHeader('Connection', 'close');