Socket
Socket
Sign inDemoInstall

http2-protocol

Package Overview
Dependencies
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

http2-protocol - npm Package Compare versions

Comparing version 0.9.1 to 0.10.0

.npmignore

2

example/client.js

@@ -8,3 +8,3 @@ var fs = require('fs');

// Advertised protocol version
var implementedVersion = 'HTTP-draft-09/2.0';
var implementedVersion = http2.ImplementedVersion;

@@ -11,0 +11,0 @@ // Bunyan logger

@@ -12,3 +12,3 @@ var fs = require('fs');

// Advertised protocol version
var implementedVersion = 'HTTP-draft-09/2.0';
var implementedVersion = http2.ImplementedVersion;

@@ -15,0 +15,0 @@ // Bunyan logger

Version history
===============
### 0.10.0 (2014-03-12) ###
* Upgrade to the latest draft: [draft-ietf-httpbis-http2-10][draft-10]
[draft-10]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-10
### 0.9.1 (2014-01-11) ###

@@ -5,0 +11,0 @@

@@ -231,3 +231,3 @@ // The implementation of the [HTTP/2 Header Compression][http2-compression] spec is separated from

util.inherits(HeaderSetDecompressor, TransformStream);
function HeaderSetDecompressor(log, table, huffmanTable) {
function HeaderSetDecompressor(log, table) {
TransformStream.call(this, { objectMode: true });

@@ -237,3 +237,2 @@

this._table = table;
this._huffmanTable = huffmanTable;
this._chunks = [];

@@ -280,3 +279,4 @@ }

// entails the following actions:
// * The reference set is emptied.
// * If the following byte starts with a set bit, the reference set is emptied.
// * Else, reduce the size of the header table to the value encoded with a 7-bit prefix
// * An _indexed representation_ corresponding to an entry _present_ in the reference set

@@ -300,4 +300,9 @@ // entails the following actions:

if (index == -1) {
for (var i = 0; i < this._table.length; i++) {
this._table[i].reference = false;
if (rep.index) {
for (var i = 0; i < this._table.length; i++) {
this._table[i].reference = false;
}
} else {
// Set a new maximum size
this.setTableSizeLimit(rep.name);
}

@@ -359,3 +364,3 @@ }

while (buffer.cursor < buffer.length) {
this._execute(HeaderSetDecompressor.header(buffer, this._huffmanTable));
this._execute(HeaderSetDecompressor.header(buffer));
}

@@ -388,3 +393,3 @@

util.inherits(HeaderSetCompressor, TransformStream);
function HeaderSetCompressor(log, table, huffmanTable) {
function HeaderSetCompressor(log, table) {
TransformStream.call(this, { objectMode: true });

@@ -394,3 +399,2 @@

this._table = table;
this._huffmanTable = huffmanTable;
this.push = TransformStream.prototype.push.bind(this);

@@ -404,3 +408,3 @@ }

if (!rep.chunks) {
rep.chunks = HeaderSetCompressor.header(rep, this._huffmanTable);
rep.chunks = HeaderSetCompressor.header(rep);
}

@@ -716,3 +720,3 @@ rep.chunks.forEach(this.push);

HuffmanTable.requestHuffmanTable = new HuffmanTable([
HuffmanTable.huffmanTable = new HuffmanTable([
'111111111111111111110111010',

@@ -977,262 +981,2 @@ '111111111111111111110111011',

HuffmanTable.responseHuffmanTable = new HuffmanTable([
'1111111111111111110111100',
'1111111111111111110111101',
'1111111111111111110111110',
'1111111111111111110111111',
'1111111111111111111000000',
'1111111111111111111000001',
'1111111111111111111000010',
'1111111111111111111000011',
'1111111111111111111000100',
'1111111111111111111000101',
'1111111111111111111000110',
'1111111111111111111000111',
'1111111111111111111001000',
'1111111111111111111001001',
'1111111111111111111001010',
'1111111111111111111001011',
'1111111111111111111001100',
'1111111111111111111001101',
'1111111111111111111001110',
'1111111111111111111001111',
'1111111111111111111010000',
'1111111111111111111010001',
'1111111111111111111010010',
'1111111111111111111010011',
'1111111111111111111010100',
'1111111111111111111010101',
'1111111111111111111010110',
'1111111111111111111010111',
'1111111111111111111011000',
'1111111111111111111011001',
'1111111111111111111011010',
'1111111111111111111011011',
'0000',
'111111111010',
'1101010',
'1111111111010',
'11111111111100',
'111101100',
'1111111000',
'1111111111011',
'111101101',
'111101110',
'111111111011',
'11111111010',
'100010',
'100011',
'100100',
'1101011',
'0001',
'0010',
'0011',
'01000',
'01001',
'01010',
'100101',
'100110',
'01011',
'01100',
'01101',
'111101111',
'1111111111111010',
'1101100',
'1111111111100',
'111111111100',
'1111111111111011',
'1101101',
'11101010',
'11101011',
'11101100',
'11101101',
'11101110',
'100111',
'111110000',
'11101111',
'11110000',
'1111111001',
'111110001',
'101000',
'11110001',
'11110010',
'111110010',
'1111111010',
'111110011',
'101001',
'01110',
'111110100',
'111110101',
'11110011',
'1111111011',
'111110110',
'1111111100',
'11111111011',
'1111111111101',
'11111111100',
'111111111111100',
'111110111',
'11111111111111110',
'01111',
'1101110',
'101010',
'101011',
'10000',
'1101111',
'1110000',
'1110001',
'101100',
'111111000',
'111111001',
'1110010',
'101101',
'101110',
'101111',
'110000',
'111111010',
'110001',
'110010',
'110011',
'110100',
'1110011',
'11110100',
'1110100',
'11110101',
'111111011',
'1111111111111100',
'11111111111101',
'1111111111111101',
'1111111111111110',
'1111111111111111111011100',
'1111111111111111111011101',
'1111111111111111111011110',
'1111111111111111111011111',
'1111111111111111111100000',
'1111111111111111111100001',
'1111111111111111111100010',
'1111111111111111111100011',
'1111111111111111111100100',
'1111111111111111111100101',
'1111111111111111111100110',
'1111111111111111111100111',
'1111111111111111111101000',
'1111111111111111111101001',
'1111111111111111111101010',
'1111111111111111111101011',
'1111111111111111111101100',
'1111111111111111111101101',
'1111111111111111111101110',
'1111111111111111111101111',
'1111111111111111111110000',
'1111111111111111111110001',
'1111111111111111111110010',
'1111111111111111111110011',
'1111111111111111111110100',
'1111111111111111111110101',
'1111111111111111111110110',
'1111111111111111111110111',
'1111111111111111111111000',
'1111111111111111111111001',
'1111111111111111111111010',
'1111111111111111111111011',
'1111111111111111111111100',
'1111111111111111111111101',
'1111111111111111111111110',
'1111111111111111111111111',
'111111111111111110000000',
'111111111111111110000001',
'111111111111111110000010',
'111111111111111110000011',
'111111111111111110000100',
'111111111111111110000101',
'111111111111111110000110',
'111111111111111110000111',
'111111111111111110001000',
'111111111111111110001001',
'111111111111111110001010',
'111111111111111110001011',
'111111111111111110001100',
'111111111111111110001101',
'111111111111111110001110',
'111111111111111110001111',
'111111111111111110010000',
'111111111111111110010001',
'111111111111111110010010',
'111111111111111110010011',
'111111111111111110010100',
'111111111111111110010101',
'111111111111111110010110',
'111111111111111110010111',
'111111111111111110011000',
'111111111111111110011001',
'111111111111111110011010',
'111111111111111110011011',
'111111111111111110011100',
'111111111111111110011101',
'111111111111111110011110',
'111111111111111110011111',
'111111111111111110100000',
'111111111111111110100001',
'111111111111111110100010',
'111111111111111110100011',
'111111111111111110100100',
'111111111111111110100101',
'111111111111111110100110',
'111111111111111110100111',
'111111111111111110101000',
'111111111111111110101001',
'111111111111111110101010',
'111111111111111110101011',
'111111111111111110101100',
'111111111111111110101101',
'111111111111111110101110',
'111111111111111110101111',
'111111111111111110110000',
'111111111111111110110001',
'111111111111111110110010',
'111111111111111110110011',
'111111111111111110110100',
'111111111111111110110101',
'111111111111111110110110',
'111111111111111110110111',
'111111111111111110111000',
'111111111111111110111001',
'111111111111111110111010',
'111111111111111110111011',
'111111111111111110111100',
'111111111111111110111101',
'111111111111111110111110',
'111111111111111110111111',
'111111111111111111000000',
'111111111111111111000001',
'111111111111111111000010',
'111111111111111111000011',
'111111111111111111000100',
'111111111111111111000101',
'111111111111111111000110',
'111111111111111111000111',
'111111111111111111001000',
'111111111111111111001001',
'111111111111111111001010',
'111111111111111111001011',
'111111111111111111001100',
'111111111111111111001101',
'111111111111111111001110',
'111111111111111111001111',
'111111111111111111010000',
'111111111111111111010001',
'111111111111111111010010',
'111111111111111111010011',
'111111111111111111010100',
'111111111111111111010101',
'111111111111111111010110',
'111111111111111111010111',
'111111111111111111011000',
'111111111111111111011001',
'111111111111111111011010',
'111111111111111111011011',
'111111111111111111011100',
'111111111111111111011101'
]);
// ### String literal representation ###

@@ -1269,6 +1013,6 @@ //

HeaderSetCompressor.string = function writeString(str, huffmanTable) {
HeaderSetCompressor.string = function writeString(str) {
str = new Buffer(str, 'utf8');
var huffman = huffmanTable.encode(str);
var huffman = HuffmanTable.huffmanTable.encode(str);
if (huffman.length < str.length) {

@@ -1286,3 +1030,3 @@ var length = HeaderSetCompressor.integer(huffman.length, 7)

HeaderSetDecompressor.string = function readString(buffer, huffmanTable) {
HeaderSetDecompressor.string = function readString(buffer) {
var huffman = buffer[buffer.cursor] & 128;

@@ -1292,3 +1036,3 @@ var length = HeaderSetDecompressor.integer(buffer, 7);

buffer.cursor += length;
return (huffman ? huffmanTable.decode(encoded) : encoded).toString('utf8');
return (huffman ? HuffmanTable.huffmanTable.decode(encoded) : encoded).toString('utf8');
};

@@ -1369,3 +1113,3 @@

HeaderSetCompressor.header = function writeHeader(header, huffmanTable) {
HeaderSetCompressor.header = function writeHeader(header) {
var representation, buffers = [];

@@ -1383,2 +1127,9 @@

buffers.push(HeaderSetCompressor.integer(header.value + 1, representation.prefix));
if (header.value == -1) {
if (header.index) {
buffers.push(HeaderSetCompressor.integer(0x80, 8));
} else {
buffers.push(HeaderSetCompressor.integer(header.name, 7));
}
}
}

@@ -1391,5 +1142,5 @@

buffers.push(HeaderSetCompressor.integer(0, representation.prefix));
buffers.push(HeaderSetCompressor.string(header.name, huffmanTable));
buffers.push(HeaderSetCompressor.string(header.name));
}
buffers.push(HeaderSetCompressor.string(header.value, huffmanTable));
buffers.push(HeaderSetCompressor.string(header.value));
}

@@ -1402,3 +1153,3 @@

HeaderSetDecompressor.header = function readHeader(buffer, huffmanTable) {
HeaderSetDecompressor.header = function readHeader(buffer) {
var representation, header = {};

@@ -1418,2 +1169,10 @@

header.index = false;
if (header.value === -1) {
if (buffer[buffer.cursor] & 0x80) {
header.index = true;
buffer.cursor += 1;
} else {
header.name = HeaderSetDecompressor.integer(buffer, 7);
}
}
}

@@ -1424,5 +1183,5 @@

if (header.name === -1) {
header.name = HeaderSetDecompressor.string(buffer, huffmanTable);
header.name = HeaderSetDecompressor.string(buffer);
}
header.value = HeaderSetDecompressor.string(buffer, huffmanTable);
header.value = HeaderSetDecompressor.string(buffer);
header.index = (representation === representations.literalIncremental);

@@ -1469,4 +1228,2 @@ }

assert((type === 'REQUEST') || (type === 'RESPONSE'));
this._huffmanTable = (type === 'REQUEST') ? HuffmanTable.requestHuffmanTable
: HuffmanTable.responseHuffmanTable;
this._table = new HeaderTable(this._log);

@@ -1484,3 +1241,3 @@ }

Compressor.prototype.compress = function compress(headers) {
var compressor = new HeaderSetCompressor(this._log, this._table, this._huffmanTable);
var compressor = new HeaderSetCompressor(this._log, this._table);
for (var name in headers) {

@@ -1588,4 +1345,2 @@ var value = headers[name];

assert((type === 'REQUEST') || (type === 'RESPONSE'));
this._huffmanTable = (type === 'REQUEST') ? HuffmanTable.requestHuffmanTable
: HuffmanTable.responseHuffmanTable;
this._table = new HeaderTable(this._log);

@@ -1606,3 +1361,3 @@

Decompressor.prototype.decompress = function decompress(block) {
var decompressor = new HeaderSetDecompressor(this._log, this._table, this._huffmanTable);
var decompressor = new HeaderSetDecompressor(this._log, this._table);
decompressor.end(block);

@@ -1609,0 +1364,0 @@

@@ -192,4 +192,4 @@ var assert = require('assert');

// * handling stream errors as connection errors
stream.on('error', this.emit.bind(this, 'error'));
// * forwarding connection errors from streams
stream.on('connectionError', this.emit.bind(this, 'error'));

@@ -381,3 +381,2 @@ return id;

var defaultSettings = {
SETTINGS_FLOW_CONTROL_OPTIONS: true
};

@@ -568,11 +567,5 @@

stream.upstream.setInitialWindow(this._initialStreamWindowSize);
if (this._remoteFlowControlDisabled) {
stream.upstream.disableRemoteFlowControl();
}
});
this.on('RECEIVING_SETTINGS_INITIAL_WINDOW_SIZE', this._setInitialStreamWindowSize);
this.on('RECEIVING_SETTINGS_FLOW_CONTROL_OPTIONS', this._setLocalFlowControl);
this.on('SENDING_SETTINGS_FLOW_CONTROL_OPTIONS', this._setRemoteFlowControl);
this._streamIds[0].upstream.setInitialWindow = function noop() {};
this._streamIds[0].upstream.disableRemoteFlowControl = function noop() {};
};

@@ -599,25 +592,1 @@

};
// `_setStreamFlowControl()` may be used to disable/enable flow control. In practice, it is just
// for turning off flow control since it can not be turned on.
Connection.prototype._setLocalFlowControl = function _setLocalFlowControl(disable) {
if (disable) {
this._increaseWindow(Infinity);
this._setInitialStreamWindowSize(Infinity);
} else if (this._initialStreamWindowSize === Infinity) {
this._log.error('Trying to re-enable flow control after it was turned off.');
this.emit('error', 'FLOW_CONTROL_ERROR');
}
};
Connection.prototype._setRemoteFlowControl = function _setRemoteFlowControl(disable) {
if (disable) {
this.disableRemoteFlowControl();
this._streamIds.forEach(function(stream) {
stream.upstream.disableRemoteFlowControl();
});
} else if (this._remoteFlowControlDisabled) {
this._log.error('Trying to re-enable flow control after it was turned off.');
throw new Error('Trying to re-enable flow control after it was turned off.');
}
};

@@ -22,7 +22,3 @@ var assert = require('assert');

//
// * **disableRemoteFlowControl()**: sends a WINDOW_UPDATE signaling that we don't want flow control
//
// * **disableLocalFlowControl()**: disables flow control for outgoing frames
//
// [1]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-09#section-6.9.2
// [1]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-6.9.2

@@ -72,3 +68,2 @@ // API for child classes

this._received = 0;
this._remoteFlowControlDisabled = false;
}

@@ -94,3 +89,3 @@ Flow.prototype = Object.create(Duplex.prototype, { constructor: { value: Flow } });

if ((frame.type === 'DATA') && (frame.data.length > 0) && !this._remoteFlowControlDisabled) {
if ((frame.type === 'DATA') && (frame.data.length > 0)) {
this._receive(frame, function() {

@@ -119,3 +114,3 @@ this._received += frame.data.length;

delete this._restoreWindowTimer;
if (!this._ended && !this._remoteFlowControlDisabled && (this._received > 0)) {
if (!this._ended && (this._received > 0)) {
this.push({

@@ -131,8 +126,2 @@ type: 'WINDOW_UPDATE',

// Must be called after sending a SETTINGS frame that turns off flow control on the remote side.
Flow.prototype.disableRemoteFlowControl = function disableRemoteFlowControl() {
this._log.debug('Turning off remote flow control');
this._remoteFlowControlDisabled = true;
};
// Outgoing frames - sending procedure

@@ -363,6 +352,1 @@ // -----------------------------------

};
// Flow control for outgoing frames can be disabled by the peer with various methods.
Flow.prototype.disableLocalFlowControl = function disableLocalFlowControl() {
this._increaseWindow(Infinity);
};

@@ -15,2 +15,3 @@ // The framer consists of two [Transform Stream][1] subclasses that operate in [object mode][2]:

var MAX_PAYLOAD_SIZE = 16383;
var WINDOW_UPDATE_PAYLOAD_SIZE = 4;

@@ -70,3 +71,4 @@ // Serializer

function Deserializer(log, sizeLimit) {
function Deserializer(log, sizeLimit, role) {
this._role = role;
this._log = log.child({ component: 'deserializer' });

@@ -132,6 +134,6 @@ this._sizeLimit = sizeLimit || MAX_PAYLOAD_SIZE;

if (this._frame.type) {
var error = Deserializer[this._frame.type](this._buffer, this._frame);
var error = Deserializer[this._frame.type](this._buffer, this._frame, this._role);
if (error) {
this._log.error('Incoming frame parsing error: ' + error);
this.emit('error', 'PROTOCOL_ERROR');
this.emit('error', error);
} else {

@@ -142,3 +144,4 @@ this._log.trace({ frame: this._frame }, 'Incoming frame');

} else {
this._log.warn({ frame: this._frame }, 'Unknown type incoming frame');
this._log.error('Unknown type incoming frame');
this.emit('error', 'PROTOCOL_ERROR');
}

@@ -152,3 +155,3 @@ this._next(COMMON_HEADER_SIZE);

// [Frame Header](http://tools.ietf.org/html/draft-ietf-httpbis-http2-09#section-4.1)
// [Frame Header](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-4.1)
// --------------------------------------------------------------

@@ -267,3 +270,3 @@ //

// [DATA Frames](http://tools.ietf.org/html/draft-ietf-httpbis-http2-09#section-6.1)
// [DATA Frames](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-6.1)
// ------------------------------------------------------------

@@ -279,8 +282,16 @@ //

// identified stream.
// * RESERVED (0x2):
// Bit 2 is reserved for future use.
// * END_SEGMENT (0x2):
// Bit 2 being set indicates that this frame is the last for the current segment. Intermediaries
// MUST NOT coalesce frames across a segment boundary and MUST preserve segment boundaries when
// forwarding frames.
// * PAD_LOW (0x10):
// Bit 5 being set indicates that the Pad Low field is present.
// * PAD_HIGH (0x20):
// Bit 6 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.
frameTypes[0x0] = 'DATA';
frameFlags.DATA = ['END_STREAM', 'RESERVED'];
frameFlags.DATA = ['END_STREAM', 'END_SEGMENT', 'RESERVED4', 'RESERVED8', 'PAD_LOW', 'PAD_HIGH'];

@@ -294,6 +305,22 @@ typeSpecificAttributes.DATA = ['data'];

Deserializer.DATA = function readData(buffer, frame) {
frame.data = buffer;
var dataOffset = 0;
var paddingLength = 0;
if (frame.flags.PAD_LOW) {
if (frame.flags.PAD_HIGH) {
paddingLength = (buffer.readUInt8(dataOffset) & 0xff) * 256;
dataOffset += 1;
}
paddingLength += (buffer.readUInt8(dataOffset) & 0xff);
dataOffset += 1;
} else if (frame.flags.PAD_HIGH) {
return 'DATA frame got PAD_HIGH without PAD_LOW';
}
if (paddingLength) {
frame.data = buffer.slice(dataOffset, -1 * paddingLength);
} else {
frame.data = buffer.slice(dataOffset);
}
};
// [HEADERS](http://tools.ietf.org/html/draft-ietf-httpbis-http2-09#section-6.2)
// [HEADERS](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-6.2)
// --------------------------------------------------------------

@@ -308,4 +335,6 @@ //

// identified stream.
// * RESERVED (0x2):
// Bit 2 is reserved for future use.
// * END_SEGMENT (0x2):
// Bit 2 being set indicates that this frame is the last for the current segment. Intermediaries
// MUST NOT coalesce frames across a segment boundary and MUST preserve segment boundaries when
// forwarding frames.
// * END_HEADERS (0x4):

@@ -317,6 +346,12 @@ // The END_HEADERS bit indicates that this frame contains the entire payload necessary to provide

// bit and a 31-bit priority.
// * PAD_LOW (0x10):
// Bit 5 being set indicates that the Pad Low field is present.
// * PAD_HIGH (0x20):
// Bit 6 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.
frameTypes[0x1] = 'HEADERS';
frameFlags.HEADERS = ['END_STREAM', 'RESERVED', 'END_HEADERS', 'PRIORITY'];
frameFlags.HEADERS = ['END_STREAM', 'END_SEGMENT', 'END_HEADERS', 'PRIORITY', 'PAD_LOW', 'PAD_HIGH'];

@@ -346,11 +381,26 @@ typeSpecificAttributes.HEADERS = ['priority', 'headers', 'data'];

Deserializer.HEADERS = function readHeadersPriority(buffer, frame) {
var dataOffset = 0;
var paddingLength = 0;
if (frame.flags.PAD_LOW) {
if (frame.flags.PAD_HIGH) {
paddingLength = (buffer.readUInt8(dataOffset) & 0xff) * 256;
dataOffset += 1;
}
paddingLength += (buffer.readUInt8(dataOffset) & 0xff);
dataOffset += 1;
} else if (frame.flags.PAD_HIGH) {
return 'HEADERS frame got PAD_HIGH without PAD_LOW';
}
if (frame.flags.PRIORITY) {
frame.priority = buffer.readUInt32BE(0) & 0x7fffffff;
frame.data = buffer.slice(4);
frame.priority = buffer.readUInt32BE(dataOffset) & 0x7fffffff;
dataOffset += 4;
}
if (paddingLength) {
frame.data = buffer.slice(dataOffset, -1 * paddingLength);
} else {
frame.data = buffer;
frame.data = buffer.slice(dataOffset);
}
};
// [PRIORITY](http://tools.ietf.org/html/draft-ietf-httpbis-http2-09#section-6.3)
// [PRIORITY](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-6.3)
// -------------------------------------------------------

@@ -386,3 +436,3 @@ //

// [RST_STREAM](http://tools.ietf.org/html/draft-ietf-httpbis-http2-09#section-6.4)
// [RST_STREAM](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-6.4)
// -----------------------------------------------------------

@@ -421,3 +471,3 @@ //

// [SETTINGS](http://tools.ietf.org/html/draft-ietf-httpbis-http2-09#section-6.5)
// [SETTINGS](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-6.5)
// -------------------------------------------------------

@@ -440,3 +490,3 @@ //

// The payload of a SETTINGS frame consists of zero or more settings. Each setting consists of an
// 8-bit reserved field, an unsigned 24-bit setting identifier, and an unsigned 32-bit value.
// 8-bit identifier, and an unsigned 32-bit value.
//

@@ -446,6 +496,6 @@ // 0 1 2 3

// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Reserved(8) | Setting Identifier (24) |
// +---------------+-----------------------------------------------+
// | Value (32) |
// +---------------------------------------------------------------+
// | Identifier(8) | Value (32) |
// +-----------------+---------------------------------------------+
// ...Value |
// +-----------------+
//

@@ -470,6 +520,6 @@ // Each setting in a SETTINGS frame replaces the existing value for that setting. Settings are

var buffer = new Buffer(settings.length * 8);
var buffer = new Buffer(settings.length * 5);
for (var i = 0; i < settings.length; i++) {
buffer.writeUInt32BE(settings[i].id & 0xffffff, i*8);
buffer.writeUInt32BE(settings[i].value, i*8 + 4);
buffer.writeUInt8(settings[i].id & 0xff, i*5);
buffer.writeUInt32BE(settings[i].value, i*5 + 1);
}

@@ -480,16 +530,27 @@

Deserializer.SETTINGS = function readSettings(buffer, frame) {
Deserializer.SETTINGS = function readSettings(buffer, frame, role) {
frame.settings = {};
// Receipt of a SETTINGS frame with the ACK flag set and a length
// field value other than 0 MUST be treated as a connection error
// (Section 5.4.1) of type FRAME_SIZE_ERROR.
if(frame.flags.ACK && buffer.length != 0) {
return 'FRAME_SIZE_ERROR';
}
if (buffer.length % 8 !== 0) {
return 'Invalid SETTINGS frame';
if (buffer.length % 5 !== 0) {
return 'PROTOCOL_ERROR';
}
for (var i = 0; i < buffer.length / 8; i++) {
var id = buffer.readUInt32BE(i*8) & 0xffffff;
for (var i = 0; i < buffer.length / 5; i++) {
var id = buffer.readUInt8(i*5) & 0xff;
var setting = definedSettings[id];
if (setting) {
var value = buffer.readUInt32BE(i*8 + 4);
if (role == 'CLIENT' && setting.name == 'SETTINGS_ENABLE_PUSH') {
return 'SETTINGS frame on client got SETTINGS_ENABLE_PUSH';
}
var value = buffer.readUInt32BE(i*5 + 1);
frame.settings[setting.name] = setting.flag ? Boolean(value & 0x1) : value;
} else {
/* Unknown setting, ignoring */
/* Unknown setting, protocol error */
return 'SETTINGS frame got unknown setting type';
}

@@ -515,15 +576,9 @@ }

// indicates the maximum number of concurrent streams that the sender will allow.
definedSettings[4] = { name: 'SETTINGS_MAX_CONCURRENT_STREAMS', flag: false };
definedSettings[3] = { name: 'SETTINGS_MAX_CONCURRENT_STREAMS', flag: false };
// * SETTINGS_INITIAL_WINDOW_SIZE (7):
// indicates the sender's initial stream window size (in bytes) for new streams.
definedSettings[7] = { name: 'SETTINGS_INITIAL_WINDOW_SIZE', flag: false };
definedSettings[4] = { name: 'SETTINGS_INITIAL_WINDOW_SIZE', flag: false };
// * SETTINGS_FLOW_CONTROL_OPTIONS (10):
// indicates that streams directed to the sender will not be subject to flow control. The least
// significant bit (0x1) is set to indicate that new streams are not flow controlled. All other
// bits are reserved.
definedSettings[10] = { name: 'SETTINGS_FLOW_CONTROL_OPTIONS', flag: true };
// [PUSH_PROMISE](http://tools.ietf.org/html/draft-ietf-httpbis-http2-09#section-6.6)
// [PUSH_PROMISE](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-6.6)
// ---------------------------------------------------------------

@@ -574,3 +629,3 @@ //

// [PING](http://tools.ietf.org/html/draft-ietf-httpbis-http2-09#section-6.7)
// [PING](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-6.7)
// -----------------------------------------------

@@ -600,3 +655,3 @@ //

if (buffer.length !== 8) {
return 'Invalid size PING frame';
return 'FRAME_SIZE_ERROR';
}

@@ -606,3 +661,3 @@ frame.data = buffer;

// [GOAWAY](http://tools.ietf.org/html/draft-ietf-httpbis-http2-09#section-6.8)
// [GOAWAY](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-6.8)
// ---------------------------------------------------

@@ -654,10 +709,10 @@ //

// [WINDOW_UPDATE](http://tools.ietf.org/html/draft-ietf-httpbis-http2-09#section-6.9)
// [WINDOW_UPDATE](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-6.9)
// -----------------------------------------------------------------
//
// The WINDOW_UPDATE frame (type=0x9) is used to implement flow control.
// The WINDOW_UPDATE frame (type=0x8) is used to implement flow control.
//
// The WINDOW_UPDATE frame does not define any flags.
frameTypes[0x9] = 'WINDOW_UPDATE';
frameTypes[0x8] = 'WINDOW_UPDATE';

@@ -684,6 +739,9 @@ frameFlags.WINDOW_UPDATE = [];

Deserializer.WINDOW_UPDATE = function readWindowUpdate(buffer, frame) {
if (buffer.length !== WINDOW_UPDATE_PAYLOAD_SIZE) {
return 'FRAME_SIZE_ERROR';
}
frame.window_size = buffer.readUInt32BE(0) & 0x7fffffff;
};
// [CONTINUATION](http://tools.ietf.org/html/draft-ietf-httpbis-http2-09#section-6.10)
// [CONTINUATION](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-6.10)
// ------------------------------------------------------------

@@ -698,6 +756,12 @@ //

// necessary to provide a complete set of headers.
// * PAD_LOW (0x10):
// Bit 5 being set indicates that the Pad Low field is present.
// * PAD_HIGH (0x20):
// Bit 6 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.
frameTypes[0xA] = 'CONTINUATION';
frameTypes[0x9] = 'CONTINUATION';
frameFlags.CONTINUATION = ['RESERVED1', 'RESERVED2', 'END_HEADERS'];
frameFlags.CONTINUATION = ['RESERVED1', 'RESERVED2', 'END_HEADERS', 'RESERVED8', 'PAD_LOW', 'PAD_HIGH'];

@@ -711,6 +775,22 @@ typeSpecificAttributes.CONTINUATION = ['headers', 'data'];

Deserializer.CONTINUATION = function readContinuation(buffer, frame) {
frame.data = buffer;
var dataOffset = 0;
var paddingLength = 0;
if (frame.flags.PAD_LOW) {
if (frame.flags.PAD_HIGH) {
paddingLength = (buffer.readUInt8(dataOffset) & 0xff) * 256;
dataOffset += 1;
}
paddingLength += (buffer.readUInt8(dataOffset) & 0xff);
dataOffset += 1;
} else if (frame.flags.PAD_HIGH) {
return 'CONTINUATION frame got PAD_HIGH without PAD_LOW';
}
if (paddingLength) {
frame.data = buffer.slice(dataOffset, -1 * paddingLength);
} else {
frame.data = buffer.slice(dataOffset);
}
};
// [Error Codes](http://tools.ietf.org/html/draft-ietf-httpbis-http2-09#section-7)
// [Error Codes](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-7)
// ------------------------------------------------------------

@@ -717,0 +797,0 @@

@@ -1,2 +0,2 @@

// [node-http2-protocol][homepage] is an implementation of the [HTTP/2 (draft 09)][http2]
// [node-http2-protocol][homepage] is an implementation of the [HTTP/2 (draft 10)][http2]
// framing layer for [node.js][node].

@@ -31,6 +31,6 @@ //

// [homepage]: https://github.com/molnarg/node-http2
// [http2]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-09
// [http2-connheader]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-09#section-3.5
// [http2-stream]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-09#section-5
// [http2-streamstate]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-09#section-5.1
// [http2]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-10
// [http2-connheader]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-3.5
// [http2-stream]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-5
// [http2-streamstate]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-5.1
// [node]: http://nodejs.org/

@@ -41,2 +41,4 @@ // [node-stream]: http://nodejs.org/api/stream.html

exports.ImplementedVersion = 'h2-10';
exports.Endpoint = require('./endpoint').Endpoint;

@@ -43,0 +45,0 @@

@@ -325,3 +325,3 @@ var assert = require('assert');

// [Stream States](http://tools.ietf.org/html/draft-ietf-httpbis-http2-09#section-5.1)
// [Stream States](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-5.1)
// ----------------

@@ -383,3 +383,4 @@ //

var receiving = !sending;
var error = undefined;
var connectionError;
var streamError;

@@ -415,3 +416,3 @@ var DATA = false, HEADERS = false, PRIORITY = false;

} else {
error = 'PROTOCOL_ERROR';
connectionError = 'PROTOCOL_ERROR';
}

@@ -437,3 +438,3 @@ break;

} else {
error = 'PROTOCOL_ERROR';
connectionError = 'PROTOCOL_ERROR';
}

@@ -457,3 +458,3 @@ break;

} else {
error = 'PROTOCOL_ERROR';
connectionError = 'PROTOCOL_ERROR';
}

@@ -493,3 +494,3 @@ break;

} else {
error = 'PROTOCOL_ERROR';
connectionError = 'PROTOCOL_ERROR';
}

@@ -514,3 +515,3 @@ break;

} else {
error = 'PROTOCOL_ERROR';
connectionError = 'PROTOCOL_ERROR';
}

@@ -545,3 +546,3 @@ break;

} else {
error = 'STREAM_CLOSED';
streamError = 'STREAM_CLOSED';
}

@@ -565,3 +566,3 @@ break;

// The state of the stream becomes "reserved (remote)".
if (PUSH_PROMISE && !error) {
if (PUSH_PROMISE && !connectionError && !streamError) {
/* This assertion must hold, because _transition is called immediately when a frame is written

@@ -588,5 +589,5 @@ to the stream. If it would be called when a frame gets out of the input queue, the state

// Common error handling.
if (error) {
if (connectionError || streamError) {
var info = {
error: error,
error: connectionError,
frame: frame,

@@ -604,2 +605,4 @@ state: this.state,

// * In case of a serious problem, emitting and error and letting someone else handle it
// (e.g. closing the connection)
// * When receiving something invalid, sending an RST_STREAM using the `reset` method.

@@ -609,3 +612,8 @@ // This will automatically cause a transition to the CLOSED state.

this._log.error(info, 'Received illegal frame.');
this.emit('error', error);
if (connectionError) {
this.emit('connectionError', connectionError);
} else {
this.reset(streamError);
this.emit('error', streamError)
}
}

@@ -612,0 +620,0 @@ }

{
"name": "http2-protocol",
"version": "0.9.1",
"version": "0.10.0",
"description": "A JavaScript implementation of the HTTP/2 framing layer",

@@ -37,3 +37,4 @@ "main": "lib/index.js",

"Nick Hurley",
"Mike Belshe"
"Mike Belshe",
"vsemogutor"
],

@@ -40,0 +41,0 @@ "license": "MIT",

node-http2-protocol
===================
An HTTP/2 ([draft-ietf-httpbis-http2-09](http://tools.ietf.org/html/draft-ietf-httpbis-http2-09))
An HTTP/2 ([draft-ietf-httpbis-http2-10](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10))
framing layer implementaion for node.js.

@@ -55,6 +55,6 @@

```
Statements : 92.43% ( 1257/1360 )
Branches : 86.36% ( 500/579 )
Functions : 90.12% ( 146/162 )
Lines : 92.39% ( 1251/1354 )
Statements : 91.86% ( 1276/1389 )
Branches : 85.62% ( 524/612 )
Functions : 92.31% ( 144/156 )
Lines : 91.83% ( 1270/1383 )
```

@@ -74,2 +74,3 @@

* Mike Belshe
* vsemogutor

@@ -76,0 +77,0 @@ Special thanks to Google for financing the development of this module as part of their [Summer of

@@ -52,10 +52,10 @@ var expect = require('chai').expect;

test_huffman_response = {
'302': '409f',
'private': 'c31b39bf387f',
'Mon, 21 OCt 2013 20:13:21 GMT': 'a2fba20320f2ebcc0c490062d2434c827a1d',
': https://www.bar.com': '6871cf3c326ebd7e9e9e926e7e32557dbf',
'200': '311f',
'Mon, 21 OCt 2013 20:13:22 GMT': 'a2fba20320f2ebcc0c490062d2434cc27a1d',
'https://www.bar.com': 'e39e7864dd7afd3d3d24dcfc64aafb7f',
'gzip': 'e1fbb30f',
'302': '98a7',
'private': '73d5cd111f',
'Mon, 21 OCt 2013 20:13:21 GMT': 'ef6b3a7a0e6e8fa7647a0e534dd072fb0d37b0e6e8f777f8ff',
': https://www.bar.com': 'f6746718ba1ec00db6d897a1e44b74',
'200': '394b',
'Mon, 21 OCt 2013 20:13:22 GMT': 'ef6b3a7a0e6e8fa7647a0e534dd072fb0d37b0e7e8f777f8ff',
'https://www.bar.com': 'ce31743d801b6db12f43c896e9',
'gzip': 'cbd54e',
'foo=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\

@@ -68,17 +68,18 @@ AAAAAAAAAAAAAAAAAAAAAAAAAALASDJKHQKBZXOQWEOPIUAXQWEOIUAXLJKHQWOEIUAL\

ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ1234 m\
ax-age=3600; version=1': 'df7dfb36eddbb76eddbb76eddbb76eddbb76eddbb76eddbb76\
eddbb76eddbb76eddbb76eddbb76eddbb76eddbb76eddbb76eddbb76eddbb76eddbb\
76eddbb76eddbb7e3b69ecf0fe7e1fd7f3d5fe7f7e5fd79f6f97cbbfe9b7fbfebcfb\
7cbbfe9b7fbf8f87f3f0febcfcbb7bfe9b7e3fd79f6f977fd36ff7f1febb7e9b7fbf\
8fc7f9f0db4f67f5e7dbe5f4efdbfdf891a13f1db4f6787f3f0febf9eaff3fbf2feb\
cfb7cbe5dff4dbfdff5e7dbe5dff4dbfdfc7c3f9f87f5e7e5dbdff4dbf1febcfb7cb\
bfe9b7fbf8ff5dbf4dbfdfc7e3fcf86da7b3faf3edf2fa77edfefc48d09f8eda7b3c\
3f9f87f5fcf57f9fdf97f5e7dbe5f2effa6dfeffaf3edf2effa6dfefe3e1fcfc3faf\
3f2edeffa6df8ff5e7dbe5dff4dbfdfc7faedfa6dfefe3f1fe7c36d3d9fd79f6f97d\
3bf6ff7e24684fc76d3d9e1fcfc3fafe7abfcfefcbfaf3edf2f977fd36ff7fd79f6f\
977fd36ff7f1f0fe7e1fd79f976f7fd36fc7faf3edf2effa6dfefe3fd76fd36ff7f1\
f8ff3e1b69ecfebcfb7cbe9dfb7fbf123427fcff3fcff3fcff3fcff3fcff3fcff3fc\
ff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3\
ax-age=3600; version=1': 'c5adb77efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7\
efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfb\
f7efdfbf7efdfbf7efdfbfe5bfc3b7e3fdfbfedfdf5ff9fbfa7dbf5ddf4fafc3f1bf\
f7f6fd777d3e1f8dffbf97c7fbf7fdbf5f4eef87e37fcbedfaeefa7c3f1bff7f2fb7\
77e37fefe5f2fefe3bfc3b7edfaeefa7e3e1bff7f331e69fe5bfc3b7e3fdfbfedfdf\
5ff9fbfa7dbf5ddf4fafc3f1bff7f6fd777d3e1f8dffbf97c7fbf7fdbf5f4eef87e3\
7fcbedfaeefa7c3f1bff7f2fb777e37fefe5f2fefe3bfc3b7edfaeefa7e3e1bff7f3\
31e69fe5bfc3b7e3fdfbfedfdf5ff9fbfa7dbf5ddf4fafc3f1bff7f6fd777d3e1f8d\
ffbf97c7fbf7fdbf5f4eef87e37fcbedfaeefa7c3f1bff7f2fb777e37fefe5f2fefe\
3bfc3b7edfaeefa7e3e1bff7f331e69fe5bfc3b7e3fdfbfedfdf5ff9fbfa7dbf5ddf\
4fafc3f1bff7f6fd777d3e1f8dffbf97c7fbf7fdbf5f4eef87e37fcbedfaeefa7c3f\
1bff7f2fb777e37fefe5f2fefe3bfc3b7edfaeefa7e3e1bff7f331e69ffcff3fcff3\
fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcf\
f3fcff3fcff08d090b5fd237f086c44a23ef0e70c72b2fbb617f',
f3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3f\
cff3fcff3fcff3fcff3fcff3fcff3fcff0c79a7e8d11e72a321b66a4a5eae8e62f82\
9acb4d',
'foo=ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ\

@@ -91,17 +92,18 @@ ZZZZZZZZZZZZZZZZZZZZZZZZZZLASDJKHQKBZXOQWEOPIUAXQWEOIUAXLJKHQWOEIUAL\

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1234 m\
ax-age=3600; version=1': 'df7dfb3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcf\
f3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3f\
ax-age=3600; version=1': 'c5adb7fcff3fcff3fcff3fcff3fcff3fcff3fcff3f\
cff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff\
3e3b69ecf0fe7e1fd7f3d5fe7f7e5fd79f6f97cbbfe9b7fbfebcfb7cbbfe9b7fbf8f\
87f3f0febcfcbb7bfe9b7e3fd79f6f977fd36ff7f1febb7e9b7fbf8fc7f9f0db4f67\
f5e7dbe5f4efdbfdf891a13f1db4f6787f3f0febf9eaff3fbf2febcfb7cbe5dff4db\
fdff5e7dbe5dff4dbfdfc7c3f9f87f5e7e5dbdff4dbf1febcfb7cbbfe9b7fbf8ff5d\
bf4dbfdfc7e3fcf86da7b3faf3edf2fa77edfefc48d09f8eda7b3c3f9f87f5fcf57f\
9fdf97f5e7dbe5f2effa6dfeffaf3edf2effa6dfefe3e1fcfc3faf3f2edeffa6df8f\
f5e7dbe5dff4dbfdfc7faedfa6dfefe3f1fe7c36d3d9fd79f6f97d3bf6ff7e24684f\
c76d3d9e1fcfc3fafe7abfcfefcbfaf3edf2f977fd36ff7fd79f6f977fd36ff7f1f0\
fe7e1fd79f976f7fd36fc7faf3edf2effa6dfefe3fd76fd36ff7f1f8ff3e1b69ecfe\
bcfb7cbe9dfb7fbf1234276eddbb76eddbb76eddbb76eddbb76eddbb76eddbb76edd\
bb76eddbb76eddbb76eddbb76eddbb76eddbb76eddbb76eddbb76eddbb76eddbb76e\
ddbb76eddbb48d090b5fd237f086c44a23ef0e70c72b2fbb617f'
3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fc\
ff3fcff3e5bfc3b7e3fdfbfedfdf5ff9fbfa7dbf5ddf4fafc3f1bff7f6fd777d3e1f\
8dffbf97c7fbf7fdbf5f4eef87e37fcbedfaeefa7c3f1bff7f2fb777e37fefe5f2fe\
fe3bfc3b7edfaeefa7e3e1bff7f331e69fe5bfc3b7e3fdfbfedfdf5ff9fbfa7dbf5d\
df4fafc3f1bff7f6fd777d3e1f8dffbf97c7fbf7fdbf5f4eef87e37fcbedfaeefa7c\
3f1bff7f2fb777e37fefe5f2fefe3bfc3b7edfaeefa7e3e1bff7f331e69fe5bfc3b7\
e3fdfbfedfdf5ff9fbfa7dbf5ddf4fafc3f1bff7f6fd777d3e1f8dffbf97c7fbf7fd\
bf5f4eef87e37fcbedfaeefa7c3f1bff7f2fb777e37fefe5f2fefe3bfc3b7edfaeef\
a7e3e1bff7f331e69fe5bfc3b7e3fdfbfedfdf5ff9fbfa7dbf5ddf4fafc3f1bff7f6\
fd777d3e1f8dffbf97c7fbf7fdbf5f4eef87e37fcbedfaeefa7c3f1bff7f2fb777e3\
7fefe5f2fefe3bfc3b7edfaeefa7e3e1bff7f331e69f7efdfbf7efdfbf7efdfbf7ef\
dfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7\
efdfbf7efdfbf7efdfbf7efdfbf7efdfbcc79a7e8d11e72a321b66a4a5eae8e62f82\
9acb4d'
};

@@ -204,5 +206,5 @@

value: -1,
index: false
index: true
},
buffer: new Buffer('80', 'hex')
buffer: new Buffer('8080', 'hex')
}];

@@ -265,3 +267,3 @@

it('should return the Huffman encoded version of the input buffer', function() {
var table = HuffmanTable.requestHuffmanTable;
var table = HuffmanTable.huffmanTable;
for (var decoded in test_huffman_request) {

@@ -271,3 +273,3 @@ var encoded = test_huffman_request[decoded];

}
table = HuffmanTable.responseHuffmanTable;
table = HuffmanTable.huffmanTable;
for (decoded in test_huffman_response) {

@@ -281,3 +283,3 @@ encoded = test_huffman_response[decoded];

it('should return the Huffman decoded version of the input buffer', function() {
var table = HuffmanTable.requestHuffmanTable;
var table = HuffmanTable.huffmanTable;
for (var decoded in test_huffman_request) {

@@ -287,3 +289,3 @@ var encoded = test_huffman_request[decoded];

}
table = HuffmanTable.responseHuffmanTable;
table = HuffmanTable.huffmanTable;
for (decoded in test_huffman_response) {

@@ -309,3 +311,3 @@ encoded = test_huffman_response[decoded];

it('should return an array of buffers that represent the encoded form of the string', function() {
var table = HuffmanTable.requestHuffmanTable;
var table = HuffmanTable.huffmanTable;
for (var i = 0; i < test_strings.length; i++) {

@@ -319,3 +321,3 @@ var test = test_strings[i];

it('should return an array of buffers that represent the encoded form of the header', function() {
var table = HuffmanTable.requestHuffmanTable;
var table = HuffmanTable.huffmanTable;
for (var i = 0; i < test_headers.length; i++) {

@@ -342,3 +344,3 @@ var test = test_headers[i];

it('should return the parsed string and increase the cursor property of buffer', function() {
var table = HuffmanTable.requestHuffmanTable;
var table = HuffmanTable.huffmanTable;
for (var i = 0; i < test_strings.length; i++) {

@@ -354,3 +356,3 @@ var test = test_strings[i];

it('should return the parsed header and increase the cursor property of buffer', function() {
var table = HuffmanTable.requestHuffmanTable;
var table = HuffmanTable.huffmanTable;
for (var i = 0; i < test_headers.length; i++) {

@@ -443,3 +445,3 @@ var test = test_headers[i];

buffer = new Buffer(buffer);
var table = HuffmanTable.requestHuffmanTable;
var table = HuffmanTable.huffmanTable;
var result = table.decode(table.encode(buffer));

@@ -446,0 +448,0 @@ expect(result).to.deep.equal(buffer);

@@ -66,43 +66,2 @@ var expect = require('chai').expect;

describe('invalid operation', function() {
describe('disabling and the re-enabling flow control', function() {
it('should result in an error event with type "FLOW_CONTROL_ERROR"', function(done) {
var connection = new Connection(util.log, 1, settings);
connection.on('error', function(error) {
expect(error).to.equal('FLOW_CONTROL_ERROR');
done();
});
connection._setLocalFlowControl(true);
connection._setLocalFlowControl(false);
});
});
describe('manipulating flow control window after flow control was turned off', function() {
it('should result in an error event with type "FLOW_CONTROL_ERROR"', function(done) {
var connection = new Connection(util.log, 1, settings);
connection.on('error', function(error) {
expect(error).to.equal('FLOW_CONTROL_ERROR');
done();
});
connection._setLocalFlowControl(true);
connection._setInitialStreamWindowSize(10);
});
});
describe('disabling flow control twice', function() {
it('should be ignored', function() {
var connection = new Connection(util.log, 1, settings);
connection._setLocalFlowControl(true);
connection._setLocalFlowControl(true);
});
});
describe('enabling flow control when already enabled', function() {
it('should be ignored', function() {
var connection = new Connection(util.log, 1, settings);
connection._setLocalFlowControl(false);
});
});
describe('unsolicited ping answer', function() {

@@ -109,0 +68,0 @@ it('should be ignored', function() {

@@ -85,9 +85,2 @@ var expect = require('chai').expect;

});
describe('.disableLocalFlowControl() method', function() {
it('should increase `this._window` by Infinity', function() {
flow._send = util.noop;
flow.disableLocalFlowControl();
expect(flow._window).to.equal(Infinity);
});
});
describe('.read() method', function() {

@@ -136,3 +129,2 @@ describe('when the flow control queue is not empty', function() {

'disabled', function(done) {
flow._remoteFlowControlDisabled = false;
flow._window = 100;

@@ -164,3 +156,2 @@ flow._send = util.noop;

flow1._flowControlId = flow2._flowControlId;
flow1._remoteFlowControlDisabled = flow2._remoteFlowControlDisabled = false;
flow1._send = flow2._send = util.noop;

@@ -167,0 +158,0 @@ flow1._receive = flow2._receive = function(frame, callback) { callback(); };

@@ -24,3 +24,4 @@ var expect = require('chai').expect;

type: 'DATA',
flags: { END_STREAM: false, RESERVED: false },
flags: { END_STREAM: false, END_SEGMENT: false, RESERVED4: false,
RESERVED8: false, PAD_LOW: false, PAD_HIGH: false },
stream: 10,

@@ -36,3 +37,4 @@

type: 'HEADERS',
flags: { END_STREAM: false, RESERVED: false, END_HEADERS: false, PRIORITY: false },
flags: { END_STREAM: false, END_SEGMENT: false, END_HEADERS: false,
PRIORITY: false, PAD_LOW: false, PAD_HIGH: false },
stream: 15,

@@ -47,3 +49,4 @@

type: 'HEADERS',
flags: { END_STREAM: false, RESERVED: false, END_HEADERS: false, PRIORITY: true },
flags: { END_STREAM: false, END_SEGMENT: false, END_HEADERS: false,
PRIORITY: true, PAD_LOW: false, PAD_HIGH: false },
stream: 15,

@@ -86,11 +89,9 @@

SETTINGS_MAX_CONCURRENT_STREAMS: 0x01234567,
SETTINGS_INITIAL_WINDOW_SIZE: 0x89ABCDEF,
SETTINGS_FLOW_CONTROL_OPTIONS: true
SETTINGS_INITIAL_WINDOW_SIZE: 0x89ABCDEF
}
},
buffer: new Buffer('0028' + '04' + '00' + '0000000A' + '00' + '000001' + '12345678' +
'00' + '000002' + '00000001' +
'00' + '000004' + '01234567' +
'00' + '000007' + '89ABCDEF' +
'00' + '00000A' + '00000001', 'hex')
buffer: new Buffer('0014' + '04' + '00' + '0000000A' + '01' + '12345678' +
'02' + '00000001' +
'03' + '01234567' +
'04' + '89ABCDEF', 'hex')

@@ -137,7 +138,8 @@ }, {

},
buffer: new Buffer('0004' + '09' + '00' + '0000000A' + '12345678', 'hex')
buffer: new Buffer('0004' + '08' + '00' + '0000000A' + '12345678', 'hex')
}, {
frame: {
type: 'CONTINUATION',
flags: { RESERVED1: false, RESERVED2: false, END_HEADERS: true },
flags: { RESERVED1: false, RESERVED2: false, END_HEADERS: true,
RESERVED8: false, PAD_LOW: false, PAD_HIGH: false },
stream: 10,

@@ -148,5 +150,57 @@

// length + type + flags + stream + content
buffer: new Buffer('0004' + '0A' + '04' + '0000000A' + '12345678', 'hex')
buffer: new Buffer('0004' + '09' + '04' + '0000000A' + '12345678', 'hex')
}];
var deserializer_test_frames = test_frames.slice(0);
var padded_test_frames = [{
frame: {
type: 'DATA',
flags: { END_STREAM: false, END_SEGMENT: false, RESERVED4: false,
RESERVED8: false, PAD_LOW: true, PAD_HIGH: false },
stream: 10,
data: new Buffer('12345678', 'hex')
},
// length + type + flags + stream + pad_low control + content + padding
buffer: new Buffer('000B' + '00' + '10' + '0000000A' + '06' + '12345678' + '000000000000', 'hex')
}, {
frame: {
type: 'HEADERS',
flags: { END_STREAM: false, END_SEGMENT: false, END_HEADERS: false,
PRIORITY: false, PAD_LOW: true, PAD_HIGH: false },
stream: 15,
data: new Buffer('12345678', 'hex')
},
buffer: new Buffer('000B' + '01' + '10' + '0000000F' + '06' + '12345678' + '000000000000', 'hex')
}, {
frame: {
type: 'HEADERS',
flags: { END_STREAM: false, END_SEGMENT: false, END_HEADERS: false,
PRIORITY: true, PAD_LOW: true, PAD_HIGH: false },
stream: 15,
priority: 3,
data: new Buffer('12345678', 'hex')
},
buffer: new Buffer('000F' + '01' + '18' + '0000000F' + '06' + '00000003' + '12345678' + '000000000000', 'hex')
}, {
frame: {
type: 'CONTINUATION',
flags: { RESERVED1: false, RESERVED2: false, END_HEADERS: true,
RESERVED8: false, PAD_LOW: true, PAD_HIGH: false },
stream: 10,
data: new Buffer('12345678', 'hex')
},
// length + type + flags + stream + content
buffer: new Buffer('000B' + '09' + '14' + '0000000A' + '06' + '12345678' + '000000000000', 'hex')
}];
for (var idx = 0; idx < padded_test_frames.length; idx++) {
deserializer_test_frames.push(padded_test_frames[idx]);
}
describe('framer.js', function() {

@@ -201,4 +255,4 @@ describe('Serializer', function() {

it('should augment the frame object with these properties: { type, flags, stream })', function() {
for (var i = 0; i < test_frames.length; i++) {
var test = test_frames[i], frame = {};
for (var i = 0; i < deserializer_test_frames.length; i++) {
var test = deserializer_test_frames[i], frame = {};
Deserializer.commonHeader(test.buffer.slice(0,8), frame);

@@ -215,3 +269,3 @@ expect(frame).to.deep.equal({

Object.keys(frame_types).forEach(function(type) {
var tests = test_frames.filter(function(test) { return test.frame.type === type; });
var tests = deserializer_test_frames.filter(function(test) { return test.frame.type === type; });
var frame_shape = '{ ' + frame_types[type].join(', ') + ' }';

@@ -238,7 +292,7 @@ describe('static method .' + type + '(payload_buffer, frame)', function() {

var shuffled = util.shuffleBuffers(test_frames.map(function(test) { return test.buffer; }));
var shuffled = util.shuffleBuffers(deserializer_test_frames.map(function(test) { return test.buffer; }));
shuffled.forEach(stream.write.bind(stream));
for (var j = 0; j < test_frames.length; j++) {
expect(stream.read()).to.be.deep.equal(test_frames[j].frame);
for (var j = 0; j < deserializer_test_frames.length; j++) {
expect(stream.read()).to.be.deep.equal(deserializer_test_frames[j].frame);
}

@@ -245,0 +299,0 @@ });

@@ -10,3 +10,2 @@ var expect = require('chai').expect;

stream.upstream._window = Infinity;
stream.upstream._remoteFlowControlDisabled = true;
return stream;

@@ -189,4 +188,7 @@ }

var stream = createStream();
var connectionErrorHappened = false
stream.state = state;
expect(stream._transition.bind(stream, false, invalid_frame)).to.throw('Uncaught, unspecified "error" event.');
stream.once('connectionError', function() { connectionErrorHappened = true; });
stream._transition(false, invalid_frame)
expect(connectionErrorHappened)
});

@@ -193,0 +195,0 @@ });

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc