Bug 1001022 (part 2) - Update unit tests for http2 draft12. r=mcmanus

This commit is contained in:
Nicholas Hurley 2014-04-29 18:46:05 -07:00
parent f0e5a8c1c1
commit 9090b45467
14 changed files with 171 additions and 194 deletions

View File

@ -25,7 +25,7 @@ var bigListenerMD5 = '8f607cfdd2c87d6a7eedb657dafbd836';
function checkIsHttp2(request) {
try {
if (request.getResponseHeader("X-Firefox-Spdy") == "h2-11") {
if (request.getResponseHeader("X-Firefox-Spdy") == "h2-12") {
if (request.getResponseHeader("X-Connection-Http2") == "yes") {
return true;
}

View File

@ -1,6 +1,12 @@
Version history
===============
### 2.5.0 (2014-04-24) ###
* Upgrade to the latest draft: [draft-ietf-httpbis-http2-12]
[draft-ietf-httpbis-http2-12]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-12
### 2.4.0 (2014-04-16) ###
* Upgrade to the latest draft: [draft-ietf-httpbis-http2-11]

View File

@ -1,7 +1,7 @@
node-http2
==========
An HTTP/2 ([draft-ietf-httpbis-http2-11](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11))
An HTTP/2 ([draft-ietf-httpbis-http2-12](http://tools.ietf.org/html/draft-ietf-httpbis-http2-12))
client and server implementation for node.js.
Installation
@ -114,12 +114,12 @@ point to understand the code.
### Test coverage ###
To generate a code coverage report, run `npm test --coverage` (which runs very slowly, be patient).
Code coverage summary as of version 2.3.0:
Code coverage summary as of version 2.4.0:
```
Statements : 94% ( 392/417 )
Branches : 80.63% ( 129/160 )
Functions : 93.65% ( 59/63 )
Lines : 94% ( 392/417 )
Statements : 93.19% ( 397/426 )
Branches : 79.88% ( 131/164 )
Functions : 93.75% ( 60/64 )
Lines : 93.19% ( 397/426 )
```
There's a hosted version of the detailed (line-by-line) coverage report

View File

@ -121,7 +121,7 @@
//
// [1]: http://nodejs.org/api/https.html
// [2]: http://nodejs.org/api/http.html
// [3]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-8.1.3.2
// [3]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-8.1.3.2
// [expect-continue]: https://github.com/http2/http2-spec/issues/18
// [connect]: https://github.com/http2/http2-spec/issues/230
@ -204,7 +204,7 @@ function IncomingMessage(stream) {
}
IncomingMessage.prototype = Object.create(PassThrough.prototype, { constructor: { value: IncomingMessage } });
// [Request Header Fields](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-8.1.3.1)
// [Request Header Fields](http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-8.1.3.1)
// * `headers` argument: HTTP/2.0 request and response header fields carry information as a series
// of key-value pairs. This includes the target URI for the request, the status code for the
// response, as well as HTTP header fields.
@ -516,7 +516,7 @@ function IncomingRequest(stream) {
}
IncomingRequest.prototype = Object.create(IncomingMessage.prototype, { constructor: { value: IncomingRequest } });
// [Request Header Fields](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-8.1.3.1)
// [Request Header Fields](http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-8.1.3.1)
// * `headers` argument: HTTP/2.0 request and response header fields carry information as a series
// of key-value pairs. This includes the target URI for the request, the status code for the
// response, as well as HTTP header fields.
@ -947,7 +947,7 @@ function IncomingResponse(stream) {
}
IncomingResponse.prototype = Object.create(IncomingMessage.prototype, { constructor: { value: IncomingResponse } });
// [Response Header Fields](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-8.1.3.2)
// [Response Header Fields](http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-8.1.3.2)
// * `headers` argument: HTTP/2.0 request and response header fields carry information as a series
// of key-value pairs. This includes the target URI for the request, the status code for the
// response, as well as HTTP header fields.

View File

@ -1,4 +1,4 @@
// [node-http2][homepage] is an [HTTP/2 (draft 11)][http2] implementation for [node.js][node].
// [node-http2][homepage] is an [HTTP/2 (draft 12)][http2] implementation for [node.js][node].
//
// The core of the protocol is implemented by the [http2-protocol] module. This module provides
// two important features on top of http2-protocol:
@ -11,7 +11,7 @@
//
// [homepage]: https://github.com/molnarg/node-http2
// [http2-protocol]: https://github.com/molnarg/node-http2-protocol
// [http2]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-11
// [http2]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-12
// [node]: http://nodejs.org/
// [node-https]: http://nodejs.org/api/https.html
// [node-http]: http://nodejs.org/api/http.html

View File

@ -1,6 +1,12 @@
Version history
===============
### 0.12.0 (2014-04-24) ###
* Upgrade to the latest draft: [draft-ietf-httpbis-http2-12][draft-12]
[draft-12]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-12
### 0.11.0 (2014-04-16) ###
* Upgrade to the latest draft: [draft-ietf-httpbis-http2-11][draft-11]

View File

@ -1,7 +1,7 @@
node-http2-protocol
===================
An HTTP/2 ([draft-ietf-httpbis-http2-11](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11))
An HTTP/2 ([draft-ietf-httpbis-http2-12](http://tools.ietf.org/html/draft-ietf-httpbis-http2-12))
framing layer implementaion for node.js.
Installation
@ -50,12 +50,12 @@ point to understand the code.
### Test coverage ###
To generate a code coverage report, run `npm test --coverage` (it may be slow, be patient).
Code coverage summary as of version 0.9.0:
Code coverage summary as of version 0.12.0:
```
Statements : 91.86% ( 1276/1389 )
Branches : 85.62% ( 524/612 )
Functions : 92.31% ( 144/156 )
Lines : 91.83% ( 1270/1383 )
Statements : 91.6% ( 1352/1476 )
Branches : 85.15% ( 562/660 )
Functions : 92.5% ( 148/160 )
Lines : 91.69% ( 1346/1468 )
```
There's a hosted version of the detailed (line-by-line) coverage report

View File

@ -19,7 +19,7 @@ exports.Flow = Flow;
// * **setInitialWindow(size)**: the initial flow control window size can be changed *any time*
// ([as described in the standard][1]) using this method
//
// [1]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-6.9.2
// [1]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-6.9.2
// API for child classes
// ---------------------

View File

@ -148,7 +148,7 @@ Deserializer.prototype._transform = function _transform(chunk, encoding, done) {
done();
};
// [Frame Header](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-4.1)
// [Frame Header](http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-4.1)
// --------------------------------------------------------------
//
// HTTP/2.0 frames share a common base format consisting of an 8-byte header followed by 0 to 65535
@ -262,7 +262,7 @@ Deserializer.commonHeader = function readCommonHeader(buffer, frame) {
// * `typeSpecificAttributes`: a register of frame specific frame object attributes (used by
// logging code and also serves as documentation for frame objects)
// [DATA Frames](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-6.1)
// [DATA Frames](http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-6.1)
// ------------------------------------------------------------
//
// DATA frames (type=0x0) convey arbitrary, variable-length sequences of octets associated with a
@ -278,15 +278,17 @@ Deserializer.commonHeader = function readCommonHeader(buffer, frame) {
// MUST NOT coalesce frames across a segment boundary and MUST preserve segment boundaries when
// forwarding frames.
// * PAD_LOW (0x08):
// Bit 5 being set indicates that the Pad Low field is present.
// Bit 4 being set indicates that the Pad Low field is present.
// * PAD_HIGH (0x10):
// Bit 6 being set indicates that the Pad High field is present. This bit MUST NOT be set unless
// Bit 5 being set indicates that the Pad High field is present. This bit MUST NOT be set unless
// the PAD_LOW flag is also set. Endpoints that receive a frame with PAD_HIGH set and PAD_LOW
// cleared MUST treat this as a connection error of type PROTOCOL_ERROR.
// * COMPRESSED (0x20):
// Bit 6 being set indicates that the data in the frame has been compressed with GZIP compression.
frameTypes[0x0] = 'DATA';
frameFlags.DATA = ['END_STREAM', 'END_SEGMENT', 'RESERVED4', 'PAD_LOW', 'PAD_HIGH'];
frameFlags.DATA = ['END_STREAM', 'END_SEGMENT', 'RESERVED4', 'PAD_LOW', 'PAD_HIGH', 'COMPRESSED'];
typeSpecificAttributes.DATA = ['data'];
@ -307,6 +309,11 @@ Deserializer.DATA = function readData(buffer, frame) {
} else if (frame.flags.PAD_HIGH) {
return 'DATA frame got PAD_HIGH without PAD_LOW';
}
if (frame.flags.COMPRESSED) {
return 'DATA frame received COMPRESSED data (unsupported)';
}
if (paddingLength) {
frame.data = buffer.slice(dataOffset, -1 * paddingLength);
} else {
@ -314,7 +321,7 @@ Deserializer.DATA = function readData(buffer, frame) {
}
};
// [HEADERS](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-6.2)
// [HEADERS](http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-6.2)
// --------------------------------------------------------------
//
// The HEADERS frame (type=0x1) allows the sender to create a stream.
@ -340,21 +347,19 @@ Deserializer.DATA = function readData(buffer, frame) {
frameTypes[0x1] = 'HEADERS';
frameFlags.HEADERS = ['END_STREAM', 'END_SEGMENT', 'END_HEADERS', 'PAD_LOW', 'PAD_HIGH', 'PRIORITY_GROUP', 'PRIORITY_DEPENDENCY'];
frameFlags.HEADERS = ['END_STREAM', 'END_SEGMENT', 'END_HEADERS', 'PAD_LOW', 'PAD_HIGH', 'PRIORITY'];
typeSpecificAttributes.HEADERS = ['priorityGroup', 'groupWeight', 'priorityDependency', 'exclusiveDependency', 'headers', 'data'];
typeSpecificAttributes.HEADERS = ['priorityDependency', 'priorityWeight', 'exclusiveDependency', 'headers', 'data'];
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Pad High? (8) | Pad Low? (8) |
// +-+-------------+---------------+-------------------------------+
// |R| Priority Group Identifier? (31) |
// |E| Stream Dependency? (31) |
// +-+-------------+-----------------------------------------------+
// | Weight? (8) |
// +-+-------------+-----------------------------------------------+
// |E| Stream Dependency? (31) |
// +-+-------------------------------------------------------------+
// | Header Block Fragment (*) ...
// +---------------------------------------------------------------+
// | Padding (*) ...
@ -363,20 +368,15 @@ typeSpecificAttributes.HEADERS = ['priorityGroup', 'groupWeight', 'priorityDepen
// The payload of a HEADERS frame contains a Headers Block
Serializer.HEADERS = function writeHeadersPriority(frame, buffers) {
if (frame.flags.PRIORITY_GROUP) {
if (frame.flags.PRIORITY) {
var buffer = new Buffer(5);
assert((0 <= frame.priorityGroup) && (frame.priorityGroup <= 0x7fffffff), frame.priorityGroup);
buffer.writeUInt32BE(frame.priorityGroup, 0);
assert((0 <= frame.groupWeight) && (frame.groupWeight <= 0xff), frame.groupWeight);
buffer.writeUInt8(frame.groupWeight, 4);
buffers.push(buffer);
} else if (frame.flags.PRIORITY_DEPENDENCY) {
var buffer = new Buffer(4);
assert((0 <= frame.priorityDependency) && (frame.priorityDependency <= 0x7fffffff), frame.priorityDependency);
buffer.writeUInt32BE(frame.priorityDependency, 0);
if (frame.exclusiveDependency) {
buffer[0] |= 0x80;
}
assert((0 <= frame.priorityWeight) && (frame.priorityWeight <= 0xff), frame.priorityWeight);
buffer.writeUInt8(frame.priorityWeight, 4);
buffers.push(buffer);
}
buffers.push(frame.data);
@ -396,21 +396,15 @@ Deserializer.HEADERS = function readHeadersPriority(buffer, frame) {
return 'HEADERS frame got PAD_HIGH without PAD_LOW';
}
if (frame.flags.PRIORITY_GROUP) {
if (frame.flags.PRIORITY_DEPENDENCY) {
return 'HEADERS frame got both PRIORITY_GROUP and PRIORITY_DEPENDENCY';
}
frame.priorityGroup = buffer.readUInt32BE(dataOffset) & 0x7fffffff;
dataOffset += 4;
frame.groupWeight = buffer.readUInt8(dataOffset);
dataOffset += 1;
} else if (frame.flags.PRIORITY_DEPENDENCY) {
if (frame.flags.PRIORITY) {
var dependencyData = new Buffer(4);
buffer.copy(dependencyData, 0, dataOffset, dataOffset + 4);
dataOffset += 4;
frame.exclusiveDependency = !!(dependencyData[0] & 0x80);
dependencyData[0] &= 0x7f;
frame.priorityDependency = dependencyData.readUInt32BE(0);
frame.priorityWeight = buffer.readUInt8(dataOffset);
dataOffset += 1;
}
if (paddingLength) {
@ -420,7 +414,7 @@ Deserializer.HEADERS = function readHeadersPriority(buffer, frame) {
}
};
// [PRIORITY](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-6.3)
// [PRIORITY](http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-6.3)
// -------------------------------------------------------
//
// The PRIORITY frame (type=0x2) specifies the sender-advised priority of a stream.
@ -429,66 +423,43 @@ Deserializer.HEADERS = function readHeadersPriority(buffer, frame) {
frameTypes[0x2] = 'PRIORITY';
frameFlags.PRIORITY = ['RESERVED1', 'RESERVED2', 'RESERVED4', 'RESERVED8', 'RESERVED16', 'PRIORITY_GROUP', 'PRIORITY_DEPENDENCY'];
frameFlags.PRIORITY = [];
typeSpecificAttributes.PRIORITY = ['priorityGroup', 'groupWeight', 'priorityDependency', 'exclusiveDependency'];
typeSpecificAttributes.PRIORITY = ['priorityDependency', 'priorityWeight', 'exclusiveDependency'];
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |R| Priority Group Identifier? (31) |
// |E| Stream Dependency? (31) |
// +-+-------------+-----------------------------------------------+
// | Weight? (8) |
// +-+-------------+-----------------------------------------------+
// |E| Stream Dependency? (31) |
// +-+-------------------------------------------------------------+
// +-+-------------+
//
// The payload of a PRIORITY frame contains a single reserved bit and a 31-bit priority.
// The payload of a PRIORITY frame contains an exclusive bit, a 31-bit dependency, and an 8-bit weight
Serializer.PRIORITY = function writePriority(frame, buffers) {
var buffer;
assert((frame.flags.PRIORITY_GROUP || frame.flags.PRIORITY_DEPENDENCY) &&
!(frame.flags.PRIORITY_GROUP && frame.flags.PRIORITY_DEPENDENCY),
frame.flags.PRIORITY_GROUP && frame.flags.PRIORITY_DEPENDENCY);
if (frame.flags.PRIORITY_GROUP) {
buffer = new Buffer(5);
assert((0 <= frame.priorityGroup) && (frame.priorityGroup <= 0x7fffffff), frame.priorityGroup);
buffer.writeUInt32BE(frame.priorityGroup, 0);
assert((0 <= frame.groupWeight) && (frame.groupWeight <= 0xff), frame.groupWeight);
buffer.writeUInt8(frame.groupWeight, 4);
} else { // frame.flags.PRIORITY_DEPENDENCY
buffer = new Buffer(4);
assert((0 <= frame.priorityDependency) && (frame.priorityDependency <= 0x7fffffff), frame.priorityDependency);
buffer.writeUInt32BE(frame.priorityDependency, 0);
if (frame.exclusiveDependency) {
buffer[0] |= 0x80;
}
var buffer = new Buffer(5);
assert((0 <= frame.priorityDependency) && (frame.priorityDependency <= 0x7fffffff), frame.priorityDependency);
buffer.writeUInt32BE(frame.priorityDependency, 0);
if (frame.exclusiveDependency) {
buffer[0] |= 0x80;
}
assert((0 <= frame.priorityWeight) && (frame.priorityWeight <= 0xff), frame.priorityWeight);
buffer.writeUInt8(frame.priorityWeight, 4);
buffers.push(buffer);
};
Deserializer.PRIORITY = function readPriority(buffer, frame) {
if (frame.flags.PRIORITY_GROUP) {
if (frame.flags.PRIORITY_DEPENDENCY) {
return 'PRIORITY frame got both PRIORITY_GROUP and PRIORITY_DEPENDENCY';
}
frame.priorityGroup = buffer.readUInt32BE(0) & 0x7fffffff;
frame.groupWeight = buffer.readUInt8(4);
} else if (frame.flags.PRIORITY_DEPENDENCY) {
var dependencyData = new Buffer(4);
buffer.copy(dependencyData, 0, 0, 4);
frame.exclusiveDependency = !!(dependencyData[0] & 0x80);
dependencyData[0] &= 0x7f;
frame.priorityDependency = dependencyData.readUInt32BE(0);
} else {
return 'PRIORITY frame got neither PRIORITY_GROUP nor PRIORITY_DEPENDENCY';
}
var dependencyData = new Buffer(4);
buffer.copy(dependencyData, 0, 0, 4);
frame.exclusiveDependency = !!(dependencyData[0] & 0x80);
dependencyData[0] &= 0x7f;
frame.priorityDependency = dependencyData.readUInt32BE(0);
frame.priorityWeight = buffer.readUInt8(4);
};
// [RST_STREAM](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-6.4)
// [RST_STREAM](http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-6.4)
// -----------------------------------------------------------
//
// The RST_STREAM frame (type=0x3) allows for abnormal termination of a stream.
@ -522,7 +493,7 @@ Deserializer.RST_STREAM = function readRstStream(buffer, frame) {
frame.error = errorCodes[buffer.readUInt32BE(0)];
};
// [SETTINGS](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-6.5)
// [SETTINGS](http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-6.5)
// -------------------------------------------------------
//
// The SETTINGS frame (type=0x4) conveys configuration parameters that affect how endpoints
@ -620,15 +591,21 @@ definedSettings[1] = { name: 'SETTINGS_HEADER_TABLE_SIZE', flag: false };
// push is permitted.
definedSettings[2] = { name: 'SETTINGS_ENABLE_PUSH', flag: true };
// * SETTINGS_MAX_CONCURRENT_STREAMS (4):
// * SETTINGS_MAX_CONCURRENT_STREAMS (3):
// indicates the maximum number of concurrent streams that the sender will allow.
definedSettings[3] = { name: 'SETTINGS_MAX_CONCURRENT_STREAMS', flag: false };
// * SETTINGS_INITIAL_WINDOW_SIZE (7):
// * SETTINGS_INITIAL_WINDOW_SIZE (4):
// indicates the sender's initial stream window size (in bytes) for new streams.
definedSettings[4] = { name: 'SETTINGS_INITIAL_WINDOW_SIZE', flag: false };
// [PUSH_PROMISE](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-6.6)
// * SETTINGS_COMPRESS_DATA (5):
// this setting is used to enable GZip compression of DATA frames. A value of 1 indicates that
// DATA frames MAY be compressed. A value of 0 indicates that compression is not permitted.
// The initial value is 0.
definedSettings[5] = { name: 'SETTINGS_COMPRESS_DATA', flag: true };
// [PUSH_PROMISE](http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-6.6)
// ---------------------------------------------------------------
//
// The PUSH_PROMISE frame (type=0x5) is used to notify the peer endpoint in advance of streams the
@ -691,7 +668,7 @@ Deserializer.PUSH_PROMISE = function readPushPromise(buffer, frame) {
}
};
// [PING](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-6.7)
// [PING](http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-6.7)
// -----------------------------------------------
//
// The PING frame (type=0x6) is a mechanism for measuring a minimal round-trip time from the
@ -721,7 +698,7 @@ Deserializer.PING = function readPing(buffer, frame) {
frame.data = buffer;
};
// [GOAWAY](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-6.8)
// [GOAWAY](http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-6.8)
// ---------------------------------------------------
//
// The GOAWAY frame (type=0x7) informs the remote peer to stop creating streams on this connection.
@ -768,7 +745,7 @@ Deserializer.GOAWAY = function readGoaway(buffer, frame) {
frame.error = errorCodes[buffer.readUInt32BE(4)];
};
// [WINDOW_UPDATE](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-6.9)
// [WINDOW_UPDATE](http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-6.9)
// -----------------------------------------------------------------
//
// The WINDOW_UPDATE frame (type=0x8) is used to implement flow control.
@ -803,7 +780,7 @@ Deserializer.WINDOW_UPDATE = function readWindowUpdate(buffer, frame) {
frame.window_size = buffer.readUInt32BE(0) & 0x7fffffff;
};
// [CONTINUATION](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-6.10)
// [CONTINUATION](http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-6.10)
// ------------------------------------------------------------
//
// The CONTINUATION frame (type=0x9) is used to continue a sequence of header block fragments.
@ -850,7 +827,7 @@ Deserializer.CONTINUATION = function readContinuation(buffer, frame) {
}
};
// [ALTSVC](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-6.11)
// [ALTSVC](http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-6.11)
// ------------------------------------------------------------
//
// The ALTSVC frame (type=0xA) advertises the availability of an alternative service to the client.
@ -939,7 +916,27 @@ Deserializer.ALTSVC = function readAltSvc(buffer, frame) {
frame.origin = buffer.toString('ascii', 9 + pidLength + hostLength);
};
// [Error Codes](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-7)
// [BLOCKED](http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-6.12)
// ------------------------------------------------------------
//
// The BLOCKED frame (type=0xB) indicates that the sender is unable to send data
// due to a closed flow control window.
//
// The BLOCKED frame does not define any flags and contains no payload.
frameTypes[0xB] = 'BLOCKED';
frameFlags.BLOCKED = [];
typeSpecificAttributes.BLOCKED = [];
Serializer.BLOCKED = function writeBlocked(frame, buffers) {
};
Deserializer.BLOCKED = function readBlocked(buffer, frame) {
};
// [Error Codes](http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-7)
// ------------------------------------------------------------
var errorCodes = [

View File

@ -1,4 +1,4 @@
// [node-http2-protocol][homepage] is an implementation of the [HTTP/2 (draft 11)][http2]
// [node-http2-protocol][homepage] is an implementation of the [HTTP/2 (draft 12)][http2]
// framing layer for [node.js][node].
//
// The main building blocks are [node.js streams][node-stream] that are connected through pipes.
@ -28,16 +28,16 @@
// between the binary and the JavaScript object representation of HTTP/2 frames
//
// [homepage]: https://github.com/molnarg/node-http2
// [http2]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-11
// [http2-connheader]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-3.5
// [http2-stream]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-5
// [http2-streamstate]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-5.1
// [http2]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-12
// [http2-connheader]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-3.5
// [http2-stream]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-5
// [http2-streamstate]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-5.1
// [node]: http://nodejs.org/
// [node-stream]: http://nodejs.org/api/stream.html
// [node-https]: http://nodejs.org/api/https.html
// [node-http]: http://nodejs.org/api/http.html
exports.ImplementedVersion = 'h2-11';
exports.ImplementedVersion = 'h2-12';
exports.Endpoint = require('./endpoint').Endpoint;

View File

@ -227,6 +227,8 @@ Stream.prototype._writeUpstream = function _writeUpstream(frame) {
this._onPriority(frame);
} else if (frame.type === 'ALTSVC') {
// TODO
} else if (frame.type === 'BLOCKED') {
// TODO
}
// * If it's an invalid stream level frame, emit error
@ -324,7 +326,7 @@ Stream.prototype._finishing = function _finishing() {
}
};
// [Stream States](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-5.1)
// [Stream States](http://tools.ietf.org/html/draft-ietf-httpbis-http2-12#section-5.1)
// ----------------
//
// +--------+
@ -384,7 +386,7 @@ Stream.prototype._transition = function transition(sending, frame) {
var connectionError;
var streamError;
var DATA = false, HEADERS = false, PRIORITY = false, ALTSVC = false;
var DATA = false, HEADERS = false, PRIORITY = false, ALTSVC = false, BLOCKED = false;
var RST_STREAM = false, PUSH_PROMISE = false, WINDOW_UPDATE = false;
switch(frame.type) {
case 'DATA' : DATA = true; break;
@ -394,6 +396,7 @@ Stream.prototype._transition = function transition(sending, frame) {
case 'PUSH_PROMISE' : PUSH_PROMISE = true; break;
case 'WINDOW_UPDATE': WINDOW_UPDATE = true; break;
case 'ALTSVC' : ALTSVC = true; break;
case 'BLOCKED' : BLOCKED = true; break;
}
var previousState = this.state;
@ -451,7 +454,7 @@ Stream.prototype._transition = function transition(sending, frame) {
this._setState('CLOSED');
} else if (receiving && HEADERS) {
this._setState('HALF_CLOSED_LOCAL');
} else if (sending && PRIORITY) {
} else if (BLOCKED || (sending && PRIORITY)) {
/* No state change */
} else {
connectionError = 'PROTOCOL_ERROR';
@ -486,7 +489,7 @@ Stream.prototype._transition = function transition(sending, frame) {
case 'HALF_CLOSED_LOCAL':
if (RST_STREAM || (receiving && frame.flags.END_STREAM)) {
this._setState('CLOSED');
} else if (receiving || (sending && (PRIORITY || WINDOW_UPDATE))) {
} else if (BLOCKED || ALTSVC ||receiving || (sending && (PRIORITY || WINDOW_UPDATE))) {
/* No state change */
} else {
connectionError = 'PROTOCOL_ERROR';
@ -506,7 +509,7 @@ Stream.prototype._transition = function transition(sending, frame) {
case 'HALF_CLOSED_REMOTE':
if (RST_STREAM || (sending && frame.flags.END_STREAM)) {
this._setState('CLOSED');
} else if (sending || (receiving && (WINDOW_UPDATE || PRIORITY))) {
} else if (BLOCKED || ALTSVC ||sending || (receiving && (WINDOW_UPDATE || PRIORITY))) {
/* No state change */
} else {
connectionError = 'PROTOCOL_ERROR';

View File

@ -1,6 +1,6 @@
{
"name": "http2-protocol",
"version": "0.11.0",
"version": "0.12.0",
"description": "A JavaScript implementation of the HTTP/2 framing layer",
"main": "lib/index.js",
"engines" : {

View File

@ -22,7 +22,7 @@ var test_frames = [{
frame: {
type: 'DATA',
flags: { END_STREAM: false, END_SEGMENT: false, RESERVED4: false,
PAD_LOW: false, PAD_HIGH: false },
PAD_LOW: false, PAD_HIGH: false, COMPRESSED: false },
stream: 10,
data: new Buffer('12345678', 'hex')
@ -34,8 +34,7 @@ var test_frames = [{
frame: {
type: 'HEADERS',
flags: { END_STREAM: false, END_SEGMENT: false, END_HEADERS: false,
PAD_LOW: false, PAD_HIGH: false, PRIORITY_GROUP: false,
PRIORITY_DEPENDENCY: false },
PAD_LOW: false, PAD_HIGH: false, PRIORITY: false },
stream: 15,
data: new Buffer('12345678', 'hex')
@ -46,82 +45,54 @@ var test_frames = [{
frame: {
type: 'HEADERS',
flags: { END_STREAM: false, END_SEGMENT: false, END_HEADERS: false,
PAD_LOW: false, PAD_HIGH: false, PRIORITY_GROUP: true,
PRIORITY_DEPENDENCY: false },
PAD_LOW: false, PAD_HIGH: false, PRIORITY: true },
stream: 15,
priorityGroup: 23,
groupWeight: 5,
data: new Buffer('12345678', 'hex')
},
buffer: new Buffer('0009' + '01' + '20' + '0000000F' + '00000017' + '05' + '12345678', 'hex')
}, {
frame: {
type: 'HEADERS',
flags: { END_STREAM: false, END_SEGMENT: false, END_HEADERS: false,
PAD_LOW: false, PAD_HIGH: false, PRIORITY_GROUP: false,
PRIORITY_DEPENDENCY: true },
stream: 15,
priorityDependency: 23,
priorityDependency: 10,
priorityWeight: 5,
exclusiveDependency: false,
data: new Buffer('12345678', 'hex')
},
buffer: new Buffer('0008' + '01' + '40' + '0000000F' + '00000017' + '12345678', 'hex')
buffer: new Buffer('0009' + '01' + '20' + '0000000F' + '0000000A' + '05' + '12345678', 'hex')
}, {
frame: {
type: 'HEADERS',
flags: { END_STREAM: false, END_SEGMENT: false, END_HEADERS: false,
PAD_LOW: false, PAD_HIGH: false, PRIORITY_GROUP: false,
PRIORITY_DEPENDENCY: true },
PAD_LOW: false, PAD_HIGH: false, PRIORITY: true },
stream: 15,
priorityDependency: 23,
priorityDependency: 10,
priorityWeight: 5,
exclusiveDependency: true,
data: new Buffer('12345678', 'hex')
},
buffer: new Buffer('0008' + '01' + '40' + '0000000F' + '80000017' + '12345678', 'hex')
buffer: new Buffer('0009' + '01' + '20' + '0000000F' + '8000000A' + '05' + '12345678', 'hex')
}, {
frame: {
type: 'PRIORITY',
flags: { RESERVED1: false, RESERVED2: false, RESERVED4: false,
RESERVED8: false, RESERVED16: false, PRIORITY_GROUP: true,
PRIORITY_DEPENDENCY: false },
flags: { },
stream: 10,
priorityGroup: 23,
groupWeight: 5
},
buffer: new Buffer('0005' + '02' + '20' + '0000000A' + '00000017' + '05', 'hex')
}, {
frame: {
type: 'PRIORITY',
flags: { RESERVED1: false, RESERVED2: false, RESERVED4: false,
RESERVED8: false, RESERVED16: false, PRIORITY_GROUP: false,
PRIORITY_DEPENDENCY: true },
stream: 10,
priorityDependency: 23,
priorityDependency: 9,
priorityWeight: 5,
exclusiveDependency: false
},
buffer: new Buffer('0004' + '02' + '40' + '0000000A' + '00000017', 'hex')
buffer: new Buffer('0005' + '02' + '00' + '0000000A' + '00000009' + '05', 'hex')
}, {
frame: {
type: 'PRIORITY',
flags: { RESERVED1: false, RESERVED2: false, RESERVED4: false,
RESERVED8: false, RESERVED16: false, PRIORITY_GROUP: false,
PRIORITY_DEPENDENCY: true },
flags: { },
stream: 10,
priorityDependency: 23,
priorityDependency: 9,
priorityWeight: 5,
exclusiveDependency: true
},
buffer: new Buffer('0004' + '02' + '40' + '0000000A' + '80000017', 'hex')
buffer: new Buffer('0005' + '02' + '00' + '0000000A' + '80000009' + '05', 'hex')
}, {
frame: {
@ -143,13 +114,15 @@ var test_frames = [{
SETTINGS_HEADER_TABLE_SIZE: 0x12345678,
SETTINGS_ENABLE_PUSH: true,
SETTINGS_MAX_CONCURRENT_STREAMS: 0x01234567,
SETTINGS_INITIAL_WINDOW_SIZE: 0x89ABCDEF
SETTINGS_INITIAL_WINDOW_SIZE: 0x89ABCDEF,
SETTINGS_COMPRESS_DATA: true
}
},
buffer: new Buffer('0014' + '04' + '00' + '0000000A' + '01' + '12345678' +
buffer: new Buffer('0019' + '04' + '00' + '0000000A' + '01' + '12345678' +
'02' + '00000001' +
'03' + '01234567' +
'04' + '89ABCDEF', 'hex')
'04' + '89ABCDEF' +
'05' + '00000001', 'hex')
}, {
frame: {
@ -230,6 +203,14 @@ var test_frames = [{
origin: "https://onlyme.example.com"
},
buffer: new Buffer('0037' + '0A' + '00' + '00000000' + '01E13380' + '115B' + '00' + '02' + '6832' + '12' + '616C747376632E6578616D706C652E636F6D' + '68747470733A2F2F6F6E6C796D652E6578616D706C652E636F6D', 'hex')
}, {
frame: {
type: 'BLOCKED',
flags: { },
stream: 10
},
buffer: new Buffer('0000' + '0B' + '00' + '0000000A', 'hex')
}];
var deserializer_test_frames = test_frames.slice(0);
@ -237,7 +218,7 @@ var padded_test_frames = [{
frame: {
type: 'DATA',
flags: { END_STREAM: false, END_SEGMENT: false, RESERVED4: false,
PAD_LOW: true, PAD_HIGH: false },
PAD_LOW: true, PAD_HIGH: false, COMPRESSED: false },
stream: 10,
data: new Buffer('12345678', 'hex')
},
@ -248,8 +229,7 @@ var padded_test_frames = [{
frame: {
type: 'HEADERS',
flags: { END_STREAM: false, END_SEGMENT: false, END_HEADERS: false,
PAD_LOW: true, PAD_HIGH: false, PRIORITY_GROUP: false,
PRIORITY_DEPENDENCY: false },
PAD_LOW: true, PAD_HIGH: false, PRIORITY: false },
stream: 15,
data: new Buffer('12345678', 'hex')
@ -261,46 +241,31 @@ var padded_test_frames = [{
frame: {
type: 'HEADERS',
flags: { END_STREAM: false, END_SEGMENT: false, END_HEADERS: false,
PAD_LOW: true, PAD_HIGH: false, PRIORITY_GROUP: true,
PRIORITY_DEPENDENCY: false },
PAD_LOW: true, PAD_HIGH: false, PRIORITY: true },
stream: 15,
priorityGroup: 23,
groupWeight: 5,
data: new Buffer('12345678', 'hex')
},
// length + type + flags + stream + pad_low control + priority group + group weight + data + padding
buffer: new Buffer('0010' + '01' + '28' + '0000000F' + '06' + '00000017' + '05' + '12345678' + '000000000000', 'hex')
}, {
frame: {
type: 'HEADERS',
flags: { END_STREAM: false, END_SEGMENT: false, END_HEADERS: false,
PAD_LOW: true, PAD_HIGH: false, PRIORITY_GROUP: false,
PRIORITY_DEPENDENCY: true },
stream: 15,
priorityDependency: 23,
priorityDependency: 10,
priorityWeight: 5,
exclusiveDependency: false,
data: new Buffer('12345678', 'hex')
},
// length + type + flags + stream + pad_low control + priority dependency + data + padding
buffer: new Buffer('000F' + '01' + '48' + '0000000F' + '06' + '00000017' + '12345678' + '000000000000', 'hex')
// length + type + flags + stream + pad_low control + priority dependency + priority weight + data + padding
buffer: new Buffer('0010' + '01' + '28' + '0000000F' + '06' + '0000000A' + '05' + '12345678' + '000000000000', 'hex')
}, {
frame: {
type: 'HEADERS',
flags: { END_STREAM: false, END_SEGMENT: false, END_HEADERS: false,
PAD_LOW: true, PAD_HIGH: false, PRIORITY_GROUP: false,
PRIORITY_DEPENDENCY: true },
PAD_LOW: true, PAD_HIGH: false, PRIORITY: true },
stream: 15,
priorityDependency: 23,
priorityDependency: 10,
priorityWeight: 5,
exclusiveDependency: true,
data: new Buffer('12345678', 'hex')
},
// length + type + flags + stream + pad_low control + priority dependency + data + padding
buffer: new Buffer('000F' + '01' + '48' + '0000000F' + '06' + '80000017' + '12345678' + '000000000000', 'hex')
// length + type + flags + stream + pad_low control + priority dependency + priority weight + data + padding
buffer: new Buffer('0010' + '01' + '28' + '0000000F' + '06' + '8000000A' + '05' + '12345678' + '000000000000', 'hex')
}, {
frame: {

View File

@ -1,13 +1,13 @@
{
"name": "http2",
"version": "2.3.0",
"version": "2.5.0",
"description": "An HTTP/2 client and server implementation",
"main": "lib/index.js",
"engines" : {
"node" : ">=0.10.19"
},
"dependencies": {
"http2-protocol": "0.11.x"
"http2-protocol": "0.12.x"
},
"devDependencies": {
"istanbul": "*",