WIP - add extractor, generate snippet_data
This commit is contained in:
14
node_modules/spdy-transport/.travis.yml
generated
vendored
Normal file
14
node_modules/spdy-transport/.travis.yml
generated
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
sudo: false
|
||||
|
||||
language: node_js
|
||||
|
||||
node_js:
|
||||
- "6"
|
||||
- "8"
|
||||
- "10"
|
||||
- "stable"
|
||||
|
||||
script:
|
||||
- npm run lint
|
||||
- npm test
|
||||
- npm run coverage
|
||||
76
node_modules/spdy-transport/README.md
generated
vendored
Normal file
76
node_modules/spdy-transport/README.md
generated
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
# spdy-transport
|
||||
|
||||
[](http://travis-ci.org/spdy-http2/spdy-transport)
|
||||
[](http://badge.fury.io/js/spdy-transport)
|
||||
[](https://david-dm.org/spdy-http2/spdy-transport)
|
||||
[](http://standardjs.com/)
|
||||
[](https://waffle.io/spdy-http2/node-spdy)
|
||||
|
||||
> SPDY/HTTP2 generic transport implementation.
|
||||
|
||||
## Usage
|
||||
|
||||
```javascript
|
||||
var transport = require('spdy-transport');
|
||||
|
||||
// NOTE: socket is some stream or net.Socket instance, may be an argument
|
||||
// of `net.createServer`'s connection handler.
|
||||
|
||||
var server = transport.connection.create(socket, {
|
||||
protocol: 'http2',
|
||||
isServer: true
|
||||
});
|
||||
|
||||
server.on('stream', function(stream) {
|
||||
console.log(stream.method, stream.path, stream.headers);
|
||||
stream.respond(200, {
|
||||
header: 'value'
|
||||
});
|
||||
|
||||
stream.on('readable', function() {
|
||||
var chunk = stream.read();
|
||||
if (!chunk)
|
||||
return;
|
||||
|
||||
console.log(chunk);
|
||||
});
|
||||
|
||||
stream.on('end', function() {
|
||||
console.log('end');
|
||||
});
|
||||
|
||||
// And other node.js Stream APIs
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
## LICENSE
|
||||
|
||||
This software is licensed under the MIT License.
|
||||
|
||||
Copyright Fedor Indutny, 2015.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
persons to whom the Software is furnished to do so, subject to the
|
||||
following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
[0]: http://json.org/
|
||||
[1]: http://github.com/indutny/bud-backend
|
||||
[2]: https://github.com/nodejs/io.js
|
||||
[3]: https://github.com/libuv/libuv
|
||||
[4]: http://openssl.org/
|
||||
25
node_modules/spdy-transport/lib/spdy-transport.js
generated
vendored
Normal file
25
node_modules/spdy-transport/lib/spdy-transport.js
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
'use strict'
|
||||
|
||||
var transport = exports
|
||||
|
||||
// Exports utils
|
||||
transport.utils = require('./spdy-transport/utils')
|
||||
|
||||
// Export parser&framer
|
||||
transport.protocol = {}
|
||||
transport.protocol.base = require('./spdy-transport/protocol/base')
|
||||
transport.protocol.spdy = require('./spdy-transport/protocol/spdy')
|
||||
transport.protocol.http2 = require('./spdy-transport/protocol/http2')
|
||||
|
||||
// Window
|
||||
transport.Window = require('./spdy-transport/window')
|
||||
|
||||
// Priority Tree
|
||||
transport.Priority = require('./spdy-transport/priority')
|
||||
|
||||
// Export Connection and Stream
|
||||
transport.Stream = require('./spdy-transport/stream').Stream
|
||||
transport.Connection = require('./spdy-transport/connection').Connection
|
||||
|
||||
// Just for `transport.connection.create()`
|
||||
transport.connection = transport.Connection
|
||||
845
node_modules/spdy-transport/lib/spdy-transport/connection.js
generated
vendored
Normal file
845
node_modules/spdy-transport/lib/spdy-transport/connection.js
generated
vendored
Normal file
@ -0,0 +1,845 @@
|
||||
'use strict'
|
||||
|
||||
var util = require('util')
|
||||
var transport = require('../spdy-transport')
|
||||
|
||||
var debug = {
|
||||
server: require('debug')('spdy:connection:server'),
|
||||
client: require('debug')('spdy:connection:client')
|
||||
}
|
||||
var EventEmitter = require('events').EventEmitter
|
||||
|
||||
var Stream = transport.Stream
|
||||
|
||||
function Connection (socket, options) {
|
||||
EventEmitter.call(this)
|
||||
|
||||
var state = {}
|
||||
this._spdyState = state
|
||||
|
||||
// NOTE: There's a big trick here. Connection is used as a `this` argument
|
||||
// to the wrapped `connection` event listener.
|
||||
// socket end doesn't necessarly mean connection drop
|
||||
this.httpAllowHalfOpen = true
|
||||
|
||||
state.timeout = new transport.utils.Timeout(this)
|
||||
|
||||
// Protocol info
|
||||
state.protocol = transport.protocol[options.protocol]
|
||||
state.version = null
|
||||
state.constants = state.protocol.constants
|
||||
state.pair = null
|
||||
state.isServer = options.isServer
|
||||
|
||||
// Root of priority tree (i.e. stream id = 0)
|
||||
state.priorityRoot = new transport.Priority({
|
||||
defaultWeight: state.constants.DEFAULT_WEIGHT,
|
||||
maxCount: transport.protocol.base.constants.MAX_PRIORITY_STREAMS
|
||||
})
|
||||
|
||||
// Defaults
|
||||
state.maxStreams = options.maxStreams ||
|
||||
state.constants.MAX_CONCURRENT_STREAMS
|
||||
|
||||
state.autoSpdy31 = options.protocol.name !== 'h2' && options.autoSpdy31
|
||||
state.acceptPush = options.acceptPush === undefined
|
||||
? !state.isServer
|
||||
: options.acceptPush
|
||||
|
||||
if (options.maxChunk === false) { state.maxChunk = Infinity } else if (options.maxChunk === undefined) { state.maxChunk = transport.protocol.base.constants.DEFAULT_MAX_CHUNK } else {
|
||||
state.maxChunk = options.maxChunk
|
||||
}
|
||||
|
||||
// Connection-level flow control
|
||||
var windowSize = options.windowSize || 1 << 20
|
||||
state.window = new transport.Window({
|
||||
id: 0,
|
||||
isServer: state.isServer,
|
||||
recv: {
|
||||
size: state.constants.DEFAULT_WINDOW,
|
||||
max: state.constants.MAX_INITIAL_WINDOW_SIZE
|
||||
},
|
||||
send: {
|
||||
size: state.constants.DEFAULT_WINDOW,
|
||||
max: state.constants.MAX_INITIAL_WINDOW_SIZE
|
||||
}
|
||||
})
|
||||
|
||||
// It starts with DEFAULT_WINDOW, update must be sent to change it on client
|
||||
state.window.recv.setMax(windowSize)
|
||||
|
||||
// Boilerplate for Stream constructor
|
||||
state.streamWindow = new transport.Window({
|
||||
id: -1,
|
||||
isServer: state.isServer,
|
||||
recv: {
|
||||
size: windowSize,
|
||||
max: state.constants.MAX_INITIAL_WINDOW_SIZE
|
||||
},
|
||||
send: {
|
||||
size: state.constants.DEFAULT_WINDOW,
|
||||
max: state.constants.MAX_INITIAL_WINDOW_SIZE
|
||||
}
|
||||
})
|
||||
|
||||
// Various state info
|
||||
state.pool = state.protocol.compressionPool.create(options.headerCompression)
|
||||
state.counters = {
|
||||
push: 0,
|
||||
stream: 0
|
||||
}
|
||||
|
||||
// Init streams list
|
||||
state.stream = {
|
||||
map: {},
|
||||
count: 0,
|
||||
nextId: state.isServer ? 2 : 1,
|
||||
lastId: {
|
||||
both: 0,
|
||||
received: 0
|
||||
}
|
||||
}
|
||||
state.ping = {
|
||||
nextId: state.isServer ? 2 : 1,
|
||||
map: {}
|
||||
}
|
||||
state.goaway = false
|
||||
|
||||
// Debug
|
||||
state.debug = state.isServer ? debug.server : debug.client
|
||||
|
||||
// X-Forwarded feature
|
||||
state.xForward = null
|
||||
|
||||
// Create parser and hole for framer
|
||||
state.parser = state.protocol.parser.create({
|
||||
// NOTE: needed to distinguish ping from ping ACK in SPDY
|
||||
isServer: state.isServer,
|
||||
window: state.window
|
||||
})
|
||||
state.framer = state.protocol.framer.create({
|
||||
window: state.window,
|
||||
timeout: state.timeout
|
||||
})
|
||||
|
||||
// SPDY has PUSH enabled on servers
|
||||
if (state.protocol.name === 'spdy') {
|
||||
state.framer.enablePush(state.isServer)
|
||||
}
|
||||
|
||||
if (!state.isServer) { state.parser.skipPreface() }
|
||||
|
||||
this.socket = socket
|
||||
|
||||
this._init()
|
||||
}
|
||||
util.inherits(Connection, EventEmitter)
|
||||
exports.Connection = Connection
|
||||
|
||||
Connection.create = function create (socket, options) {
|
||||
return new Connection(socket, options)
|
||||
}
|
||||
|
||||
Connection.prototype._init = function init () {
|
||||
var self = this
|
||||
var state = this._spdyState
|
||||
var pool = state.pool
|
||||
|
||||
// Initialize session window
|
||||
state.window.recv.on('drain', function () {
|
||||
self._onSessionWindowDrain()
|
||||
})
|
||||
|
||||
// Initialize parser
|
||||
state.parser.on('data', function (frame) {
|
||||
self._handleFrame(frame)
|
||||
})
|
||||
state.parser.once('version', function (version) {
|
||||
self._onVersion(version)
|
||||
})
|
||||
|
||||
// Propagate parser errors
|
||||
state.parser.on('error', function (err) {
|
||||
self._onParserError(err)
|
||||
})
|
||||
|
||||
// Propagate framer errors
|
||||
state.framer.on('error', function (err) {
|
||||
self.emit('error', err)
|
||||
})
|
||||
|
||||
this.socket.pipe(state.parser)
|
||||
state.framer.pipe(this.socket)
|
||||
|
||||
// Allow high-level api to catch socket errors
|
||||
this.socket.on('error', function onSocketError (e) {
|
||||
self.emit('error', e)
|
||||
})
|
||||
|
||||
this.socket.once('close', function onclose (hadError) {
|
||||
var err
|
||||
if (hadError) {
|
||||
err = new Error('socket hang up')
|
||||
err.code = 'ECONNRESET'
|
||||
}
|
||||
|
||||
self.destroyStreams(err)
|
||||
self.emit('close')
|
||||
|
||||
if (state.pair) {
|
||||
pool.put(state.pair)
|
||||
}
|
||||
|
||||
state.framer.resume()
|
||||
})
|
||||
|
||||
// Reset timeout on close
|
||||
this.once('close', function () {
|
||||
self.setTimeout(0)
|
||||
})
|
||||
|
||||
function _onWindowOverflow () {
|
||||
self._onWindowOverflow()
|
||||
}
|
||||
|
||||
state.window.recv.on('overflow', _onWindowOverflow)
|
||||
state.window.send.on('overflow', _onWindowOverflow)
|
||||
|
||||
// Do not allow half-open connections
|
||||
this.socket.allowHalfOpen = false
|
||||
}
|
||||
|
||||
Connection.prototype._onVersion = function _onVersion (version) {
|
||||
var state = this._spdyState
|
||||
var prev = state.version
|
||||
var parser = state.parser
|
||||
var framer = state.framer
|
||||
var pool = state.pool
|
||||
|
||||
state.version = version
|
||||
state.debug('id=0 version=%d', version)
|
||||
|
||||
// Ignore transition to 3.1
|
||||
if (!prev) {
|
||||
state.pair = pool.get(version)
|
||||
parser.setCompression(state.pair)
|
||||
framer.setCompression(state.pair)
|
||||
}
|
||||
framer.setVersion(version)
|
||||
|
||||
if (!state.isServer) {
|
||||
framer.prefaceFrame()
|
||||
if (state.xForward !== null) {
|
||||
framer.xForwardedFor({ host: state.xForward })
|
||||
}
|
||||
}
|
||||
|
||||
// Send preface+settings frame (once)
|
||||
framer.settingsFrame({
|
||||
max_header_list_size: state.constants.DEFAULT_MAX_HEADER_LIST_SIZE,
|
||||
max_concurrent_streams: state.maxStreams,
|
||||
enable_push: state.acceptPush ? 1 : 0,
|
||||
initial_window_size: state.window.recv.max
|
||||
})
|
||||
|
||||
// Update session window
|
||||
if (state.version >= 3.1 || (state.isServer && state.autoSpdy31)) { this._onSessionWindowDrain() }
|
||||
|
||||
this.emit('version', version)
|
||||
}
|
||||
|
||||
Connection.prototype._onParserError = function _onParserError (err) {
|
||||
var state = this._spdyState
|
||||
|
||||
// Prevent further errors
|
||||
state.parser.kill()
|
||||
|
||||
// Send GOAWAY
|
||||
if (err instanceof transport.protocol.base.utils.ProtocolError) {
|
||||
this._goaway({
|
||||
lastId: state.stream.lastId.both,
|
||||
code: err.code,
|
||||
extra: err.message,
|
||||
send: true
|
||||
})
|
||||
}
|
||||
|
||||
this.emit('error', err)
|
||||
}
|
||||
|
||||
Connection.prototype._handleFrame = function _handleFrame (frame) {
|
||||
var state = this._spdyState
|
||||
|
||||
state.debug('id=0 frame', frame)
|
||||
state.timeout.reset()
|
||||
|
||||
// For testing purposes
|
||||
this.emit('frame', frame)
|
||||
|
||||
var stream
|
||||
|
||||
// Session window update
|
||||
if (frame.type === 'WINDOW_UPDATE' && frame.id === 0) {
|
||||
if (state.version < 3.1 && state.autoSpdy31) {
|
||||
state.debug('id=0 switch version to 3.1')
|
||||
state.version = 3.1
|
||||
this.emit('version', 3.1)
|
||||
}
|
||||
state.window.send.update(frame.delta)
|
||||
return
|
||||
}
|
||||
|
||||
if (state.isServer && frame.type === 'PUSH_PROMISE') {
|
||||
state.debug('id=0 server PUSH_PROMISE')
|
||||
this._goaway({
|
||||
lastId: state.stream.lastId.both,
|
||||
code: 'PROTOCOL_ERROR',
|
||||
send: true
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (!stream && frame.id !== undefined) {
|
||||
// Load created one
|
||||
stream = state.stream.map[frame.id]
|
||||
|
||||
// Fail if not found
|
||||
if (!stream &&
|
||||
frame.type !== 'HEADERS' &&
|
||||
frame.type !== 'PRIORITY' &&
|
||||
frame.type !== 'RST') {
|
||||
// Other side should destroy the stream upon receiving GOAWAY
|
||||
if (this._isGoaway(frame.id)) { return }
|
||||
|
||||
state.debug('id=0 stream=%d not found', frame.id)
|
||||
state.framer.rstFrame({ id: frame.id, code: 'INVALID_STREAM' })
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Create new stream
|
||||
if (!stream && frame.type === 'HEADERS') {
|
||||
this._handleHeaders(frame)
|
||||
return
|
||||
}
|
||||
|
||||
if (stream) {
|
||||
stream._handleFrame(frame)
|
||||
} else if (frame.type === 'SETTINGS') {
|
||||
this._handleSettings(frame.settings)
|
||||
} else if (frame.type === 'ACK_SETTINGS') {
|
||||
// TODO(indutny): handle it one day
|
||||
} else if (frame.type === 'PING') {
|
||||
this._handlePing(frame)
|
||||
} else if (frame.type === 'GOAWAY') {
|
||||
this._handleGoaway(frame)
|
||||
} else if (frame.type === 'X_FORWARDED_FOR') {
|
||||
// Set X-Forwarded-For only once
|
||||
if (state.xForward === null) {
|
||||
state.xForward = frame.host
|
||||
}
|
||||
} else if (frame.type === 'PRIORITY') {
|
||||
// TODO(indutny): handle this
|
||||
} else {
|
||||
state.debug('id=0 unknown frame type: %s', frame.type)
|
||||
}
|
||||
}
|
||||
|
||||
Connection.prototype._onWindowOverflow = function _onWindowOverflow () {
|
||||
var state = this._spdyState
|
||||
state.debug('id=0 window overflow')
|
||||
this._goaway({
|
||||
lastId: state.stream.lastId.both,
|
||||
code: 'FLOW_CONTROL_ERROR',
|
||||
send: true
|
||||
})
|
||||
}
|
||||
|
||||
Connection.prototype._isGoaway = function _isGoaway (id) {
|
||||
var state = this._spdyState
|
||||
if (state.goaway !== false && state.goaway < id) { return true }
|
||||
return false
|
||||
}
|
||||
|
||||
Connection.prototype._getId = function _getId () {
|
||||
var state = this._spdyState
|
||||
|
||||
var id = state.stream.nextId
|
||||
state.stream.nextId += 2
|
||||
return id
|
||||
}
|
||||
|
||||
Connection.prototype._createStream = function _createStream (uri) {
|
||||
var state = this._spdyState
|
||||
var id = uri.id
|
||||
if (id === undefined) { id = this._getId() }
|
||||
|
||||
var isGoaway = this._isGoaway(id)
|
||||
|
||||
if (uri.push && !state.acceptPush) {
|
||||
state.debug('id=0 push disabled promisedId=%d', id)
|
||||
|
||||
// Fatal error
|
||||
this._goaway({
|
||||
lastId: state.stream.lastId.both,
|
||||
code: 'PROTOCOL_ERROR',
|
||||
send: true
|
||||
})
|
||||
isGoaway = true
|
||||
}
|
||||
|
||||
var stream = new Stream(this, {
|
||||
id: id,
|
||||
request: uri.request !== false,
|
||||
method: uri.method,
|
||||
path: uri.path,
|
||||
host: uri.host,
|
||||
priority: uri.priority,
|
||||
headers: uri.headers,
|
||||
parent: uri.parent,
|
||||
readable: !isGoaway && uri.readable,
|
||||
writable: !isGoaway && uri.writable
|
||||
})
|
||||
var self = this
|
||||
|
||||
// Just an empty stream for API consistency
|
||||
if (isGoaway) {
|
||||
return stream
|
||||
}
|
||||
|
||||
state.stream.lastId.both = Math.max(state.stream.lastId.both, id)
|
||||
|
||||
state.debug('id=0 add stream=%d', stream.id)
|
||||
state.stream.map[stream.id] = stream
|
||||
state.stream.count++
|
||||
state.counters.stream++
|
||||
if (stream.parent !== null) {
|
||||
state.counters.push++
|
||||
}
|
||||
|
||||
stream.once('close', function () {
|
||||
self._removeStream(stream)
|
||||
})
|
||||
|
||||
return stream
|
||||
}
|
||||
|
||||
Connection.prototype._handleHeaders = function _handleHeaders (frame) {
|
||||
var state = this._spdyState
|
||||
|
||||
// Must be HEADERS frame after stream close
|
||||
if (frame.id <= state.stream.lastId.received) { return }
|
||||
|
||||
// Someone is using our ids!
|
||||
if ((frame.id + state.stream.nextId) % 2 === 0) {
|
||||
state.framer.rstFrame({ id: frame.id, code: 'PROTOCOL_ERROR' })
|
||||
return
|
||||
}
|
||||
|
||||
var stream = this._createStream({
|
||||
id: frame.id,
|
||||
request: false,
|
||||
method: frame.headers[':method'],
|
||||
path: frame.headers[':path'],
|
||||
host: frame.headers[':authority'],
|
||||
priority: frame.priority,
|
||||
headers: frame.headers,
|
||||
writable: frame.writable
|
||||
})
|
||||
|
||||
// GOAWAY
|
||||
if (this._isGoaway(stream.id)) {
|
||||
return
|
||||
}
|
||||
|
||||
state.stream.lastId.received = Math.max(
|
||||
state.stream.lastId.received,
|
||||
stream.id
|
||||
)
|
||||
|
||||
// TODO(indutny) handle stream limit
|
||||
if (!this.emit('stream', stream)) {
|
||||
// No listeners was set - abort the stream
|
||||
stream.abort()
|
||||
return
|
||||
}
|
||||
|
||||
// Create fake frame to simulate end of the data
|
||||
if (frame.fin) {
|
||||
stream._handleFrame({ type: 'FIN', fin: true })
|
||||
}
|
||||
|
||||
return stream
|
||||
}
|
||||
|
||||
Connection.prototype._onSessionWindowDrain = function _onSessionWindowDrain () {
|
||||
var state = this._spdyState
|
||||
if (state.version < 3.1 && !(state.isServer && state.autoSpdy31)) {
|
||||
return
|
||||
}
|
||||
|
||||
var delta = state.window.recv.getDelta()
|
||||
if (delta === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
state.debug('id=0 session window drain, update by %d', delta)
|
||||
|
||||
state.framer.windowUpdateFrame({
|
||||
id: 0,
|
||||
delta: delta
|
||||
})
|
||||
state.window.recv.update(delta)
|
||||
}
|
||||
|
||||
Connection.prototype.start = function start (version) {
|
||||
this._spdyState.parser.setVersion(version)
|
||||
}
|
||||
|
||||
// Mostly for testing
|
||||
Connection.prototype.getVersion = function getVersion () {
|
||||
return this._spdyState.version
|
||||
}
|
||||
|
||||
Connection.prototype._handleSettings = function _handleSettings (settings) {
|
||||
var state = this._spdyState
|
||||
|
||||
state.framer.ackSettingsFrame()
|
||||
|
||||
this._setDefaultWindow(settings)
|
||||
if (settings.max_frame_size) { state.framer.setMaxFrameSize(settings.max_frame_size) }
|
||||
|
||||
// TODO(indutny): handle max_header_list_size
|
||||
if (settings.header_table_size) {
|
||||
try {
|
||||
state.pair.compress.updateTableSize(settings.header_table_size)
|
||||
} catch (e) {
|
||||
this._goaway({
|
||||
lastId: 0,
|
||||
code: 'PROTOCOL_ERROR',
|
||||
send: true
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// HTTP2 clients needs to enable PUSH streams explicitly
|
||||
if (state.protocol.name !== 'spdy') {
|
||||
if (settings.enable_push === undefined) {
|
||||
state.framer.enablePush(state.isServer)
|
||||
} else {
|
||||
state.framer.enablePush(settings.enable_push === 1)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(indutny): handle max_concurrent_streams
|
||||
}
|
||||
|
||||
Connection.prototype._setDefaultWindow = function _setDefaultWindow (settings) {
|
||||
if (settings.initial_window_size === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
var state = this._spdyState
|
||||
|
||||
// Update defaults
|
||||
var window = state.streamWindow
|
||||
window.send.setMax(settings.initial_window_size)
|
||||
|
||||
// Update existing streams
|
||||
Object.keys(state.stream.map).forEach(function (id) {
|
||||
var stream = state.stream.map[id]
|
||||
var window = stream._spdyState.window
|
||||
|
||||
window.send.updateMax(settings.initial_window_size)
|
||||
})
|
||||
}
|
||||
|
||||
Connection.prototype._handlePing = function handlePing (frame) {
|
||||
var self = this
|
||||
var state = this._spdyState
|
||||
|
||||
// Handle incoming PING
|
||||
if (!frame.ack) {
|
||||
state.framer.pingFrame({
|
||||
opaque: frame.opaque,
|
||||
ack: true
|
||||
})
|
||||
|
||||
self.emit('ping', frame.opaque)
|
||||
return
|
||||
}
|
||||
|
||||
// Handle reply PING
|
||||
var hex = frame.opaque.toString('hex')
|
||||
if (!state.ping.map[hex]) {
|
||||
return
|
||||
}
|
||||
var ping = state.ping.map[hex]
|
||||
delete state.ping.map[hex]
|
||||
|
||||
if (ping.cb) {
|
||||
ping.cb(null)
|
||||
}
|
||||
}
|
||||
|
||||
Connection.prototype._handleGoaway = function handleGoaway (frame) {
|
||||
this._goaway({
|
||||
lastId: frame.lastId,
|
||||
code: frame.code,
|
||||
send: false
|
||||
})
|
||||
}
|
||||
|
||||
Connection.prototype.ping = function ping (callback) {
|
||||
var state = this._spdyState
|
||||
|
||||
// HTTP2 is using 8-byte opaque
|
||||
var opaque = Buffer.alloc(state.constants.PING_OPAQUE_SIZE)
|
||||
opaque.fill(0)
|
||||
opaque.writeUInt32BE(state.ping.nextId, opaque.length - 4)
|
||||
state.ping.nextId += 2
|
||||
|
||||
state.ping.map[opaque.toString('hex')] = { cb: callback }
|
||||
state.framer.pingFrame({
|
||||
opaque: opaque,
|
||||
ack: false
|
||||
})
|
||||
}
|
||||
|
||||
Connection.prototype.getCounter = function getCounter (name) {
|
||||
return this._spdyState.counters[name]
|
||||
}
|
||||
|
||||
Connection.prototype.reserveStream = function reserveStream (uri, callback) {
|
||||
var stream = this._createStream(uri)
|
||||
|
||||
// GOAWAY
|
||||
if (this._isGoaway(stream.id)) {
|
||||
var err = new Error('Can\'t send request after GOAWAY')
|
||||
process.nextTick(function () {
|
||||
if (callback) { callback(err) } else {
|
||||
stream.emit('error', err)
|
||||
}
|
||||
})
|
||||
return stream
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
process.nextTick(function () {
|
||||
callback(null, stream)
|
||||
})
|
||||
}
|
||||
|
||||
return stream
|
||||
}
|
||||
|
||||
Connection.prototype.request = function request (uri, callback) {
|
||||
var stream = this.reserveStream(uri, function (err) {
|
||||
if (err) {
|
||||
if (callback) {
|
||||
callback(err)
|
||||
} else {
|
||||
stream.emit('error', err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (stream._wasSent()) {
|
||||
if (callback) {
|
||||
callback(null, stream)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
stream.send(function (err) {
|
||||
if (err) {
|
||||
if (callback) { return callback(err) } else { return stream.emit('error', err) }
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
callback(null, stream)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
return stream
|
||||
}
|
||||
|
||||
Connection.prototype._removeStream = function _removeStream (stream) {
|
||||
var state = this._spdyState
|
||||
|
||||
state.debug('id=0 remove stream=%d', stream.id)
|
||||
delete state.stream.map[stream.id]
|
||||
state.stream.count--
|
||||
|
||||
if (state.stream.count === 0) {
|
||||
this.emit('_streamDrain')
|
||||
}
|
||||
}
|
||||
|
||||
Connection.prototype._goaway = function _goaway (params) {
|
||||
var state = this._spdyState
|
||||
var self = this
|
||||
|
||||
state.goaway = params.lastId
|
||||
state.debug('id=0 goaway from=%d', state.goaway)
|
||||
|
||||
Object.keys(state.stream.map).forEach(function (id) {
|
||||
var stream = state.stream.map[id]
|
||||
|
||||
// Abort every stream started after GOAWAY
|
||||
if (stream.id <= params.lastId) {
|
||||
return
|
||||
}
|
||||
|
||||
stream.abort()
|
||||
stream.emit('error', new Error('New stream after GOAWAY'))
|
||||
})
|
||||
|
||||
function finish () {
|
||||
// Destroy socket if there are no streams
|
||||
if (state.stream.count === 0 || params.code !== 'OK') {
|
||||
// No further frames should be processed
|
||||
state.parser.kill()
|
||||
|
||||
process.nextTick(function () {
|
||||
var err = new Error('Fatal error: ' + params.code)
|
||||
self._onStreamDrain(err)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
self.on('_streamDrain', self._onStreamDrain)
|
||||
}
|
||||
|
||||
if (params.send) {
|
||||
// Make sure that GOAWAY frame is sent before dumping framer
|
||||
state.framer.goawayFrame({
|
||||
lastId: params.lastId,
|
||||
code: params.code,
|
||||
extra: params.extra
|
||||
}, finish)
|
||||
} else {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
Connection.prototype._onStreamDrain = function _onStreamDrain (error) {
|
||||
var state = this._spdyState
|
||||
|
||||
state.debug('id=0 _onStreamDrain')
|
||||
|
||||
state.framer.dump()
|
||||
state.framer.unpipe(this.socket)
|
||||
state.framer.resume()
|
||||
|
||||
if (this.socket.destroySoon) {
|
||||
this.socket.destroySoon()
|
||||
}
|
||||
this.emit('close', error)
|
||||
}
|
||||
|
||||
Connection.prototype.end = function end (callback) {
|
||||
var state = this._spdyState
|
||||
|
||||
if (callback) {
|
||||
this.once('close', callback)
|
||||
}
|
||||
this._goaway({
|
||||
lastId: state.stream.lastId.both,
|
||||
code: 'OK',
|
||||
send: true
|
||||
})
|
||||
}
|
||||
|
||||
Connection.prototype.destroyStreams = function destroyStreams (err) {
|
||||
var state = this._spdyState
|
||||
Object.keys(state.stream.map).forEach(function (id) {
|
||||
var stream = state.stream.map[id]
|
||||
|
||||
stream.destroy()
|
||||
if (err) {
|
||||
stream.emit('error', err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Connection.prototype.isServer = function isServer () {
|
||||
return this._spdyState.isServer
|
||||
}
|
||||
|
||||
Connection.prototype.getXForwardedFor = function getXForwardFor () {
|
||||
return this._spdyState.xForward
|
||||
}
|
||||
|
||||
Connection.prototype.sendXForwardedFor = function sendXForwardedFor (host) {
|
||||
var state = this._spdyState
|
||||
if (state.version !== null) {
|
||||
state.framer.xForwardedFor({ host: host })
|
||||
} else {
|
||||
state.xForward = host
|
||||
}
|
||||
}
|
||||
|
||||
Connection.prototype.pushPromise = function pushPromise (parent, uri, callback) {
|
||||
var state = this._spdyState
|
||||
|
||||
var stream = this._createStream({
|
||||
request: false,
|
||||
parent: parent,
|
||||
method: uri.method,
|
||||
path: uri.path,
|
||||
host: uri.host,
|
||||
priority: uri.priority,
|
||||
headers: uri.headers,
|
||||
readable: false
|
||||
})
|
||||
|
||||
var err
|
||||
|
||||
// TODO(indutny): deduplicate this logic somehow
|
||||
if (this._isGoaway(stream.id)) {
|
||||
err = new Error('Can\'t send PUSH_PROMISE after GOAWAY')
|
||||
|
||||
process.nextTick(function () {
|
||||
if (callback) {
|
||||
callback(err)
|
||||
} else {
|
||||
stream.emit('error', err)
|
||||
}
|
||||
})
|
||||
return stream
|
||||
}
|
||||
|
||||
if (uri.push && !state.acceptPush) {
|
||||
err = new Error(
|
||||
'Can\'t send PUSH_PROMISE, other side won\'t accept it')
|
||||
process.nextTick(function () {
|
||||
if (callback) { callback(err) } else {
|
||||
stream.emit('error', err)
|
||||
}
|
||||
})
|
||||
return stream
|
||||
}
|
||||
|
||||
stream._sendPush(uri.status, uri.response, function (err) {
|
||||
if (!callback) {
|
||||
if (err) {
|
||||
stream.emit('error', err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (err) { return callback(err) }
|
||||
callback(null, stream)
|
||||
})
|
||||
|
||||
return stream
|
||||
}
|
||||
|
||||
Connection.prototype.setTimeout = function setTimeout (delay, callback) {
|
||||
var state = this._spdyState
|
||||
|
||||
state.timeout.set(delay, callback)
|
||||
}
|
||||
188
node_modules/spdy-transport/lib/spdy-transport/priority.js
generated
vendored
Normal file
188
node_modules/spdy-transport/lib/spdy-transport/priority.js
generated
vendored
Normal file
@ -0,0 +1,188 @@
|
||||
'use strict'
|
||||
|
||||
var transport = require('../spdy-transport')
|
||||
var utils = transport.utils
|
||||
|
||||
var assert = require('assert')
|
||||
var debug = require('debug')('spdy:priority')
|
||||
|
||||
function PriorityNode (tree, options) {
|
||||
this.tree = tree
|
||||
|
||||
this.id = options.id
|
||||
this.parent = options.parent
|
||||
this.weight = options.weight
|
||||
|
||||
// To be calculated in `addChild`
|
||||
this.priorityFrom = 0
|
||||
this.priorityTo = 1
|
||||
this.priority = 1
|
||||
|
||||
this.children = {
|
||||
list: [],
|
||||
weight: 0
|
||||
}
|
||||
|
||||
if (this.parent !== null) {
|
||||
this.parent.addChild(this)
|
||||
}
|
||||
}
|
||||
|
||||
function compareChildren (a, b) {
|
||||
return a.weight === b.weight ? a.id - b.id : a.weight - b.weight
|
||||
}
|
||||
|
||||
PriorityNode.prototype.toJSON = function toJSON () {
|
||||
return {
|
||||
parent: this.parent,
|
||||
weight: this.weight,
|
||||
exclusive: this.exclusive
|
||||
}
|
||||
}
|
||||
|
||||
PriorityNode.prototype.getPriority = function getPriority () {
|
||||
return this.priority
|
||||
}
|
||||
|
||||
PriorityNode.prototype.getPriorityRange = function getPriorityRange () {
|
||||
return { from: this.priorityFrom, to: this.priorityTo }
|
||||
}
|
||||
|
||||
PriorityNode.prototype.addChild = function addChild (child) {
|
||||
child.parent = this
|
||||
utils.binaryInsert(this.children.list, child, compareChildren)
|
||||
this.children.weight += child.weight
|
||||
|
||||
this._updatePriority(this.priorityFrom, this.priorityTo)
|
||||
}
|
||||
|
||||
PriorityNode.prototype.remove = function remove () {
|
||||
assert(this.parent, 'Can\'t remove root node')
|
||||
|
||||
this.parent.removeChild(this)
|
||||
this.tree._removeNode(this)
|
||||
|
||||
// Move all children to the parent
|
||||
for (var i = 0; i < this.children.list.length; i++) {
|
||||
this.parent.addChild(this.children.list[i])
|
||||
}
|
||||
}
|
||||
|
||||
PriorityNode.prototype.removeChild = function removeChild (child) {
|
||||
this.children.weight -= child.weight
|
||||
var index = utils.binarySearch(this.children.list, child, compareChildren)
|
||||
if (index !== -1 && this.children.list.length >= index) {
|
||||
this.children.list.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
PriorityNode.prototype.removeChildren = function removeChildren () {
|
||||
var children = this.children.list
|
||||
this.children.list = []
|
||||
this.children.weight = 0
|
||||
return children
|
||||
}
|
||||
|
||||
PriorityNode.prototype._updatePriority = function _updatePriority (from, to) {
|
||||
this.priority = to - from
|
||||
this.priorityFrom = from
|
||||
this.priorityTo = to
|
||||
|
||||
var weight = 0
|
||||
for (var i = 0; i < this.children.list.length; i++) {
|
||||
var node = this.children.list[i]
|
||||
var nextWeight = weight + node.weight
|
||||
|
||||
node._updatePriority(
|
||||
from + this.priority * (weight / this.children.weight),
|
||||
from + this.priority * (nextWeight / this.children.weight)
|
||||
)
|
||||
weight = nextWeight
|
||||
}
|
||||
}
|
||||
|
||||
function PriorityTree (options) {
|
||||
this.map = {}
|
||||
this.list = []
|
||||
this.defaultWeight = options.defaultWeight || 16
|
||||
|
||||
this.count = 0
|
||||
this.maxCount = options.maxCount
|
||||
|
||||
// Root
|
||||
this.root = this.add({
|
||||
id: 0,
|
||||
parent: null,
|
||||
weight: 1
|
||||
})
|
||||
}
|
||||
module.exports = PriorityTree
|
||||
|
||||
PriorityTree.create = function create (options) {
|
||||
return new PriorityTree(options)
|
||||
}
|
||||
|
||||
PriorityTree.prototype.add = function add (options) {
|
||||
if (options.id === options.parent) {
|
||||
return this.addDefault(options.id)
|
||||
}
|
||||
|
||||
var parent = options.parent === null ? null : this.map[options.parent]
|
||||
if (parent === undefined) {
|
||||
return this.addDefault(options.id)
|
||||
}
|
||||
|
||||
debug('add node=%d parent=%d weight=%d exclusive=%d',
|
||||
options.id,
|
||||
options.parent === null ? -1 : options.parent,
|
||||
options.weight || this.defaultWeight,
|
||||
options.exclusive ? 1 : 0)
|
||||
|
||||
var children
|
||||
if (options.exclusive) {
|
||||
children = parent.removeChildren()
|
||||
}
|
||||
|
||||
var node = new PriorityNode(this, {
|
||||
id: options.id,
|
||||
parent: parent,
|
||||
weight: options.weight || this.defaultWeight
|
||||
})
|
||||
this.map[options.id] = node
|
||||
|
||||
if (options.exclusive) {
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
node.addChild(children[i])
|
||||
}
|
||||
}
|
||||
|
||||
this.count++
|
||||
if (this.count > this.maxCount) {
|
||||
debug('hit maximum remove id=%d', this.list[0].id)
|
||||
this.list.shift().remove()
|
||||
}
|
||||
|
||||
// Root node is not subject to removal
|
||||
if (node.parent !== null) {
|
||||
this.list.push(node)
|
||||
}
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
// Only for testing, should use `node`'s methods
|
||||
PriorityTree.prototype.get = function get (id) {
|
||||
return this.map[id]
|
||||
}
|
||||
|
||||
PriorityTree.prototype.addDefault = function addDefault (id) {
|
||||
debug('creating default node')
|
||||
return this.add({ id: id, parent: 0, weight: this.defaultWeight })
|
||||
}
|
||||
|
||||
PriorityTree.prototype._removeNode = function _removeNode (node) {
|
||||
delete this.map[node.id]
|
||||
var index = utils.binarySearch(this.list, node, compareChildren)
|
||||
this.list.splice(index, 1)
|
||||
this.count--
|
||||
}
|
||||
4
node_modules/spdy-transport/lib/spdy-transport/protocol/base/constants.js
generated
vendored
Normal file
4
node_modules/spdy-transport/lib/spdy-transport/protocol/base/constants.js
generated
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
exports.DEFAULT_METHOD = 'GET'
|
||||
exports.DEFAULT_HOST = 'localhost'
|
||||
exports.MAX_PRIORITY_STREAMS = 100
|
||||
exports.DEFAULT_MAX_CHUNK = 8 * 1024
|
||||
58
node_modules/spdy-transport/lib/spdy-transport/protocol/base/framer.js
generated
vendored
Normal file
58
node_modules/spdy-transport/lib/spdy-transport/protocol/base/framer.js
generated
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
'use strict'
|
||||
|
||||
var util = require('util')
|
||||
|
||||
var transport = require('../../../spdy-transport')
|
||||
var base = require('./')
|
||||
var Scheduler = base.Scheduler
|
||||
|
||||
function Framer (options) {
|
||||
Scheduler.call(this)
|
||||
|
||||
this.version = null
|
||||
this.compress = null
|
||||
this.window = options.window
|
||||
this.timeout = options.timeout
|
||||
|
||||
// Wait for `enablePush`
|
||||
this.pushEnabled = null
|
||||
}
|
||||
util.inherits(Framer, Scheduler)
|
||||
module.exports = Framer
|
||||
|
||||
Framer.prototype.setVersion = function setVersion (version) {
|
||||
this.version = version
|
||||
this.emit('version')
|
||||
}
|
||||
|
||||
Framer.prototype.setCompression = function setCompresion (pair) {
|
||||
this.compress = new transport.utils.LockStream(pair.compress)
|
||||
}
|
||||
|
||||
Framer.prototype.enablePush = function enablePush (enable) {
|
||||
this.pushEnabled = enable
|
||||
this.emit('_pushEnabled')
|
||||
}
|
||||
|
||||
Framer.prototype._checkPush = function _checkPush (callback) {
|
||||
if (this.pushEnabled === null) {
|
||||
this.once('_pushEnabled', function () {
|
||||
this._checkPush(callback)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var err = null
|
||||
if (!this.pushEnabled) {
|
||||
err = new Error('PUSH_PROMISE disabled by other side')
|
||||
}
|
||||
process.nextTick(function () {
|
||||
return callback(err)
|
||||
})
|
||||
}
|
||||
|
||||
Framer.prototype._resetTimeout = function _resetTimeout () {
|
||||
if (this.timeout) {
|
||||
this.timeout.reset()
|
||||
}
|
||||
}
|
||||
7
node_modules/spdy-transport/lib/spdy-transport/protocol/base/index.js
generated
vendored
Normal file
7
node_modules/spdy-transport/lib/spdy-transport/protocol/base/index.js
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
'use strict'
|
||||
|
||||
exports.utils = require('./utils')
|
||||
exports.constants = require('./constants')
|
||||
exports.Scheduler = require('./scheduler')
|
||||
exports.Parser = require('./parser')
|
||||
exports.Framer = require('./framer')
|
||||
106
node_modules/spdy-transport/lib/spdy-transport/protocol/base/parser.js
generated
vendored
Normal file
106
node_modules/spdy-transport/lib/spdy-transport/protocol/base/parser.js
generated
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
'use strict'
|
||||
|
||||
var transport = require('../../../spdy-transport')
|
||||
|
||||
var util = require('util')
|
||||
var utils = require('./').utils
|
||||
var OffsetBuffer = require('obuf')
|
||||
var Transform = require('readable-stream').Transform
|
||||
|
||||
function Parser (options) {
|
||||
Transform.call(this, {
|
||||
readableObjectMode: true
|
||||
})
|
||||
|
||||
this.buffer = new OffsetBuffer()
|
||||
this.partial = false
|
||||
this.waiting = 0
|
||||
|
||||
this.window = options.window
|
||||
|
||||
this.version = null
|
||||
this.decompress = null
|
||||
this.dead = false
|
||||
}
|
||||
module.exports = Parser
|
||||
util.inherits(Parser, Transform)
|
||||
|
||||
Parser.prototype.error = utils.error
|
||||
|
||||
Parser.prototype.kill = function kill () {
|
||||
this.dead = true
|
||||
}
|
||||
|
||||
Parser.prototype._transform = function transform (data, encoding, cb) {
|
||||
if (!this.dead) { this.buffer.push(data) }
|
||||
|
||||
this._consume(cb)
|
||||
}
|
||||
|
||||
Parser.prototype._consume = function _consume (cb) {
|
||||
var self = this
|
||||
|
||||
function next (err, frame) {
|
||||
if (err) {
|
||||
return cb(err)
|
||||
}
|
||||
|
||||
if (Array.isArray(frame)) {
|
||||
for (var i = 0; i < frame.length; i++) {
|
||||
self.push(frame[i])
|
||||
}
|
||||
} else if (frame) {
|
||||
self.push(frame)
|
||||
}
|
||||
|
||||
// Consume more packets
|
||||
if (!sync) {
|
||||
return self._consume(cb)
|
||||
}
|
||||
|
||||
process.nextTick(function () {
|
||||
self._consume(cb)
|
||||
})
|
||||
}
|
||||
|
||||
if (this.dead) {
|
||||
return cb()
|
||||
}
|
||||
|
||||
if (this.buffer.size < this.waiting) {
|
||||
// No data at all
|
||||
if (this.buffer.size === 0) {
|
||||
return cb()
|
||||
}
|
||||
|
||||
// Partial DATA frame or something that we can process partially
|
||||
if (this.partial) {
|
||||
var partial = this.buffer.clone(this.buffer.size)
|
||||
this.buffer.skip(partial.size)
|
||||
this.waiting -= partial.size
|
||||
|
||||
this.executePartial(partial, next)
|
||||
return
|
||||
}
|
||||
|
||||
// We shall not do anything until we get all expected data
|
||||
return cb()
|
||||
}
|
||||
|
||||
var sync = true
|
||||
|
||||
var content = this.buffer.clone(this.waiting)
|
||||
this.buffer.skip(this.waiting)
|
||||
|
||||
this.execute(content, next)
|
||||
sync = false
|
||||
}
|
||||
|
||||
Parser.prototype.setVersion = function setVersion (version) {
|
||||
this.version = version
|
||||
this.emit('version', version)
|
||||
}
|
||||
|
||||
Parser.prototype.setCompression = function setCompresion (pair) {
|
||||
this.decompress = new transport.utils.LockStream(pair.decompress)
|
||||
}
|
||||
216
node_modules/spdy-transport/lib/spdy-transport/protocol/base/scheduler.js
generated
vendored
Normal file
216
node_modules/spdy-transport/lib/spdy-transport/protocol/base/scheduler.js
generated
vendored
Normal file
@ -0,0 +1,216 @@
|
||||
'use strict'
|
||||
|
||||
var transport = require('../../../spdy-transport')
|
||||
var utils = transport.utils
|
||||
|
||||
var assert = require('assert')
|
||||
var util = require('util')
|
||||
var debug = require('debug')('spdy:scheduler')
|
||||
var Readable = require('readable-stream').Readable
|
||||
|
||||
/*
|
||||
* We create following structure in `pending`:
|
||||
* [ [ id = 0 ], [ id = 1 ], [ id = 2 ], [ id = 0 ] ]
|
||||
* chunks chunks chunks chunks
|
||||
* chunks chunks
|
||||
* chunks
|
||||
*
|
||||
* Then on the `.tick()` pass we pick one chunks from each item and remove the
|
||||
* item if it is empty:
|
||||
*
|
||||
* [ [ id = 0 ], [ id = 2 ] ]
|
||||
* chunks chunks
|
||||
* chunks
|
||||
*
|
||||
* Writing out: chunks for 0, chunks for 1, chunks for 2, chunks for 0
|
||||
*
|
||||
* This way data is interleaved between the different streams.
|
||||
*/
|
||||
|
||||
function Scheduler (options) {
|
||||
Readable.call(this)
|
||||
|
||||
// Pretty big window by default
|
||||
this.window = 0.25
|
||||
|
||||
if (options && options.window) { this.window = options.window }
|
||||
|
||||
this.sync = []
|
||||
this.list = []
|
||||
this.count = 0
|
||||
this.pendingTick = false
|
||||
}
|
||||
util.inherits(Scheduler, Readable)
|
||||
module.exports = Scheduler
|
||||
|
||||
// Just for testing, really
|
||||
Scheduler.create = function create (options) {
|
||||
return new Scheduler(options)
|
||||
}
|
||||
|
||||
function insertCompare (a, b) {
|
||||
return a.priority === b.priority
|
||||
? a.stream - b.stream
|
||||
: b.priority - a.priority
|
||||
}
|
||||
|
||||
Scheduler.prototype.schedule = function schedule (data) {
|
||||
var priority = data.priority
|
||||
var stream = data.stream
|
||||
var chunks = data.chunks
|
||||
|
||||
// Synchronous frames should not be interleaved
|
||||
if (priority === false) {
|
||||
debug('queue sync', chunks)
|
||||
this.sync.push(data)
|
||||
this.count += chunks.length
|
||||
|
||||
this._read()
|
||||
return
|
||||
}
|
||||
|
||||
debug('queue async priority=%d stream=%d', priority, stream, chunks)
|
||||
var item = new SchedulerItem(stream, priority)
|
||||
var index = utils.binaryLookup(this.list, item, insertCompare)
|
||||
|
||||
// Push new item
|
||||
if (index >= this.list.length || insertCompare(this.list[index], item) !== 0) {
|
||||
this.list.splice(index, 0, item)
|
||||
} else { // Coalesce
|
||||
item = this.list[index]
|
||||
}
|
||||
|
||||
item.push(data)
|
||||
|
||||
this.count += chunks.length
|
||||
|
||||
this._read()
|
||||
}
|
||||
|
||||
Scheduler.prototype._read = function _read () {
|
||||
if (this.count === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
if (this.pendingTick) {
|
||||
return
|
||||
}
|
||||
this.pendingTick = true
|
||||
|
||||
var self = this
|
||||
process.nextTick(function () {
|
||||
self.pendingTick = false
|
||||
self.tick()
|
||||
})
|
||||
}
|
||||
|
||||
Scheduler.prototype.tick = function tick () {
|
||||
// No luck for async frames
|
||||
if (!this.tickSync()) { return false }
|
||||
|
||||
return this.tickAsync()
|
||||
}
|
||||
|
||||
Scheduler.prototype.tickSync = function tickSync () {
|
||||
// Empty sync queue first
|
||||
var sync = this.sync
|
||||
var res = true
|
||||
this.sync = []
|
||||
for (var i = 0; i < sync.length; i++) {
|
||||
var item = sync[i]
|
||||
debug('tick sync pending=%d', this.count, item.chunks)
|
||||
for (var j = 0; j < item.chunks.length; j++) {
|
||||
this.count--
|
||||
// TODO: handle stream backoff properly
|
||||
try {
|
||||
res = this.push(item.chunks[j])
|
||||
} catch (err) {
|
||||
this.emit('error', err)
|
||||
return false
|
||||
}
|
||||
}
|
||||
debug('after tick sync pending=%d', this.count)
|
||||
|
||||
// TODO(indutny): figure out the way to invoke callback on actual write
|
||||
if (item.callback) {
|
||||
item.callback(null)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
Scheduler.prototype.tickAsync = function tickAsync () {
|
||||
var res = true
|
||||
var list = this.list
|
||||
if (list.length === 0) {
|
||||
return res
|
||||
}
|
||||
|
||||
var startPriority = list[0].priority
|
||||
for (var index = 0; list.length > 0; index++) {
|
||||
// Loop index
|
||||
index %= list.length
|
||||
if (startPriority - list[index].priority > this.window) { index = 0 }
|
||||
debug('tick async index=%d start=%d', index, startPriority)
|
||||
|
||||
var current = list[index]
|
||||
var item = current.shift()
|
||||
|
||||
if (current.isEmpty()) {
|
||||
list.splice(index, 1)
|
||||
if (index === 0 && list.length > 0) {
|
||||
startPriority = list[0].priority
|
||||
}
|
||||
index--
|
||||
}
|
||||
|
||||
debug('tick async pending=%d', this.count, item.chunks)
|
||||
for (var i = 0; i < item.chunks.length; i++) {
|
||||
this.count--
|
||||
// TODO: handle stream backoff properly
|
||||
try {
|
||||
res = this.push(item.chunks[i])
|
||||
} catch (err) {
|
||||
this.emit('error', err)
|
||||
return false
|
||||
}
|
||||
}
|
||||
debug('after tick pending=%d', this.count)
|
||||
|
||||
// TODO(indutny): figure out the way to invoke callback on actual write
|
||||
if (item.callback) {
|
||||
item.callback(null)
|
||||
}
|
||||
if (!res) { break }
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
Scheduler.prototype.dump = function dump () {
|
||||
this.tickSync()
|
||||
|
||||
// Write everything out
|
||||
while (!this.tickAsync()) {
|
||||
// Intentional no-op
|
||||
}
|
||||
assert.strictEqual(this.count, 0)
|
||||
}
|
||||
|
||||
function SchedulerItem (stream, priority) {
|
||||
this.stream = stream
|
||||
this.priority = priority
|
||||
this.queue = []
|
||||
}
|
||||
|
||||
SchedulerItem.prototype.push = function push (chunks) {
|
||||
this.queue.push(chunks)
|
||||
}
|
||||
|
||||
SchedulerItem.prototype.shift = function shift () {
|
||||
return this.queue.shift()
|
||||
}
|
||||
|
||||
SchedulerItem.prototype.isEmpty = function isEmpty () {
|
||||
return this.queue.length === 0
|
||||
}
|
||||
94
node_modules/spdy-transport/lib/spdy-transport/protocol/base/utils.js
generated
vendored
Normal file
94
node_modules/spdy-transport/lib/spdy-transport/protocol/base/utils.js
generated
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
'use strict'
|
||||
|
||||
var utils = exports
|
||||
|
||||
var util = require('util')
|
||||
|
||||
function ProtocolError (code, message) {
|
||||
this.code = code
|
||||
this.message = message
|
||||
}
|
||||
util.inherits(ProtocolError, Error)
|
||||
utils.ProtocolError = ProtocolError
|
||||
|
||||
utils.error = function error (code, message) {
|
||||
return new ProtocolError(code, message)
|
||||
}
|
||||
|
||||
utils.reverse = function reverse (object) {
|
||||
var result = []
|
||||
|
||||
Object.keys(object).forEach(function (key) {
|
||||
result[object[key] | 0] = key
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// weight [1, 36] <=> priority [0, 7]
|
||||
// This way weight=16 is preserved and has priority=3
|
||||
utils.weightToPriority = function weightToPriority (weight) {
|
||||
return ((Math.min(35, (weight - 1)) / 35) * 7) | 0
|
||||
}
|
||||
|
||||
utils.priorityToWeight = function priorityToWeight (priority) {
|
||||
return (((priority / 7) * 35) | 0) + 1
|
||||
}
|
||||
|
||||
// Copy-Paste from node
|
||||
exports.addHeaderLine = function addHeaderLine (field, value, dest) {
|
||||
field = field.toLowerCase()
|
||||
if (/^:/.test(field)) {
|
||||
dest[field] = value
|
||||
return
|
||||
}
|
||||
|
||||
switch (field) {
|
||||
// Array headers:
|
||||
case 'set-cookie':
|
||||
if (dest[field] !== undefined) {
|
||||
dest[field].push(value)
|
||||
} else {
|
||||
dest[field] = [ value ]
|
||||
}
|
||||
break
|
||||
|
||||
/* eslint-disable max-len */
|
||||
// list is taken from:
|
||||
/* eslint-enable max-len */
|
||||
case 'content-type':
|
||||
case 'content-length':
|
||||
case 'user-agent':
|
||||
case 'referer':
|
||||
case 'host':
|
||||
case 'authorization':
|
||||
case 'proxy-authorization':
|
||||
case 'if-modified-since':
|
||||
case 'if-unmodified-since':
|
||||
case 'from':
|
||||
case 'location':
|
||||
case 'max-forwards':
|
||||
// drop duplicates
|
||||
if (dest[field] === undefined) {
|
||||
dest[field] = value
|
||||
}
|
||||
break
|
||||
|
||||
case 'cookie':
|
||||
// make semicolon-separated list
|
||||
if (dest[field] !== undefined) {
|
||||
dest[field] += '; ' + value
|
||||
} else {
|
||||
dest[field] = value
|
||||
}
|
||||
break
|
||||
|
||||
default:
|
||||
// make comma-separated list
|
||||
if (dest[field] !== undefined) {
|
||||
dest[field] += ', ' + value
|
||||
} else {
|
||||
dest[field] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
93
node_modules/spdy-transport/lib/spdy-transport/protocol/http2/constants.js
generated
vendored
Normal file
93
node_modules/spdy-transport/lib/spdy-transport/protocol/http2/constants.js
generated
vendored
Normal file
@ -0,0 +1,93 @@
|
||||
'use strict'
|
||||
|
||||
var transport = require('../../../spdy-transport')
|
||||
var base = transport.protocol.base
|
||||
|
||||
exports.PREFACE_SIZE = 24
|
||||
exports.PREFACE = 'PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n'
|
||||
exports.PREFACE_BUFFER = Buffer.from(exports.PREFACE)
|
||||
|
||||
exports.PING_OPAQUE_SIZE = 8
|
||||
|
||||
exports.FRAME_HEADER_SIZE = 9
|
||||
exports.INITIAL_MAX_FRAME_SIZE = 16384
|
||||
exports.ABSOLUTE_MAX_FRAME_SIZE = 16777215
|
||||
exports.HEADER_TABLE_SIZE = 4096
|
||||
exports.DEFAULT_MAX_HEADER_LIST_SIZE = 80 * 1024 // as in http_parser
|
||||
exports.MAX_INITIAL_WINDOW_SIZE = 2147483647
|
||||
|
||||
exports.DEFAULT_WEIGHT = 16
|
||||
|
||||
exports.MAX_CONCURRENT_STREAMS = Infinity
|
||||
|
||||
exports.frameType = {
|
||||
DATA: 0,
|
||||
HEADERS: 1,
|
||||
PRIORITY: 2,
|
||||
RST_STREAM: 3,
|
||||
SETTINGS: 4,
|
||||
PUSH_PROMISE: 5,
|
||||
PING: 6,
|
||||
GOAWAY: 7,
|
||||
WINDOW_UPDATE: 8,
|
||||
CONTINUATION: 9,
|
||||
|
||||
// Custom
|
||||
X_FORWARDED_FOR: 0xde
|
||||
}
|
||||
|
||||
exports.flags = {
|
||||
ACK: 0x01, // SETTINGS-only
|
||||
END_STREAM: 0x01,
|
||||
END_HEADERS: 0x04,
|
||||
PADDED: 0x08,
|
||||
PRIORITY: 0x20
|
||||
}
|
||||
|
||||
exports.settings = {
|
||||
SETTINGS_HEADER_TABLE_SIZE: 0x01,
|
||||
SETTINGS_ENABLE_PUSH: 0x02,
|
||||
SETTINGS_MAX_CONCURRENT_STREAMS: 0x03,
|
||||
SETTINGS_INITIAL_WINDOW_SIZE: 0x04,
|
||||
SETTINGS_MAX_FRAME_SIZE: 0x05,
|
||||
SETTINGS_MAX_HEADER_LIST_SIZE: 0x06
|
||||
}
|
||||
|
||||
exports.settingsIndex = [
|
||||
null,
|
||||
'header_table_size',
|
||||
'enable_push',
|
||||
'max_concurrent_streams',
|
||||
'initial_window_size',
|
||||
'max_frame_size',
|
||||
'max_header_list_size'
|
||||
]
|
||||
|
||||
exports.error = {
|
||||
OK: 0,
|
||||
NO_ERROR: 0,
|
||||
|
||||
PROTOCOL_ERROR: 1,
|
||||
INTERNAL_ERROR: 2,
|
||||
FLOW_CONTROL_ERROR: 3,
|
||||
SETTINGS_TIMEOUT: 4,
|
||||
|
||||
STREAM_CLOSED: 5,
|
||||
INVALID_STREAM: 5,
|
||||
|
||||
FRAME_SIZE_ERROR: 6,
|
||||
REFUSED_STREAM: 7,
|
||||
CANCEL: 8,
|
||||
COMPRESSION_ERROR: 9,
|
||||
CONNECT_ERROR: 10,
|
||||
ENHANCE_YOUR_CALM: 11,
|
||||
INADEQUATE_SECURITY: 12,
|
||||
HTTP_1_1_REQUIRED: 13
|
||||
}
|
||||
exports.errorByCode = base.utils.reverse(exports.error)
|
||||
|
||||
exports.DEFAULT_WINDOW = 64 * 1024 - 1
|
||||
|
||||
exports.goaway = exports.error
|
||||
exports.goawayByCode = Object.assign({}, exports.errorByCode)
|
||||
exports.goawayByCode[0] = 'OK'
|
||||
542
node_modules/spdy-transport/lib/spdy-transport/protocol/http2/framer.js
generated
vendored
Normal file
542
node_modules/spdy-transport/lib/spdy-transport/protocol/http2/framer.js
generated
vendored
Normal file
@ -0,0 +1,542 @@
|
||||
'use strict'
|
||||
|
||||
var transport = require('../../../spdy-transport')
|
||||
var base = transport.protocol.base
|
||||
var constants = require('./').constants
|
||||
|
||||
var assert = require('assert')
|
||||
var util = require('util')
|
||||
var WriteBuffer = require('wbuf')
|
||||
var OffsetBuffer = require('obuf')
|
||||
var debug = require('debug')('spdy:framer')
|
||||
var debugExtra = require('debug')('spdy:framer:extra')
|
||||
|
||||
function Framer (options) {
|
||||
base.Framer.call(this, options)
|
||||
|
||||
this.maxFrameSize = constants.INITIAL_MAX_FRAME_SIZE
|
||||
}
|
||||
util.inherits(Framer, base.Framer)
|
||||
module.exports = Framer
|
||||
|
||||
Framer.create = function create (options) {
|
||||
return new Framer(options)
|
||||
}
|
||||
|
||||
Framer.prototype.setMaxFrameSize = function setMaxFrameSize (size) {
|
||||
this.maxFrameSize = size
|
||||
}
|
||||
|
||||
Framer.prototype._frame = function _frame (frame, body, callback) {
|
||||
debug('id=%d type=%s', frame.id, frame.type)
|
||||
|
||||
var buffer = new WriteBuffer()
|
||||
|
||||
buffer.reserve(constants.FRAME_HEADER_SIZE)
|
||||
var len = buffer.skip(3)
|
||||
buffer.writeUInt8(constants.frameType[frame.type])
|
||||
buffer.writeUInt8(frame.flags)
|
||||
buffer.writeUInt32BE(frame.id & 0x7fffffff)
|
||||
|
||||
body(buffer)
|
||||
|
||||
var frameSize = buffer.size - constants.FRAME_HEADER_SIZE
|
||||
len.writeUInt24BE(frameSize)
|
||||
|
||||
var chunks = buffer.render()
|
||||
var toWrite = {
|
||||
stream: frame.id,
|
||||
priority: frame.priority === undefined ? false : frame.priority,
|
||||
chunks: chunks,
|
||||
callback: callback
|
||||
}
|
||||
|
||||
if (this.window && frame.type === 'DATA') {
|
||||
var self = this
|
||||
this._resetTimeout()
|
||||
this.window.send.update(-frameSize, function () {
|
||||
self._resetTimeout()
|
||||
self.schedule(toWrite)
|
||||
})
|
||||
} else {
|
||||
this._resetTimeout()
|
||||
this.schedule(toWrite)
|
||||
}
|
||||
|
||||
return chunks
|
||||
}
|
||||
|
||||
Framer.prototype._split = function _split (frame) {
|
||||
var buf = new OffsetBuffer()
|
||||
for (var i = 0; i < frame.chunks.length; i++) { buf.push(frame.chunks[i]) }
|
||||
|
||||
var frames = []
|
||||
while (!buf.isEmpty()) {
|
||||
// First frame may have reserved bytes in it
|
||||
var size = this.maxFrameSize
|
||||
if (frames.length === 0) {
|
||||
size -= frame.reserve
|
||||
}
|
||||
size = Math.min(size, buf.size)
|
||||
|
||||
var frameBuf = buf.clone(size)
|
||||
buf.skip(size)
|
||||
|
||||
frames.push({
|
||||
size: frameBuf.size,
|
||||
chunks: frameBuf.toChunks()
|
||||
})
|
||||
}
|
||||
|
||||
return frames
|
||||
}
|
||||
|
||||
Framer.prototype._continuationFrame = function _continuationFrame (frame,
|
||||
body,
|
||||
callback) {
|
||||
var frames = this._split(frame)
|
||||
|
||||
frames.forEach(function (subFrame, i) {
|
||||
var isFirst = i === 0
|
||||
var isLast = i === frames.length - 1
|
||||
|
||||
var flags = isLast ? constants.flags.END_HEADERS : 0
|
||||
|
||||
// PRIORITY and friends
|
||||
if (isFirst) {
|
||||
flags |= frame.flags
|
||||
}
|
||||
|
||||
this._frame({
|
||||
id: frame.id,
|
||||
priority: false,
|
||||
type: isFirst ? frame.type : 'CONTINUATION',
|
||||
flags: flags
|
||||
}, function (buf) {
|
||||
// Fill those reserved bytes
|
||||
if (isFirst && body) { body(buf) }
|
||||
|
||||
buf.reserve(subFrame.size)
|
||||
for (var i = 0; i < subFrame.chunks.length; i++) { buf.copyFrom(subFrame.chunks[i]) }
|
||||
}, isLast ? callback : null)
|
||||
}, this)
|
||||
|
||||
if (frames.length === 0) {
|
||||
this._frame({
|
||||
id: frame.id,
|
||||
priority: false,
|
||||
type: frame.type,
|
||||
flags: frame.flags | constants.flags.END_HEADERS
|
||||
}, function (buf) {
|
||||
if (body) { body(buf) }
|
||||
}, callback)
|
||||
}
|
||||
}
|
||||
|
||||
Framer.prototype._compressHeaders = function _compressHeaders (headers,
|
||||
pairs,
|
||||
callback) {
|
||||
Object.keys(headers || {}).forEach(function (name) {
|
||||
var lowName = name.toLowerCase()
|
||||
|
||||
// Not allowed in HTTP2
|
||||
switch (lowName) {
|
||||
case 'host':
|
||||
case 'connection':
|
||||
case 'keep-alive':
|
||||
case 'proxy-connection':
|
||||
case 'transfer-encoding':
|
||||
case 'upgrade':
|
||||
return
|
||||
}
|
||||
|
||||
// Should be in `pairs`
|
||||
if (/^:/.test(lowName)) {
|
||||
return
|
||||
}
|
||||
|
||||
// Do not compress, or index Cookie field (for security reasons)
|
||||
var neverIndex = lowName === 'cookie' || lowName === 'set-cookie'
|
||||
|
||||
var value = headers[name]
|
||||
if (Array.isArray(value)) {
|
||||
for (var i = 0; i < value.length; i++) {
|
||||
pairs.push({
|
||||
name: lowName,
|
||||
value: value[i] + '',
|
||||
neverIndex: neverIndex,
|
||||
huffman: !neverIndex
|
||||
})
|
||||
}
|
||||
} else {
|
||||
pairs.push({
|
||||
name: lowName,
|
||||
value: value + '',
|
||||
neverIndex: neverIndex,
|
||||
huffman: !neverIndex
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
assert(this.compress !== null, 'Framer version not initialized')
|
||||
debugExtra('compressing headers=%j', pairs)
|
||||
this.compress.write([ pairs ], callback)
|
||||
}
|
||||
|
||||
Framer.prototype._isDefaultPriority = function _isDefaultPriority (priority) {
|
||||
if (!priority) { return true }
|
||||
|
||||
return !priority.parent &&
|
||||
priority.weight === constants.DEFAULT &&
|
||||
!priority.exclusive
|
||||
}
|
||||
|
||||
Framer.prototype._defaultHeaders = function _defaultHeaders (frame, pairs) {
|
||||
if (!frame.path) {
|
||||
throw new Error('`path` is required frame argument')
|
||||
}
|
||||
|
||||
pairs.push({
|
||||
name: ':method',
|
||||
value: frame.method || base.constants.DEFAULT_METHOD
|
||||
})
|
||||
pairs.push({ name: ':path', value: frame.path })
|
||||
pairs.push({ name: ':scheme', value: frame.scheme || 'https' })
|
||||
pairs.push({
|
||||
name: ':authority',
|
||||
value: frame.host ||
|
||||
(frame.headers && frame.headers.host) ||
|
||||
base.constants.DEFAULT_HOST
|
||||
})
|
||||
}
|
||||
|
||||
Framer.prototype._headersFrame = function _headersFrame (kind, frame, callback) {
|
||||
var pairs = []
|
||||
|
||||
if (kind === 'request') {
|
||||
this._defaultHeaders(frame, pairs)
|
||||
} else if (kind === 'response') {
|
||||
pairs.push({ name: ':status', value: (frame.status || 200) + '' })
|
||||
}
|
||||
|
||||
var self = this
|
||||
this._compressHeaders(frame.headers, pairs, function (err, chunks) {
|
||||
if (err) {
|
||||
if (callback) {
|
||||
return callback(err)
|
||||
} else {
|
||||
return self.emit('error', err)
|
||||
}
|
||||
}
|
||||
|
||||
var reserve = 0
|
||||
|
||||
// If priority info is present, and the values are not default ones
|
||||
// reserve space for the priority info and add PRIORITY flag
|
||||
var priority = frame.priority
|
||||
if (!self._isDefaultPriority(priority)) { reserve = 5 }
|
||||
|
||||
var flags = reserve === 0 ? 0 : constants.flags.PRIORITY
|
||||
|
||||
// Mostly for testing
|
||||
if (frame.fin) {
|
||||
flags |= constants.flags.END_STREAM
|
||||
}
|
||||
|
||||
self._continuationFrame({
|
||||
id: frame.id,
|
||||
type: 'HEADERS',
|
||||
flags: flags,
|
||||
reserve: reserve,
|
||||
chunks: chunks
|
||||
}, function (buf) {
|
||||
if (reserve === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
buf.writeUInt32BE(((priority.exclusive ? 0x80000000 : 0) |
|
||||
priority.parent) >>> 0)
|
||||
buf.writeUInt8((priority.weight | 0) - 1)
|
||||
}, callback)
|
||||
})
|
||||
}
|
||||
|
||||
Framer.prototype.requestFrame = function requestFrame (frame, callback) {
|
||||
return this._headersFrame('request', frame, callback)
|
||||
}
|
||||
|
||||
Framer.prototype.responseFrame = function responseFrame (frame, callback) {
|
||||
return this._headersFrame('response', frame, callback)
|
||||
}
|
||||
|
||||
Framer.prototype.headersFrame = function headersFrame (frame, callback) {
|
||||
return this._headersFrame('headers', frame, callback)
|
||||
}
|
||||
|
||||
Framer.prototype.pushFrame = function pushFrame (frame, callback) {
|
||||
var self = this
|
||||
|
||||
function compress (headers, pairs, callback) {
|
||||
self._compressHeaders(headers, pairs, function (err, chunks) {
|
||||
if (err) {
|
||||
if (callback) {
|
||||
return callback(err)
|
||||
} else {
|
||||
return self.emit('error', err)
|
||||
}
|
||||
}
|
||||
|
||||
callback(chunks)
|
||||
})
|
||||
}
|
||||
|
||||
function sendPromise (chunks) {
|
||||
self._continuationFrame({
|
||||
id: frame.id,
|
||||
type: 'PUSH_PROMISE',
|
||||
reserve: 4,
|
||||
chunks: chunks
|
||||
}, function (buf) {
|
||||
buf.writeUInt32BE(frame.promisedId)
|
||||
})
|
||||
}
|
||||
|
||||
function sendResponse (chunks, callback) {
|
||||
var priority = frame.priority
|
||||
var isDefaultPriority = self._isDefaultPriority(priority)
|
||||
var flags = isDefaultPriority ? 0 : constants.flags.PRIORITY
|
||||
|
||||
// Mostly for testing
|
||||
if (frame.fin) {
|
||||
flags |= constants.flags.END_STREAM
|
||||
}
|
||||
|
||||
self._continuationFrame({
|
||||
id: frame.promisedId,
|
||||
type: 'HEADERS',
|
||||
flags: flags,
|
||||
reserve: isDefaultPriority ? 0 : 5,
|
||||
chunks: chunks
|
||||
}, function (buf) {
|
||||
if (isDefaultPriority) {
|
||||
return
|
||||
}
|
||||
|
||||
buf.writeUInt32BE((priority.exclusive ? 0x80000000 : 0) |
|
||||
priority.parent)
|
||||
buf.writeUInt8((priority.weight | 0) - 1)
|
||||
}, callback)
|
||||
}
|
||||
|
||||
this._checkPush(function (err) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
var pairs = {
|
||||
promise: [],
|
||||
response: []
|
||||
}
|
||||
|
||||
self._defaultHeaders(frame, pairs.promise)
|
||||
pairs.response.push({ name: ':status', value: (frame.status || 200) + '' })
|
||||
|
||||
compress(frame.headers, pairs.promise, function (promiseChunks) {
|
||||
sendPromise(promiseChunks)
|
||||
if (frame.response === false) {
|
||||
return callback(null)
|
||||
}
|
||||
compress(frame.response, pairs.response, function (responseChunks) {
|
||||
sendResponse(responseChunks, callback)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Framer.prototype.priorityFrame = function priorityFrame (frame, callback) {
|
||||
this._frame({
|
||||
id: frame.id,
|
||||
priority: false,
|
||||
type: 'PRIORITY',
|
||||
flags: 0
|
||||
}, function (buf) {
|
||||
var priority = frame.priority
|
||||
buf.writeUInt32BE((priority.exclusive ? 0x80000000 : 0) |
|
||||
priority.parent)
|
||||
buf.writeUInt8((priority.weight | 0) - 1)
|
||||
}, callback)
|
||||
}
|
||||
|
||||
Framer.prototype.dataFrame = function dataFrame (frame, callback) {
|
||||
var frames = this._split({
|
||||
reserve: 0,
|
||||
chunks: [ frame.data ]
|
||||
})
|
||||
|
||||
var fin = frame.fin ? constants.flags.END_STREAM : 0
|
||||
|
||||
var self = this
|
||||
frames.forEach(function (subFrame, i) {
|
||||
var isLast = i === frames.length - 1
|
||||
var flags = 0
|
||||
if (isLast) {
|
||||
flags |= fin
|
||||
}
|
||||
|
||||
self._frame({
|
||||
id: frame.id,
|
||||
priority: frame.priority,
|
||||
type: 'DATA',
|
||||
flags: flags
|
||||
}, function (buf) {
|
||||
buf.reserve(subFrame.size)
|
||||
for (var i = 0; i < subFrame.chunks.length; i++) { buf.copyFrom(subFrame.chunks[i]) }
|
||||
}, isLast ? callback : null)
|
||||
})
|
||||
|
||||
// Empty DATA
|
||||
if (frames.length === 0) {
|
||||
this._frame({
|
||||
id: frame.id,
|
||||
priority: frame.priority,
|
||||
type: 'DATA',
|
||||
flags: fin
|
||||
}, function (buf) {
|
||||
// No-op
|
||||
}, callback)
|
||||
}
|
||||
}
|
||||
|
||||
Framer.prototype.pingFrame = function pingFrame (frame, callback) {
|
||||
this._frame({
|
||||
id: 0,
|
||||
type: 'PING',
|
||||
flags: frame.ack ? constants.flags.ACK : 0
|
||||
}, function (buf) {
|
||||
buf.copyFrom(frame.opaque)
|
||||
}, callback)
|
||||
}
|
||||
|
||||
Framer.prototype.rstFrame = function rstFrame (frame, callback) {
|
||||
this._frame({
|
||||
id: frame.id,
|
||||
type: 'RST_STREAM',
|
||||
flags: 0
|
||||
}, function (buf) {
|
||||
buf.writeUInt32BE(constants.error[frame.code])
|
||||
}, callback)
|
||||
}
|
||||
|
||||
Framer.prototype.prefaceFrame = function prefaceFrame (callback) {
|
||||
debug('preface')
|
||||
this._resetTimeout()
|
||||
this.schedule({
|
||||
stream: 0,
|
||||
priority: false,
|
||||
chunks: [ constants.PREFACE_BUFFER ],
|
||||
callback: callback
|
||||
})
|
||||
}
|
||||
|
||||
Framer.prototype.settingsFrame = function settingsFrame (options, callback) {
|
||||
var key = JSON.stringify(options)
|
||||
|
||||
var settings = Framer.settingsCache[key]
|
||||
if (settings) {
|
||||
debug('cached settings')
|
||||
this._resetTimeout()
|
||||
this.schedule({
|
||||
id: 0,
|
||||
priority: false,
|
||||
chunks: settings,
|
||||
callback: callback
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var params = []
|
||||
for (var i = 0; i < constants.settingsIndex.length; i++) {
|
||||
var name = constants.settingsIndex[i]
|
||||
if (!name) {
|
||||
continue
|
||||
}
|
||||
|
||||
// value: Infinity
|
||||
if (!isFinite(options[name])) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (options[name] !== undefined) {
|
||||
params.push({ key: i, value: options[name] })
|
||||
}
|
||||
}
|
||||
|
||||
var bodySize = params.length * 6
|
||||
|
||||
var chunks = this._frame({
|
||||
id: 0,
|
||||
type: 'SETTINGS',
|
||||
flags: 0
|
||||
}, function (buffer) {
|
||||
buffer.reserve(bodySize)
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
var param = params[i]
|
||||
|
||||
buffer.writeUInt16BE(param.key)
|
||||
buffer.writeUInt32BE(param.value)
|
||||
}
|
||||
}, callback)
|
||||
|
||||
Framer.settingsCache[key] = chunks
|
||||
}
|
||||
Framer.settingsCache = {}
|
||||
|
||||
Framer.prototype.ackSettingsFrame = function ackSettingsFrame (callback) {
|
||||
/* var chunks = */ this._frame({
|
||||
id: 0,
|
||||
type: 'SETTINGS',
|
||||
flags: constants.flags.ACK
|
||||
}, function (buffer) {
|
||||
// No-op
|
||||
}, callback)
|
||||
}
|
||||
|
||||
Framer.prototype.windowUpdateFrame = function windowUpdateFrame (frame,
|
||||
callback) {
|
||||
this._frame({
|
||||
id: frame.id,
|
||||
type: 'WINDOW_UPDATE',
|
||||
flags: 0
|
||||
}, function (buffer) {
|
||||
buffer.reserve(4)
|
||||
buffer.writeInt32BE(frame.delta)
|
||||
}, callback)
|
||||
}
|
||||
|
||||
Framer.prototype.goawayFrame = function goawayFrame (frame, callback) {
|
||||
this._frame({
|
||||
type: 'GOAWAY',
|
||||
id: 0,
|
||||
flags: 0
|
||||
}, function (buf) {
|
||||
buf.reserve(8)
|
||||
|
||||
// Last-good-stream-ID
|
||||
buf.writeUInt32BE(frame.lastId & 0x7fffffff)
|
||||
// Code
|
||||
buf.writeUInt32BE(constants.goaway[frame.code])
|
||||
|
||||
// Extra debugging information
|
||||
if (frame.extra) { buf.write(frame.extra) }
|
||||
}, callback)
|
||||
}
|
||||
|
||||
Framer.prototype.xForwardedFor = function xForwardedFor (frame, callback) {
|
||||
this._frame({
|
||||
type: 'X_FORWARDED_FOR',
|
||||
id: 0,
|
||||
flags: 0
|
||||
}, function (buf) {
|
||||
buf.write(frame.host)
|
||||
}, callback)
|
||||
}
|
||||
34
node_modules/spdy-transport/lib/spdy-transport/protocol/http2/hpack-pool.js
generated
vendored
Normal file
34
node_modules/spdy-transport/lib/spdy-transport/protocol/http2/hpack-pool.js
generated
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
'use strict'
|
||||
|
||||
var constants = require('./').constants
|
||||
|
||||
var hpack = require('hpack.js')
|
||||
|
||||
function Pool () {
|
||||
}
|
||||
module.exports = Pool
|
||||
|
||||
Pool.create = function create () {
|
||||
return new Pool()
|
||||
}
|
||||
|
||||
Pool.prototype.get = function get (version) {
|
||||
var options = {
|
||||
table: {
|
||||
maxSize: constants.HEADER_TABLE_SIZE
|
||||
}
|
||||
}
|
||||
|
||||
var compress = hpack.compressor.create(options)
|
||||
var decompress = hpack.decompressor.create(options)
|
||||
|
||||
return {
|
||||
version: version,
|
||||
|
||||
compress: compress,
|
||||
decompress: decompress
|
||||
}
|
||||
}
|
||||
|
||||
Pool.prototype.put = function put () {
|
||||
}
|
||||
8
node_modules/spdy-transport/lib/spdy-transport/protocol/http2/index.js
generated
vendored
Normal file
8
node_modules/spdy-transport/lib/spdy-transport/protocol/http2/index.js
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
'use strict'
|
||||
|
||||
exports.name = 'h2'
|
||||
|
||||
exports.constants = require('./constants')
|
||||
exports.parser = require('./parser')
|
||||
exports.framer = require('./framer')
|
||||
exports.compressionPool = require('./hpack-pool')
|
||||
578
node_modules/spdy-transport/lib/spdy-transport/protocol/http2/parser.js
generated
vendored
Normal file
578
node_modules/spdy-transport/lib/spdy-transport/protocol/http2/parser.js
generated
vendored
Normal file
@ -0,0 +1,578 @@
|
||||
'use strict'
|
||||
|
||||
var parser = exports
|
||||
|
||||
var transport = require('../../../spdy-transport')
|
||||
var base = transport.protocol.base
|
||||
var utils = base.utils
|
||||
var constants = require('./').constants
|
||||
|
||||
var assert = require('assert')
|
||||
var util = require('util')
|
||||
|
||||
function Parser (options) {
|
||||
base.Parser.call(this, options)
|
||||
|
||||
this.isServer = options.isServer
|
||||
|
||||
this.waiting = constants.PREFACE_SIZE
|
||||
this.state = 'preface'
|
||||
this.pendingHeader = null
|
||||
|
||||
// Header Block queue
|
||||
this._lastHeaderBlock = null
|
||||
this.maxFrameSize = constants.INITIAL_MAX_FRAME_SIZE
|
||||
this.maxHeaderListSize = constants.DEFAULT_MAX_HEADER_LIST_SIZE
|
||||
}
|
||||
util.inherits(Parser, base.Parser)
|
||||
|
||||
parser.create = function create (options) {
|
||||
return new Parser(options)
|
||||
}
|
||||
|
||||
Parser.prototype.setMaxFrameSize = function setMaxFrameSize (size) {
|
||||
this.maxFrameSize = size
|
||||
}
|
||||
|
||||
Parser.prototype.setMaxHeaderListSize = function setMaxHeaderListSize (size) {
|
||||
this.maxHeaderListSize = size
|
||||
}
|
||||
|
||||
// Only for testing
|
||||
Parser.prototype.skipPreface = function skipPreface () {
|
||||
// Just some number bigger than 3.1, doesn't really matter for HTTP2
|
||||
this.setVersion(4)
|
||||
|
||||
// Parse frame header!
|
||||
this.state = 'frame-head'
|
||||
this.waiting = constants.FRAME_HEADER_SIZE
|
||||
}
|
||||
|
||||
Parser.prototype.execute = function execute (buffer, callback) {
|
||||
if (this.state === 'preface') { return this.onPreface(buffer, callback) }
|
||||
|
||||
if (this.state === 'frame-head') {
|
||||
return this.onFrameHead(buffer, callback)
|
||||
}
|
||||
|
||||
assert(this.state === 'frame-body' && this.pendingHeader !== null)
|
||||
|
||||
var self = this
|
||||
var header = this.pendingHeader
|
||||
this.pendingHeader = null
|
||||
|
||||
this.onFrameBody(header, buffer, function (err, frame) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
self.state = 'frame-head'
|
||||
self.partial = false
|
||||
self.waiting = constants.FRAME_HEADER_SIZE
|
||||
callback(null, frame)
|
||||
})
|
||||
}
|
||||
|
||||
Parser.prototype.executePartial = function executePartial (buffer, callback) {
|
||||
var header = this.pendingHeader
|
||||
|
||||
assert.strictEqual(header.flags & constants.flags.PADDED, 0)
|
||||
|
||||
if (this.window) { this.window.recv.update(-buffer.size) }
|
||||
|
||||
callback(null, {
|
||||
type: 'DATA',
|
||||
id: header.id,
|
||||
|
||||
// Partial DATA can't be FIN
|
||||
fin: false,
|
||||
data: buffer.take(buffer.size)
|
||||
})
|
||||
}
|
||||
|
||||
Parser.prototype.onPreface = function onPreface (buffer, callback) {
|
||||
if (buffer.take(buffer.size).toString() !== constants.PREFACE) {
|
||||
return callback(this.error(constants.error.PROTOCOL_ERROR,
|
||||
'Invalid preface'))
|
||||
}
|
||||
|
||||
this.skipPreface()
|
||||
callback(null, null)
|
||||
}
|
||||
|
||||
Parser.prototype.onFrameHead = function onFrameHead (buffer, callback) {
|
||||
var header = {
|
||||
length: buffer.readUInt24BE(),
|
||||
control: true,
|
||||
type: buffer.readUInt8(),
|
||||
flags: buffer.readUInt8(),
|
||||
id: buffer.readUInt32BE() & 0x7fffffff
|
||||
}
|
||||
|
||||
if (header.length > this.maxFrameSize) {
|
||||
return callback(this.error(constants.error.FRAME_SIZE_ERROR,
|
||||
'Frame length OOB'))
|
||||
}
|
||||
|
||||
header.control = header.type !== constants.frameType.DATA
|
||||
|
||||
this.state = 'frame-body'
|
||||
this.pendingHeader = header
|
||||
this.waiting = header.length
|
||||
this.partial = !header.control
|
||||
|
||||
// TODO(indutny): eventually support partial padded DATA
|
||||
if (this.partial) {
|
||||
this.partial = (header.flags & constants.flags.PADDED) === 0
|
||||
}
|
||||
|
||||
callback(null, null)
|
||||
}
|
||||
|
||||
Parser.prototype.onFrameBody = function onFrameBody (header, buffer, callback) {
|
||||
var frameType = constants.frameType
|
||||
|
||||
if (header.type === frameType.DATA) {
|
||||
this.onDataFrame(header, buffer, callback)
|
||||
} else if (header.type === frameType.HEADERS) {
|
||||
this.onHeadersFrame(header, buffer, callback)
|
||||
} else if (header.type === frameType.CONTINUATION) {
|
||||
this.onContinuationFrame(header, buffer, callback)
|
||||
} else if (header.type === frameType.WINDOW_UPDATE) {
|
||||
this.onWindowUpdateFrame(header, buffer, callback)
|
||||
} else if (header.type === frameType.RST_STREAM) {
|
||||
this.onRSTFrame(header, buffer, callback)
|
||||
} else if (header.type === frameType.SETTINGS) {
|
||||
this.onSettingsFrame(header, buffer, callback)
|
||||
} else if (header.type === frameType.PUSH_PROMISE) {
|
||||
this.onPushPromiseFrame(header, buffer, callback)
|
||||
} else if (header.type === frameType.PING) {
|
||||
this.onPingFrame(header, buffer, callback)
|
||||
} else if (header.type === frameType.GOAWAY) {
|
||||
this.onGoawayFrame(header, buffer, callback)
|
||||
} else if (header.type === frameType.PRIORITY) {
|
||||
this.onPriorityFrame(header, buffer, callback)
|
||||
} else if (header.type === frameType.X_FORWARDED_FOR) {
|
||||
this.onXForwardedFrame(header, buffer, callback)
|
||||
} else {
|
||||
this.onUnknownFrame(header, buffer, callback)
|
||||
}
|
||||
}
|
||||
|
||||
Parser.prototype.onUnknownFrame = function onUnknownFrame (header, buffer, callback) {
|
||||
if (this._lastHeaderBlock !== null) {
|
||||
callback(this.error(constants.error.PROTOCOL_ERROR,
|
||||
'Received unknown frame in the middle of a header block'))
|
||||
return
|
||||
}
|
||||
callback(null, { type: 'unknown: ' + header.type })
|
||||
}
|
||||
|
||||
Parser.prototype.unpadData = function unpadData (header, body, callback) {
|
||||
var isPadded = (header.flags & constants.flags.PADDED) !== 0
|
||||
|
||||
if (!isPadded) { return callback(null, body) }
|
||||
|
||||
if (!body.has(1)) {
|
||||
return callback(this.error(constants.error.FRAME_SIZE_ERROR,
|
||||
'Not enough space for padding'))
|
||||
}
|
||||
|
||||
var pad = body.readUInt8()
|
||||
if (!body.has(pad)) {
|
||||
return callback(this.error(constants.error.PROTOCOL_ERROR,
|
||||
'Invalid padding size'))
|
||||
}
|
||||
|
||||
var contents = body.clone(body.size - pad)
|
||||
body.skip(body.size)
|
||||
callback(null, contents)
|
||||
}
|
||||
|
||||
Parser.prototype.onDataFrame = function onDataFrame (header, body, callback) {
|
||||
var isEndStream = (header.flags & constants.flags.END_STREAM) !== 0
|
||||
|
||||
if (header.id === 0) {
|
||||
return callback(this.error(constants.error.PROTOCOL_ERROR,
|
||||
'Received DATA frame with stream=0'))
|
||||
}
|
||||
|
||||
// Count received bytes
|
||||
if (this.window) {
|
||||
this.window.recv.update(-body.size)
|
||||
}
|
||||
|
||||
this.unpadData(header, body, function (err, data) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
callback(null, {
|
||||
type: 'DATA',
|
||||
id: header.id,
|
||||
fin: isEndStream,
|
||||
data: data.take(data.size)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Parser.prototype.initHeaderBlock = function initHeaderBlock (header,
|
||||
frame,
|
||||
block,
|
||||
callback) {
|
||||
if (this._lastHeaderBlock) {
|
||||
return callback(this.error(constants.error.PROTOCOL_ERROR,
|
||||
'Duplicate Stream ID'))
|
||||
}
|
||||
|
||||
this._lastHeaderBlock = {
|
||||
id: header.id,
|
||||
frame: frame,
|
||||
queue: [],
|
||||
size: 0
|
||||
}
|
||||
|
||||
this.queueHeaderBlock(header, block, callback)
|
||||
}
|
||||
|
||||
Parser.prototype.queueHeaderBlock = function queueHeaderBlock (header,
|
||||
block,
|
||||
callback) {
|
||||
var self = this
|
||||
var item = this._lastHeaderBlock
|
||||
if (!this._lastHeaderBlock || item.id !== header.id) {
|
||||
return callback(this.error(constants.error.PROTOCOL_ERROR,
|
||||
'No matching stream for continuation'))
|
||||
}
|
||||
|
||||
var fin = (header.flags & constants.flags.END_HEADERS) !== 0
|
||||
|
||||
var chunks = block.toChunks()
|
||||
for (var i = 0; i < chunks.length; i++) {
|
||||
var chunk = chunks[i]
|
||||
item.queue.push(chunk)
|
||||
item.size += chunk.length
|
||||
}
|
||||
|
||||
if (item.size >= self.maxHeaderListSize) {
|
||||
return callback(this.error(constants.error.PROTOCOL_ERROR,
|
||||
'Compressed header list is too large'))
|
||||
}
|
||||
|
||||
if (!fin) { return callback(null, null) }
|
||||
this._lastHeaderBlock = null
|
||||
|
||||
this.decompress.write(item.queue, function (err, chunks) {
|
||||
if (err) {
|
||||
return callback(self.error(constants.error.COMPRESSION_ERROR,
|
||||
err.message))
|
||||
}
|
||||
|
||||
var headers = {}
|
||||
var size = 0
|
||||
for (var i = 0; i < chunks.length; i++) {
|
||||
var header = chunks[i]
|
||||
|
||||
size += header.name.length + header.value.length + 32
|
||||
if (size >= self.maxHeaderListSize) {
|
||||
return callback(self.error(constants.error.PROTOCOL_ERROR,
|
||||
'Header list is too large'))
|
||||
}
|
||||
|
||||
if (/[A-Z]/.test(header.name)) {
|
||||
return callback(self.error(constants.error.PROTOCOL_ERROR,
|
||||
'Header name must be lowercase'))
|
||||
}
|
||||
|
||||
utils.addHeaderLine(header.name, header.value, headers)
|
||||
}
|
||||
|
||||
item.frame.headers = headers
|
||||
item.frame.path = headers[':path']
|
||||
|
||||
callback(null, item.frame)
|
||||
})
|
||||
}
|
||||
|
||||
Parser.prototype.onHeadersFrame = function onHeadersFrame (header,
|
||||
body,
|
||||
callback) {
|
||||
var self = this
|
||||
|
||||
if (header.id === 0) {
|
||||
return callback(this.error(constants.error.PROTOCOL_ERROR,
|
||||
'Invalid stream id for HEADERS'))
|
||||
}
|
||||
|
||||
this.unpadData(header, body, function (err, data) {
|
||||
if (err) { return callback(err) }
|
||||
|
||||
var isPriority = (header.flags & constants.flags.PRIORITY) !== 0
|
||||
if (!data.has(isPriority ? 5 : 0)) {
|
||||
return callback(self.error(constants.error.FRAME_SIZE_ERROR,
|
||||
'Not enough data for HEADERS'))
|
||||
}
|
||||
|
||||
var exclusive = false
|
||||
var dependency = 0
|
||||
var weight = constants.DEFAULT_WEIGHT
|
||||
if (isPriority) {
|
||||
dependency = data.readUInt32BE()
|
||||
exclusive = (dependency & 0x80000000) !== 0
|
||||
dependency &= 0x7fffffff
|
||||
|
||||
// Weight's range is [1, 256]
|
||||
weight = data.readUInt8() + 1
|
||||
}
|
||||
|
||||
if (dependency === header.id) {
|
||||
return callback(self.error(constants.error.PROTOCOL_ERROR,
|
||||
'Stream can\'t dependend on itself'))
|
||||
}
|
||||
|
||||
var streamInfo = {
|
||||
type: 'HEADERS',
|
||||
id: header.id,
|
||||
priority: {
|
||||
parent: dependency,
|
||||
exclusive: exclusive,
|
||||
weight: weight
|
||||
},
|
||||
fin: (header.flags & constants.flags.END_STREAM) !== 0,
|
||||
writable: true,
|
||||
headers: null,
|
||||
path: null
|
||||
}
|
||||
|
||||
self.initHeaderBlock(header, streamInfo, data, callback)
|
||||
})
|
||||
}
|
||||
|
||||
Parser.prototype.onContinuationFrame = function onContinuationFrame (header,
|
||||
body,
|
||||
callback) {
|
||||
this.queueHeaderBlock(header, body, callback)
|
||||
}
|
||||
|
||||
Parser.prototype.onRSTFrame = function onRSTFrame (header, body, callback) {
|
||||
if (body.size !== 4) {
|
||||
return callback(this.error(constants.error.FRAME_SIZE_ERROR,
|
||||
'RST_STREAM length not 4'))
|
||||
}
|
||||
|
||||
if (header.id === 0) {
|
||||
return callback(this.error(constants.error.PROTOCOL_ERROR,
|
||||
'Invalid stream id for RST_STREAM'))
|
||||
}
|
||||
|
||||
callback(null, {
|
||||
type: 'RST',
|
||||
id: header.id,
|
||||
code: constants.errorByCode[body.readUInt32BE()]
|
||||
})
|
||||
}
|
||||
|
||||
Parser.prototype._validateSettings = function _validateSettings (settings) {
|
||||
if (settings['enable_push'] !== undefined &&
|
||||
settings['enable_push'] !== 0 &&
|
||||
settings['enable_push'] !== 1) {
|
||||
return this.error(constants.error.PROTOCOL_ERROR,
|
||||
'SETTINGS_ENABLE_PUSH must be 0 or 1')
|
||||
}
|
||||
|
||||
if (settings['initial_window_size'] !== undefined &&
|
||||
(settings['initial_window_size'] > constants.MAX_INITIAL_WINDOW_SIZE ||
|
||||
settings['initial_window_size'] < 0)) {
|
||||
return this.error(constants.error.FLOW_CONTROL_ERROR,
|
||||
'SETTINGS_INITIAL_WINDOW_SIZE is OOB')
|
||||
}
|
||||
|
||||
if (settings['max_frame_size'] !== undefined &&
|
||||
(settings['max_frame_size'] > constants.ABSOLUTE_MAX_FRAME_SIZE ||
|
||||
settings['max_frame_size'] < constants.INITIAL_MAX_FRAME_SIZE)) {
|
||||
return this.error(constants.error.PROTOCOL_ERROR,
|
||||
'SETTINGS_MAX_FRAME_SIZE is OOB')
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
Parser.prototype.onSettingsFrame = function onSettingsFrame (header,
|
||||
body,
|
||||
callback) {
|
||||
if (header.id !== 0) {
|
||||
return callback(this.error(constants.error.PROTOCOL_ERROR,
|
||||
'Invalid stream id for SETTINGS'))
|
||||
}
|
||||
|
||||
var isAck = (header.flags & constants.flags.ACK) !== 0
|
||||
if (isAck && body.size !== 0) {
|
||||
return callback(this.error(constants.error.FRAME_SIZE_ERROR,
|
||||
'SETTINGS with ACK and non-zero length'))
|
||||
}
|
||||
|
||||
if (isAck) {
|
||||
return callback(null, { type: 'ACK_SETTINGS' })
|
||||
}
|
||||
|
||||
if (body.size % 6 !== 0) {
|
||||
return callback(this.error(constants.error.FRAME_SIZE_ERROR,
|
||||
'SETTINGS length not multiple of 6'))
|
||||
}
|
||||
|
||||
var settings = {}
|
||||
while (!body.isEmpty()) {
|
||||
var id = body.readUInt16BE()
|
||||
var value = body.readUInt32BE()
|
||||
var name = constants.settingsIndex[id]
|
||||
|
||||
if (name) {
|
||||
settings[name] = value
|
||||
}
|
||||
}
|
||||
|
||||
var err = this._validateSettings(settings)
|
||||
if (err !== undefined) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
callback(null, {
|
||||
type: 'SETTINGS',
|
||||
settings: settings
|
||||
})
|
||||
}
|
||||
|
||||
Parser.prototype.onPushPromiseFrame = function onPushPromiseFrame (header,
|
||||
body,
|
||||
callback) {
|
||||
if (header.id === 0) {
|
||||
return callback(this.error(constants.error.PROTOCOL_ERROR,
|
||||
'Invalid stream id for PUSH_PROMISE'))
|
||||
}
|
||||
|
||||
var self = this
|
||||
this.unpadData(header, body, function (err, data) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
if (!data.has(4)) {
|
||||
return callback(self.error(constants.error.FRAME_SIZE_ERROR,
|
||||
'PUSH_PROMISE length less than 4'))
|
||||
}
|
||||
|
||||
var streamInfo = {
|
||||
type: 'PUSH_PROMISE',
|
||||
id: header.id,
|
||||
fin: false,
|
||||
promisedId: data.readUInt32BE() & 0x7fffffff,
|
||||
headers: null,
|
||||
path: null
|
||||
}
|
||||
|
||||
self.initHeaderBlock(header, streamInfo, data, callback)
|
||||
})
|
||||
}
|
||||
|
||||
Parser.prototype.onPingFrame = function onPingFrame (header, body, callback) {
|
||||
if (body.size !== 8) {
|
||||
return callback(this.error(constants.error.FRAME_SIZE_ERROR,
|
||||
'PING length != 8'))
|
||||
}
|
||||
|
||||
if (header.id !== 0) {
|
||||
return callback(this.error(constants.error.PROTOCOL_ERROR,
|
||||
'Invalid stream id for PING'))
|
||||
}
|
||||
|
||||
var ack = (header.flags & constants.flags.ACK) !== 0
|
||||
callback(null, { type: 'PING', opaque: body.take(body.size), ack: ack })
|
||||
}
|
||||
|
||||
Parser.prototype.onGoawayFrame = function onGoawayFrame (header,
|
||||
body,
|
||||
callback) {
|
||||
if (!body.has(8)) {
|
||||
return callback(this.error(constants.error.FRAME_SIZE_ERROR,
|
||||
'GOAWAY length < 8'))
|
||||
}
|
||||
|
||||
if (header.id !== 0) {
|
||||
return callback(this.error(constants.error.PROTOCOL_ERROR,
|
||||
'Invalid stream id for GOAWAY'))
|
||||
}
|
||||
|
||||
var frame = {
|
||||
type: 'GOAWAY',
|
||||
lastId: body.readUInt32BE(),
|
||||
code: constants.goawayByCode[body.readUInt32BE()]
|
||||
}
|
||||
|
||||
if (body.size !== 0) { frame.debug = body.take(body.size) }
|
||||
|
||||
callback(null, frame)
|
||||
}
|
||||
|
||||
Parser.prototype.onPriorityFrame = function onPriorityFrame (header,
|
||||
body,
|
||||
callback) {
|
||||
if (body.size !== 5) {
|
||||
return callback(this.error(constants.error.FRAME_SIZE_ERROR,
|
||||
'PRIORITY length != 5'))
|
||||
}
|
||||
|
||||
if (header.id === 0) {
|
||||
return callback(this.error(constants.error.PROTOCOL_ERROR,
|
||||
'Invalid stream id for PRIORITY'))
|
||||
}
|
||||
|
||||
var dependency = body.readUInt32BE()
|
||||
|
||||
// Again the range is from 1 to 256
|
||||
var weight = body.readUInt8() + 1
|
||||
|
||||
if (dependency === header.id) {
|
||||
return callback(this.error(constants.error.PROTOCOL_ERROR,
|
||||
'Stream can\'t dependend on itself'))
|
||||
}
|
||||
|
||||
callback(null, {
|
||||
type: 'PRIORITY',
|
||||
id: header.id,
|
||||
priority: {
|
||||
exclusive: (dependency & 0x80000000) !== 0,
|
||||
parent: dependency & 0x7fffffff,
|
||||
weight: weight
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Parser.prototype.onWindowUpdateFrame = function onWindowUpdateFrame (header,
|
||||
body,
|
||||
callback) {
|
||||
if (body.size !== 4) {
|
||||
return callback(this.error(constants.error.FRAME_SIZE_ERROR,
|
||||
'WINDOW_UPDATE length != 4'))
|
||||
}
|
||||
|
||||
var delta = body.readInt32BE()
|
||||
if (delta === 0) {
|
||||
return callback(this.error(constants.error.PROTOCOL_ERROR,
|
||||
'WINDOW_UPDATE delta == 0'))
|
||||
}
|
||||
|
||||
callback(null, {
|
||||
type: 'WINDOW_UPDATE',
|
||||
id: header.id,
|
||||
delta: delta
|
||||
})
|
||||
}
|
||||
|
||||
Parser.prototype.onXForwardedFrame = function onXForwardedFrame (header,
|
||||
body,
|
||||
callback) {
|
||||
callback(null, {
|
||||
type: 'X_FORWARDED_FOR',
|
||||
host: body.take(body.size).toString()
|
||||
})
|
||||
}
|
||||
146
node_modules/spdy-transport/lib/spdy-transport/protocol/spdy/constants.js
generated
vendored
Normal file
146
node_modules/spdy-transport/lib/spdy-transport/protocol/spdy/constants.js
generated
vendored
Normal file
@ -0,0 +1,146 @@
|
||||
'use strict'
|
||||
|
||||
var transport = require('../../../spdy-transport')
|
||||
var base = transport.protocol.base
|
||||
|
||||
exports.FRAME_HEADER_SIZE = 8
|
||||
|
||||
exports.PING_OPAQUE_SIZE = 4
|
||||
|
||||
exports.MAX_CONCURRENT_STREAMS = Infinity
|
||||
exports.DEFAULT_MAX_HEADER_LIST_SIZE = Infinity
|
||||
|
||||
exports.DEFAULT_WEIGHT = 16
|
||||
|
||||
exports.frameType = {
|
||||
SYN_STREAM: 1,
|
||||
SYN_REPLY: 2,
|
||||
RST_STREAM: 3,
|
||||
SETTINGS: 4,
|
||||
PING: 6,
|
||||
GOAWAY: 7,
|
||||
HEADERS: 8,
|
||||
WINDOW_UPDATE: 9,
|
||||
|
||||
// Custom
|
||||
X_FORWARDED_FOR: 0xf000
|
||||
}
|
||||
|
||||
exports.flags = {
|
||||
FLAG_FIN: 0x01,
|
||||
FLAG_COMPRESSED: 0x02,
|
||||
FLAG_UNIDIRECTIONAL: 0x02
|
||||
}
|
||||
|
||||
exports.error = {
|
||||
PROTOCOL_ERROR: 1,
|
||||
INVALID_STREAM: 2,
|
||||
REFUSED_STREAM: 3,
|
||||
UNSUPPORTED_VERSION: 4,
|
||||
CANCEL: 5,
|
||||
INTERNAL_ERROR: 6,
|
||||
FLOW_CONTROL_ERROR: 7,
|
||||
STREAM_IN_USE: 8,
|
||||
// STREAM_ALREADY_CLOSED: 9
|
||||
STREAM_CLOSED: 9,
|
||||
INVALID_CREDENTIALS: 10,
|
||||
FRAME_TOO_LARGE: 11
|
||||
}
|
||||
exports.errorByCode = base.utils.reverse(exports.error)
|
||||
|
||||
exports.settings = {
|
||||
FLAG_SETTINGS_PERSIST_VALUE: 1,
|
||||
FLAG_SETTINGS_PERSISTED: 2,
|
||||
|
||||
SETTINGS_UPLOAD_BANDWIDTH: 1,
|
||||
SETTINGS_DOWNLOAD_BANDWIDTH: 2,
|
||||
SETTINGS_ROUND_TRIP_TIME: 3,
|
||||
SETTINGS_MAX_CONCURRENT_STREAMS: 4,
|
||||
SETTINGS_CURRENT_CWND: 5,
|
||||
SETTINGS_DOWNLOAD_RETRANS_RATE: 6,
|
||||
SETTINGS_INITIAL_WINDOW_SIZE: 7,
|
||||
SETTINGS_CLIENT_CERTIFICATE_VECTOR_SIZE: 8
|
||||
}
|
||||
|
||||
exports.settingsIndex = [
|
||||
null,
|
||||
|
||||
'upload_bandwidth',
|
||||
'download_bandwidth',
|
||||
'round_trip_time',
|
||||
'max_concurrent_streams',
|
||||
'current_cwnd',
|
||||
'download_retrans_rate',
|
||||
'initial_window_size',
|
||||
'client_certificate_vector_size'
|
||||
]
|
||||
|
||||
exports.DEFAULT_WINDOW = 64 * 1024
|
||||
exports.MAX_INITIAL_WINDOW_SIZE = 2147483647
|
||||
|
||||
exports.goaway = {
|
||||
OK: 0,
|
||||
PROTOCOL_ERROR: 1,
|
||||
INTERNAL_ERROR: 2
|
||||
}
|
||||
exports.goawayByCode = base.utils.reverse(exports.goaway)
|
||||
|
||||
exports.statusReason = {
|
||||
100: 'Continue',
|
||||
101: 'Switching Protocols',
|
||||
102: 'Processing', // RFC 2518, obsoleted by RFC 4918
|
||||
200: 'OK',
|
||||
201: 'Created',
|
||||
202: 'Accepted',
|
||||
203: 'Non-Authoritative Information',
|
||||
204: 'No Content',
|
||||
205: 'Reset Content',
|
||||
206: 'Partial Content',
|
||||
207: 'Multi-Status', // RFC 4918
|
||||
300: 'Multiple Choices',
|
||||
301: 'Moved Permanently',
|
||||
302: 'Moved Temporarily',
|
||||
303: 'See Other',
|
||||
304: 'Not Modified',
|
||||
305: 'Use Proxy',
|
||||
307: 'Temporary Redirect',
|
||||
308: 'Permanent Redirect', // RFC 7238
|
||||
400: 'Bad Request',
|
||||
401: 'Unauthorized',
|
||||
402: 'Payment Required',
|
||||
403: 'Forbidden',
|
||||
404: 'Not Found',
|
||||
405: 'Method Not Allowed',
|
||||
406: 'Not Acceptable',
|
||||
407: 'Proxy Authentication Required',
|
||||
408: 'Request Time-out',
|
||||
409: 'Conflict',
|
||||
410: 'Gone',
|
||||
411: 'Length Required',
|
||||
412: 'Precondition Failed',
|
||||
413: 'Request Entity Too Large',
|
||||
414: 'Request-URI Too Large',
|
||||
415: 'Unsupported Media Type',
|
||||
416: 'Requested Range Not Satisfiable',
|
||||
417: 'Expectation Failed',
|
||||
418: 'I\'m a teapot', // RFC 2324
|
||||
422: 'Unprocessable Entity', // RFC 4918
|
||||
423: 'Locked', // RFC 4918
|
||||
424: 'Failed Dependency', // RFC 4918
|
||||
425: 'Unordered Collection', // RFC 4918
|
||||
426: 'Upgrade Required', // RFC 2817
|
||||
428: 'Precondition Required', // RFC 6585
|
||||
429: 'Too Many Requests', // RFC 6585
|
||||
431: 'Request Header Fields Too Large', // RFC 6585
|
||||
500: 'Internal Server Error',
|
||||
501: 'Not Implemented',
|
||||
502: 'Bad Gateway',
|
||||
503: 'Service Unavailable',
|
||||
504: 'Gateway Time-out',
|
||||
505: 'HTTP Version Not Supported',
|
||||
506: 'Variant Also Negotiates', // RFC 2295
|
||||
507: 'Insufficient Storage', // RFC 4918
|
||||
509: 'Bandwidth Limit Exceeded',
|
||||
510: 'Not Extended', // RFC 2774
|
||||
511: 'Network Authentication Required' // RFC 6585
|
||||
}
|
||||
203
node_modules/spdy-transport/lib/spdy-transport/protocol/spdy/dictionary.js
generated
vendored
Normal file
203
node_modules/spdy-transport/lib/spdy-transport/protocol/spdy/dictionary.js
generated
vendored
Normal file
@ -0,0 +1,203 @@
|
||||
'use strict'
|
||||
|
||||
var dictionary = {}
|
||||
module.exports = dictionary
|
||||
|
||||
dictionary[2] = Buffer.from([
|
||||
'optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-',
|
||||
'languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi',
|
||||
'f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser',
|
||||
'-agent10010120020120220320420520630030130230330430530630740040140240340440',
|
||||
'5406407408409410411412413414415416417500501502503504505accept-rangesageeta',
|
||||
'glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic',
|
||||
'ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran',
|
||||
'sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati',
|
||||
'oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo',
|
||||
'ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe',
|
||||
'pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic',
|
||||
'ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1',
|
||||
'.1statusversionurl\x00'
|
||||
].join(''))
|
||||
|
||||
dictionary[3] = Buffer.from([
|
||||
0x00, 0x00, 0x00, 0x07, 0x6f, 0x70, 0x74, 0x69, // ....opti
|
||||
0x6f, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x04, 0x68, // ons....h
|
||||
0x65, 0x61, 0x64, 0x00, 0x00, 0x00, 0x04, 0x70, // ead....p
|
||||
0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x03, 0x70, // ost....p
|
||||
0x75, 0x74, 0x00, 0x00, 0x00, 0x06, 0x64, 0x65, // ut....de
|
||||
0x6c, 0x65, 0x74, 0x65, 0x00, 0x00, 0x00, 0x05, // lete....
|
||||
0x74, 0x72, 0x61, 0x63, 0x65, 0x00, 0x00, 0x00, // trace...
|
||||
0x06, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x00, // .accept.
|
||||
0x00, 0x00, 0x0e, 0x61, 0x63, 0x63, 0x65, 0x70, // ...accep
|
||||
0x74, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, // t-charse
|
||||
0x74, 0x00, 0x00, 0x00, 0x0f, 0x61, 0x63, 0x63, // t....acc
|
||||
0x65, 0x70, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, // ept-enco
|
||||
0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x0f, // ding....
|
||||
0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x2d, 0x6c, // accept-l
|
||||
0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x00, // anguage.
|
||||
0x00, 0x00, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x70, // ...accep
|
||||
0x74, 0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x73, // t-ranges
|
||||
0x00, 0x00, 0x00, 0x03, 0x61, 0x67, 0x65, 0x00, // ....age.
|
||||
0x00, 0x00, 0x05, 0x61, 0x6c, 0x6c, 0x6f, 0x77, // ...allow
|
||||
0x00, 0x00, 0x00, 0x0d, 0x61, 0x75, 0x74, 0x68, // ....auth
|
||||
0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, // orizatio
|
||||
0x6e, 0x00, 0x00, 0x00, 0x0d, 0x63, 0x61, 0x63, // n....cac
|
||||
0x68, 0x65, 0x2d, 0x63, 0x6f, 0x6e, 0x74, 0x72, // he-contr
|
||||
0x6f, 0x6c, 0x00, 0x00, 0x00, 0x0a, 0x63, 0x6f, // ol....co
|
||||
0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, // nnection
|
||||
0x00, 0x00, 0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, // ....cont
|
||||
0x65, 0x6e, 0x74, 0x2d, 0x62, 0x61, 0x73, 0x65, // ent-base
|
||||
0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, 0x6e, 0x74, // ....cont
|
||||
0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, // ent-enco
|
||||
0x64, 0x69, 0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, // ding....
|
||||
0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, // content-
|
||||
0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, // language
|
||||
0x00, 0x00, 0x00, 0x0e, 0x63, 0x6f, 0x6e, 0x74, // ....cont
|
||||
0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x65, 0x6e, 0x67, // ent-leng
|
||||
0x74, 0x68, 0x00, 0x00, 0x00, 0x10, 0x63, 0x6f, // th....co
|
||||
0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x6c, 0x6f, // ntent-lo
|
||||
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, // cation..
|
||||
0x00, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, // ..conten
|
||||
0x74, 0x2d, 0x6d, 0x64, 0x35, 0x00, 0x00, 0x00, // t-md5...
|
||||
0x0d, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, // .content
|
||||
0x2d, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, // -range..
|
||||
0x00, 0x0c, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, // ..conten
|
||||
0x74, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x00, 0x00, // t-type..
|
||||
0x00, 0x04, 0x64, 0x61, 0x74, 0x65, 0x00, 0x00, // ..date..
|
||||
0x00, 0x04, 0x65, 0x74, 0x61, 0x67, 0x00, 0x00, // ..etag..
|
||||
0x00, 0x06, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, // ..expect
|
||||
0x00, 0x00, 0x00, 0x07, 0x65, 0x78, 0x70, 0x69, // ....expi
|
||||
0x72, 0x65, 0x73, 0x00, 0x00, 0x00, 0x04, 0x66, // res....f
|
||||
0x72, 0x6f, 0x6d, 0x00, 0x00, 0x00, 0x04, 0x68, // rom....h
|
||||
0x6f, 0x73, 0x74, 0x00, 0x00, 0x00, 0x08, 0x69, // ost....i
|
||||
0x66, 0x2d, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, // f-match.
|
||||
0x00, 0x00, 0x11, 0x69, 0x66, 0x2d, 0x6d, 0x6f, // ...if-mo
|
||||
0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x2d, 0x73, // dified-s
|
||||
0x69, 0x6e, 0x63, 0x65, 0x00, 0x00, 0x00, 0x0d, // ince....
|
||||
0x69, 0x66, 0x2d, 0x6e, 0x6f, 0x6e, 0x65, 0x2d, // if-none-
|
||||
0x6d, 0x61, 0x74, 0x63, 0x68, 0x00, 0x00, 0x00, // match...
|
||||
0x08, 0x69, 0x66, 0x2d, 0x72, 0x61, 0x6e, 0x67, // .if-rang
|
||||
0x65, 0x00, 0x00, 0x00, 0x13, 0x69, 0x66, 0x2d, // e....if-
|
||||
0x75, 0x6e, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, // unmodifi
|
||||
0x65, 0x64, 0x2d, 0x73, 0x69, 0x6e, 0x63, 0x65, // ed-since
|
||||
0x00, 0x00, 0x00, 0x0d, 0x6c, 0x61, 0x73, 0x74, // ....last
|
||||
0x2d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, // -modifie
|
||||
0x64, 0x00, 0x00, 0x00, 0x08, 0x6c, 0x6f, 0x63, // d....loc
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, // ation...
|
||||
0x0c, 0x6d, 0x61, 0x78, 0x2d, 0x66, 0x6f, 0x72, // .max-for
|
||||
0x77, 0x61, 0x72, 0x64, 0x73, 0x00, 0x00, 0x00, // wards...
|
||||
0x06, 0x70, 0x72, 0x61, 0x67, 0x6d, 0x61, 0x00, // .pragma.
|
||||
0x00, 0x00, 0x12, 0x70, 0x72, 0x6f, 0x78, 0x79, // ...proxy
|
||||
0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, // -authent
|
||||
0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, // icate...
|
||||
0x13, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2d, 0x61, // .proxy-a
|
||||
0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, // uthoriza
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x00, 0x00, 0x00, 0x05, // tion....
|
||||
0x72, 0x61, 0x6e, 0x67, 0x65, 0x00, 0x00, 0x00, // range...
|
||||
0x07, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x72, // .referer
|
||||
0x00, 0x00, 0x00, 0x0b, 0x72, 0x65, 0x74, 0x72, // ....retr
|
||||
0x79, 0x2d, 0x61, 0x66, 0x74, 0x65, 0x72, 0x00, // y-after.
|
||||
0x00, 0x00, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, // ...serve
|
||||
0x72, 0x00, 0x00, 0x00, 0x02, 0x74, 0x65, 0x00, // r....te.
|
||||
0x00, 0x00, 0x07, 0x74, 0x72, 0x61, 0x69, 0x6c, // ...trail
|
||||
0x65, 0x72, 0x00, 0x00, 0x00, 0x11, 0x74, 0x72, // er....tr
|
||||
0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x2d, 0x65, // ansfer-e
|
||||
0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x00, // ncoding.
|
||||
0x00, 0x00, 0x07, 0x75, 0x70, 0x67, 0x72, 0x61, // ...upgra
|
||||
0x64, 0x65, 0x00, 0x00, 0x00, 0x0a, 0x75, 0x73, // de....us
|
||||
0x65, 0x72, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, // er-agent
|
||||
0x00, 0x00, 0x00, 0x04, 0x76, 0x61, 0x72, 0x79, // ....vary
|
||||
0x00, 0x00, 0x00, 0x03, 0x76, 0x69, 0x61, 0x00, // ....via.
|
||||
0x00, 0x00, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, // ...warni
|
||||
0x6e, 0x67, 0x00, 0x00, 0x00, 0x10, 0x77, 0x77, // ng....ww
|
||||
0x77, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, // w-authen
|
||||
0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x00, // ticate..
|
||||
0x00, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, // ..method
|
||||
0x00, 0x00, 0x00, 0x03, 0x67, 0x65, 0x74, 0x00, // ....get.
|
||||
0x00, 0x00, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, // ...statu
|
||||
0x73, 0x00, 0x00, 0x00, 0x06, 0x32, 0x30, 0x30, // s....200
|
||||
0x20, 0x4f, 0x4b, 0x00, 0x00, 0x00, 0x07, 0x76, // .OK....v
|
||||
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x00, 0x00, // ersion..
|
||||
0x00, 0x08, 0x48, 0x54, 0x54, 0x50, 0x2f, 0x31, // ..HTTP.1
|
||||
0x2e, 0x31, 0x00, 0x00, 0x00, 0x03, 0x75, 0x72, // .1....ur
|
||||
0x6c, 0x00, 0x00, 0x00, 0x06, 0x70, 0x75, 0x62, // l....pub
|
||||
0x6c, 0x69, 0x63, 0x00, 0x00, 0x00, 0x0a, 0x73, // lic....s
|
||||
0x65, 0x74, 0x2d, 0x63, 0x6f, 0x6f, 0x6b, 0x69, // et-cooki
|
||||
0x65, 0x00, 0x00, 0x00, 0x0a, 0x6b, 0x65, 0x65, // e....kee
|
||||
0x70, 0x2d, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x00, // p-alive.
|
||||
0x00, 0x00, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, // ...origi
|
||||
0x6e, 0x31, 0x30, 0x30, 0x31, 0x30, 0x31, 0x32, // n1001012
|
||||
0x30, 0x31, 0x32, 0x30, 0x32, 0x32, 0x30, 0x35, // 01202205
|
||||
0x32, 0x30, 0x36, 0x33, 0x30, 0x30, 0x33, 0x30, // 20630030
|
||||
0x32, 0x33, 0x30, 0x33, 0x33, 0x30, 0x34, 0x33, // 23033043
|
||||
0x30, 0x35, 0x33, 0x30, 0x36, 0x33, 0x30, 0x37, // 05306307
|
||||
0x34, 0x30, 0x32, 0x34, 0x30, 0x35, 0x34, 0x30, // 40240540
|
||||
0x36, 0x34, 0x30, 0x37, 0x34, 0x30, 0x38, 0x34, // 64074084
|
||||
0x30, 0x39, 0x34, 0x31, 0x30, 0x34, 0x31, 0x31, // 09410411
|
||||
0x34, 0x31, 0x32, 0x34, 0x31, 0x33, 0x34, 0x31, // 41241341
|
||||
0x34, 0x34, 0x31, 0x35, 0x34, 0x31, 0x36, 0x34, // 44154164
|
||||
0x31, 0x37, 0x35, 0x30, 0x32, 0x35, 0x30, 0x34, // 17502504
|
||||
0x35, 0x30, 0x35, 0x32, 0x30, 0x33, 0x20, 0x4e, // 505203.N
|
||||
0x6f, 0x6e, 0x2d, 0x41, 0x75, 0x74, 0x68, 0x6f, // on-Autho
|
||||
0x72, 0x69, 0x74, 0x61, 0x74, 0x69, 0x76, 0x65, // ritative
|
||||
0x20, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, // .Informa
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x32, 0x30, 0x34, 0x20, // tion204.
|
||||
0x4e, 0x6f, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x65, // No.Conte
|
||||
0x6e, 0x74, 0x33, 0x30, 0x31, 0x20, 0x4d, 0x6f, // nt301.Mo
|
||||
0x76, 0x65, 0x64, 0x20, 0x50, 0x65, 0x72, 0x6d, // ved.Perm
|
||||
0x61, 0x6e, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x34, // anently4
|
||||
0x30, 0x30, 0x20, 0x42, 0x61, 0x64, 0x20, 0x52, // 00.Bad.R
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x34, 0x30, // equest40
|
||||
0x31, 0x20, 0x55, 0x6e, 0x61, 0x75, 0x74, 0x68, // 1.Unauth
|
||||
0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x34, 0x30, // orized40
|
||||
0x33, 0x20, 0x46, 0x6f, 0x72, 0x62, 0x69, 0x64, // 3.Forbid
|
||||
0x64, 0x65, 0x6e, 0x34, 0x30, 0x34, 0x20, 0x4e, // den404.N
|
||||
0x6f, 0x74, 0x20, 0x46, 0x6f, 0x75, 0x6e, 0x64, // ot.Found
|
||||
0x35, 0x30, 0x30, 0x20, 0x49, 0x6e, 0x74, 0x65, // 500.Inte
|
||||
0x72, 0x6e, 0x61, 0x6c, 0x20, 0x53, 0x65, 0x72, // rnal.Ser
|
||||
0x76, 0x65, 0x72, 0x20, 0x45, 0x72, 0x72, 0x6f, // ver.Erro
|
||||
0x72, 0x35, 0x30, 0x31, 0x20, 0x4e, 0x6f, 0x74, // r501.Not
|
||||
0x20, 0x49, 0x6d, 0x70, 0x6c, 0x65, 0x6d, 0x65, // .Impleme
|
||||
0x6e, 0x74, 0x65, 0x64, 0x35, 0x30, 0x33, 0x20, // nted503.
|
||||
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20, // Service.
|
||||
0x55, 0x6e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, // Unavaila
|
||||
0x62, 0x6c, 0x65, 0x4a, 0x61, 0x6e, 0x20, 0x46, // bleJan.F
|
||||
0x65, 0x62, 0x20, 0x4d, 0x61, 0x72, 0x20, 0x41, // eb.Mar.A
|
||||
0x70, 0x72, 0x20, 0x4d, 0x61, 0x79, 0x20, 0x4a, // pr.May.J
|
||||
0x75, 0x6e, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x41, // un.Jul.A
|
||||
0x75, 0x67, 0x20, 0x53, 0x65, 0x70, 0x74, 0x20, // ug.Sept.
|
||||
0x4f, 0x63, 0x74, 0x20, 0x4e, 0x6f, 0x76, 0x20, // Oct.Nov.
|
||||
0x44, 0x65, 0x63, 0x20, 0x30, 0x30, 0x3a, 0x30, // Dec.00.0
|
||||
0x30, 0x3a, 0x30, 0x30, 0x20, 0x4d, 0x6f, 0x6e, // 0.00.Mon
|
||||
0x2c, 0x20, 0x54, 0x75, 0x65, 0x2c, 0x20, 0x57, // ..Tue..W
|
||||
0x65, 0x64, 0x2c, 0x20, 0x54, 0x68, 0x75, 0x2c, // ed..Thu.
|
||||
0x20, 0x46, 0x72, 0x69, 0x2c, 0x20, 0x53, 0x61, // .Fri..Sa
|
||||
0x74, 0x2c, 0x20, 0x53, 0x75, 0x6e, 0x2c, 0x20, // t..Sun..
|
||||
0x47, 0x4d, 0x54, 0x63, 0x68, 0x75, 0x6e, 0x6b, // GMTchunk
|
||||
0x65, 0x64, 0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, // ed.text.
|
||||
0x68, 0x74, 0x6d, 0x6c, 0x2c, 0x69, 0x6d, 0x61, // html.ima
|
||||
0x67, 0x65, 0x2f, 0x70, 0x6e, 0x67, 0x2c, 0x69, // ge.png.i
|
||||
0x6d, 0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x67, // mage.jpg
|
||||
0x2c, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f, 0x67, // .image.g
|
||||
0x69, 0x66, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, // if.appli
|
||||
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, // cation.x
|
||||
0x6d, 0x6c, 0x2c, 0x61, 0x70, 0x70, 0x6c, 0x69, // ml.appli
|
||||
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x78, // cation.x
|
||||
0x68, 0x74, 0x6d, 0x6c, 0x2b, 0x78, 0x6d, 0x6c, // html.xml
|
||||
0x2c, 0x74, 0x65, 0x78, 0x74, 0x2f, 0x70, 0x6c, // .text.pl
|
||||
0x61, 0x69, 0x6e, 0x2c, 0x74, 0x65, 0x78, 0x74, // ain.text
|
||||
0x2f, 0x6a, 0x61, 0x76, 0x61, 0x73, 0x63, 0x72, // .javascr
|
||||
0x69, 0x70, 0x74, 0x2c, 0x70, 0x75, 0x62, 0x6c, // ipt.publ
|
||||
0x69, 0x63, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, // icprivat
|
||||
0x65, 0x6d, 0x61, 0x78, 0x2d, 0x61, 0x67, 0x65, // emax-age
|
||||
0x3d, 0x67, 0x7a, 0x69, 0x70, 0x2c, 0x64, 0x65, // .gzip.de
|
||||
0x66, 0x6c, 0x61, 0x74, 0x65, 0x2c, 0x73, 0x64, // flate.sd
|
||||
0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65, // chcharse
|
||||
0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63, // t.utf-8c
|
||||
0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69, // harset.i
|
||||
0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d, // so-8859-
|
||||
0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a, // 1.utf-..
|
||||
0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e // .enq.0.
|
||||
])
|
||||
|
||||
dictionary[3.1] = dictionary[3]
|
||||
519
node_modules/spdy-transport/lib/spdy-transport/protocol/spdy/framer.js
generated
vendored
Normal file
519
node_modules/spdy-transport/lib/spdy-transport/protocol/spdy/framer.js
generated
vendored
Normal file
@ -0,0 +1,519 @@
|
||||
'use strict'
|
||||
|
||||
var transport = require('../../../spdy-transport')
|
||||
var constants = require('./').constants
|
||||
var base = transport.protocol.base
|
||||
var utils = base.utils
|
||||
|
||||
var assert = require('assert')
|
||||
var util = require('util')
|
||||
var Buffer = require('buffer').Buffer
|
||||
var WriteBuffer = require('wbuf')
|
||||
|
||||
var debug = require('debug')('spdy:framer')
|
||||
|
||||
function Framer (options) {
|
||||
base.Framer.call(this, options)
|
||||
}
|
||||
util.inherits(Framer, base.Framer)
|
||||
module.exports = Framer
|
||||
|
||||
Framer.create = function create (options) {
|
||||
return new Framer(options)
|
||||
}
|
||||
|
||||
Framer.prototype.setMaxFrameSize = function setMaxFrameSize (size) {
|
||||
// http2-only
|
||||
}
|
||||
|
||||
Framer.prototype.headersToDict = function headersToDict (headers,
|
||||
preprocess,
|
||||
callback) {
|
||||
function stringify (value) {
|
||||
if (value !== undefined) {
|
||||
if (Array.isArray(value)) {
|
||||
return value.join('\x00')
|
||||
} else if (typeof value === 'string') {
|
||||
return value
|
||||
} else {
|
||||
return value.toString()
|
||||
}
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
// Lower case of all headers keys
|
||||
var loweredHeaders = {}
|
||||
Object.keys(headers || {}).map(function (key) {
|
||||
loweredHeaders[key.toLowerCase()] = headers[key]
|
||||
})
|
||||
|
||||
// Allow outer code to add custom headers or remove something
|
||||
if (preprocess) { preprocess(loweredHeaders) }
|
||||
|
||||
// Transform object into kv pairs
|
||||
var size = this.version === 2 ? 2 : 4
|
||||
var len = size
|
||||
var pairs = Object.keys(loweredHeaders).filter(function (key) {
|
||||
var lkey = key.toLowerCase()
|
||||
|
||||
// Will be in `:host`
|
||||
if (lkey === 'host' && this.version >= 3) {
|
||||
return false
|
||||
}
|
||||
|
||||
return lkey !== 'connection' && lkey !== 'keep-alive' &&
|
||||
lkey !== 'proxy-connection' && lkey !== 'transfer-encoding'
|
||||
}, this).map(function (key) {
|
||||
var klen = Buffer.byteLength(key)
|
||||
var value = stringify(loweredHeaders[key])
|
||||
var vlen = Buffer.byteLength(value)
|
||||
|
||||
len += size * 2 + klen + vlen
|
||||
return [klen, key, vlen, value]
|
||||
})
|
||||
|
||||
var block = new WriteBuffer()
|
||||
block.reserve(len)
|
||||
|
||||
if (this.version === 2) {
|
||||
block.writeUInt16BE(pairs.length)
|
||||
} else {
|
||||
block.writeUInt32BE(pairs.length)
|
||||
}
|
||||
|
||||
pairs.forEach(function (pair) {
|
||||
// Write key length
|
||||
if (this.version === 2) {
|
||||
block.writeUInt16BE(pair[0])
|
||||
} else {
|
||||
block.writeUInt32BE(pair[0])
|
||||
}
|
||||
|
||||
// Write key
|
||||
block.write(pair[1])
|
||||
|
||||
// Write value length
|
||||
if (this.version === 2) {
|
||||
block.writeUInt16BE(pair[2])
|
||||
} else {
|
||||
block.writeUInt32BE(pair[2])
|
||||
}
|
||||
// Write value
|
||||
block.write(pair[3])
|
||||
}, this)
|
||||
|
||||
assert(this.compress !== null, 'Framer version not initialized')
|
||||
this.compress.write(block.render(), callback)
|
||||
}
|
||||
|
||||
Framer.prototype._frame = function _frame (frame, body, callback) {
|
||||
if (!this.version) {
|
||||
this.on('version', function () {
|
||||
this._frame(frame, body, callback)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
debug('id=%d type=%s', frame.id, frame.type)
|
||||
|
||||
var buffer = new WriteBuffer()
|
||||
|
||||
buffer.writeUInt16BE(0x8000 | this.version)
|
||||
buffer.writeUInt16BE(constants.frameType[frame.type])
|
||||
buffer.writeUInt8(frame.flags)
|
||||
var len = buffer.skip(3)
|
||||
|
||||
body(buffer)
|
||||
|
||||
var frameSize = buffer.size - constants.FRAME_HEADER_SIZE
|
||||
len.writeUInt24BE(frameSize)
|
||||
|
||||
var chunks = buffer.render()
|
||||
var toWrite = {
|
||||
stream: frame.id,
|
||||
priority: false,
|
||||
chunks: chunks,
|
||||
callback: callback
|
||||
}
|
||||
|
||||
this._resetTimeout()
|
||||
this.schedule(toWrite)
|
||||
|
||||
return chunks
|
||||
}
|
||||
|
||||
Framer.prototype._synFrame = function _synFrame (frame, callback) {
|
||||
var self = this
|
||||
|
||||
if (!frame.path) {
|
||||
throw new Error('`path` is required frame argument')
|
||||
}
|
||||
|
||||
function preprocess (headers) {
|
||||
var method = frame.method || base.constants.DEFAULT_METHOD
|
||||
var version = frame.version || 'HTTP/1.1'
|
||||
var scheme = frame.scheme || 'https'
|
||||
var host = frame.host ||
|
||||
(frame.headers && frame.headers.host) ||
|
||||
base.constants.DEFAULT_HOST
|
||||
|
||||
if (self.version === 2) {
|
||||
headers.method = method
|
||||
headers.version = version
|
||||
headers.url = frame.path
|
||||
headers.scheme = scheme
|
||||
headers.host = host
|
||||
if (frame.status) {
|
||||
headers.status = frame.status
|
||||
}
|
||||
} else {
|
||||
headers[':method'] = method
|
||||
headers[':version'] = version
|
||||
headers[':path'] = frame.path
|
||||
headers[':scheme'] = scheme
|
||||
headers[':host'] = host
|
||||
if (frame.status) { headers[':status'] = frame.status }
|
||||
}
|
||||
}
|
||||
|
||||
this.headersToDict(frame.headers, preprocess, function (err, chunks) {
|
||||
if (err) {
|
||||
if (callback) {
|
||||
return callback(err)
|
||||
} else {
|
||||
return self.emit('error', err)
|
||||
}
|
||||
}
|
||||
|
||||
self._frame({
|
||||
type: 'SYN_STREAM',
|
||||
id: frame.id,
|
||||
flags: frame.fin ? constants.flags.FLAG_FIN : 0
|
||||
}, function (buf) {
|
||||
buf.reserve(10)
|
||||
|
||||
buf.writeUInt32BE(frame.id & 0x7fffffff)
|
||||
buf.writeUInt32BE(frame.associated & 0x7fffffff)
|
||||
|
||||
var weight = (frame.priority && frame.priority.weight) ||
|
||||
constants.DEFAULT_WEIGHT
|
||||
|
||||
// We only have 3 bits for priority in SPDY, try to fit it into this
|
||||
var priority = utils.weightToPriority(weight)
|
||||
buf.writeUInt8(priority << 5)
|
||||
|
||||
// CREDENTIALS slot
|
||||
buf.writeUInt8(0)
|
||||
|
||||
for (var i = 0; i < chunks.length; i++) {
|
||||
buf.copyFrom(chunks[i])
|
||||
}
|
||||
}, callback)
|
||||
})
|
||||
}
|
||||
|
||||
Framer.prototype.requestFrame = function requestFrame (frame, callback) {
|
||||
this._synFrame({
|
||||
id: frame.id,
|
||||
fin: frame.fin,
|
||||
associated: 0,
|
||||
method: frame.method,
|
||||
version: frame.version,
|
||||
scheme: frame.scheme,
|
||||
host: frame.host,
|
||||
path: frame.path,
|
||||
priority: frame.priority,
|
||||
headers: frame.headers
|
||||
}, callback)
|
||||
}
|
||||
|
||||
Framer.prototype.responseFrame = function responseFrame (frame, callback) {
|
||||
var self = this
|
||||
|
||||
var reason = frame.reason
|
||||
if (!reason) {
|
||||
reason = constants.statusReason[frame.status]
|
||||
}
|
||||
|
||||
function preprocess (headers) {
|
||||
if (self.version === 2) {
|
||||
headers.status = frame.status + ' ' + reason
|
||||
headers.version = 'HTTP/1.1'
|
||||
} else {
|
||||
headers[':status'] = frame.status + ' ' + reason
|
||||
headers[':version'] = 'HTTP/1.1'
|
||||
}
|
||||
}
|
||||
|
||||
this.headersToDict(frame.headers, preprocess, function (err, chunks) {
|
||||
if (err) {
|
||||
if (callback) {
|
||||
return callback(err)
|
||||
} else {
|
||||
return self.emit('error', err)
|
||||
}
|
||||
}
|
||||
|
||||
self._frame({
|
||||
type: 'SYN_REPLY',
|
||||
id: frame.id,
|
||||
flags: 0
|
||||
}, function (buf) {
|
||||
buf.reserve(self.version === 2 ? 6 : 4)
|
||||
|
||||
buf.writeUInt32BE(frame.id & 0x7fffffff)
|
||||
|
||||
// Unused data
|
||||
if (self.version === 2) {
|
||||
buf.writeUInt16BE(0)
|
||||
}
|
||||
|
||||
for (var i = 0; i < chunks.length; i++) {
|
||||
buf.copyFrom(chunks[i])
|
||||
}
|
||||
}, callback)
|
||||
})
|
||||
}
|
||||
|
||||
Framer.prototype.pushFrame = function pushFrame (frame, callback) {
|
||||
var self = this
|
||||
|
||||
this._checkPush(function (err) {
|
||||
if (err) { return callback(err) }
|
||||
|
||||
self._synFrame({
|
||||
id: frame.promisedId,
|
||||
associated: frame.id,
|
||||
method: frame.method,
|
||||
status: frame.status || 200,
|
||||
version: frame.version,
|
||||
scheme: frame.scheme,
|
||||
host: frame.host,
|
||||
path: frame.path,
|
||||
priority: frame.priority,
|
||||
|
||||
// Merge everything together, there is no difference in SPDY protocol
|
||||
headers: Object.assign(Object.assign({}, frame.headers), frame.response)
|
||||
}, callback)
|
||||
})
|
||||
}
|
||||
|
||||
Framer.prototype.headersFrame = function headersFrame (frame, callback) {
|
||||
var self = this
|
||||
|
||||
this.headersToDict(frame.headers, null, function (err, chunks) {
|
||||
if (err) {
|
||||
if (callback) { return callback(err) } else {
|
||||
return self.emit('error', err)
|
||||
}
|
||||
}
|
||||
|
||||
self._frame({
|
||||
type: 'HEADERS',
|
||||
id: frame.id,
|
||||
priority: false,
|
||||
flags: 0
|
||||
}, function (buf) {
|
||||
buf.reserve(4 + (self.version === 2 ? 2 : 0))
|
||||
buf.writeUInt32BE(frame.id & 0x7fffffff)
|
||||
|
||||
// Unused data
|
||||
if (self.version === 2) { buf.writeUInt16BE(0) }
|
||||
|
||||
for (var i = 0; i < chunks.length; i++) {
|
||||
buf.copyFrom(chunks[i])
|
||||
}
|
||||
}, callback)
|
||||
})
|
||||
}
|
||||
|
||||
Framer.prototype.dataFrame = function dataFrame (frame, callback) {
|
||||
if (!this.version) {
|
||||
return this.on('version', function () {
|
||||
this.dataFrame(frame, callback)
|
||||
})
|
||||
}
|
||||
|
||||
debug('id=%d type=DATA', frame.id)
|
||||
|
||||
var buffer = new WriteBuffer()
|
||||
buffer.reserve(8 + frame.data.length)
|
||||
|
||||
buffer.writeUInt32BE(frame.id & 0x7fffffff)
|
||||
buffer.writeUInt8(frame.fin ? 0x01 : 0x0)
|
||||
buffer.writeUInt24BE(frame.data.length)
|
||||
buffer.copyFrom(frame.data)
|
||||
|
||||
var chunks = buffer.render()
|
||||
var toWrite = {
|
||||
stream: frame.id,
|
||||
priority: frame.priority,
|
||||
chunks: chunks,
|
||||
callback: callback
|
||||
}
|
||||
|
||||
var self = this
|
||||
this._resetTimeout()
|
||||
|
||||
var bypass = this.version < 3.1
|
||||
this.window.send.update(-frame.data.length, bypass ? undefined : function () {
|
||||
self._resetTimeout()
|
||||
self.schedule(toWrite)
|
||||
})
|
||||
|
||||
if (bypass) {
|
||||
this._resetTimeout()
|
||||
this.schedule(toWrite)
|
||||
}
|
||||
}
|
||||
|
||||
Framer.prototype.pingFrame = function pingFrame (frame, callback) {
|
||||
this._frame({
|
||||
type: 'PING',
|
||||
id: 0,
|
||||
flags: 0
|
||||
}, function (buf, callback) {
|
||||
buf.reserve(4)
|
||||
|
||||
var opaque = frame.opaque
|
||||
buf.writeUInt32BE(opaque.readUInt32BE(opaque.length - 4, true))
|
||||
}, callback)
|
||||
}
|
||||
|
||||
Framer.prototype.rstFrame = function rstFrame (frame, callback) {
|
||||
this._frame({
|
||||
type: 'RST_STREAM',
|
||||
id: frame.id,
|
||||
flags: 0
|
||||
}, function (buf) {
|
||||
buf.reserve(8)
|
||||
|
||||
// Stream ID
|
||||
buf.writeUInt32BE(frame.id & 0x7fffffff)
|
||||
// Status Code
|
||||
buf.writeUInt32BE(constants.error[frame.code])
|
||||
|
||||
// Extra debugging information
|
||||
if (frame.extra) {
|
||||
buf.write(frame.extra)
|
||||
}
|
||||
}, callback)
|
||||
}
|
||||
|
||||
Framer.prototype.prefaceFrame = function prefaceFrame () {
|
||||
}
|
||||
|
||||
Framer.prototype.settingsFrame = function settingsFrame (options, callback) {
|
||||
var self = this
|
||||
|
||||
var key = this.version + '/' + JSON.stringify(options)
|
||||
|
||||
var settings = Framer.settingsCache[key]
|
||||
if (settings) {
|
||||
debug('cached settings')
|
||||
this._resetTimeout()
|
||||
this.schedule({
|
||||
stream: 0,
|
||||
priority: false,
|
||||
chunks: settings,
|
||||
callback: callback
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var params = []
|
||||
for (var i = 0; i < constants.settingsIndex.length; i++) {
|
||||
var name = constants.settingsIndex[i]
|
||||
if (!name) { continue }
|
||||
|
||||
// value: Infinity
|
||||
if (!isFinite(options[name])) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (options[name] !== undefined) {
|
||||
params.push({ key: i, value: options[name] })
|
||||
}
|
||||
}
|
||||
|
||||
var frame = this._frame({
|
||||
type: 'SETTINGS',
|
||||
id: 0,
|
||||
flags: 0
|
||||
}, function (buf) {
|
||||
buf.reserve(4 + 8 * params.length)
|
||||
|
||||
// Count of entries
|
||||
buf.writeUInt32BE(params.length)
|
||||
|
||||
params.forEach(function (param) {
|
||||
var flag = constants.settings.FLAG_SETTINGS_PERSIST_VALUE << 24
|
||||
|
||||
if (self.version === 2) {
|
||||
buf.writeUInt32LE(flag | param.key)
|
||||
} else { buf.writeUInt32BE(flag | param.key) }
|
||||
buf.writeUInt32BE(param.value & 0x7fffffff)
|
||||
})
|
||||
}, callback)
|
||||
|
||||
Framer.settingsCache[key] = frame
|
||||
}
|
||||
Framer.settingsCache = {}
|
||||
|
||||
Framer.prototype.ackSettingsFrame = function ackSettingsFrame (callback) {
|
||||
if (callback) {
|
||||
process.nextTick(callback)
|
||||
}
|
||||
}
|
||||
|
||||
Framer.prototype.windowUpdateFrame = function windowUpdateFrame (frame,
|
||||
callback) {
|
||||
this._frame({
|
||||
type: 'WINDOW_UPDATE',
|
||||
id: frame.id,
|
||||
flags: 0
|
||||
}, function (buf) {
|
||||
buf.reserve(8)
|
||||
|
||||
// ID
|
||||
buf.writeUInt32BE(frame.id & 0x7fffffff)
|
||||
|
||||
// Delta
|
||||
buf.writeInt32BE(frame.delta)
|
||||
}, callback)
|
||||
}
|
||||
|
||||
Framer.prototype.goawayFrame = function goawayFrame (frame, callback) {
|
||||
this._frame({
|
||||
type: 'GOAWAY',
|
||||
id: 0,
|
||||
flags: 0
|
||||
}, function (buf) {
|
||||
buf.reserve(8)
|
||||
|
||||
// Last-good-stream-ID
|
||||
buf.writeUInt32BE(frame.lastId & 0x7fffffff)
|
||||
// Status
|
||||
buf.writeUInt32BE(constants.goaway[frame.code])
|
||||
}, callback)
|
||||
}
|
||||
|
||||
Framer.prototype.priorityFrame = function priorityFrame (frame, callback) {
|
||||
// No such thing in SPDY
|
||||
if (callback) {
|
||||
process.nextTick(callback)
|
||||
}
|
||||
}
|
||||
|
||||
Framer.prototype.xForwardedFor = function xForwardedFor (frame, callback) {
|
||||
this._frame({
|
||||
type: 'X_FORWARDED_FOR',
|
||||
id: 0,
|
||||
flags: 0
|
||||
}, function (buf) {
|
||||
buf.writeUInt32BE(Buffer.byteLength(frame.host))
|
||||
buf.write(frame.host)
|
||||
}, callback)
|
||||
}
|
||||
9
node_modules/spdy-transport/lib/spdy-transport/protocol/spdy/index.js
generated
vendored
Normal file
9
node_modules/spdy-transport/lib/spdy-transport/protocol/spdy/index.js
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
'use strict'
|
||||
|
||||
exports.name = 'spdy'
|
||||
|
||||
exports.dictionary = require('./dictionary')
|
||||
exports.constants = require('./constants')
|
||||
exports.parser = require('./parser')
|
||||
exports.framer = require('./framer')
|
||||
exports.compressionPool = require('./zlib-pool')
|
||||
485
node_modules/spdy-transport/lib/spdy-transport/protocol/spdy/parser.js
generated
vendored
Normal file
485
node_modules/spdy-transport/lib/spdy-transport/protocol/spdy/parser.js
generated
vendored
Normal file
@ -0,0 +1,485 @@
|
||||
'use strict'
|
||||
|
||||
var parser = exports
|
||||
|
||||
var transport = require('../../../spdy-transport')
|
||||
var base = transport.protocol.base
|
||||
var utils = base.utils
|
||||
var constants = require('./constants')
|
||||
|
||||
var assert = require('assert')
|
||||
var util = require('util')
|
||||
var OffsetBuffer = require('obuf')
|
||||
|
||||
function Parser (options) {
|
||||
base.Parser.call(this, options)
|
||||
|
||||
this.isServer = options.isServer
|
||||
this.waiting = constants.FRAME_HEADER_SIZE
|
||||
this.state = 'frame-head'
|
||||
this.pendingHeader = null
|
||||
}
|
||||
util.inherits(Parser, base.Parser)
|
||||
|
||||
parser.create = function create (options) {
|
||||
return new Parser(options)
|
||||
}
|
||||
|
||||
Parser.prototype.setMaxFrameSize = function setMaxFrameSize (size) {
|
||||
// http2-only
|
||||
}
|
||||
|
||||
Parser.prototype.setMaxHeaderListSize = function setMaxHeaderListSize (size) {
|
||||
// http2-only
|
||||
}
|
||||
|
||||
// Only for testing
|
||||
Parser.prototype.skipPreface = function skipPreface () {
|
||||
}
|
||||
|
||||
Parser.prototype.execute = function execute (buffer, callback) {
|
||||
if (this.state === 'frame-head') { return this.onFrameHead(buffer, callback) }
|
||||
|
||||
assert(this.state === 'frame-body' && this.pendingHeader !== null)
|
||||
|
||||
var self = this
|
||||
var header = this.pendingHeader
|
||||
this.pendingHeader = null
|
||||
|
||||
this.onFrameBody(header, buffer, function (err, frame) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
self.state = 'frame-head'
|
||||
self.waiting = constants.FRAME_HEADER_SIZE
|
||||
self.partial = false
|
||||
callback(null, frame)
|
||||
})
|
||||
}
|
||||
|
||||
Parser.prototype.executePartial = function executePartial (buffer, callback) {
|
||||
var header = this.pendingHeader
|
||||
|
||||
if (this.window) {
|
||||
this.window.recv.update(-buffer.size)
|
||||
}
|
||||
|
||||
// DATA frame
|
||||
callback(null, {
|
||||
type: 'DATA',
|
||||
id: header.id,
|
||||
|
||||
// Partial DATA can't be FIN
|
||||
fin: false,
|
||||
data: buffer.take(buffer.size)
|
||||
})
|
||||
}
|
||||
|
||||
Parser.prototype.onFrameHead = function onFrameHead (buffer, callback) {
|
||||
var header = {
|
||||
control: (buffer.peekUInt8() & 0x80) === 0x80,
|
||||
version: null,
|
||||
type: null,
|
||||
id: null,
|
||||
flags: null,
|
||||
length: null
|
||||
}
|
||||
|
||||
if (header.control) {
|
||||
header.version = buffer.readUInt16BE() & 0x7fff
|
||||
header.type = buffer.readUInt16BE()
|
||||
} else {
|
||||
header.id = buffer.readUInt32BE(0) & 0x7fffffff
|
||||
}
|
||||
header.flags = buffer.readUInt8()
|
||||
header.length = buffer.readUInt24BE()
|
||||
|
||||
if (this.version === null && header.control) {
|
||||
// TODO(indutny): do ProtocolError here and in the rest of errors
|
||||
if (header.version !== 2 && header.version !== 3) {
|
||||
return callback(new Error('Unsupported SPDY version: ' + header.version))
|
||||
}
|
||||
this.setVersion(header.version)
|
||||
}
|
||||
|
||||
this.state = 'frame-body'
|
||||
this.waiting = header.length
|
||||
this.pendingHeader = header
|
||||
this.partial = !header.control
|
||||
|
||||
callback(null, null)
|
||||
}
|
||||
|
||||
Parser.prototype.onFrameBody = function onFrameBody (header, buffer, callback) {
|
||||
// Data frame
|
||||
if (!header.control) {
|
||||
// Count received bytes
|
||||
if (this.window) {
|
||||
this.window.recv.update(-buffer.size)
|
||||
}
|
||||
|
||||
// No support for compressed DATA
|
||||
if ((header.flags & constants.flags.FLAG_COMPRESSED) !== 0) {
|
||||
return callback(new Error('DATA compression not supported'))
|
||||
}
|
||||
|
||||
if (header.id === 0) {
|
||||
return callback(this.error(constants.error.PROTOCOL_ERROR,
|
||||
'Invalid stream id for DATA'))
|
||||
}
|
||||
|
||||
return callback(null, {
|
||||
type: 'DATA',
|
||||
id: header.id,
|
||||
fin: (header.flags & constants.flags.FLAG_FIN) !== 0,
|
||||
data: buffer.take(buffer.size)
|
||||
})
|
||||
}
|
||||
|
||||
if (header.type === 0x01 || header.type === 0x02) { // SYN_STREAM or SYN_REPLY
|
||||
this.onSynHeadFrame(header.type, header.flags, buffer, callback)
|
||||
} else if (header.type === 0x03) { // RST_STREAM
|
||||
this.onRSTFrame(buffer, callback)
|
||||
} else if (header.type === 0x04) { // SETTINGS
|
||||
this.onSettingsFrame(buffer, callback)
|
||||
} else if (header.type === 0x05) {
|
||||
callback(null, { type: 'NOOP' })
|
||||
} else if (header.type === 0x06) { // PING
|
||||
this.onPingFrame(buffer, callback)
|
||||
} else if (header.type === 0x07) { // GOAWAY
|
||||
this.onGoawayFrame(buffer, callback)
|
||||
} else if (header.type === 0x08) { // HEADERS
|
||||
this.onHeaderFrames(buffer, callback)
|
||||
} else if (header.type === 0x09) { // WINDOW_UPDATE
|
||||
this.onWindowUpdateFrame(buffer, callback)
|
||||
} else if (header.type === 0xf000) { // X-FORWARDED
|
||||
this.onXForwardedFrame(buffer, callback)
|
||||
} else {
|
||||
callback(null, { type: 'unknown: ' + header.type })
|
||||
}
|
||||
}
|
||||
|
||||
Parser.prototype._filterHeader = function _filterHeader (headers, name) {
|
||||
var res = {}
|
||||
var keys = Object.keys(headers)
|
||||
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var key = keys[i]
|
||||
if (key !== name) {
|
||||
res[key] = headers[key]
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
Parser.prototype.onSynHeadFrame = function onSynHeadFrame (type,
|
||||
flags,
|
||||
body,
|
||||
callback) {
|
||||
var self = this
|
||||
var stream = type === 0x01
|
||||
var offset = stream ? 10 : this.version === 2 ? 6 : 4
|
||||
|
||||
if (!body.has(offset)) {
|
||||
return callback(new Error('SynHead OOB'))
|
||||
}
|
||||
|
||||
var head = body.clone(offset)
|
||||
body.skip(offset)
|
||||
this.parseKVs(body, function (err, headers) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
if (stream &&
|
||||
(!headers[':method'] || !headers[':path'])) {
|
||||
return callback(new Error('Missing `:method` and/or `:path` header'))
|
||||
}
|
||||
|
||||
var id = head.readUInt32BE() & 0x7fffffff
|
||||
|
||||
if (id === 0) {
|
||||
return callback(self.error(constants.error.PROTOCOL_ERROR,
|
||||
'Invalid stream id for HEADERS'))
|
||||
}
|
||||
|
||||
var associated = stream ? head.readUInt32BE() & 0x7fffffff : 0
|
||||
var priority = stream
|
||||
? head.readUInt8() >> 5
|
||||
: utils.weightToPriority(constants.DEFAULT_WEIGHT)
|
||||
var fin = (flags & constants.flags.FLAG_FIN) !== 0
|
||||
var unidir = (flags & constants.flags.FLAG_UNIDIRECTIONAL) !== 0
|
||||
var path = headers[':path']
|
||||
|
||||
var isPush = stream && associated !== 0
|
||||
|
||||
var weight = utils.priorityToWeight(priority)
|
||||
var priorityInfo = {
|
||||
weight: weight,
|
||||
exclusive: false,
|
||||
parent: 0
|
||||
}
|
||||
|
||||
if (!isPush) {
|
||||
callback(null, {
|
||||
type: 'HEADERS',
|
||||
id: id,
|
||||
priority: priorityInfo,
|
||||
fin: fin,
|
||||
writable: !unidir,
|
||||
headers: headers,
|
||||
path: path
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (stream && !headers[':status']) {
|
||||
return callback(new Error('Missing `:status` header'))
|
||||
}
|
||||
|
||||
var filteredHeaders = self._filterHeader(headers, ':status')
|
||||
|
||||
callback(null, [ {
|
||||
type: 'PUSH_PROMISE',
|
||||
id: associated,
|
||||
fin: false,
|
||||
promisedId: id,
|
||||
headers: filteredHeaders,
|
||||
path: path
|
||||
}, {
|
||||
type: 'HEADERS',
|
||||
id: id,
|
||||
fin: fin,
|
||||
priority: priorityInfo,
|
||||
writable: true,
|
||||
path: undefined,
|
||||
headers: {
|
||||
':status': headers[':status']
|
||||
}
|
||||
}])
|
||||
})
|
||||
}
|
||||
|
||||
Parser.prototype.onHeaderFrames = function onHeaderFrames (body, callback) {
|
||||
var offset = this.version === 2 ? 6 : 4
|
||||
if (!body.has(offset)) {
|
||||
return callback(new Error('HEADERS OOB'))
|
||||
}
|
||||
|
||||
var streamId = body.readUInt32BE() & 0x7fffffff
|
||||
if (this.version === 2) { body.skip(2) }
|
||||
|
||||
this.parseKVs(body, function (err, headers) {
|
||||
if (err) { return callback(err) }
|
||||
|
||||
callback(null, {
|
||||
type: 'HEADERS',
|
||||
priority: {
|
||||
parent: 0,
|
||||
exclusive: false,
|
||||
weight: constants.DEFAULT_WEIGHT
|
||||
},
|
||||
id: streamId,
|
||||
fin: false,
|
||||
writable: true,
|
||||
path: undefined,
|
||||
headers: headers
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Parser.prototype.parseKVs = function parseKVs (buffer, callback) {
|
||||
var self = this
|
||||
|
||||
this.decompress.write(buffer.toChunks(), function (err, chunks) {
|
||||
if (err) {
|
||||
return callback(err)
|
||||
}
|
||||
|
||||
var buffer = new OffsetBuffer()
|
||||
for (var i = 0; i < chunks.length; i++) {
|
||||
buffer.push(chunks[i])
|
||||
}
|
||||
|
||||
var size = self.version === 2 ? 2 : 4
|
||||
if (!buffer.has(size)) { return callback(new Error('KV OOB')) }
|
||||
|
||||
var count = self.version === 2
|
||||
? buffer.readUInt16BE()
|
||||
: buffer.readUInt32BE()
|
||||
|
||||
var headers = {}
|
||||
|
||||
function readString () {
|
||||
if (!buffer.has(size)) { return null }
|
||||
var len = self.version === 2
|
||||
? buffer.readUInt16BE()
|
||||
: buffer.readUInt32BE()
|
||||
|
||||
if (!buffer.has(len)) { return null }
|
||||
|
||||
var value = buffer.take(len)
|
||||
return value.toString()
|
||||
}
|
||||
|
||||
while (count > 0) {
|
||||
var key = readString()
|
||||
var value = readString()
|
||||
|
||||
if (key === null || value === null) {
|
||||
return callback(new Error('Headers OOB'))
|
||||
}
|
||||
|
||||
if (self.version < 3) {
|
||||
var isInternal = /^(method|version|url|host|scheme|status)$/.test(key)
|
||||
if (key === 'url') {
|
||||
key = 'path'
|
||||
}
|
||||
if (isInternal) {
|
||||
key = ':' + key
|
||||
}
|
||||
}
|
||||
|
||||
// Compatibility with HTTP2
|
||||
if (key === ':status') {
|
||||
value = value.split(/ /g, 2)[0]
|
||||
}
|
||||
|
||||
count--
|
||||
if (key === ':host') {
|
||||
key = ':authority'
|
||||
}
|
||||
|
||||
// Skip version, not present in HTTP2
|
||||
if (key === ':version') {
|
||||
continue
|
||||
}
|
||||
|
||||
value = value.split(/\0/g)
|
||||
for (var j = 0; j < value.length; j++) {
|
||||
utils.addHeaderLine(key, value[j], headers)
|
||||
}
|
||||
}
|
||||
|
||||
callback(null, headers)
|
||||
})
|
||||
}
|
||||
|
||||
Parser.prototype.onRSTFrame = function onRSTFrame (body, callback) {
|
||||
if (!body.has(8)) { return callback(new Error('RST OOB')) }
|
||||
|
||||
var frame = {
|
||||
type: 'RST',
|
||||
id: body.readUInt32BE() & 0x7fffffff,
|
||||
code: constants.errorByCode[body.readUInt32BE()]
|
||||
}
|
||||
|
||||
if (frame.id === 0) {
|
||||
return callback(this.error(constants.error.PROTOCOL_ERROR,
|
||||
'Invalid stream id for RST'))
|
||||
}
|
||||
|
||||
if (body.size !== 0) {
|
||||
frame.extra = body.take(body.size)
|
||||
}
|
||||
callback(null, frame)
|
||||
}
|
||||
|
||||
Parser.prototype.onSettingsFrame = function onSettingsFrame (body, callback) {
|
||||
if (!body.has(4)) {
|
||||
return callback(new Error('SETTINGS OOB'))
|
||||
}
|
||||
|
||||
var settings = {}
|
||||
var number = body.readUInt32BE()
|
||||
var idMap = {
|
||||
1: 'upload_bandwidth',
|
||||
2: 'download_bandwidth',
|
||||
3: 'round_trip_time',
|
||||
4: 'max_concurrent_streams',
|
||||
5: 'current_cwnd',
|
||||
6: 'download_retrans_rate',
|
||||
7: 'initial_window_size',
|
||||
8: 'client_certificate_vector_size'
|
||||
}
|
||||
|
||||
if (!body.has(number * 8)) {
|
||||
return callback(new Error('SETTINGS OOB#2'))
|
||||
}
|
||||
|
||||
for (var i = 0; i < number; i++) {
|
||||
var id = this.version === 2
|
||||
? body.readUInt32LE()
|
||||
: body.readUInt32BE()
|
||||
|
||||
var flags = (id >> 24) & 0xff
|
||||
id = id & 0xffffff
|
||||
|
||||
// Skip persisted settings
|
||||
if (flags & 0x2) { continue }
|
||||
|
||||
var name = idMap[id]
|
||||
|
||||
settings[name] = body.readUInt32BE()
|
||||
}
|
||||
|
||||
callback(null, {
|
||||
type: 'SETTINGS',
|
||||
settings: settings
|
||||
})
|
||||
}
|
||||
|
||||
Parser.prototype.onPingFrame = function onPingFrame (body, callback) {
|
||||
if (!body.has(4)) {
|
||||
return callback(new Error('PING OOB'))
|
||||
}
|
||||
|
||||
var isServer = this.isServer
|
||||
var opaque = body.clone(body.size).take(body.size)
|
||||
var id = body.readUInt32BE()
|
||||
var ack = isServer ? (id % 2 === 0) : (id % 2 === 1)
|
||||
|
||||
callback(null, { type: 'PING', opaque: opaque, ack: ack })
|
||||
}
|
||||
|
||||
Parser.prototype.onGoawayFrame = function onGoawayFrame (body, callback) {
|
||||
if (!body.has(8)) {
|
||||
return callback(new Error('GOAWAY OOB'))
|
||||
}
|
||||
|
||||
callback(null, {
|
||||
type: 'GOAWAY',
|
||||
lastId: body.readUInt32BE() & 0x7fffffff,
|
||||
code: constants.goawayByCode[body.readUInt32BE()]
|
||||
})
|
||||
}
|
||||
|
||||
Parser.prototype.onWindowUpdateFrame = function onWindowUpdateFrame (body,
|
||||
callback) {
|
||||
if (!body.has(8)) {
|
||||
return callback(new Error('WINDOW_UPDATE OOB'))
|
||||
}
|
||||
|
||||
callback(null, {
|
||||
type: 'WINDOW_UPDATE',
|
||||
id: body.readUInt32BE() & 0x7fffffff,
|
||||
delta: body.readInt32BE()
|
||||
})
|
||||
}
|
||||
|
||||
Parser.prototype.onXForwardedFrame = function onXForwardedFrame (body,
|
||||
callback) {
|
||||
if (!body.has(4)) {
|
||||
return callback(new Error('X_FORWARDED OOB'))
|
||||
}
|
||||
|
||||
var len = body.readUInt32BE()
|
||||
if (!body.has(len)) { return callback(new Error('X_FORWARDED host length OOB')) }
|
||||
|
||||
callback(null, {
|
||||
type: 'X_FORWARDED_FOR',
|
||||
host: body.take(len).toString()
|
||||
})
|
||||
}
|
||||
65
node_modules/spdy-transport/lib/spdy-transport/protocol/spdy/zlib-pool.js
generated
vendored
Normal file
65
node_modules/spdy-transport/lib/spdy-transport/protocol/spdy/zlib-pool.js
generated
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
'use strict'
|
||||
|
||||
var zlibpool = exports
|
||||
var zlib = require('zlib')
|
||||
|
||||
var transport = require('../../../spdy-transport')
|
||||
|
||||
// TODO(indutny): think about it, why has it always been Z_SYNC_FLUSH here.
|
||||
// It should be possible to manually flush stuff after the write instead
|
||||
function createDeflate (version, compression) {
|
||||
var deflate = zlib.createDeflate({
|
||||
dictionary: transport.protocol.spdy.dictionary[version],
|
||||
flush: zlib.Z_SYNC_FLUSH,
|
||||
windowBits: 11,
|
||||
level: compression ? zlib.Z_DEFAULT_COMPRESSION : zlib.Z_NO_COMPRESSION
|
||||
})
|
||||
|
||||
// For node.js v0.8
|
||||
deflate._flush = zlib.Z_SYNC_FLUSH
|
||||
|
||||
return deflate
|
||||
}
|
||||
|
||||
function createInflate (version) {
|
||||
var inflate = zlib.createInflate({
|
||||
dictionary: transport.protocol.spdy.dictionary[version],
|
||||
flush: zlib.Z_SYNC_FLUSH
|
||||
})
|
||||
|
||||
// For node.js v0.8
|
||||
inflate._flush = zlib.Z_SYNC_FLUSH
|
||||
|
||||
return inflate
|
||||
}
|
||||
|
||||
function Pool (compression) {
|
||||
this.compression = compression
|
||||
this.pool = {
|
||||
2: [],
|
||||
3: [],
|
||||
3.1: []
|
||||
}
|
||||
}
|
||||
|
||||
zlibpool.create = function create (compression) {
|
||||
return new Pool(compression)
|
||||
}
|
||||
|
||||
Pool.prototype.get = function get (version) {
|
||||
if (this.pool[version].length > 0) {
|
||||
return this.pool[version].pop()
|
||||
} else {
|
||||
var id = version
|
||||
|
||||
return {
|
||||
version: version,
|
||||
compress: createDeflate(id, this.compression),
|
||||
decompress: createInflate(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Pool.prototype.put = function put (pair) {
|
||||
this.pool[pair.version].push(pair)
|
||||
}
|
||||
710
node_modules/spdy-transport/lib/spdy-transport/stream.js
generated
vendored
Normal file
710
node_modules/spdy-transport/lib/spdy-transport/stream.js
generated
vendored
Normal file
@ -0,0 +1,710 @@
|
||||
'use strict'
|
||||
|
||||
var transport = require('../spdy-transport')
|
||||
|
||||
var assert = require('assert')
|
||||
var util = require('util')
|
||||
|
||||
var debug = {
|
||||
client: require('debug')('spdy:stream:client'),
|
||||
server: require('debug')('spdy:stream:server')
|
||||
}
|
||||
var Duplex = require('readable-stream').Duplex
|
||||
|
||||
function Stream (connection, options) {
|
||||
Duplex.call(this)
|
||||
|
||||
var connectionState = connection._spdyState
|
||||
|
||||
var state = {}
|
||||
this._spdyState = state
|
||||
|
||||
this.id = options.id
|
||||
this.method = options.method
|
||||
this.path = options.path
|
||||
this.host = options.host
|
||||
this.headers = options.headers || {}
|
||||
this.connection = connection
|
||||
this.parent = options.parent || null
|
||||
|
||||
state.socket = null
|
||||
state.protocol = connectionState.protocol
|
||||
state.constants = state.protocol.constants
|
||||
|
||||
// See _initPriority()
|
||||
state.priority = null
|
||||
|
||||
state.version = this.connection.getVersion()
|
||||
state.isServer = this.connection.isServer()
|
||||
state.debug = state.isServer ? debug.server : debug.client
|
||||
|
||||
state.framer = connectionState.framer
|
||||
state.parser = connectionState.parser
|
||||
|
||||
state.request = options.request
|
||||
state.needResponse = options.request
|
||||
state.window = connectionState.streamWindow.clone(options.id)
|
||||
state.sessionWindow = connectionState.window
|
||||
state.maxChunk = connectionState.maxChunk
|
||||
|
||||
// Can't send incoming request
|
||||
// (See `.send()` method)
|
||||
state.sent = !state.request
|
||||
|
||||
state.readable = options.readable !== false
|
||||
state.writable = options.writable !== false
|
||||
|
||||
state.aborted = false
|
||||
|
||||
state.corked = 0
|
||||
state.corkQueue = []
|
||||
|
||||
state.timeout = new transport.utils.Timeout(this)
|
||||
|
||||
this.on('finish', this._onFinish)
|
||||
this.on('end', this._onEnd)
|
||||
|
||||
var self = this
|
||||
function _onWindowOverflow () {
|
||||
self._onWindowOverflow()
|
||||
}
|
||||
|
||||
state.window.recv.on('overflow', _onWindowOverflow)
|
||||
state.window.send.on('overflow', _onWindowOverflow)
|
||||
|
||||
this._initPriority(options.priority)
|
||||
|
||||
if (!state.readable) { this.push(null) }
|
||||
if (!state.writable) {
|
||||
this._writableState.ended = true
|
||||
this._writableState.finished = true
|
||||
}
|
||||
}
|
||||
util.inherits(Stream, Duplex)
|
||||
exports.Stream = Stream
|
||||
|
||||
Stream.prototype._init = function _init (socket) {
|
||||
this.socket = socket
|
||||
}
|
||||
|
||||
Stream.prototype._initPriority = function _initPriority (priority) {
|
||||
var state = this._spdyState
|
||||
var connectionState = this.connection._spdyState
|
||||
var root = connectionState.priorityRoot
|
||||
|
||||
if (!priority) {
|
||||
state.priority = root.addDefault(this.id)
|
||||
return
|
||||
}
|
||||
|
||||
state.priority = root.add({
|
||||
id: this.id,
|
||||
parent: priority.parent,
|
||||
weight: priority.weight,
|
||||
exclusive: priority.exclusive
|
||||
})
|
||||
}
|
||||
|
||||
Stream.prototype._handleFrame = function _handleFrame (frame) {
|
||||
var state = this._spdyState
|
||||
|
||||
// Ignore any kind of data after abort
|
||||
if (state.aborted) {
|
||||
state.debug('id=%d ignoring frame=%s after abort', this.id, frame.type)
|
||||
return
|
||||
}
|
||||
|
||||
// Restart the timer on incoming frames
|
||||
state.timeout.reset()
|
||||
|
||||
if (frame.type === 'DATA') {
|
||||
this._handleData(frame)
|
||||
} else if (frame.type === 'HEADERS') {
|
||||
this._handleHeaders(frame)
|
||||
} else if (frame.type === 'RST') {
|
||||
this._handleRST(frame)
|
||||
} else if (frame.type === 'WINDOW_UPDATE') { this._handleWindowUpdate(frame) } else if (frame.type === 'PRIORITY') {
|
||||
this._handlePriority(frame)
|
||||
} else if (frame.type === 'PUSH_PROMISE') { this._handlePushPromise(frame) }
|
||||
|
||||
if (frame.fin) {
|
||||
state.debug('id=%d end', this.id)
|
||||
this.push(null)
|
||||
}
|
||||
}
|
||||
|
||||
function checkAborted (stream, state, callback) {
|
||||
if (state.aborted) {
|
||||
state.debug('id=%d abort write', stream.id)
|
||||
process.nextTick(function () {
|
||||
callback(new Error('Stream write aborted'))
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
function _send (stream, state, data, callback) {
|
||||
if (checkAborted(stream, state, callback)) {
|
||||
return
|
||||
}
|
||||
|
||||
state.debug('id=%d presend=%d', stream.id, data.length)
|
||||
|
||||
state.timeout.reset()
|
||||
|
||||
state.window.send.update(-data.length, function () {
|
||||
if (checkAborted(stream, state, callback)) {
|
||||
return
|
||||
}
|
||||
|
||||
state.debug('id=%d send=%d', stream.id, data.length)
|
||||
|
||||
state.timeout.reset()
|
||||
|
||||
state.framer.dataFrame({
|
||||
id: stream.id,
|
||||
priority: state.priority.getPriority(),
|
||||
fin: false,
|
||||
data: data
|
||||
}, function (err) {
|
||||
state.debug('id=%d postsend=%d', stream.id, data.length)
|
||||
callback(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Stream.prototype._write = function _write (data, enc, callback) {
|
||||
var state = this._spdyState
|
||||
|
||||
// Send the request if it wasn't sent
|
||||
if (!state.sent) { this.send() }
|
||||
|
||||
// Writes should come after pending control frames (response and headers)
|
||||
if (state.corked !== 0) {
|
||||
var self = this
|
||||
state.corkQueue.push(function () {
|
||||
self._write(data, enc, callback)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Split DATA in chunks to prevent window from going negative
|
||||
this._splitStart(data, _send, callback)
|
||||
}
|
||||
|
||||
Stream.prototype._splitStart = function _splitStart (data, onChunk, callback) {
|
||||
return this._split(data, 0, onChunk, callback)
|
||||
}
|
||||
|
||||
Stream.prototype._split = function _split (data, offset, onChunk, callback) {
|
||||
if (offset === data.length) {
|
||||
return process.nextTick(callback)
|
||||
}
|
||||
|
||||
var state = this._spdyState
|
||||
var local = state.window.send
|
||||
var session = state.sessionWindow.send
|
||||
|
||||
var availSession = Math.max(0, session.getCurrent())
|
||||
if (availSession === 0) {
|
||||
availSession = session.getMax()
|
||||
}
|
||||
var availLocal = Math.max(0, local.getCurrent())
|
||||
if (availLocal === 0) {
|
||||
availLocal = local.getMax()
|
||||
}
|
||||
|
||||
var avail = Math.min(availSession, availLocal)
|
||||
avail = Math.min(avail, state.maxChunk)
|
||||
|
||||
var self = this
|
||||
|
||||
if (avail === 0) {
|
||||
state.window.send.update(0, function () {
|
||||
self._split(data, offset, onChunk, callback)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Split data in chunks in a following way:
|
||||
var limit = avail
|
||||
var size = Math.min(data.length - offset, limit)
|
||||
|
||||
var chunk = data.slice(offset, offset + size)
|
||||
|
||||
onChunk(this, state, chunk, function (err) {
|
||||
if (err) { return callback(err) }
|
||||
|
||||
// Get the next chunk
|
||||
self._split(data, offset + size, onChunk, callback)
|
||||
})
|
||||
}
|
||||
|
||||
Stream.prototype._read = function _read () {
|
||||
var state = this._spdyState
|
||||
|
||||
if (!state.window.recv.isDraining()) {
|
||||
return
|
||||
}
|
||||
|
||||
var delta = state.window.recv.getDelta()
|
||||
|
||||
state.debug('id=%d window emptying, update by %d', this.id, delta)
|
||||
|
||||
state.window.recv.update(delta)
|
||||
state.framer.windowUpdateFrame({
|
||||
id: this.id,
|
||||
delta: delta
|
||||
})
|
||||
}
|
||||
|
||||
Stream.prototype._handleData = function _handleData (frame) {
|
||||
var state = this._spdyState
|
||||
|
||||
// DATA on ended or not readable stream!
|
||||
if (!state.readable || this._readableState.ended) {
|
||||
state.framer.rstFrame({ id: this.id, code: 'STREAM_CLOSED' })
|
||||
return
|
||||
}
|
||||
|
||||
state.debug('id=%d recv=%d', this.id, frame.data.length)
|
||||
state.window.recv.update(-frame.data.length)
|
||||
|
||||
this.push(frame.data)
|
||||
}
|
||||
|
||||
Stream.prototype._handleRST = function _handleRST (frame) {
|
||||
if (frame.code !== 'CANCEL') {
|
||||
this.emit('error', new Error('Got RST: ' + frame.code))
|
||||
}
|
||||
this.abort()
|
||||
}
|
||||
|
||||
Stream.prototype._handleWindowUpdate = function _handleWindowUpdate (frame) {
|
||||
var state = this._spdyState
|
||||
|
||||
state.window.send.update(frame.delta)
|
||||
}
|
||||
|
||||
Stream.prototype._onWindowOverflow = function _onWindowOverflow () {
|
||||
var state = this._spdyState
|
||||
|
||||
state.debug('id=%d window overflow', this.id)
|
||||
state.framer.rstFrame({ id: this.id, code: 'FLOW_CONTROL_ERROR' })
|
||||
|
||||
this.aborted = true
|
||||
this.emit('error', new Error('HTTP2 window overflow'))
|
||||
}
|
||||
|
||||
Stream.prototype._handlePriority = function _handlePriority (frame) {
|
||||
var state = this._spdyState
|
||||
|
||||
state.priority.remove()
|
||||
state.priority = null
|
||||
this._initPriority(frame.priority)
|
||||
|
||||
// Mostly for testing purposes
|
||||
this.emit('priority', frame.priority)
|
||||
}
|
||||
|
||||
Stream.prototype._handleHeaders = function _handleHeaders (frame) {
|
||||
var state = this._spdyState
|
||||
|
||||
if (!state.readable || this._readableState.ended) {
|
||||
state.framer.rstFrame({ id: this.id, code: 'STREAM_CLOSED' })
|
||||
return
|
||||
}
|
||||
|
||||
if (state.needResponse) {
|
||||
return this._handleResponse(frame)
|
||||
}
|
||||
|
||||
this.emit('headers', frame.headers)
|
||||
}
|
||||
|
||||
Stream.prototype._handleResponse = function _handleResponse (frame) {
|
||||
var state = this._spdyState
|
||||
|
||||
if (frame.headers[':status'] === undefined) {
|
||||
state.framer.rstFrame({ id: this.id, code: 'PROTOCOL_ERROR' })
|
||||
return
|
||||
}
|
||||
|
||||
state.needResponse = false
|
||||
this.emit('response', frame.headers[':status'] | 0, frame.headers)
|
||||
}
|
||||
|
||||
Stream.prototype._onFinish = function _onFinish () {
|
||||
var state = this._spdyState
|
||||
|
||||
// Send the request if it wasn't sent
|
||||
if (!state.sent) {
|
||||
// NOTE: will send HEADERS with FIN flag
|
||||
this.send()
|
||||
} else {
|
||||
// Just an `.end()` without any writes will trigger immediate `finish` event
|
||||
// without any calls to `_write()`.
|
||||
if (state.corked !== 0) {
|
||||
var self = this
|
||||
state.corkQueue.push(function () {
|
||||
self._onFinish()
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
state.framer.dataFrame({
|
||||
id: this.id,
|
||||
priority: state.priority.getPriority(),
|
||||
fin: true,
|
||||
data: Buffer.alloc(0)
|
||||
})
|
||||
}
|
||||
|
||||
this._maybeClose()
|
||||
}
|
||||
|
||||
Stream.prototype._onEnd = function _onEnd () {
|
||||
this._maybeClose()
|
||||
}
|
||||
|
||||
Stream.prototype._checkEnded = function _checkEnded (callback) {
|
||||
var state = this._spdyState
|
||||
|
||||
var ended = false
|
||||
if (state.aborted) { ended = true }
|
||||
|
||||
if (!state.writable || this._writableState.finished) { ended = true }
|
||||
|
||||
if (!ended) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (!callback) {
|
||||
return false
|
||||
}
|
||||
|
||||
var err = new Error('Ended stream can\'t send frames')
|
||||
process.nextTick(function () {
|
||||
callback(err)
|
||||
})
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Stream.prototype._maybeClose = function _maybeClose () {
|
||||
var state = this._spdyState
|
||||
|
||||
// .abort() emits `close`
|
||||
if (state.aborted) {
|
||||
return
|
||||
}
|
||||
|
||||
if ((!state.readable || this._readableState.ended) &&
|
||||
this._writableState.finished) {
|
||||
// Clear timeout
|
||||
state.timeout.set(0)
|
||||
|
||||
this.emit('close')
|
||||
}
|
||||
}
|
||||
|
||||
Stream.prototype._handlePushPromise = function _handlePushPromise (frame) {
|
||||
var push = this.connection._createStream({
|
||||
id: frame.promisedId,
|
||||
parent: this,
|
||||
push: true,
|
||||
request: true,
|
||||
method: frame.headers[':method'],
|
||||
path: frame.headers[':path'],
|
||||
host: frame.headers[':authority'],
|
||||
priority: frame.priority,
|
||||
headers: frame.headers,
|
||||
writable: false
|
||||
})
|
||||
|
||||
// GOAWAY
|
||||
if (this.connection._isGoaway(push.id)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!this.emit('pushPromise', push)) {
|
||||
push.abort()
|
||||
}
|
||||
}
|
||||
|
||||
Stream.prototype._hardCork = function _hardCork () {
|
||||
var state = this._spdyState
|
||||
|
||||
this.cork()
|
||||
state.corked++
|
||||
}
|
||||
|
||||
Stream.prototype._hardUncork = function _hardUncork () {
|
||||
var state = this._spdyState
|
||||
|
||||
this.uncork()
|
||||
state.corked--
|
||||
if (state.corked !== 0) {
|
||||
return
|
||||
}
|
||||
|
||||
// Invoke callbacks
|
||||
var queue = state.corkQueue
|
||||
state.corkQueue = []
|
||||
for (var i = 0; i < queue.length; i++) {
|
||||
queue[i]()
|
||||
}
|
||||
}
|
||||
|
||||
Stream.prototype._sendPush = function _sendPush (status, response, callback) {
|
||||
var self = this
|
||||
var state = this._spdyState
|
||||
|
||||
this._hardCork()
|
||||
state.framer.pushFrame({
|
||||
id: this.parent.id,
|
||||
promisedId: this.id,
|
||||
priority: state.priority.toJSON(),
|
||||
path: this.path,
|
||||
host: this.host,
|
||||
method: this.method,
|
||||
status: status,
|
||||
headers: this.headers,
|
||||
response: response
|
||||
}, function (err) {
|
||||
self._hardUncork()
|
||||
|
||||
callback(err)
|
||||
})
|
||||
}
|
||||
|
||||
Stream.prototype._wasSent = function _wasSent () {
|
||||
var state = this._spdyState
|
||||
return state.sent
|
||||
}
|
||||
|
||||
// Public API
|
||||
|
||||
Stream.prototype.send = function send (callback) {
|
||||
var state = this._spdyState
|
||||
|
||||
if (state.sent) {
|
||||
var err = new Error('Stream was already sent')
|
||||
process.nextTick(function () {
|
||||
if (callback) {
|
||||
callback(err)
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
state.sent = true
|
||||
state.timeout.reset()
|
||||
|
||||
// GET requests should always be auto-finished
|
||||
if (this.method === 'GET') {
|
||||
this._writableState.ended = true
|
||||
this._writableState.finished = true
|
||||
}
|
||||
|
||||
// TODO(indunty): ideally it should just take a stream object as an input
|
||||
var self = this
|
||||
this._hardCork()
|
||||
state.framer.requestFrame({
|
||||
id: this.id,
|
||||
method: this.method,
|
||||
path: this.path,
|
||||
host: this.host,
|
||||
priority: state.priority.toJSON(),
|
||||
headers: this.headers,
|
||||
fin: this._writableState.finished
|
||||
}, function (err) {
|
||||
self._hardUncork()
|
||||
|
||||
if (!callback) {
|
||||
return
|
||||
}
|
||||
|
||||
callback(err)
|
||||
})
|
||||
}
|
||||
|
||||
Stream.prototype.respond = function respond (status, headers, callback) {
|
||||
var self = this
|
||||
var state = this._spdyState
|
||||
assert(!state.request, 'Can\'t respond on request')
|
||||
|
||||
state.timeout.reset()
|
||||
|
||||
if (!this._checkEnded(callback)) { return }
|
||||
|
||||
var frame = {
|
||||
id: this.id,
|
||||
status: status,
|
||||
headers: headers
|
||||
}
|
||||
this._hardCork()
|
||||
state.framer.responseFrame(frame, function (err) {
|
||||
self._hardUncork()
|
||||
if (callback) { callback(err) }
|
||||
})
|
||||
}
|
||||
|
||||
Stream.prototype.setWindow = function setWindow (size) {
|
||||
var state = this._spdyState
|
||||
|
||||
state.timeout.reset()
|
||||
|
||||
if (!this._checkEnded()) {
|
||||
return
|
||||
}
|
||||
|
||||
state.debug('id=%d force window max=%d', this.id, size)
|
||||
state.window.recv.setMax(size)
|
||||
|
||||
var delta = state.window.recv.getDelta()
|
||||
if (delta === 0) { return }
|
||||
|
||||
state.framer.windowUpdateFrame({
|
||||
id: this.id,
|
||||
delta: delta
|
||||
})
|
||||
state.window.recv.update(delta)
|
||||
}
|
||||
|
||||
Stream.prototype.sendHeaders = function sendHeaders (headers, callback) {
|
||||
var self = this
|
||||
var state = this._spdyState
|
||||
|
||||
state.timeout.reset()
|
||||
|
||||
if (!this._checkEnded(callback)) {
|
||||
return
|
||||
}
|
||||
|
||||
// Request wasn't yet send, coalesce headers
|
||||
if (!state.sent) {
|
||||
this.headers = Object.assign({}, this.headers)
|
||||
Object.assign(this.headers, headers)
|
||||
process.nextTick(function () {
|
||||
if (callback) {
|
||||
callback(null)
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
this._hardCork()
|
||||
state.framer.headersFrame({
|
||||
id: this.id,
|
||||
headers: headers
|
||||
}, function (err) {
|
||||
self._hardUncork()
|
||||
if (callback) { callback(err) }
|
||||
})
|
||||
}
|
||||
|
||||
Stream.prototype._destroy = function destroy () {
|
||||
this.abort()
|
||||
}
|
||||
|
||||
Stream.prototype.abort = function abort (code, callback) {
|
||||
var state = this._spdyState
|
||||
|
||||
// .abort(callback)
|
||||
if (typeof code === 'function') {
|
||||
callback = code
|
||||
code = null
|
||||
}
|
||||
|
||||
if (this._readableState.ended && this._writableState.finished) {
|
||||
state.debug('id=%d already closed', this.id)
|
||||
if (callback) {
|
||||
process.nextTick(callback)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (state.aborted) {
|
||||
state.debug('id=%d already aborted', this.id)
|
||||
if (callback) { process.nextTick(callback) }
|
||||
return
|
||||
}
|
||||
|
||||
state.aborted = true
|
||||
state.debug('id=%d abort', this.id)
|
||||
|
||||
this.setTimeout(0)
|
||||
|
||||
var abortCode = code || 'CANCEL'
|
||||
|
||||
state.framer.rstFrame({
|
||||
id: this.id,
|
||||
code: abortCode
|
||||
})
|
||||
|
||||
var self = this
|
||||
process.nextTick(function () {
|
||||
if (callback) {
|
||||
callback(null)
|
||||
}
|
||||
self.emit('close', new Error('Aborted, code: ' + abortCode))
|
||||
})
|
||||
}
|
||||
|
||||
Stream.prototype.setPriority = function setPriority (info) {
|
||||
var state = this._spdyState
|
||||
|
||||
state.timeout.reset()
|
||||
|
||||
if (!this._checkEnded()) {
|
||||
return
|
||||
}
|
||||
|
||||
state.debug('id=%d priority change', this.id, info)
|
||||
|
||||
var frame = { id: this.id, priority: info }
|
||||
|
||||
// Change priority on this side
|
||||
this._handlePriority(frame)
|
||||
|
||||
// And on the other too
|
||||
state.framer.priorityFrame(frame)
|
||||
}
|
||||
|
||||
Stream.prototype.pushPromise = function pushPromise (uri, callback) {
|
||||
if (!this._checkEnded(callback)) {
|
||||
return
|
||||
}
|
||||
|
||||
var self = this
|
||||
this._hardCork()
|
||||
var push = this.connection.pushPromise(this, uri, function (err) {
|
||||
self._hardUncork()
|
||||
if (!err) {
|
||||
push._hardUncork()
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
return callback(err, push)
|
||||
}
|
||||
|
||||
if (err) { push.emit('error', err) }
|
||||
})
|
||||
push._hardCork()
|
||||
|
||||
return push
|
||||
}
|
||||
|
||||
Stream.prototype.setMaxChunk = function setMaxChunk (size) {
|
||||
var state = this._spdyState
|
||||
state.maxChunk = size
|
||||
}
|
||||
|
||||
Stream.prototype.setTimeout = function setTimeout (delay, callback) {
|
||||
var state = this._spdyState
|
||||
|
||||
state.timeout.set(delay, callback)
|
||||
}
|
||||
196
node_modules/spdy-transport/lib/spdy-transport/utils.js
generated
vendored
Normal file
196
node_modules/spdy-transport/lib/spdy-transport/utils.js
generated
vendored
Normal file
@ -0,0 +1,196 @@
|
||||
'use strict'
|
||||
|
||||
var util = require('util')
|
||||
var isNode = require('detect-node')
|
||||
|
||||
// Node.js 0.8, 0.10 and 0.12 support
|
||||
Object.assign = (process.versions.modules >= 46 || !isNode)
|
||||
? Object.assign // eslint-disable-next-line
|
||||
: util._extend
|
||||
|
||||
function QueueItem () {
|
||||
this.prev = null
|
||||
this.next = null
|
||||
}
|
||||
exports.QueueItem = QueueItem
|
||||
|
||||
function Queue () {
|
||||
QueueItem.call(this)
|
||||
|
||||
this.prev = this
|
||||
this.next = this
|
||||
}
|
||||
util.inherits(Queue, QueueItem)
|
||||
exports.Queue = Queue
|
||||
|
||||
Queue.prototype.insertTail = function insertTail (item) {
|
||||
item.prev = this.prev
|
||||
item.next = this
|
||||
item.prev.next = item
|
||||
item.next.prev = item
|
||||
}
|
||||
|
||||
Queue.prototype.remove = function remove (item) {
|
||||
var next = item.next
|
||||
var prev = item.prev
|
||||
|
||||
item.next = item
|
||||
item.prev = item
|
||||
next.prev = prev
|
||||
prev.next = next
|
||||
}
|
||||
|
||||
Queue.prototype.head = function head () {
|
||||
return this.next
|
||||
}
|
||||
|
||||
Queue.prototype.tail = function tail () {
|
||||
return this.prev
|
||||
}
|
||||
|
||||
Queue.prototype.isEmpty = function isEmpty () {
|
||||
return this.next === this
|
||||
}
|
||||
|
||||
Queue.prototype.isRoot = function isRoot (item) {
|
||||
return this === item
|
||||
}
|
||||
|
||||
function LockStream (stream) {
|
||||
this.locked = false
|
||||
this.queue = []
|
||||
this.stream = stream
|
||||
}
|
||||
exports.LockStream = LockStream
|
||||
|
||||
LockStream.prototype.write = function write (chunks, callback) {
|
||||
var self = this
|
||||
|
||||
// Do not let it interleave
|
||||
if (this.locked) {
|
||||
this.queue.push(function () {
|
||||
return self.write(chunks, callback)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
this.locked = true
|
||||
|
||||
function done (err, chunks) {
|
||||
self.stream.removeListener('error', done)
|
||||
|
||||
self.locked = false
|
||||
if (self.queue.length > 0) { self.queue.shift()() }
|
||||
callback(err, chunks)
|
||||
}
|
||||
|
||||
this.stream.on('error', done)
|
||||
|
||||
// Accumulate all output data
|
||||
var output = []
|
||||
function onData (chunk) {
|
||||
output.push(chunk)
|
||||
}
|
||||
this.stream.on('data', onData)
|
||||
|
||||
function next (err) {
|
||||
self.stream.removeListener('data', onData)
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
|
||||
done(null, output)
|
||||
}
|
||||
|
||||
for (var i = 0; i < chunks.length - 1; i++) { this.stream.write(chunks[i]) }
|
||||
|
||||
if (chunks.length > 0) {
|
||||
this.stream.write(chunks[i], next)
|
||||
} else { process.nextTick(next) }
|
||||
|
||||
if (this.stream.execute) {
|
||||
this.stream.execute(function (err) {
|
||||
if (err) { return done(err) }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Just finds the place in array to insert
|
||||
function binaryLookup (list, item, compare) {
|
||||
var start = 0
|
||||
var end = list.length
|
||||
|
||||
while (start < end) {
|
||||
var pos = (start + end) >> 1
|
||||
var cmp = compare(item, list[pos])
|
||||
|
||||
if (cmp === 0) {
|
||||
start = pos
|
||||
end = pos
|
||||
break
|
||||
} else if (cmp < 0) {
|
||||
end = pos
|
||||
} else {
|
||||
start = pos + 1
|
||||
}
|
||||
}
|
||||
|
||||
return start
|
||||
}
|
||||
exports.binaryLookup = binaryLookup
|
||||
|
||||
function binaryInsert (list, item, compare) {
|
||||
var index = binaryLookup(list, item, compare)
|
||||
|
||||
list.splice(index, 0, item)
|
||||
}
|
||||
exports.binaryInsert = binaryInsert
|
||||
|
||||
function binarySearch (list, item, compare) {
|
||||
var index = binaryLookup(list, item, compare)
|
||||
|
||||
if (index >= list.length) {
|
||||
return -1
|
||||
}
|
||||
|
||||
if (compare(item, list[index]) === 0) {
|
||||
return index
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
exports.binarySearch = binarySearch
|
||||
|
||||
function Timeout (object) {
|
||||
this.delay = 0
|
||||
this.timer = null
|
||||
this.object = object
|
||||
}
|
||||
exports.Timeout = Timeout
|
||||
|
||||
Timeout.prototype.set = function set (delay, callback) {
|
||||
this.delay = delay
|
||||
this.reset()
|
||||
if (!callback) { return }
|
||||
|
||||
if (this.delay === 0) {
|
||||
this.object.removeListener('timeout', callback)
|
||||
} else {
|
||||
this.object.once('timeout', callback)
|
||||
}
|
||||
}
|
||||
|
||||
Timeout.prototype.reset = function reset () {
|
||||
if (this.timer !== null) {
|
||||
clearTimeout(this.timer)
|
||||
this.timer = null
|
||||
}
|
||||
|
||||
if (this.delay === 0) { return }
|
||||
|
||||
var self = this
|
||||
this.timer = setTimeout(function () {
|
||||
self.timer = null
|
||||
self.object.emit('timeout')
|
||||
}, this.delay)
|
||||
}
|
||||
174
node_modules/spdy-transport/lib/spdy-transport/window.js
generated
vendored
Normal file
174
node_modules/spdy-transport/lib/spdy-transport/window.js
generated
vendored
Normal file
@ -0,0 +1,174 @@
|
||||
'use strict'
|
||||
|
||||
var util = require('util')
|
||||
var EventEmitter = require('events').EventEmitter
|
||||
var debug = {
|
||||
server: require('debug')('spdy:window:server'),
|
||||
client: require('debug')('spdy:window:client')
|
||||
}
|
||||
|
||||
function Side (window, name, options) {
|
||||
EventEmitter.call(this)
|
||||
|
||||
this.name = name
|
||||
this.window = window
|
||||
this.current = options.size
|
||||
this.max = options.size
|
||||
this.limit = options.max
|
||||
this.lowWaterMark = options.lowWaterMark === undefined
|
||||
? this.max / 2
|
||||
: options.lowWaterMark
|
||||
|
||||
this._refilling = false
|
||||
this._refillQueue = []
|
||||
}
|
||||
util.inherits(Side, EventEmitter)
|
||||
|
||||
Side.prototype.setMax = function setMax (max) {
|
||||
this.window.debug('id=%d side=%s setMax=%d',
|
||||
this.window.id,
|
||||
this.name,
|
||||
max)
|
||||
this.max = max
|
||||
this.lowWaterMark = this.max / 2
|
||||
}
|
||||
|
||||
Side.prototype.updateMax = function updateMax (max) {
|
||||
var delta = max - this.max
|
||||
this.window.debug('id=%d side=%s updateMax=%d delta=%d',
|
||||
this.window.id,
|
||||
this.name,
|
||||
max,
|
||||
delta)
|
||||
|
||||
this.max = max
|
||||
this.lowWaterMark = max / 2
|
||||
|
||||
this.update(delta)
|
||||
}
|
||||
|
||||
Side.prototype.setLowWaterMark = function setLowWaterMark (lwm) {
|
||||
this.lowWaterMark = lwm
|
||||
}
|
||||
|
||||
Side.prototype.update = function update (size, callback) {
|
||||
// Not enough space for the update, wait for refill
|
||||
if (size <= 0 && callback && this.isEmpty()) {
|
||||
this.window.debug('id=%d side=%s wait for refill=%d [%d/%d]',
|
||||
this.window.id,
|
||||
this.name,
|
||||
-size,
|
||||
this.current,
|
||||
this.max)
|
||||
this._refillQueue.push({
|
||||
size: size,
|
||||
callback: callback
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
this.current += size
|
||||
|
||||
if (this.current > this.limit) {
|
||||
this.emit('overflow')
|
||||
return
|
||||
}
|
||||
|
||||
this.window.debug('id=%d side=%s update by=%d [%d/%d]',
|
||||
this.window.id,
|
||||
this.name,
|
||||
size,
|
||||
this.current,
|
||||
this.max)
|
||||
|
||||
// Time to send WINDOW_UPDATE
|
||||
if (size < 0 && this.isDraining()) {
|
||||
this.window.debug('id=%d side=%s drained', this.window.id, this.name)
|
||||
this.emit('drain')
|
||||
}
|
||||
|
||||
// Time to write
|
||||
if (size > 0 && this.current > 0 && this.current <= size) {
|
||||
this.window.debug('id=%d side=%s full', this.window.id, this.name)
|
||||
this.emit('full')
|
||||
}
|
||||
|
||||
this._processRefillQueue()
|
||||
|
||||
if (callback) { process.nextTick(callback) }
|
||||
}
|
||||
|
||||
Side.prototype.getCurrent = function getCurrent () {
|
||||
return this.current
|
||||
}
|
||||
|
||||
Side.prototype.getMax = function getMax () {
|
||||
return this.max
|
||||
}
|
||||
|
||||
Side.prototype.getDelta = function getDelta () {
|
||||
return this.max - this.current
|
||||
}
|
||||
|
||||
Side.prototype.isDraining = function isDraining () {
|
||||
return this.current <= this.lowWaterMark
|
||||
}
|
||||
|
||||
Side.prototype.isEmpty = function isEmpty () {
|
||||
return this.current <= 0
|
||||
}
|
||||
|
||||
// Private
|
||||
|
||||
Side.prototype._processRefillQueue = function _processRefillQueue () {
|
||||
// Prevent recursion
|
||||
if (this._refilling) {
|
||||
return
|
||||
}
|
||||
this._refilling = true
|
||||
|
||||
while (this._refillQueue.length > 0) {
|
||||
var item = this._refillQueue[0]
|
||||
|
||||
if (this.isEmpty()) {
|
||||
break
|
||||
}
|
||||
|
||||
this.window.debug('id=%d side=%s refilled for size=%d',
|
||||
this.window.id,
|
||||
this.name,
|
||||
-item.size)
|
||||
|
||||
this._refillQueue.shift()
|
||||
this.update(item.size, item.callback)
|
||||
}
|
||||
|
||||
this._refilling = false
|
||||
}
|
||||
|
||||
function Window (options) {
|
||||
this.id = options.id
|
||||
this.isServer = options.isServer
|
||||
this.debug = this.isServer ? debug.server : debug.client
|
||||
|
||||
this.recv = new Side(this, 'recv', options.recv)
|
||||
this.send = new Side(this, 'send', options.send)
|
||||
}
|
||||
module.exports = Window
|
||||
|
||||
Window.prototype.clone = function clone (id) {
|
||||
return new Window({
|
||||
id: id,
|
||||
isServer: this.isServer,
|
||||
recv: {
|
||||
size: this.recv.max,
|
||||
max: this.recv.limit,
|
||||
lowWaterMark: this.recv.lowWaterMark
|
||||
},
|
||||
send: {
|
||||
size: this.send.max,
|
||||
max: this.send.limit,
|
||||
lowWaterMark: this.send.lowWaterMark
|
||||
}
|
||||
})
|
||||
}
|
||||
38
node_modules/spdy-transport/node_modules/readable-stream/CONTRIBUTING.md
generated
vendored
Normal file
38
node_modules/spdy-transport/node_modules/readable-stream/CONTRIBUTING.md
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
# Developer's Certificate of Origin 1.1
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
* (a) The contribution was created in whole or in part by me and I
|
||||
have the right to submit it under the open source license
|
||||
indicated in the file; or
|
||||
|
||||
* (b) The contribution is based upon previous work that, to the best
|
||||
of my knowledge, is covered under an appropriate open source
|
||||
license and I have the right under that license to submit that
|
||||
work with modifications, whether created in whole or in part
|
||||
by me, under the same open source license (unless I am
|
||||
permitted to submit under a different license), as indicated
|
||||
in the file; or
|
||||
|
||||
* (c) The contribution was provided directly to me by some other
|
||||
person who certified (a), (b) or (c) and I have not modified
|
||||
it.
|
||||
|
||||
* (d) I understand and agree that this project and the contribution
|
||||
are public and that a record of the contribution (including all
|
||||
personal information I submit with it, including my sign-off) is
|
||||
maintained indefinitely and may be redistributed consistent with
|
||||
this project or the open source license(s) involved.
|
||||
|
||||
## Moderation Policy
|
||||
|
||||
The [Node.js Moderation Policy] applies to this WG.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
The [Node.js Code of Conduct][] applies to this WG.
|
||||
|
||||
[Node.js Code of Conduct]:
|
||||
https://github.com/nodejs/node/blob/master/CODE_OF_CONDUCT.md
|
||||
[Node.js Moderation Policy]:
|
||||
https://github.com/nodejs/TSC/blob/master/Moderation-Policy.md
|
||||
136
node_modules/spdy-transport/node_modules/readable-stream/GOVERNANCE.md
generated
vendored
Normal file
136
node_modules/spdy-transport/node_modules/readable-stream/GOVERNANCE.md
generated
vendored
Normal file
@ -0,0 +1,136 @@
|
||||
### Streams Working Group
|
||||
|
||||
The Node.js Streams is jointly governed by a Working Group
|
||||
(WG)
|
||||
that is responsible for high-level guidance of the project.
|
||||
|
||||
The WG has final authority over this project including:
|
||||
|
||||
* Technical direction
|
||||
* Project governance and process (including this policy)
|
||||
* Contribution policy
|
||||
* GitHub repository hosting
|
||||
* Conduct guidelines
|
||||
* Maintaining the list of additional Collaborators
|
||||
|
||||
For the current list of WG members, see the project
|
||||
[README.md](./README.md#current-project-team-members).
|
||||
|
||||
### Collaborators
|
||||
|
||||
The readable-stream GitHub repository is
|
||||
maintained by the WG and additional Collaborators who are added by the
|
||||
WG on an ongoing basis.
|
||||
|
||||
Individuals making significant and valuable contributions are made
|
||||
Collaborators and given commit-access to the project. These
|
||||
individuals are identified by the WG and their addition as
|
||||
Collaborators is discussed during the WG meeting.
|
||||
|
||||
_Note:_ If you make a significant contribution and are not considered
|
||||
for commit-access log an issue or contact a WG member directly and it
|
||||
will be brought up in the next WG meeting.
|
||||
|
||||
Modifications of the contents of the readable-stream repository are
|
||||
made on
|
||||
a collaborative basis. Anybody with a GitHub account may propose a
|
||||
modification via pull request and it will be considered by the project
|
||||
Collaborators. All pull requests must be reviewed and accepted by a
|
||||
Collaborator with sufficient expertise who is able to take full
|
||||
responsibility for the change. In the case of pull requests proposed
|
||||
by an existing Collaborator, an additional Collaborator is required
|
||||
for sign-off. Consensus should be sought if additional Collaborators
|
||||
participate and there is disagreement around a particular
|
||||
modification. See _Consensus Seeking Process_ below for further detail
|
||||
on the consensus model used for governance.
|
||||
|
||||
Collaborators may opt to elevate significant or controversial
|
||||
modifications, or modifications that have not found consensus to the
|
||||
WG for discussion by assigning the ***WG-agenda*** tag to a pull
|
||||
request or issue. The WG should serve as the final arbiter where
|
||||
required.
|
||||
|
||||
For the current list of Collaborators, see the project
|
||||
[README.md](./README.md#members).
|
||||
|
||||
### WG Membership
|
||||
|
||||
WG seats are not time-limited. There is no fixed size of the WG.
|
||||
However, the expected target is between 6 and 12, to ensure adequate
|
||||
coverage of important areas of expertise, balanced with the ability to
|
||||
make decisions efficiently.
|
||||
|
||||
There is no specific set of requirements or qualifications for WG
|
||||
membership beyond these rules.
|
||||
|
||||
The WG may add additional members to the WG by unanimous consensus.
|
||||
|
||||
A WG member may be removed from the WG by voluntary resignation, or by
|
||||
unanimous consensus of all other WG members.
|
||||
|
||||
Changes to WG membership should be posted in the agenda, and may be
|
||||
suggested as any other agenda item (see "WG Meetings" below).
|
||||
|
||||
If an addition or removal is proposed during a meeting, and the full
|
||||
WG is not in attendance to participate, then the addition or removal
|
||||
is added to the agenda for the subsequent meeting. This is to ensure
|
||||
that all members are given the opportunity to participate in all
|
||||
membership decisions. If a WG member is unable to attend a meeting
|
||||
where a planned membership decision is being made, then their consent
|
||||
is assumed.
|
||||
|
||||
No more than 1/3 of the WG members may be affiliated with the same
|
||||
employer. If removal or resignation of a WG member, or a change of
|
||||
employment by a WG member, creates a situation where more than 1/3 of
|
||||
the WG membership shares an employer, then the situation must be
|
||||
immediately remedied by the resignation or removal of one or more WG
|
||||
members affiliated with the over-represented employer(s).
|
||||
|
||||
### WG Meetings
|
||||
|
||||
The WG meets occasionally on a Google Hangout On Air. A designated moderator
|
||||
approved by the WG runs the meeting. Each meeting should be
|
||||
published to YouTube.
|
||||
|
||||
Items are added to the WG agenda that are considered contentious or
|
||||
are modifications of governance, contribution policy, WG membership,
|
||||
or release process.
|
||||
|
||||
The intention of the agenda is not to approve or review all patches;
|
||||
that should happen continuously on GitHub and be handled by the larger
|
||||
group of Collaborators.
|
||||
|
||||
Any community member or contributor can ask that something be added to
|
||||
the next meeting's agenda by logging a GitHub Issue. Any Collaborator,
|
||||
WG member or the moderator can add the item to the agenda by adding
|
||||
the ***WG-agenda*** tag to the issue.
|
||||
|
||||
Prior to each WG meeting the moderator will share the Agenda with
|
||||
members of the WG. WG members can add any items they like to the
|
||||
agenda at the beginning of each meeting. The moderator and the WG
|
||||
cannot veto or remove items.
|
||||
|
||||
The WG may invite persons or representatives from certain projects to
|
||||
participate in a non-voting capacity.
|
||||
|
||||
The moderator is responsible for summarizing the discussion of each
|
||||
agenda item and sends it as a pull request after the meeting.
|
||||
|
||||
### Consensus Seeking Process
|
||||
|
||||
The WG follows a
|
||||
[Consensus
|
||||
Seeking](http://en.wikipedia.org/wiki/Consensus-seeking_decision-making)
|
||||
decision-making model.
|
||||
|
||||
When an agenda item has appeared to reach a consensus the moderator
|
||||
will ask "Does anyone object?" as a final call for dissent from the
|
||||
consensus.
|
||||
|
||||
If an agenda item cannot reach a consensus a WG member can call for
|
||||
either a closing vote or a vote to table the issue to the next
|
||||
meeting. The call for a vote must be seconded by a majority of the WG
|
||||
or else the discussion will continue. Simple majority wins.
|
||||
|
||||
Note that changes to WG membership require a majority consensus. See
|
||||
"WG Membership" above.
|
||||
47
node_modules/spdy-transport/node_modules/readable-stream/LICENSE
generated
vendored
Normal file
47
node_modules/spdy-transport/node_modules/readable-stream/LICENSE
generated
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
Node.js is licensed for use as follows:
|
||||
|
||||
"""
|
||||
Copyright Node.js contributors. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
"""
|
||||
|
||||
This license applies to parts of Node.js originating from the
|
||||
https://github.com/joyent/node repository:
|
||||
|
||||
"""
|
||||
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
"""
|
||||
111
node_modules/spdy-transport/node_modules/readable-stream/README.md
generated
vendored
Normal file
111
node_modules/spdy-transport/node_modules/readable-stream/README.md
generated
vendored
Normal file
@ -0,0 +1,111 @@
|
||||
# readable-stream
|
||||
|
||||
***Node.js core streams for userland*** [](https://travis-ci.com/nodejs/readable-stream)
|
||||
|
||||
|
||||
[](https://nodei.co/npm/readable-stream/)
|
||||
[](https://nodei.co/npm/readable-stream/)
|
||||
|
||||
|
||||
[](https://saucelabs.com/u/readabe-stream)
|
||||
|
||||
```bash
|
||||
npm install --save readable-stream
|
||||
```
|
||||
|
||||
This package is a mirror of the streams implementations in Node.js.
|
||||
|
||||
Full documentation may be found on the [Node.js website](https://nodejs.org/dist/v10.15.3/docs/api/stream.html).
|
||||
|
||||
If you want to guarantee a stable streams base, regardless of what version of
|
||||
Node you, or the users of your libraries are using, use **readable-stream** *only* and avoid the *"stream"* module in Node-core, for background see [this blogpost](http://r.va.gg/2014/06/why-i-dont-use-nodes-core-stream-module.html).
|
||||
|
||||
As of version 2.0.0 **readable-stream** uses semantic versioning.
|
||||
|
||||
## Version 3.x.x
|
||||
|
||||
v3.x.x of `readable-stream` supports Node 6, 8, and 10, as well as
|
||||
evergreen browsers, IE 11 and latest Safari. The breaking changes
|
||||
introduced by v3 are composed by the combined breaking changes in [Node v9](https://nodejs.org/en/blog/release/v9.0.0/)
|
||||
and [Node v10](https://nodejs.org/en/blog/release/v10.0.0/), as follows:
|
||||
|
||||
1. Error codes: https://github.com/nodejs/node/pull/13310,
|
||||
https://github.com/nodejs/node/pull/13291,
|
||||
https://github.com/nodejs/node/pull/16589,
|
||||
https://github.com/nodejs/node/pull/15042,
|
||||
https://github.com/nodejs/node/pull/15665,
|
||||
https://github.com/nodejs/readable-stream/pull/344
|
||||
2. 'readable' have precedence over flowing
|
||||
https://github.com/nodejs/node/pull/18994
|
||||
3. make virtual methods errors consistent
|
||||
https://github.com/nodejs/node/pull/18813
|
||||
4. updated streams error handling
|
||||
https://github.com/nodejs/node/pull/18438
|
||||
5. writable.end should return this.
|
||||
https://github.com/nodejs/node/pull/18780
|
||||
6. readable continues to read when push('')
|
||||
https://github.com/nodejs/node/pull/18211
|
||||
7. add custom inspect to BufferList
|
||||
https://github.com/nodejs/node/pull/17907
|
||||
8. always defer 'readable' with nextTick
|
||||
https://github.com/nodejs/node/pull/17979
|
||||
|
||||
## Version 2.x.x
|
||||
|
||||
v2.x.x of `readable-stream` supports all Node.js version from 0.8, as well as
|
||||
evergreen browsers and IE 10 & 11.
|
||||
|
||||
### Big Thanks
|
||||
|
||||
Cross-browser Testing Platform and Open Source <3 Provided by [Sauce Labs][sauce]
|
||||
|
||||
# Usage
|
||||
|
||||
You can swap your `require('stream')` with `require('readable-stream')`
|
||||
without any changes, if you are just using one of the main classes and
|
||||
functions.
|
||||
|
||||
```js
|
||||
const {
|
||||
Readable,
|
||||
Writable,
|
||||
Transform,
|
||||
Duplex,
|
||||
pipeline,
|
||||
finished
|
||||
} = require('readable-stream')
|
||||
````
|
||||
|
||||
Note that `require('stream')` will return `Stream`, while
|
||||
`require('readable-stream')` will return `Readable`. We discourage using
|
||||
whatever is exported directly, but rather use one of the properties as
|
||||
shown in the example above.
|
||||
|
||||
# Streams Working Group
|
||||
|
||||
`readable-stream` is maintained by the Streams Working Group, which
|
||||
oversees the development and maintenance of the Streams API within
|
||||
Node.js. The responsibilities of the Streams Working Group include:
|
||||
|
||||
* Addressing stream issues on the Node.js issue tracker.
|
||||
* Authoring and editing stream documentation within the Node.js project.
|
||||
* Reviewing changes to stream subclasses within the Node.js project.
|
||||
* Redirecting changes to streams from the Node.js project to this
|
||||
project.
|
||||
* Assisting in the implementation of stream providers within Node.js.
|
||||
* Recommending versions of `readable-stream` to be included in Node.js.
|
||||
* Messaging about the future of streams to give the community advance
|
||||
notice of changes.
|
||||
|
||||
<a name="members"></a>
|
||||
## Team Members
|
||||
|
||||
* **Calvin Metcalf** ([@calvinmetcalf](https://github.com/calvinmetcalf)) <calvin.metcalf@gmail.com>
|
||||
- Release GPG key: F3EF5F62A87FC27A22E643F714CE4FF5015AA242
|
||||
* **Mathias Buus** ([@mafintosh](https://github.com/mafintosh)) <mathiasbuus@gmail.com>
|
||||
* **Matteo Collina** ([@mcollina](https://github.com/mcollina)) <matteo.collina@gmail.com>
|
||||
- Release GPG key: 3ABC01543F22DD2239285CDD818674489FBC127E
|
||||
* **Irina Shestak** ([@lrlna](https://github.com/lrlna)) <shestak.irina@gmail.com>
|
||||
* **Yoshua Wyuts** ([@yoshuawuyts](https://github.com/yoshuawuyts)) <yoshuawuyts@gmail.com>
|
||||
|
||||
[sauce]: https://saucelabs.com
|
||||
127
node_modules/spdy-transport/node_modules/readable-stream/errors-browser.js
generated
vendored
Normal file
127
node_modules/spdy-transport/node_modules/readable-stream/errors-browser.js
generated
vendored
Normal file
@ -0,0 +1,127 @@
|
||||
'use strict';
|
||||
|
||||
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
|
||||
|
||||
var codes = {};
|
||||
|
||||
function createErrorType(code, message, Base) {
|
||||
if (!Base) {
|
||||
Base = Error;
|
||||
}
|
||||
|
||||
function getMessage(arg1, arg2, arg3) {
|
||||
if (typeof message === 'string') {
|
||||
return message;
|
||||
} else {
|
||||
return message(arg1, arg2, arg3);
|
||||
}
|
||||
}
|
||||
|
||||
var NodeError =
|
||||
/*#__PURE__*/
|
||||
function (_Base) {
|
||||
_inheritsLoose(NodeError, _Base);
|
||||
|
||||
function NodeError(arg1, arg2, arg3) {
|
||||
return _Base.call(this, getMessage(arg1, arg2, arg3)) || this;
|
||||
}
|
||||
|
||||
return NodeError;
|
||||
}(Base);
|
||||
|
||||
NodeError.prototype.name = Base.name;
|
||||
NodeError.prototype.code = code;
|
||||
codes[code] = NodeError;
|
||||
} // https://github.com/nodejs/node/blob/v10.8.0/lib/internal/errors.js
|
||||
|
||||
|
||||
function oneOf(expected, thing) {
|
||||
if (Array.isArray(expected)) {
|
||||
var len = expected.length;
|
||||
expected = expected.map(function (i) {
|
||||
return String(i);
|
||||
});
|
||||
|
||||
if (len > 2) {
|
||||
return "one of ".concat(thing, " ").concat(expected.slice(0, len - 1).join(', '), ", or ") + expected[len - 1];
|
||||
} else if (len === 2) {
|
||||
return "one of ".concat(thing, " ").concat(expected[0], " or ").concat(expected[1]);
|
||||
} else {
|
||||
return "of ".concat(thing, " ").concat(expected[0]);
|
||||
}
|
||||
} else {
|
||||
return "of ".concat(thing, " ").concat(String(expected));
|
||||
}
|
||||
} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith
|
||||
|
||||
|
||||
function startsWith(str, search, pos) {
|
||||
return str.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search;
|
||||
} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
|
||||
|
||||
|
||||
function endsWith(str, search, this_len) {
|
||||
if (this_len === undefined || this_len > str.length) {
|
||||
this_len = str.length;
|
||||
}
|
||||
|
||||
return str.substring(this_len - search.length, this_len) === search;
|
||||
} // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes
|
||||
|
||||
|
||||
function includes(str, search, start) {
|
||||
if (typeof start !== 'number') {
|
||||
start = 0;
|
||||
}
|
||||
|
||||
if (start + search.length > str.length) {
|
||||
return false;
|
||||
} else {
|
||||
return str.indexOf(search, start) !== -1;
|
||||
}
|
||||
}
|
||||
|
||||
createErrorType('ERR_INVALID_OPT_VALUE', function (name, value) {
|
||||
return 'The value "' + value + '" is invalid for option "' + name + '"';
|
||||
}, TypeError);
|
||||
createErrorType('ERR_INVALID_ARG_TYPE', function (name, expected, actual) {
|
||||
// determiner: 'must be' or 'must not be'
|
||||
var determiner;
|
||||
|
||||
if (typeof expected === 'string' && startsWith(expected, 'not ')) {
|
||||
determiner = 'must not be';
|
||||
expected = expected.replace(/^not /, '');
|
||||
} else {
|
||||
determiner = 'must be';
|
||||
}
|
||||
|
||||
var msg;
|
||||
|
||||
if (endsWith(name, ' argument')) {
|
||||
// For cases like 'first argument'
|
||||
msg = "The ".concat(name, " ").concat(determiner, " ").concat(oneOf(expected, 'type'));
|
||||
} else {
|
||||
var type = includes(name, '.') ? 'property' : 'argument';
|
||||
msg = "The \"".concat(name, "\" ").concat(type, " ").concat(determiner, " ").concat(oneOf(expected, 'type'));
|
||||
}
|
||||
|
||||
msg += ". Received type ".concat(typeof actual);
|
||||
return msg;
|
||||
}, TypeError);
|
||||
createErrorType('ERR_STREAM_PUSH_AFTER_EOF', 'stream.push() after EOF');
|
||||
createErrorType('ERR_METHOD_NOT_IMPLEMENTED', function (name) {
|
||||
return 'The ' + name + ' method is not implemented';
|
||||
});
|
||||
createErrorType('ERR_STREAM_PREMATURE_CLOSE', 'Premature close');
|
||||
createErrorType('ERR_STREAM_DESTROYED', function (name) {
|
||||
return 'Cannot call ' + name + ' after a stream was destroyed';
|
||||
});
|
||||
createErrorType('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times');
|
||||
createErrorType('ERR_STREAM_CANNOT_PIPE', 'Cannot pipe, not readable');
|
||||
createErrorType('ERR_STREAM_WRITE_AFTER_END', 'write after end');
|
||||
createErrorType('ERR_STREAM_NULL_VALUES', 'May not write null values to stream', TypeError);
|
||||
createErrorType('ERR_UNKNOWN_ENCODING', function (arg) {
|
||||
return 'Unknown encoding: ' + arg;
|
||||
}, TypeError);
|
||||
createErrorType('ERR_STREAM_UNSHIFT_AFTER_END_EVENT', 'stream.unshift() after end event');
|
||||
module.exports.codes = codes;
|
||||
116
node_modules/spdy-transport/node_modules/readable-stream/errors.js
generated
vendored
Normal file
116
node_modules/spdy-transport/node_modules/readable-stream/errors.js
generated
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
'use strict';
|
||||
|
||||
const codes = {};
|
||||
|
||||
function createErrorType(code, message, Base) {
|
||||
if (!Base) {
|
||||
Base = Error
|
||||
}
|
||||
|
||||
function getMessage (arg1, arg2, arg3) {
|
||||
if (typeof message === 'string') {
|
||||
return message
|
||||
} else {
|
||||
return message(arg1, arg2, arg3)
|
||||
}
|
||||
}
|
||||
|
||||
class NodeError extends Base {
|
||||
constructor (arg1, arg2, arg3) {
|
||||
super(getMessage(arg1, arg2, arg3));
|
||||
}
|
||||
}
|
||||
|
||||
NodeError.prototype.name = Base.name;
|
||||
NodeError.prototype.code = code;
|
||||
|
||||
codes[code] = NodeError;
|
||||
}
|
||||
|
||||
// https://github.com/nodejs/node/blob/v10.8.0/lib/internal/errors.js
|
||||
function oneOf(expected, thing) {
|
||||
if (Array.isArray(expected)) {
|
||||
const len = expected.length;
|
||||
expected = expected.map((i) => String(i));
|
||||
if (len > 2) {
|
||||
return `one of ${thing} ${expected.slice(0, len - 1).join(', ')}, or ` +
|
||||
expected[len - 1];
|
||||
} else if (len === 2) {
|
||||
return `one of ${thing} ${expected[0]} or ${expected[1]}`;
|
||||
} else {
|
||||
return `of ${thing} ${expected[0]}`;
|
||||
}
|
||||
} else {
|
||||
return `of ${thing} ${String(expected)}`;
|
||||
}
|
||||
}
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith
|
||||
function startsWith(str, search, pos) {
|
||||
return str.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search;
|
||||
}
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
|
||||
function endsWith(str, search, this_len) {
|
||||
if (this_len === undefined || this_len > str.length) {
|
||||
this_len = str.length;
|
||||
}
|
||||
return str.substring(this_len - search.length, this_len) === search;
|
||||
}
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes
|
||||
function includes(str, search, start) {
|
||||
if (typeof start !== 'number') {
|
||||
start = 0;
|
||||
}
|
||||
|
||||
if (start + search.length > str.length) {
|
||||
return false;
|
||||
} else {
|
||||
return str.indexOf(search, start) !== -1;
|
||||
}
|
||||
}
|
||||
|
||||
createErrorType('ERR_INVALID_OPT_VALUE', function (name, value) {
|
||||
return 'The value "' + value + '" is invalid for option "' + name + '"'
|
||||
}, TypeError);
|
||||
createErrorType('ERR_INVALID_ARG_TYPE', function (name, expected, actual) {
|
||||
// determiner: 'must be' or 'must not be'
|
||||
let determiner;
|
||||
if (typeof expected === 'string' && startsWith(expected, 'not ')) {
|
||||
determiner = 'must not be';
|
||||
expected = expected.replace(/^not /, '');
|
||||
} else {
|
||||
determiner = 'must be';
|
||||
}
|
||||
|
||||
let msg;
|
||||
if (endsWith(name, ' argument')) {
|
||||
// For cases like 'first argument'
|
||||
msg = `The ${name} ${determiner} ${oneOf(expected, 'type')}`;
|
||||
} else {
|
||||
const type = includes(name, '.') ? 'property' : 'argument';
|
||||
msg = `The "${name}" ${type} ${determiner} ${oneOf(expected, 'type')}`;
|
||||
}
|
||||
|
||||
msg += `. Received type ${typeof actual}`;
|
||||
return msg;
|
||||
}, TypeError);
|
||||
createErrorType('ERR_STREAM_PUSH_AFTER_EOF', 'stream.push() after EOF');
|
||||
createErrorType('ERR_METHOD_NOT_IMPLEMENTED', function (name) {
|
||||
return 'The ' + name + ' method is not implemented'
|
||||
});
|
||||
createErrorType('ERR_STREAM_PREMATURE_CLOSE', 'Premature close');
|
||||
createErrorType('ERR_STREAM_DESTROYED', function (name) {
|
||||
return 'Cannot call ' + name + ' after a stream was destroyed';
|
||||
});
|
||||
createErrorType('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times');
|
||||
createErrorType('ERR_STREAM_CANNOT_PIPE', 'Cannot pipe, not readable');
|
||||
createErrorType('ERR_STREAM_WRITE_AFTER_END', 'write after end');
|
||||
createErrorType('ERR_STREAM_NULL_VALUES', 'May not write null values to stream', TypeError);
|
||||
createErrorType('ERR_UNKNOWN_ENCODING', function (arg) {
|
||||
return 'Unknown encoding: ' + arg
|
||||
}, TypeError);
|
||||
createErrorType('ERR_STREAM_UNSHIFT_AFTER_END_EVENT', 'stream.unshift() after end event');
|
||||
|
||||
module.exports.codes = codes;
|
||||
17
node_modules/spdy-transport/node_modules/readable-stream/experimentalWarning.js
generated
vendored
Normal file
17
node_modules/spdy-transport/node_modules/readable-stream/experimentalWarning.js
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
'use strict'
|
||||
|
||||
var experimentalWarnings = new Set();
|
||||
|
||||
function emitExperimentalWarning(feature) {
|
||||
if (experimentalWarnings.has(feature)) return;
|
||||
var msg = feature + ' is an experimental feature. This feature could ' +
|
||||
'change at any time';
|
||||
experimentalWarnings.add(feature);
|
||||
process.emitWarning(msg, 'ExperimentalWarning');
|
||||
}
|
||||
|
||||
function noop() {}
|
||||
|
||||
module.exports.emitExperimentalWarning = process.emitWarning
|
||||
? emitExperimentalWarning
|
||||
: noop;
|
||||
139
node_modules/spdy-transport/node_modules/readable-stream/lib/_stream_duplex.js
generated
vendored
Normal file
139
node_modules/spdy-transport/node_modules/readable-stream/lib/_stream_duplex.js
generated
vendored
Normal file
@ -0,0 +1,139 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// a duplex stream is just a stream that is both readable and writable.
|
||||
// Since JS doesn't have multiple prototypal inheritance, this class
|
||||
// prototypally inherits from Readable, and then parasitically from
|
||||
// Writable.
|
||||
'use strict';
|
||||
/*<replacement>*/
|
||||
|
||||
var objectKeys = Object.keys || function (obj) {
|
||||
var keys = [];
|
||||
|
||||
for (var key in obj) {
|
||||
keys.push(key);
|
||||
}
|
||||
|
||||
return keys;
|
||||
};
|
||||
/*</replacement>*/
|
||||
|
||||
|
||||
module.exports = Duplex;
|
||||
|
||||
var Readable = require('./_stream_readable');
|
||||
|
||||
var Writable = require('./_stream_writable');
|
||||
|
||||
require('inherits')(Duplex, Readable);
|
||||
|
||||
{
|
||||
// Allow the keys array to be GC'ed.
|
||||
var keys = objectKeys(Writable.prototype);
|
||||
|
||||
for (var v = 0; v < keys.length; v++) {
|
||||
var method = keys[v];
|
||||
if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method];
|
||||
}
|
||||
}
|
||||
|
||||
function Duplex(options) {
|
||||
if (!(this instanceof Duplex)) return new Duplex(options);
|
||||
Readable.call(this, options);
|
||||
Writable.call(this, options);
|
||||
this.allowHalfOpen = true;
|
||||
|
||||
if (options) {
|
||||
if (options.readable === false) this.readable = false;
|
||||
if (options.writable === false) this.writable = false;
|
||||
|
||||
if (options.allowHalfOpen === false) {
|
||||
this.allowHalfOpen = false;
|
||||
this.once('end', onend);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', {
|
||||
// making it explicit this property is not enumerable
|
||||
// because otherwise some prototype manipulation in
|
||||
// userland will fail
|
||||
enumerable: false,
|
||||
get: function get() {
|
||||
return this._writableState.highWaterMark;
|
||||
}
|
||||
});
|
||||
Object.defineProperty(Duplex.prototype, 'writableBuffer', {
|
||||
// making it explicit this property is not enumerable
|
||||
// because otherwise some prototype manipulation in
|
||||
// userland will fail
|
||||
enumerable: false,
|
||||
get: function get() {
|
||||
return this._writableState && this._writableState.getBuffer();
|
||||
}
|
||||
});
|
||||
Object.defineProperty(Duplex.prototype, 'writableLength', {
|
||||
// making it explicit this property is not enumerable
|
||||
// because otherwise some prototype manipulation in
|
||||
// userland will fail
|
||||
enumerable: false,
|
||||
get: function get() {
|
||||
return this._writableState.length;
|
||||
}
|
||||
}); // the no-half-open enforcer
|
||||
|
||||
function onend() {
|
||||
// If the writable side ended, then we're ok.
|
||||
if (this._writableState.ended) return; // no more data can be written.
|
||||
// But allow more writes to happen in this tick.
|
||||
|
||||
process.nextTick(onEndNT, this);
|
||||
}
|
||||
|
||||
function onEndNT(self) {
|
||||
self.end();
|
||||
}
|
||||
|
||||
Object.defineProperty(Duplex.prototype, 'destroyed', {
|
||||
// making it explicit this property is not enumerable
|
||||
// because otherwise some prototype manipulation in
|
||||
// userland will fail
|
||||
enumerable: false,
|
||||
get: function get() {
|
||||
if (this._readableState === undefined || this._writableState === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this._readableState.destroyed && this._writableState.destroyed;
|
||||
},
|
||||
set: function set(value) {
|
||||
// we ignore the value if the stream
|
||||
// has not been initialized yet
|
||||
if (this._readableState === undefined || this._writableState === undefined) {
|
||||
return;
|
||||
} // backward compatibility, the user is explicitly
|
||||
// managing destroyed
|
||||
|
||||
|
||||
this._readableState.destroyed = value;
|
||||
this._writableState.destroyed = value;
|
||||
}
|
||||
});
|
||||
39
node_modules/spdy-transport/node_modules/readable-stream/lib/_stream_passthrough.js
generated
vendored
Normal file
39
node_modules/spdy-transport/node_modules/readable-stream/lib/_stream_passthrough.js
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// a passthrough stream.
|
||||
// basically just the most minimal sort of Transform stream.
|
||||
// Every written chunk gets output as-is.
|
||||
'use strict';
|
||||
|
||||
module.exports = PassThrough;
|
||||
|
||||
var Transform = require('./_stream_transform');
|
||||
|
||||
require('inherits')(PassThrough, Transform);
|
||||
|
||||
function PassThrough(options) {
|
||||
if (!(this instanceof PassThrough)) return new PassThrough(options);
|
||||
Transform.call(this, options);
|
||||
}
|
||||
|
||||
PassThrough.prototype._transform = function (chunk, encoding, cb) {
|
||||
cb(null, chunk);
|
||||
};
|
||||
1087
node_modules/spdy-transport/node_modules/readable-stream/lib/_stream_readable.js
generated
vendored
Normal file
1087
node_modules/spdy-transport/node_modules/readable-stream/lib/_stream_readable.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
201
node_modules/spdy-transport/node_modules/readable-stream/lib/_stream_transform.js
generated
vendored
Normal file
201
node_modules/spdy-transport/node_modules/readable-stream/lib/_stream_transform.js
generated
vendored
Normal file
@ -0,0 +1,201 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// a transform stream is a readable/writable stream where you do
|
||||
// something with the data. Sometimes it's called a "filter",
|
||||
// but that's not a great name for it, since that implies a thing where
|
||||
// some bits pass through, and others are simply ignored. (That would
|
||||
// be a valid example of a transform, of course.)
|
||||
//
|
||||
// While the output is causally related to the input, it's not a
|
||||
// necessarily symmetric or synchronous transformation. For example,
|
||||
// a zlib stream might take multiple plain-text writes(), and then
|
||||
// emit a single compressed chunk some time in the future.
|
||||
//
|
||||
// Here's how this works:
|
||||
//
|
||||
// The Transform stream has all the aspects of the readable and writable
|
||||
// stream classes. When you write(chunk), that calls _write(chunk,cb)
|
||||
// internally, and returns false if there's a lot of pending writes
|
||||
// buffered up. When you call read(), that calls _read(n) until
|
||||
// there's enough pending readable data buffered up.
|
||||
//
|
||||
// In a transform stream, the written data is placed in a buffer. When
|
||||
// _read(n) is called, it transforms the queued up data, calling the
|
||||
// buffered _write cb's as it consumes chunks. If consuming a single
|
||||
// written chunk would result in multiple output chunks, then the first
|
||||
// outputted bit calls the readcb, and subsequent chunks just go into
|
||||
// the read buffer, and will cause it to emit 'readable' if necessary.
|
||||
//
|
||||
// This way, back-pressure is actually determined by the reading side,
|
||||
// since _read has to be called to start processing a new chunk. However,
|
||||
// a pathological inflate type of transform can cause excessive buffering
|
||||
// here. For example, imagine a stream where every byte of input is
|
||||
// interpreted as an integer from 0-255, and then results in that many
|
||||
// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in
|
||||
// 1kb of data being output. In this case, you could write a very small
|
||||
// amount of input, and end up with a very large amount of output. In
|
||||
// such a pathological inflating mechanism, there'd be no way to tell
|
||||
// the system to stop doing the transform. A single 4MB write could
|
||||
// cause the system to run out of memory.
|
||||
//
|
||||
// However, even in such a pathological case, only a single written chunk
|
||||
// would be consumed, and then the rest would wait (un-transformed) until
|
||||
// the results of the previous transformed chunk were consumed.
|
||||
'use strict';
|
||||
|
||||
module.exports = Transform;
|
||||
|
||||
var _require$codes = require('../errors').codes,
|
||||
ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED,
|
||||
ERR_MULTIPLE_CALLBACK = _require$codes.ERR_MULTIPLE_CALLBACK,
|
||||
ERR_TRANSFORM_ALREADY_TRANSFORMING = _require$codes.ERR_TRANSFORM_ALREADY_TRANSFORMING,
|
||||
ERR_TRANSFORM_WITH_LENGTH_0 = _require$codes.ERR_TRANSFORM_WITH_LENGTH_0;
|
||||
|
||||
var Duplex = require('./_stream_duplex');
|
||||
|
||||
require('inherits')(Transform, Duplex);
|
||||
|
||||
function afterTransform(er, data) {
|
||||
var ts = this._transformState;
|
||||
ts.transforming = false;
|
||||
var cb = ts.writecb;
|
||||
|
||||
if (cb === null) {
|
||||
return this.emit('error', new ERR_MULTIPLE_CALLBACK());
|
||||
}
|
||||
|
||||
ts.writechunk = null;
|
||||
ts.writecb = null;
|
||||
if (data != null) // single equals check for both `null` and `undefined`
|
||||
this.push(data);
|
||||
cb(er);
|
||||
var rs = this._readableState;
|
||||
rs.reading = false;
|
||||
|
||||
if (rs.needReadable || rs.length < rs.highWaterMark) {
|
||||
this._read(rs.highWaterMark);
|
||||
}
|
||||
}
|
||||
|
||||
function Transform(options) {
|
||||
if (!(this instanceof Transform)) return new Transform(options);
|
||||
Duplex.call(this, options);
|
||||
this._transformState = {
|
||||
afterTransform: afterTransform.bind(this),
|
||||
needTransform: false,
|
||||
transforming: false,
|
||||
writecb: null,
|
||||
writechunk: null,
|
||||
writeencoding: null
|
||||
}; // start out asking for a readable event once data is transformed.
|
||||
|
||||
this._readableState.needReadable = true; // we have implemented the _read method, and done the other things
|
||||
// that Readable wants before the first _read call, so unset the
|
||||
// sync guard flag.
|
||||
|
||||
this._readableState.sync = false;
|
||||
|
||||
if (options) {
|
||||
if (typeof options.transform === 'function') this._transform = options.transform;
|
||||
if (typeof options.flush === 'function') this._flush = options.flush;
|
||||
} // When the writable side finishes, then flush out anything remaining.
|
||||
|
||||
|
||||
this.on('prefinish', prefinish);
|
||||
}
|
||||
|
||||
function prefinish() {
|
||||
var _this = this;
|
||||
|
||||
if (typeof this._flush === 'function' && !this._readableState.destroyed) {
|
||||
this._flush(function (er, data) {
|
||||
done(_this, er, data);
|
||||
});
|
||||
} else {
|
||||
done(this, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
Transform.prototype.push = function (chunk, encoding) {
|
||||
this._transformState.needTransform = false;
|
||||
return Duplex.prototype.push.call(this, chunk, encoding);
|
||||
}; // This is the part where you do stuff!
|
||||
// override this function in implementation classes.
|
||||
// 'chunk' is an input chunk.
|
||||
//
|
||||
// Call `push(newChunk)` to pass along transformed output
|
||||
// to the readable side. You may call 'push' zero or more times.
|
||||
//
|
||||
// Call `cb(err)` when you are done with this chunk. If you pass
|
||||
// an error, then that'll put the hurt on the whole operation. If you
|
||||
// never call cb(), then you'll never get another chunk.
|
||||
|
||||
|
||||
Transform.prototype._transform = function (chunk, encoding, cb) {
|
||||
cb(new ERR_METHOD_NOT_IMPLEMENTED('_transform()'));
|
||||
};
|
||||
|
||||
Transform.prototype._write = function (chunk, encoding, cb) {
|
||||
var ts = this._transformState;
|
||||
ts.writecb = cb;
|
||||
ts.writechunk = chunk;
|
||||
ts.writeencoding = encoding;
|
||||
|
||||
if (!ts.transforming) {
|
||||
var rs = this._readableState;
|
||||
if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark);
|
||||
}
|
||||
}; // Doesn't matter what the args are here.
|
||||
// _transform does all the work.
|
||||
// That we got here means that the readable side wants more data.
|
||||
|
||||
|
||||
Transform.prototype._read = function (n) {
|
||||
var ts = this._transformState;
|
||||
|
||||
if (ts.writechunk !== null && !ts.transforming) {
|
||||
ts.transforming = true;
|
||||
|
||||
this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
|
||||
} else {
|
||||
// mark that we need a transform, so that any data that comes in
|
||||
// will get processed, now that we've asked for it.
|
||||
ts.needTransform = true;
|
||||
}
|
||||
};
|
||||
|
||||
Transform.prototype._destroy = function (err, cb) {
|
||||
Duplex.prototype._destroy.call(this, err, function (err2) {
|
||||
cb(err2);
|
||||
});
|
||||
};
|
||||
|
||||
function done(stream, er, data) {
|
||||
if (er) return stream.emit('error', er);
|
||||
if (data != null) // single equals check for both `null` and `undefined`
|
||||
stream.push(data); // TODO(BridgeAR): Write a test for these two error cases
|
||||
// if there's nothing in the write buffer, then that means
|
||||
// that nothing more will ever be provided
|
||||
|
||||
if (stream._writableState.length) throw new ERR_TRANSFORM_WITH_LENGTH_0();
|
||||
if (stream._transformState.transforming) throw new ERR_TRANSFORM_ALREADY_TRANSFORMING();
|
||||
return stream.push(null);
|
||||
}
|
||||
683
node_modules/spdy-transport/node_modules/readable-stream/lib/_stream_writable.js
generated
vendored
Normal file
683
node_modules/spdy-transport/node_modules/readable-stream/lib/_stream_writable.js
generated
vendored
Normal file
@ -0,0 +1,683 @@
|
||||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
// persons to whom the Software is furnished to do so, subject to the
|
||||
// following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
// A bit simpler than readable streams.
|
||||
// Implement an async ._write(chunk, encoding, cb), and it'll handle all
|
||||
// the drain event emission and buffering.
|
||||
'use strict';
|
||||
|
||||
module.exports = Writable;
|
||||
/* <replacement> */
|
||||
|
||||
function WriteReq(chunk, encoding, cb) {
|
||||
this.chunk = chunk;
|
||||
this.encoding = encoding;
|
||||
this.callback = cb;
|
||||
this.next = null;
|
||||
} // It seems a linked list but it is not
|
||||
// there will be only 2 of these for each stream
|
||||
|
||||
|
||||
function CorkedRequest(state) {
|
||||
var _this = this;
|
||||
|
||||
this.next = null;
|
||||
this.entry = null;
|
||||
|
||||
this.finish = function () {
|
||||
onCorkedFinish(_this, state);
|
||||
};
|
||||
}
|
||||
/* </replacement> */
|
||||
|
||||
/*<replacement>*/
|
||||
|
||||
|
||||
var Duplex;
|
||||
/*</replacement>*/
|
||||
|
||||
Writable.WritableState = WritableState;
|
||||
/*<replacement>*/
|
||||
|
||||
var internalUtil = {
|
||||
deprecate: require('util-deprecate')
|
||||
};
|
||||
/*</replacement>*/
|
||||
|
||||
/*<replacement>*/
|
||||
|
||||
var Stream = require('./internal/streams/stream');
|
||||
/*</replacement>*/
|
||||
|
||||
|
||||
var Buffer = require('buffer').Buffer;
|
||||
|
||||
var OurUint8Array = global.Uint8Array || function () {};
|
||||
|
||||
function _uint8ArrayToBuffer(chunk) {
|
||||
return Buffer.from(chunk);
|
||||
}
|
||||
|
||||
function _isUint8Array(obj) {
|
||||
return Buffer.isBuffer(obj) || obj instanceof OurUint8Array;
|
||||
}
|
||||
|
||||
var destroyImpl = require('./internal/streams/destroy');
|
||||
|
||||
var _require = require('./internal/streams/state'),
|
||||
getHighWaterMark = _require.getHighWaterMark;
|
||||
|
||||
var _require$codes = require('../errors').codes,
|
||||
ERR_INVALID_ARG_TYPE = _require$codes.ERR_INVALID_ARG_TYPE,
|
||||
ERR_METHOD_NOT_IMPLEMENTED = _require$codes.ERR_METHOD_NOT_IMPLEMENTED,
|
||||
ERR_MULTIPLE_CALLBACK = _require$codes.ERR_MULTIPLE_CALLBACK,
|
||||
ERR_STREAM_CANNOT_PIPE = _require$codes.ERR_STREAM_CANNOT_PIPE,
|
||||
ERR_STREAM_DESTROYED = _require$codes.ERR_STREAM_DESTROYED,
|
||||
ERR_STREAM_NULL_VALUES = _require$codes.ERR_STREAM_NULL_VALUES,
|
||||
ERR_STREAM_WRITE_AFTER_END = _require$codes.ERR_STREAM_WRITE_AFTER_END,
|
||||
ERR_UNKNOWN_ENCODING = _require$codes.ERR_UNKNOWN_ENCODING;
|
||||
|
||||
require('inherits')(Writable, Stream);
|
||||
|
||||
function nop() {}
|
||||
|
||||
function WritableState(options, stream, isDuplex) {
|
||||
Duplex = Duplex || require('./_stream_duplex');
|
||||
options = options || {}; // Duplex streams are both readable and writable, but share
|
||||
// the same options object.
|
||||
// However, some cases require setting options to different
|
||||
// values for the readable and the writable sides of the duplex stream,
|
||||
// e.g. options.readableObjectMode vs. options.writableObjectMode, etc.
|
||||
|
||||
if (typeof isDuplex !== 'boolean') isDuplex = stream instanceof Duplex; // object stream flag to indicate whether or not this stream
|
||||
// contains buffers or objects.
|
||||
|
||||
this.objectMode = !!options.objectMode;
|
||||
if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode; // the point at which write() starts returning false
|
||||
// Note: 0 is a valid value, means that we always return false if
|
||||
// the entire buffer is not flushed immediately on write()
|
||||
|
||||
this.highWaterMark = getHighWaterMark(this, options, 'writableHighWaterMark', isDuplex); // if _final has been called
|
||||
|
||||
this.finalCalled = false; // drain event flag.
|
||||
|
||||
this.needDrain = false; // at the start of calling end()
|
||||
|
||||
this.ending = false; // when end() has been called, and returned
|
||||
|
||||
this.ended = false; // when 'finish' is emitted
|
||||
|
||||
this.finished = false; // has it been destroyed
|
||||
|
||||
this.destroyed = false; // should we decode strings into buffers before passing to _write?
|
||||
// this is here so that some node-core streams can optimize string
|
||||
// handling at a lower level.
|
||||
|
||||
var noDecode = options.decodeStrings === false;
|
||||
this.decodeStrings = !noDecode; // Crypto is kind of old and crusty. Historically, its default string
|
||||
// encoding is 'binary' so we have to make this configurable.
|
||||
// Everything else in the universe uses 'utf8', though.
|
||||
|
||||
this.defaultEncoding = options.defaultEncoding || 'utf8'; // not an actual buffer we keep track of, but a measurement
|
||||
// of how much we're waiting to get pushed to some underlying
|
||||
// socket or file.
|
||||
|
||||
this.length = 0; // a flag to see when we're in the middle of a write.
|
||||
|
||||
this.writing = false; // when true all writes will be buffered until .uncork() call
|
||||
|
||||
this.corked = 0; // a flag to be able to tell if the onwrite cb is called immediately,
|
||||
// or on a later tick. We set this to true at first, because any
|
||||
// actions that shouldn't happen until "later" should generally also
|
||||
// not happen before the first write call.
|
||||
|
||||
this.sync = true; // a flag to know if we're processing previously buffered items, which
|
||||
// may call the _write() callback in the same tick, so that we don't
|
||||
// end up in an overlapped onwrite situation.
|
||||
|
||||
this.bufferProcessing = false; // the callback that's passed to _write(chunk,cb)
|
||||
|
||||
this.onwrite = function (er) {
|
||||
onwrite(stream, er);
|
||||
}; // the callback that the user supplies to write(chunk,encoding,cb)
|
||||
|
||||
|
||||
this.writecb = null; // the amount that is being written when _write is called.
|
||||
|
||||
this.writelen = 0;
|
||||
this.bufferedRequest = null;
|
||||
this.lastBufferedRequest = null; // number of pending user-supplied write callbacks
|
||||
// this must be 0 before 'finish' can be emitted
|
||||
|
||||
this.pendingcb = 0; // emit prefinish if the only thing we're waiting for is _write cbs
|
||||
// This is relevant for synchronous Transform streams
|
||||
|
||||
this.prefinished = false; // True if the error was already emitted and should not be thrown again
|
||||
|
||||
this.errorEmitted = false; // Should close be emitted on destroy. Defaults to true.
|
||||
|
||||
this.emitClose = options.emitClose !== false; // count buffered requests
|
||||
|
||||
this.bufferedRequestCount = 0; // allocate the first CorkedRequest, there is always
|
||||
// one allocated and free to use, and we maintain at most two
|
||||
|
||||
this.corkedRequestsFree = new CorkedRequest(this);
|
||||
}
|
||||
|
||||
WritableState.prototype.getBuffer = function getBuffer() {
|
||||
var current = this.bufferedRequest;
|
||||
var out = [];
|
||||
|
||||
while (current) {
|
||||
out.push(current);
|
||||
current = current.next;
|
||||
}
|
||||
|
||||
return out;
|
||||
};
|
||||
|
||||
(function () {
|
||||
try {
|
||||
Object.defineProperty(WritableState.prototype, 'buffer', {
|
||||
get: internalUtil.deprecate(function writableStateBufferGetter() {
|
||||
return this.getBuffer();
|
||||
}, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003')
|
||||
});
|
||||
} catch (_) {}
|
||||
})(); // Test _writableState for inheritance to account for Duplex streams,
|
||||
// whose prototype chain only points to Readable.
|
||||
|
||||
|
||||
var realHasInstance;
|
||||
|
||||
if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') {
|
||||
realHasInstance = Function.prototype[Symbol.hasInstance];
|
||||
Object.defineProperty(Writable, Symbol.hasInstance, {
|
||||
value: function value(object) {
|
||||
if (realHasInstance.call(this, object)) return true;
|
||||
if (this !== Writable) return false;
|
||||
return object && object._writableState instanceof WritableState;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
realHasInstance = function realHasInstance(object) {
|
||||
return object instanceof this;
|
||||
};
|
||||
}
|
||||
|
||||
function Writable(options) {
|
||||
Duplex = Duplex || require('./_stream_duplex'); // Writable ctor is applied to Duplexes, too.
|
||||
// `realHasInstance` is necessary because using plain `instanceof`
|
||||
// would return false, as no `_writableState` property is attached.
|
||||
// Trying to use the custom `instanceof` for Writable here will also break the
|
||||
// Node.js LazyTransform implementation, which has a non-trivial getter for
|
||||
// `_writableState` that would lead to infinite recursion.
|
||||
// Checking for a Stream.Duplex instance is faster here instead of inside
|
||||
// the WritableState constructor, at least with V8 6.5
|
||||
|
||||
var isDuplex = this instanceof Duplex;
|
||||
if (!isDuplex && !realHasInstance.call(Writable, this)) return new Writable(options);
|
||||
this._writableState = new WritableState(options, this, isDuplex); // legacy.
|
||||
|
||||
this.writable = true;
|
||||
|
||||
if (options) {
|
||||
if (typeof options.write === 'function') this._write = options.write;
|
||||
if (typeof options.writev === 'function') this._writev = options.writev;
|
||||
if (typeof options.destroy === 'function') this._destroy = options.destroy;
|
||||
if (typeof options.final === 'function') this._final = options.final;
|
||||
}
|
||||
|
||||
Stream.call(this);
|
||||
} // Otherwise people can pipe Writable streams, which is just wrong.
|
||||
|
||||
|
||||
Writable.prototype.pipe = function () {
|
||||
this.emit('error', new ERR_STREAM_CANNOT_PIPE());
|
||||
};
|
||||
|
||||
function writeAfterEnd(stream, cb) {
|
||||
var er = new ERR_STREAM_WRITE_AFTER_END(); // TODO: defer error events consistently everywhere, not just the cb
|
||||
|
||||
stream.emit('error', er);
|
||||
process.nextTick(cb, er);
|
||||
} // Checks that a user-supplied chunk is valid, especially for the particular
|
||||
// mode the stream is in. Currently this means that `null` is never accepted
|
||||
// and undefined/non-string values are only allowed in object mode.
|
||||
|
||||
|
||||
function validChunk(stream, state, chunk, cb) {
|
||||
var er;
|
||||
|
||||
if (chunk === null) {
|
||||
er = new ERR_STREAM_NULL_VALUES();
|
||||
} else if (typeof chunk !== 'string' && !state.objectMode) {
|
||||
er = new ERR_INVALID_ARG_TYPE('chunk', ['string', 'Buffer'], chunk);
|
||||
}
|
||||
|
||||
if (er) {
|
||||
stream.emit('error', er);
|
||||
process.nextTick(cb, er);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Writable.prototype.write = function (chunk, encoding, cb) {
|
||||
var state = this._writableState;
|
||||
var ret = false;
|
||||
|
||||
var isBuf = !state.objectMode && _isUint8Array(chunk);
|
||||
|
||||
if (isBuf && !Buffer.isBuffer(chunk)) {
|
||||
chunk = _uint8ArrayToBuffer(chunk);
|
||||
}
|
||||
|
||||
if (typeof encoding === 'function') {
|
||||
cb = encoding;
|
||||
encoding = null;
|
||||
}
|
||||
|
||||
if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding;
|
||||
if (typeof cb !== 'function') cb = nop;
|
||||
if (state.ending) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) {
|
||||
state.pendingcb++;
|
||||
ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb);
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
Writable.prototype.cork = function () {
|
||||
this._writableState.corked++;
|
||||
};
|
||||
|
||||
Writable.prototype.uncork = function () {
|
||||
var state = this._writableState;
|
||||
|
||||
if (state.corked) {
|
||||
state.corked--;
|
||||
if (!state.writing && !state.corked && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state);
|
||||
}
|
||||
};
|
||||
|
||||
Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) {
|
||||
// node::ParseEncoding() requires lower case.
|
||||
if (typeof encoding === 'string') encoding = encoding.toLowerCase();
|
||||
if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new ERR_UNKNOWN_ENCODING(encoding);
|
||||
this._writableState.defaultEncoding = encoding;
|
||||
return this;
|
||||
};
|
||||
|
||||
Object.defineProperty(Writable.prototype, 'writableBuffer', {
|
||||
// making it explicit this property is not enumerable
|
||||
// because otherwise some prototype manipulation in
|
||||
// userland will fail
|
||||
enumerable: false,
|
||||
get: function get() {
|
||||
return this._writableState && this._writableState.getBuffer();
|
||||
}
|
||||
});
|
||||
|
||||
function decodeChunk(state, chunk, encoding) {
|
||||
if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') {
|
||||
chunk = Buffer.from(chunk, encoding);
|
||||
}
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
Object.defineProperty(Writable.prototype, 'writableHighWaterMark', {
|
||||
// making it explicit this property is not enumerable
|
||||
// because otherwise some prototype manipulation in
|
||||
// userland will fail
|
||||
enumerable: false,
|
||||
get: function get() {
|
||||
return this._writableState.highWaterMark;
|
||||
}
|
||||
}); // if we're already writing something, then just put this
|
||||
// in the queue, and wait our turn. Otherwise, call _write
|
||||
// If we return false, then we need a drain event, so set that flag.
|
||||
|
||||
function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) {
|
||||
if (!isBuf) {
|
||||
var newChunk = decodeChunk(state, chunk, encoding);
|
||||
|
||||
if (chunk !== newChunk) {
|
||||
isBuf = true;
|
||||
encoding = 'buffer';
|
||||
chunk = newChunk;
|
||||
}
|
||||
}
|
||||
|
||||
var len = state.objectMode ? 1 : chunk.length;
|
||||
state.length += len;
|
||||
var ret = state.length < state.highWaterMark; // we must ensure that previous needDrain will not be reset to false.
|
||||
|
||||
if (!ret) state.needDrain = true;
|
||||
|
||||
if (state.writing || state.corked) {
|
||||
var last = state.lastBufferedRequest;
|
||||
state.lastBufferedRequest = {
|
||||
chunk: chunk,
|
||||
encoding: encoding,
|
||||
isBuf: isBuf,
|
||||
callback: cb,
|
||||
next: null
|
||||
};
|
||||
|
||||
if (last) {
|
||||
last.next = state.lastBufferedRequest;
|
||||
} else {
|
||||
state.bufferedRequest = state.lastBufferedRequest;
|
||||
}
|
||||
|
||||
state.bufferedRequestCount += 1;
|
||||
} else {
|
||||
doWrite(stream, state, false, len, chunk, encoding, cb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
function doWrite(stream, state, writev, len, chunk, encoding, cb) {
|
||||
state.writelen = len;
|
||||
state.writecb = cb;
|
||||
state.writing = true;
|
||||
state.sync = true;
|
||||
if (state.destroyed) state.onwrite(new ERR_STREAM_DESTROYED('write'));else if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite);
|
||||
state.sync = false;
|
||||
}
|
||||
|
||||
function onwriteError(stream, state, sync, er, cb) {
|
||||
--state.pendingcb;
|
||||
|
||||
if (sync) {
|
||||
// defer the callback if we are being called synchronously
|
||||
// to avoid piling up things on the stack
|
||||
process.nextTick(cb, er); // this can emit finish, and it will always happen
|
||||
// after error
|
||||
|
||||
process.nextTick(finishMaybe, stream, state);
|
||||
stream._writableState.errorEmitted = true;
|
||||
stream.emit('error', er);
|
||||
} else {
|
||||
// the caller expect this to happen before if
|
||||
// it is async
|
||||
cb(er);
|
||||
stream._writableState.errorEmitted = true;
|
||||
stream.emit('error', er); // this can emit finish, but finish must
|
||||
// always follow error
|
||||
|
||||
finishMaybe(stream, state);
|
||||
}
|
||||
}
|
||||
|
||||
function onwriteStateUpdate(state) {
|
||||
state.writing = false;
|
||||
state.writecb = null;
|
||||
state.length -= state.writelen;
|
||||
state.writelen = 0;
|
||||
}
|
||||
|
||||
function onwrite(stream, er) {
|
||||
var state = stream._writableState;
|
||||
var sync = state.sync;
|
||||
var cb = state.writecb;
|
||||
if (typeof cb !== 'function') throw new ERR_MULTIPLE_CALLBACK();
|
||||
onwriteStateUpdate(state);
|
||||
if (er) onwriteError(stream, state, sync, er, cb);else {
|
||||
// Check if we're actually ready to finish, but don't emit yet
|
||||
var finished = needFinish(state) || stream.destroyed;
|
||||
|
||||
if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) {
|
||||
clearBuffer(stream, state);
|
||||
}
|
||||
|
||||
if (sync) {
|
||||
process.nextTick(afterWrite, stream, state, finished, cb);
|
||||
} else {
|
||||
afterWrite(stream, state, finished, cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function afterWrite(stream, state, finished, cb) {
|
||||
if (!finished) onwriteDrain(stream, state);
|
||||
state.pendingcb--;
|
||||
cb();
|
||||
finishMaybe(stream, state);
|
||||
} // Must force callback to be called on nextTick, so that we don't
|
||||
// emit 'drain' before the write() consumer gets the 'false' return
|
||||
// value, and has a chance to attach a 'drain' listener.
|
||||
|
||||
|
||||
function onwriteDrain(stream, state) {
|
||||
if (state.length === 0 && state.needDrain) {
|
||||
state.needDrain = false;
|
||||
stream.emit('drain');
|
||||
}
|
||||
} // if there's something in the buffer waiting, then process it
|
||||
|
||||
|
||||
function clearBuffer(stream, state) {
|
||||
state.bufferProcessing = true;
|
||||
var entry = state.bufferedRequest;
|
||||
|
||||
if (stream._writev && entry && entry.next) {
|
||||
// Fast case, write everything using _writev()
|
||||
var l = state.bufferedRequestCount;
|
||||
var buffer = new Array(l);
|
||||
var holder = state.corkedRequestsFree;
|
||||
holder.entry = entry;
|
||||
var count = 0;
|
||||
var allBuffers = true;
|
||||
|
||||
while (entry) {
|
||||
buffer[count] = entry;
|
||||
if (!entry.isBuf) allBuffers = false;
|
||||
entry = entry.next;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
buffer.allBuffers = allBuffers;
|
||||
doWrite(stream, state, true, state.length, buffer, '', holder.finish); // doWrite is almost always async, defer these to save a bit of time
|
||||
// as the hot path ends with doWrite
|
||||
|
||||
state.pendingcb++;
|
||||
state.lastBufferedRequest = null;
|
||||
|
||||
if (holder.next) {
|
||||
state.corkedRequestsFree = holder.next;
|
||||
holder.next = null;
|
||||
} else {
|
||||
state.corkedRequestsFree = new CorkedRequest(state);
|
||||
}
|
||||
|
||||
state.bufferedRequestCount = 0;
|
||||
} else {
|
||||
// Slow case, write chunks one-by-one
|
||||
while (entry) {
|
||||
var chunk = entry.chunk;
|
||||
var encoding = entry.encoding;
|
||||
var cb = entry.callback;
|
||||
var len = state.objectMode ? 1 : chunk.length;
|
||||
doWrite(stream, state, false, len, chunk, encoding, cb);
|
||||
entry = entry.next;
|
||||
state.bufferedRequestCount--; // if we didn't call the onwrite immediately, then
|
||||
// it means that we need to wait until it does.
|
||||
// also, that means that the chunk and cb are currently
|
||||
// being processed, so move the buffer counter past them.
|
||||
|
||||
if (state.writing) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (entry === null) state.lastBufferedRequest = null;
|
||||
}
|
||||
|
||||
state.bufferedRequest = entry;
|
||||
state.bufferProcessing = false;
|
||||
}
|
||||
|
||||
Writable.prototype._write = function (chunk, encoding, cb) {
|
||||
cb(new ERR_METHOD_NOT_IMPLEMENTED('_write()'));
|
||||
};
|
||||
|
||||
Writable.prototype._writev = null;
|
||||
|
||||
Writable.prototype.end = function (chunk, encoding, cb) {
|
||||
var state = this._writableState;
|
||||
|
||||
if (typeof chunk === 'function') {
|
||||
cb = chunk;
|
||||
chunk = null;
|
||||
encoding = null;
|
||||
} else if (typeof encoding === 'function') {
|
||||
cb = encoding;
|
||||
encoding = null;
|
||||
}
|
||||
|
||||
if (chunk !== null && chunk !== undefined) this.write(chunk, encoding); // .end() fully uncorks
|
||||
|
||||
if (state.corked) {
|
||||
state.corked = 1;
|
||||
this.uncork();
|
||||
} // ignore unnecessary end() calls.
|
||||
|
||||
|
||||
if (!state.ending) endWritable(this, state, cb);
|
||||
return this;
|
||||
};
|
||||
|
||||
Object.defineProperty(Writable.prototype, 'writableLength', {
|
||||
// making it explicit this property is not enumerable
|
||||
// because otherwise some prototype manipulation in
|
||||
// userland will fail
|
||||
enumerable: false,
|
||||
get: function get() {
|
||||
return this._writableState.length;
|
||||
}
|
||||
});
|
||||
|
||||
function needFinish(state) {
|
||||
return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing;
|
||||
}
|
||||
|
||||
function callFinal(stream, state) {
|
||||
stream._final(function (err) {
|
||||
state.pendingcb--;
|
||||
|
||||
if (err) {
|
||||
stream.emit('error', err);
|
||||
}
|
||||
|
||||
state.prefinished = true;
|
||||
stream.emit('prefinish');
|
||||
finishMaybe(stream, state);
|
||||
});
|
||||
}
|
||||
|
||||
function prefinish(stream, state) {
|
||||
if (!state.prefinished && !state.finalCalled) {
|
||||
if (typeof stream._final === 'function' && !state.destroyed) {
|
||||
state.pendingcb++;
|
||||
state.finalCalled = true;
|
||||
process.nextTick(callFinal, stream, state);
|
||||
} else {
|
||||
state.prefinished = true;
|
||||
stream.emit('prefinish');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function finishMaybe(stream, state) {
|
||||
var need = needFinish(state);
|
||||
|
||||
if (need) {
|
||||
prefinish(stream, state);
|
||||
|
||||
if (state.pendingcb === 0) {
|
||||
state.finished = true;
|
||||
stream.emit('finish');
|
||||
}
|
||||
}
|
||||
|
||||
return need;
|
||||
}
|
||||
|
||||
function endWritable(stream, state, cb) {
|
||||
state.ending = true;
|
||||
finishMaybe(stream, state);
|
||||
|
||||
if (cb) {
|
||||
if (state.finished) process.nextTick(cb);else stream.once('finish', cb);
|
||||
}
|
||||
|
||||
state.ended = true;
|
||||
stream.writable = false;
|
||||
}
|
||||
|
||||
function onCorkedFinish(corkReq, state, err) {
|
||||
var entry = corkReq.entry;
|
||||
corkReq.entry = null;
|
||||
|
||||
while (entry) {
|
||||
var cb = entry.callback;
|
||||
state.pendingcb--;
|
||||
cb(err);
|
||||
entry = entry.next;
|
||||
} // reuse the free corkReq.
|
||||
|
||||
|
||||
state.corkedRequestsFree.next = corkReq;
|
||||
}
|
||||
|
||||
Object.defineProperty(Writable.prototype, 'destroyed', {
|
||||
// making it explicit this property is not enumerable
|
||||
// because otherwise some prototype manipulation in
|
||||
// userland will fail
|
||||
enumerable: false,
|
||||
get: function get() {
|
||||
if (this._writableState === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this._writableState.destroyed;
|
||||
},
|
||||
set: function set(value) {
|
||||
// we ignore the value if the stream
|
||||
// has not been initialized yet
|
||||
if (!this._writableState) {
|
||||
return;
|
||||
} // backward compatibility, the user is explicitly
|
||||
// managing destroyed
|
||||
|
||||
|
||||
this._writableState.destroyed = value;
|
||||
}
|
||||
});
|
||||
Writable.prototype.destroy = destroyImpl.destroy;
|
||||
Writable.prototype._undestroy = destroyImpl.undestroy;
|
||||
|
||||
Writable.prototype._destroy = function (err, cb) {
|
||||
cb(err);
|
||||
};
|
||||
207
node_modules/spdy-transport/node_modules/readable-stream/lib/internal/streams/async_iterator.js
generated
vendored
Normal file
207
node_modules/spdy-transport/node_modules/readable-stream/lib/internal/streams/async_iterator.js
generated
vendored
Normal file
@ -0,0 +1,207 @@
|
||||
'use strict';
|
||||
|
||||
var _Object$setPrototypeO;
|
||||
|
||||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||
|
||||
var finished = require('./end-of-stream');
|
||||
|
||||
var kLastResolve = Symbol('lastResolve');
|
||||
var kLastReject = Symbol('lastReject');
|
||||
var kError = Symbol('error');
|
||||
var kEnded = Symbol('ended');
|
||||
var kLastPromise = Symbol('lastPromise');
|
||||
var kHandlePromise = Symbol('handlePromise');
|
||||
var kStream = Symbol('stream');
|
||||
|
||||
function createIterResult(value, done) {
|
||||
return {
|
||||
value: value,
|
||||
done: done
|
||||
};
|
||||
}
|
||||
|
||||
function readAndResolve(iter) {
|
||||
var resolve = iter[kLastResolve];
|
||||
|
||||
if (resolve !== null) {
|
||||
var data = iter[kStream].read(); // we defer if data is null
|
||||
// we can be expecting either 'end' or
|
||||
// 'error'
|
||||
|
||||
if (data !== null) {
|
||||
iter[kLastPromise] = null;
|
||||
iter[kLastResolve] = null;
|
||||
iter[kLastReject] = null;
|
||||
resolve(createIterResult(data, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onReadable(iter) {
|
||||
// we wait for the next tick, because it might
|
||||
// emit an error with process.nextTick
|
||||
process.nextTick(readAndResolve, iter);
|
||||
}
|
||||
|
||||
function wrapForNext(lastPromise, iter) {
|
||||
return function (resolve, reject) {
|
||||
lastPromise.then(function () {
|
||||
if (iter[kEnded]) {
|
||||
resolve(createIterResult(undefined, true));
|
||||
return;
|
||||
}
|
||||
|
||||
iter[kHandlePromise](resolve, reject);
|
||||
}, reject);
|
||||
};
|
||||
}
|
||||
|
||||
var AsyncIteratorPrototype = Object.getPrototypeOf(function () {});
|
||||
var ReadableStreamAsyncIteratorPrototype = Object.setPrototypeOf((_Object$setPrototypeO = {
|
||||
get stream() {
|
||||
return this[kStream];
|
||||
},
|
||||
|
||||
next: function next() {
|
||||
var _this = this;
|
||||
|
||||
// if we have detected an error in the meanwhile
|
||||
// reject straight away
|
||||
var error = this[kError];
|
||||
|
||||
if (error !== null) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
if (this[kEnded]) {
|
||||
return Promise.resolve(createIterResult(undefined, true));
|
||||
}
|
||||
|
||||
if (this[kStream].destroyed) {
|
||||
// We need to defer via nextTick because if .destroy(err) is
|
||||
// called, the error will be emitted via nextTick, and
|
||||
// we cannot guarantee that there is no error lingering around
|
||||
// waiting to be emitted.
|
||||
return new Promise(function (resolve, reject) {
|
||||
process.nextTick(function () {
|
||||
if (_this[kError]) {
|
||||
reject(_this[kError]);
|
||||
} else {
|
||||
resolve(createIterResult(undefined, true));
|
||||
}
|
||||
});
|
||||
});
|
||||
} // if we have multiple next() calls
|
||||
// we will wait for the previous Promise to finish
|
||||
// this logic is optimized to support for await loops,
|
||||
// where next() is only called once at a time
|
||||
|
||||
|
||||
var lastPromise = this[kLastPromise];
|
||||
var promise;
|
||||
|
||||
if (lastPromise) {
|
||||
promise = new Promise(wrapForNext(lastPromise, this));
|
||||
} else {
|
||||
// fast path needed to support multiple this.push()
|
||||
// without triggering the next() queue
|
||||
var data = this[kStream].read();
|
||||
|
||||
if (data !== null) {
|
||||
return Promise.resolve(createIterResult(data, false));
|
||||
}
|
||||
|
||||
promise = new Promise(this[kHandlePromise]);
|
||||
}
|
||||
|
||||
this[kLastPromise] = promise;
|
||||
return promise;
|
||||
}
|
||||
}, _defineProperty(_Object$setPrototypeO, Symbol.asyncIterator, function () {
|
||||
return this;
|
||||
}), _defineProperty(_Object$setPrototypeO, "return", function _return() {
|
||||
var _this2 = this;
|
||||
|
||||
// destroy(err, cb) is a private API
|
||||
// we can guarantee we have that here, because we control the
|
||||
// Readable class this is attached to
|
||||
return new Promise(function (resolve, reject) {
|
||||
_this2[kStream].destroy(null, function (err) {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(createIterResult(undefined, true));
|
||||
});
|
||||
});
|
||||
}), _Object$setPrototypeO), AsyncIteratorPrototype);
|
||||
|
||||
var createReadableStreamAsyncIterator = function createReadableStreamAsyncIterator(stream) {
|
||||
var _Object$create;
|
||||
|
||||
var iterator = Object.create(ReadableStreamAsyncIteratorPrototype, (_Object$create = {}, _defineProperty(_Object$create, kStream, {
|
||||
value: stream,
|
||||
writable: true
|
||||
}), _defineProperty(_Object$create, kLastResolve, {
|
||||
value: null,
|
||||
writable: true
|
||||
}), _defineProperty(_Object$create, kLastReject, {
|
||||
value: null,
|
||||
writable: true
|
||||
}), _defineProperty(_Object$create, kError, {
|
||||
value: null,
|
||||
writable: true
|
||||
}), _defineProperty(_Object$create, kEnded, {
|
||||
value: stream._readableState.endEmitted,
|
||||
writable: true
|
||||
}), _defineProperty(_Object$create, kHandlePromise, {
|
||||
value: function value(resolve, reject) {
|
||||
var data = iterator[kStream].read();
|
||||
|
||||
if (data) {
|
||||
iterator[kLastPromise] = null;
|
||||
iterator[kLastResolve] = null;
|
||||
iterator[kLastReject] = null;
|
||||
resolve(createIterResult(data, false));
|
||||
} else {
|
||||
iterator[kLastResolve] = resolve;
|
||||
iterator[kLastReject] = reject;
|
||||
}
|
||||
},
|
||||
writable: true
|
||||
}), _Object$create));
|
||||
iterator[kLastPromise] = null;
|
||||
finished(stream, function (err) {
|
||||
if (err && err.code !== 'ERR_STREAM_PREMATURE_CLOSE') {
|
||||
var reject = iterator[kLastReject]; // reject if we are waiting for data in the Promise
|
||||
// returned by next() and store the error
|
||||
|
||||
if (reject !== null) {
|
||||
iterator[kLastPromise] = null;
|
||||
iterator[kLastResolve] = null;
|
||||
iterator[kLastReject] = null;
|
||||
reject(err);
|
||||
}
|
||||
|
||||
iterator[kError] = err;
|
||||
return;
|
||||
}
|
||||
|
||||
var resolve = iterator[kLastResolve];
|
||||
|
||||
if (resolve !== null) {
|
||||
iterator[kLastPromise] = null;
|
||||
iterator[kLastResolve] = null;
|
||||
iterator[kLastReject] = null;
|
||||
resolve(createIterResult(undefined, true));
|
||||
}
|
||||
|
||||
iterator[kEnded] = true;
|
||||
});
|
||||
stream.on('readable', onReadable.bind(null, iterator));
|
||||
return iterator;
|
||||
};
|
||||
|
||||
module.exports = createReadableStreamAsyncIterator;
|
||||
189
node_modules/spdy-transport/node_modules/readable-stream/lib/internal/streams/buffer_list.js
generated
vendored
Normal file
189
node_modules/spdy-transport/node_modules/readable-stream/lib/internal/streams/buffer_list.js
generated
vendored
Normal file
@ -0,0 +1,189 @@
|
||||
'use strict';
|
||||
|
||||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
|
||||
|
||||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
||||
|
||||
var _require = require('buffer'),
|
||||
Buffer = _require.Buffer;
|
||||
|
||||
var _require2 = require('util'),
|
||||
inspect = _require2.inspect;
|
||||
|
||||
var custom = inspect && inspect.custom || 'inspect';
|
||||
|
||||
function copyBuffer(src, target, offset) {
|
||||
Buffer.prototype.copy.call(src, target, offset);
|
||||
}
|
||||
|
||||
module.exports =
|
||||
/*#__PURE__*/
|
||||
function () {
|
||||
function BufferList() {
|
||||
this.head = null;
|
||||
this.tail = null;
|
||||
this.length = 0;
|
||||
}
|
||||
|
||||
var _proto = BufferList.prototype;
|
||||
|
||||
_proto.push = function push(v) {
|
||||
var entry = {
|
||||
data: v,
|
||||
next: null
|
||||
};
|
||||
if (this.length > 0) this.tail.next = entry;else this.head = entry;
|
||||
this.tail = entry;
|
||||
++this.length;
|
||||
};
|
||||
|
||||
_proto.unshift = function unshift(v) {
|
||||
var entry = {
|
||||
data: v,
|
||||
next: this.head
|
||||
};
|
||||
if (this.length === 0) this.tail = entry;
|
||||
this.head = entry;
|
||||
++this.length;
|
||||
};
|
||||
|
||||
_proto.shift = function shift() {
|
||||
if (this.length === 0) return;
|
||||
var ret = this.head.data;
|
||||
if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next;
|
||||
--this.length;
|
||||
return ret;
|
||||
};
|
||||
|
||||
_proto.clear = function clear() {
|
||||
this.head = this.tail = null;
|
||||
this.length = 0;
|
||||
};
|
||||
|
||||
_proto.join = function join(s) {
|
||||
if (this.length === 0) return '';
|
||||
var p = this.head;
|
||||
var ret = '' + p.data;
|
||||
|
||||
while (p = p.next) {
|
||||
ret += s + p.data;
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
_proto.concat = function concat(n) {
|
||||
if (this.length === 0) return Buffer.alloc(0);
|
||||
var ret = Buffer.allocUnsafe(n >>> 0);
|
||||
var p = this.head;
|
||||
var i = 0;
|
||||
|
||||
while (p) {
|
||||
copyBuffer(p.data, ret, i);
|
||||
i += p.data.length;
|
||||
p = p.next;
|
||||
}
|
||||
|
||||
return ret;
|
||||
} // Consumes a specified amount of bytes or characters from the buffered data.
|
||||
;
|
||||
|
||||
_proto.consume = function consume(n, hasStrings) {
|
||||
var ret;
|
||||
|
||||
if (n < this.head.data.length) {
|
||||
// `slice` is the same for buffers and strings.
|
||||
ret = this.head.data.slice(0, n);
|
||||
this.head.data = this.head.data.slice(n);
|
||||
} else if (n === this.head.data.length) {
|
||||
// First chunk is a perfect match.
|
||||
ret = this.shift();
|
||||
} else {
|
||||
// Result spans more than one buffer.
|
||||
ret = hasStrings ? this._getString(n) : this._getBuffer(n);
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
_proto.first = function first() {
|
||||
return this.head.data;
|
||||
} // Consumes a specified amount of characters from the buffered data.
|
||||
;
|
||||
|
||||
_proto._getString = function _getString(n) {
|
||||
var p = this.head;
|
||||
var c = 1;
|
||||
var ret = p.data;
|
||||
n -= ret.length;
|
||||
|
||||
while (p = p.next) {
|
||||
var str = p.data;
|
||||
var nb = n > str.length ? str.length : n;
|
||||
if (nb === str.length) ret += str;else ret += str.slice(0, n);
|
||||
n -= nb;
|
||||
|
||||
if (n === 0) {
|
||||
if (nb === str.length) {
|
||||
++c;
|
||||
if (p.next) this.head = p.next;else this.head = this.tail = null;
|
||||
} else {
|
||||
this.head = p;
|
||||
p.data = str.slice(nb);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
++c;
|
||||
}
|
||||
|
||||
this.length -= c;
|
||||
return ret;
|
||||
} // Consumes a specified amount of bytes from the buffered data.
|
||||
;
|
||||
|
||||
_proto._getBuffer = function _getBuffer(n) {
|
||||
var ret = Buffer.allocUnsafe(n);
|
||||
var p = this.head;
|
||||
var c = 1;
|
||||
p.data.copy(ret);
|
||||
n -= p.data.length;
|
||||
|
||||
while (p = p.next) {
|
||||
var buf = p.data;
|
||||
var nb = n > buf.length ? buf.length : n;
|
||||
buf.copy(ret, ret.length - n, 0, nb);
|
||||
n -= nb;
|
||||
|
||||
if (n === 0) {
|
||||
if (nb === buf.length) {
|
||||
++c;
|
||||
if (p.next) this.head = p.next;else this.head = this.tail = null;
|
||||
} else {
|
||||
this.head = p;
|
||||
p.data = buf.slice(nb);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
++c;
|
||||
}
|
||||
|
||||
this.length -= c;
|
||||
return ret;
|
||||
} // Make sure the linked list only shows the minimal necessary information.
|
||||
;
|
||||
|
||||
_proto[custom] = function (_, options) {
|
||||
return inspect(this, _objectSpread({}, options, {
|
||||
// Only inspect one level.
|
||||
depth: 0,
|
||||
// It should not recurse.
|
||||
customInspect: false
|
||||
}));
|
||||
};
|
||||
|
||||
return BufferList;
|
||||
}();
|
||||
85
node_modules/spdy-transport/node_modules/readable-stream/lib/internal/streams/destroy.js
generated
vendored
Normal file
85
node_modules/spdy-transport/node_modules/readable-stream/lib/internal/streams/destroy.js
generated
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
'use strict'; // undocumented cb() API, needed for core, not for public API
|
||||
|
||||
function destroy(err, cb) {
|
||||
var _this = this;
|
||||
|
||||
var readableDestroyed = this._readableState && this._readableState.destroyed;
|
||||
var writableDestroyed = this._writableState && this._writableState.destroyed;
|
||||
|
||||
if (readableDestroyed || writableDestroyed) {
|
||||
if (cb) {
|
||||
cb(err);
|
||||
} else if (err && (!this._writableState || !this._writableState.errorEmitted)) {
|
||||
process.nextTick(emitErrorNT, this, err);
|
||||
}
|
||||
|
||||
return this;
|
||||
} // we set destroyed to true before firing error callbacks in order
|
||||
// to make it re-entrance safe in case destroy() is called within callbacks
|
||||
|
||||
|
||||
if (this._readableState) {
|
||||
this._readableState.destroyed = true;
|
||||
} // if this is a duplex stream mark the writable part as destroyed as well
|
||||
|
||||
|
||||
if (this._writableState) {
|
||||
this._writableState.destroyed = true;
|
||||
}
|
||||
|
||||
this._destroy(err || null, function (err) {
|
||||
if (!cb && err) {
|
||||
process.nextTick(emitErrorAndCloseNT, _this, err);
|
||||
|
||||
if (_this._writableState) {
|
||||
_this._writableState.errorEmitted = true;
|
||||
}
|
||||
} else if (cb) {
|
||||
process.nextTick(emitCloseNT, _this);
|
||||
cb(err);
|
||||
} else {
|
||||
process.nextTick(emitCloseNT, _this);
|
||||
}
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
function emitErrorAndCloseNT(self, err) {
|
||||
emitErrorNT(self, err);
|
||||
emitCloseNT(self);
|
||||
}
|
||||
|
||||
function emitCloseNT(self) {
|
||||
if (self._writableState && !self._writableState.emitClose) return;
|
||||
if (self._readableState && !self._readableState.emitClose) return;
|
||||
self.emit('close');
|
||||
}
|
||||
|
||||
function undestroy() {
|
||||
if (this._readableState) {
|
||||
this._readableState.destroyed = false;
|
||||
this._readableState.reading = false;
|
||||
this._readableState.ended = false;
|
||||
this._readableState.endEmitted = false;
|
||||
}
|
||||
|
||||
if (this._writableState) {
|
||||
this._writableState.destroyed = false;
|
||||
this._writableState.ended = false;
|
||||
this._writableState.ending = false;
|
||||
this._writableState.finalCalled = false;
|
||||
this._writableState.prefinished = false;
|
||||
this._writableState.finished = false;
|
||||
this._writableState.errorEmitted = false;
|
||||
}
|
||||
}
|
||||
|
||||
function emitErrorNT(self, err) {
|
||||
self.emit('error', err);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
destroy: destroy,
|
||||
undestroy: undestroy
|
||||
};
|
||||
104
node_modules/spdy-transport/node_modules/readable-stream/lib/internal/streams/end-of-stream.js
generated
vendored
Normal file
104
node_modules/spdy-transport/node_modules/readable-stream/lib/internal/streams/end-of-stream.js
generated
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
// Ported from https://github.com/mafintosh/end-of-stream with
|
||||
// permission from the author, Mathias Buus (@mafintosh).
|
||||
'use strict';
|
||||
|
||||
var ERR_STREAM_PREMATURE_CLOSE = require('../../../errors').codes.ERR_STREAM_PREMATURE_CLOSE;
|
||||
|
||||
function once(callback) {
|
||||
var called = false;
|
||||
return function () {
|
||||
if (called) return;
|
||||
called = true;
|
||||
|
||||
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
||||
args[_key] = arguments[_key];
|
||||
}
|
||||
|
||||
callback.apply(this, args);
|
||||
};
|
||||
}
|
||||
|
||||
function noop() {}
|
||||
|
||||
function isRequest(stream) {
|
||||
return stream.setHeader && typeof stream.abort === 'function';
|
||||
}
|
||||
|
||||
function eos(stream, opts, callback) {
|
||||
if (typeof opts === 'function') return eos(stream, null, opts);
|
||||
if (!opts) opts = {};
|
||||
callback = once(callback || noop);
|
||||
var readable = opts.readable || opts.readable !== false && stream.readable;
|
||||
var writable = opts.writable || opts.writable !== false && stream.writable;
|
||||
|
||||
var onlegacyfinish = function onlegacyfinish() {
|
||||
if (!stream.writable) onfinish();
|
||||
};
|
||||
|
||||
var writableEnded = stream._writableState && stream._writableState.finished;
|
||||
|
||||
var onfinish = function onfinish() {
|
||||
writable = false;
|
||||
writableEnded = true;
|
||||
if (!readable) callback.call(stream);
|
||||
};
|
||||
|
||||
var readableEnded = stream._readableState && stream._readableState.endEmitted;
|
||||
|
||||
var onend = function onend() {
|
||||
readable = false;
|
||||
readableEnded = true;
|
||||
if (!writable) callback.call(stream);
|
||||
};
|
||||
|
||||
var onerror = function onerror(err) {
|
||||
callback.call(stream, err);
|
||||
};
|
||||
|
||||
var onclose = function onclose() {
|
||||
var err;
|
||||
|
||||
if (readable && !readableEnded) {
|
||||
if (!stream._readableState || !stream._readableState.ended) err = new ERR_STREAM_PREMATURE_CLOSE();
|
||||
return callback.call(stream, err);
|
||||
}
|
||||
|
||||
if (writable && !writableEnded) {
|
||||
if (!stream._writableState || !stream._writableState.ended) err = new ERR_STREAM_PREMATURE_CLOSE();
|
||||
return callback.call(stream, err);
|
||||
}
|
||||
};
|
||||
|
||||
var onrequest = function onrequest() {
|
||||
stream.req.on('finish', onfinish);
|
||||
};
|
||||
|
||||
if (isRequest(stream)) {
|
||||
stream.on('complete', onfinish);
|
||||
stream.on('abort', onclose);
|
||||
if (stream.req) onrequest();else stream.on('request', onrequest);
|
||||
} else if (writable && !stream._writableState) {
|
||||
// legacy streams
|
||||
stream.on('end', onlegacyfinish);
|
||||
stream.on('close', onlegacyfinish);
|
||||
}
|
||||
|
||||
stream.on('end', onend);
|
||||
stream.on('finish', onfinish);
|
||||
if (opts.error !== false) stream.on('error', onerror);
|
||||
stream.on('close', onclose);
|
||||
return function () {
|
||||
stream.removeListener('complete', onfinish);
|
||||
stream.removeListener('abort', onclose);
|
||||
stream.removeListener('request', onrequest);
|
||||
if (stream.req) stream.req.removeListener('finish', onfinish);
|
||||
stream.removeListener('end', onlegacyfinish);
|
||||
stream.removeListener('close', onlegacyfinish);
|
||||
stream.removeListener('finish', onfinish);
|
||||
stream.removeListener('end', onend);
|
||||
stream.removeListener('error', onerror);
|
||||
stream.removeListener('close', onclose);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = eos;
|
||||
97
node_modules/spdy-transport/node_modules/readable-stream/lib/internal/streams/pipeline.js
generated
vendored
Normal file
97
node_modules/spdy-transport/node_modules/readable-stream/lib/internal/streams/pipeline.js
generated
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
// Ported from https://github.com/mafintosh/pump with
|
||||
// permission from the author, Mathias Buus (@mafintosh).
|
||||
'use strict';
|
||||
|
||||
var eos;
|
||||
|
||||
function once(callback) {
|
||||
var called = false;
|
||||
return function () {
|
||||
if (called) return;
|
||||
called = true;
|
||||
callback.apply(void 0, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
var _require$codes = require('../../../errors').codes,
|
||||
ERR_MISSING_ARGS = _require$codes.ERR_MISSING_ARGS,
|
||||
ERR_STREAM_DESTROYED = _require$codes.ERR_STREAM_DESTROYED;
|
||||
|
||||
function noop(err) {
|
||||
// Rethrow the error if it exists to avoid swallowing it
|
||||
if (err) throw err;
|
||||
}
|
||||
|
||||
function isRequest(stream) {
|
||||
return stream.setHeader && typeof stream.abort === 'function';
|
||||
}
|
||||
|
||||
function destroyer(stream, reading, writing, callback) {
|
||||
callback = once(callback);
|
||||
var closed = false;
|
||||
stream.on('close', function () {
|
||||
closed = true;
|
||||
});
|
||||
if (eos === undefined) eos = require('./end-of-stream');
|
||||
eos(stream, {
|
||||
readable: reading,
|
||||
writable: writing
|
||||
}, function (err) {
|
||||
if (err) return callback(err);
|
||||
closed = true;
|
||||
callback();
|
||||
});
|
||||
var destroyed = false;
|
||||
return function (err) {
|
||||
if (closed) return;
|
||||
if (destroyed) return;
|
||||
destroyed = true; // request.destroy just do .end - .abort is what we want
|
||||
|
||||
if (isRequest(stream)) return stream.abort();
|
||||
if (typeof stream.destroy === 'function') return stream.destroy();
|
||||
callback(err || new ERR_STREAM_DESTROYED('pipe'));
|
||||
};
|
||||
}
|
||||
|
||||
function call(fn) {
|
||||
fn();
|
||||
}
|
||||
|
||||
function pipe(from, to) {
|
||||
return from.pipe(to);
|
||||
}
|
||||
|
||||
function popCallback(streams) {
|
||||
if (!streams.length) return noop;
|
||||
if (typeof streams[streams.length - 1] !== 'function') return noop;
|
||||
return streams.pop();
|
||||
}
|
||||
|
||||
function pipeline() {
|
||||
for (var _len = arguments.length, streams = new Array(_len), _key = 0; _key < _len; _key++) {
|
||||
streams[_key] = arguments[_key];
|
||||
}
|
||||
|
||||
var callback = popCallback(streams);
|
||||
if (Array.isArray(streams[0])) streams = streams[0];
|
||||
|
||||
if (streams.length < 2) {
|
||||
throw new ERR_MISSING_ARGS('streams');
|
||||
}
|
||||
|
||||
var error;
|
||||
var destroys = streams.map(function (stream, i) {
|
||||
var reading = i < streams.length - 1;
|
||||
var writing = i > 0;
|
||||
return destroyer(stream, reading, writing, function (err) {
|
||||
if (!error) error = err;
|
||||
if (err) destroys.forEach(call);
|
||||
if (reading) return;
|
||||
destroys.forEach(call);
|
||||
callback(error);
|
||||
});
|
||||
});
|
||||
return streams.reduce(pipe);
|
||||
}
|
||||
|
||||
module.exports = pipeline;
|
||||
27
node_modules/spdy-transport/node_modules/readable-stream/lib/internal/streams/state.js
generated
vendored
Normal file
27
node_modules/spdy-transport/node_modules/readable-stream/lib/internal/streams/state.js
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
'use strict';
|
||||
|
||||
var ERR_INVALID_OPT_VALUE = require('../../../errors').codes.ERR_INVALID_OPT_VALUE;
|
||||
|
||||
function highWaterMarkFrom(options, isDuplex, duplexKey) {
|
||||
return options.highWaterMark != null ? options.highWaterMark : isDuplex ? options[duplexKey] : null;
|
||||
}
|
||||
|
||||
function getHighWaterMark(state, options, duplexKey, isDuplex) {
|
||||
var hwm = highWaterMarkFrom(options, isDuplex, duplexKey);
|
||||
|
||||
if (hwm != null) {
|
||||
if (!(isFinite(hwm) && Math.floor(hwm) === hwm) || hwm < 0) {
|
||||
var name = isDuplex ? duplexKey : 'highWaterMark';
|
||||
throw new ERR_INVALID_OPT_VALUE(name, hwm);
|
||||
}
|
||||
|
||||
return Math.floor(hwm);
|
||||
} // Default value
|
||||
|
||||
|
||||
return state.objectMode ? 16 : 16 * 1024;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getHighWaterMark: getHighWaterMark
|
||||
};
|
||||
1
node_modules/spdy-transport/node_modules/readable-stream/lib/internal/streams/stream-browser.js
generated
vendored
Normal file
1
node_modules/spdy-transport/node_modules/readable-stream/lib/internal/streams/stream-browser.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
module.exports = require('events').EventEmitter;
|
||||
1
node_modules/spdy-transport/node_modules/readable-stream/lib/internal/streams/stream.js
generated
vendored
Normal file
1
node_modules/spdy-transport/node_modules/readable-stream/lib/internal/streams/stream.js
generated
vendored
Normal file
@ -0,0 +1 @@
|
||||
module.exports = require('stream');
|
||||
95
node_modules/spdy-transport/node_modules/readable-stream/package.json
generated
vendored
Normal file
95
node_modules/spdy-transport/node_modules/readable-stream/package.json
generated
vendored
Normal file
@ -0,0 +1,95 @@
|
||||
{
|
||||
"_from": "readable-stream@^3.0.6",
|
||||
"_id": "readable-stream@3.4.0",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==",
|
||||
"_location": "/spdy-transport/readable-stream",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "readable-stream@^3.0.6",
|
||||
"name": "readable-stream",
|
||||
"escapedName": "readable-stream",
|
||||
"rawSpec": "^3.0.6",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^3.0.6"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/spdy-transport"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz",
|
||||
"_shasum": "a51c26754658e0a3c21dbf59163bd45ba6f447fc",
|
||||
"_spec": "readable-stream@^3.0.6",
|
||||
"_where": "/Users/stefanfejes/Projects/30-seconds-of-python-code/node_modules/spdy-transport",
|
||||
"browser": {
|
||||
"util": false,
|
||||
"worker_threads": false,
|
||||
"./errors": "./errors-browser.js",
|
||||
"./readable.js": "./readable-browser.js",
|
||||
"./lib/internal/streams/stream.js": "./lib/internal/streams/stream-browser.js"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/nodejs/readable-stream/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"dependencies": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
},
|
||||
"deprecated": false,
|
||||
"description": "Streams3, a user-land copy of the stream library from Node.js",
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.2.0",
|
||||
"@babel/core": "^7.2.0",
|
||||
"@babel/polyfill": "^7.0.0",
|
||||
"@babel/preset-env": "^7.2.0",
|
||||
"airtap": "0.0.9",
|
||||
"assert": "^1.4.0",
|
||||
"bl": "^2.0.0",
|
||||
"deep-strict-equal": "^0.2.0",
|
||||
"glob": "^7.1.2",
|
||||
"gunzip-maybe": "^1.4.1",
|
||||
"hyperquest": "^2.1.3",
|
||||
"lolex": "^2.6.0",
|
||||
"nyc": "^11.0.0",
|
||||
"pump": "^3.0.0",
|
||||
"rimraf": "^2.6.2",
|
||||
"tap": "^12.0.0",
|
||||
"tape": "^4.9.0",
|
||||
"tar-fs": "^1.16.2",
|
||||
"util-promisify": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
},
|
||||
"homepage": "https://github.com/nodejs/readable-stream#readme",
|
||||
"keywords": [
|
||||
"readable",
|
||||
"stream",
|
||||
"pipe"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "readable.js",
|
||||
"name": "readable-stream",
|
||||
"nyc": {
|
||||
"include": [
|
||||
"lib/**.js"
|
||||
]
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/nodejs/readable-stream.git"
|
||||
},
|
||||
"scripts": {
|
||||
"ci": "TAP=1 tap --no-esm test/parallel/*.js test/ours/*.js | tee test.tap",
|
||||
"cover": "nyc npm test",
|
||||
"report": "nyc report --reporter=lcov",
|
||||
"test": "tap -J --no-esm test/parallel/*.js test/ours/*.js",
|
||||
"test-browser-local": "airtap --open --local -- test/browser.js",
|
||||
"test-browsers": "airtap --sauce-connect --loopback airtap.local -- test/browser.js",
|
||||
"update-browser-errors": "babel -o errors-browser.js errors.js"
|
||||
},
|
||||
"version": "3.4.0"
|
||||
}
|
||||
9
node_modules/spdy-transport/node_modules/readable-stream/readable-browser.js
generated
vendored
Normal file
9
node_modules/spdy-transport/node_modules/readable-stream/readable-browser.js
generated
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
exports = module.exports = require('./lib/_stream_readable.js');
|
||||
exports.Stream = exports;
|
||||
exports.Readable = exports;
|
||||
exports.Writable = require('./lib/_stream_writable.js');
|
||||
exports.Duplex = require('./lib/_stream_duplex.js');
|
||||
exports.Transform = require('./lib/_stream_transform.js');
|
||||
exports.PassThrough = require('./lib/_stream_passthrough.js');
|
||||
exports.finished = require('./lib/internal/streams/end-of-stream.js');
|
||||
exports.pipeline = require('./lib/internal/streams/pipeline.js');
|
||||
16
node_modules/spdy-transport/node_modules/readable-stream/readable.js
generated
vendored
Normal file
16
node_modules/spdy-transport/node_modules/readable-stream/readable.js
generated
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
var Stream = require('stream');
|
||||
if (process.env.READABLE_STREAM === 'disable' && Stream) {
|
||||
module.exports = Stream.Readable;
|
||||
Object.assign(module.exports, Stream);
|
||||
module.exports.Stream = Stream;
|
||||
} else {
|
||||
exports = module.exports = require('./lib/_stream_readable.js');
|
||||
exports.Stream = Stream || exports;
|
||||
exports.Readable = exports;
|
||||
exports.Writable = require('./lib/_stream_writable.js');
|
||||
exports.Duplex = require('./lib/_stream_duplex.js');
|
||||
exports.Transform = require('./lib/_stream_transform.js');
|
||||
exports.PassThrough = require('./lib/_stream_passthrough.js');
|
||||
exports.finished = require('./lib/internal/streams/end-of-stream.js');
|
||||
exports.pipeline = require('./lib/internal/streams/pipeline.js');
|
||||
}
|
||||
78
node_modules/spdy-transport/package.json
generated
vendored
Normal file
78
node_modules/spdy-transport/package.json
generated
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
{
|
||||
"_from": "spdy-transport@^3.0.0",
|
||||
"_id": "spdy-transport@3.0.0",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==",
|
||||
"_location": "/spdy-transport",
|
||||
"_phantomChildren": {
|
||||
"inherits": "2.0.4",
|
||||
"string_decoder": "1.1.1",
|
||||
"util-deprecate": "1.0.2"
|
||||
},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "spdy-transport@^3.0.0",
|
||||
"name": "spdy-transport",
|
||||
"escapedName": "spdy-transport",
|
||||
"rawSpec": "^3.0.0",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^3.0.0"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/spdy"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz",
|
||||
"_shasum": "00d4863a6400ad75df93361a1608605e5dcdcf31",
|
||||
"_spec": "spdy-transport@^3.0.0",
|
||||
"_where": "/Users/stefanfejes/Projects/30-seconds-of-python-code/node_modules/spdy",
|
||||
"author": {
|
||||
"name": "Fedor Indutny",
|
||||
"email": "fedor@indutny.com"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/spdy-http2/spdy-transport/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"dependencies": {
|
||||
"debug": "^4.1.0",
|
||||
"detect-node": "^2.0.4",
|
||||
"hpack.js": "^2.1.6",
|
||||
"obuf": "^1.1.2",
|
||||
"readable-stream": "^3.0.6",
|
||||
"wbuf": "^1.7.3"
|
||||
},
|
||||
"deprecated": false,
|
||||
"description": "SPDY v2, v3, v3.1 and HTTP2 transport",
|
||||
"devDependencies": {
|
||||
"async": "^2.6.1",
|
||||
"istanbul": "^0.4.5",
|
||||
"mocha": "^5.2.0",
|
||||
"pre-commit": "^1.2.2",
|
||||
"standard": "^12.0.1",
|
||||
"stream-pair": "^1.0.3"
|
||||
},
|
||||
"homepage": "https://github.com/spdy-http2/spdy-transport",
|
||||
"keywords": [
|
||||
"spdy",
|
||||
"http2",
|
||||
"transport"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "lib/spdy-transport",
|
||||
"name": "spdy-transport",
|
||||
"pre-commit": [
|
||||
"lint",
|
||||
"test"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/spdy-http2/spdy-transport.git"
|
||||
},
|
||||
"scripts": {
|
||||
"coverage": "istanbul cover node_modules/.bin/_mocha -- --reporter=spec test/**/*-test.js test/**/**/*-test.js",
|
||||
"lint": "standard",
|
||||
"test": "mocha --reporter=spec test/**/*-test.js test/**/**/*-test.js"
|
||||
},
|
||||
"version": "3.0.0"
|
||||
}
|
||||
Reference in New Issue
Block a user