Comparing version 0.2.1 to 0.2.2
@@ -6,5 +6,7 @@ import { BufferVisitor } from './common'; | ||
static fromBuffer(bufv: BufferVisitor): QUICError; | ||
static checkAny(err?: any): QUICError | null; | ||
name: string; | ||
code: number; | ||
constructor(nameOrCode: string | number); | ||
readonly isNoError: boolean; | ||
valueOf(): { | ||
@@ -22,5 +24,7 @@ name: string; | ||
static fromBuffer(bufv: BufferVisitor): QUICStreamError; | ||
static checkAny(err?: any): QUICError | null; | ||
name: string; | ||
code: number; | ||
constructor(nameOrCode: string | number); | ||
readonly isNoError: boolean; | ||
valueOf(): { | ||
@@ -27,0 +31,0 @@ name: string; |
@@ -476,3 +476,9 @@ 'use strict'; | ||
} | ||
return new QUICError(err.name); | ||
switch (typeof err) { | ||
case 'string': | ||
return new QUICError(err); | ||
case 'number': | ||
return new QUICError(err); | ||
} | ||
return new QUICError(err.code >= 0 ? err.code : err.message); | ||
} | ||
@@ -487,2 +493,8 @@ static fromBuffer(bufv) { | ||
} | ||
static checkAny(err) { | ||
if (err == null) { | ||
return null; | ||
} | ||
return QUICError.fromError(err); | ||
} | ||
constructor(nameOrCode) { | ||
@@ -495,2 +507,5 @@ const error = _errors[nameOrCode] == null ? INVALID_ERROR : _errors[nameOrCode]; | ||
} | ||
get isNoError() { | ||
return this.code === errors.QUIC_NO_ERROR.code; | ||
} | ||
valueOf() { | ||
@@ -519,3 +534,9 @@ return { | ||
} | ||
return new QUICStreamError(err.code != null ? err.code : err.name); | ||
switch (typeof err) { | ||
case 'string': | ||
return new QUICStreamError(err); | ||
case 'number': | ||
return new QUICStreamError(err); | ||
} | ||
return new QUICStreamError(err.code >= 0 ? err.code : err.message); | ||
} | ||
@@ -530,2 +551,8 @@ static fromBuffer(bufv) { | ||
} | ||
static checkAny(err) { | ||
if (err == null) { | ||
return null; | ||
} | ||
return QUICStreamError.fromError(err); | ||
} | ||
constructor(nameOrCode) { | ||
@@ -538,2 +565,5 @@ const error = _streamErrors[nameOrCode] == null ? INVALID_RST_STREAM_ERROR : _streamErrors[nameOrCode]; | ||
} | ||
get isNoError() { | ||
return this.code === streamErrors.QUIC_STREAM_NO_ERROR.code; | ||
} | ||
valueOf() { | ||
@@ -540,0 +570,0 @@ return { |
@@ -24,3 +24,3 @@ 'use strict'; | ||
// This is the value used by Chromium for a QUIC packet sent using IPv6 (for IPv4 it would be 1370) | ||
// const MaxPacketSize = exports.MaxPacketSize = 1350 | ||
// export const MaxPacketSize = 1350 | ||
// MaxFrameAndPublicHeaderSize is the maximum size of a QUIC frame plus PublicHeader | ||
@@ -27,0 +27,0 @@ // const MaxFrameAndPublicHeaderSize = exports.MaxFrameAndPublicHeaderSize = MaxPacketSize - 12 /*crypto signature*/ |
@@ -31,3 +31,3 @@ /// <reference types="node" /> | ||
shutdown(_timeout: number): Promise<void>; | ||
close(err: any): void; | ||
close(err?: any): Promise<void>; | ||
getConnections(): Promise<number>; | ||
@@ -34,0 +34,0 @@ ref(): void; |
@@ -66,2 +66,3 @@ 'use strict'; | ||
const socket = this[symbol_1.kSocket] = socket_1.createSocket(addr.family); | ||
socket[symbol_1.kState].exclusive = false; // socket is shared between all sessions | ||
socket | ||
@@ -79,4 +80,4 @@ .on('error', (err) => this.emit('error', err)) | ||
this.listening = true; | ||
process.nextTick(() => this.emit('listening')); | ||
resolve(); | ||
this.emit('listening'); | ||
}); | ||
@@ -110,3 +111,3 @@ socket.once('error', reject); | ||
} | ||
close(err) { | ||
async close(err) { | ||
if (this[symbol_1.kState].destroyed) { | ||
@@ -117,3 +118,3 @@ return; | ||
for (const session of this[exports.kConns].values()) { | ||
session.close(err); | ||
await session.close(err); | ||
} | ||
@@ -124,4 +125,3 @@ const timer = this[symbol_1.kIntervalCheck]; | ||
} | ||
this.emit('close'); | ||
return; | ||
process.nextTick(() => this.emit('close')); | ||
} | ||
@@ -140,3 +140,2 @@ getConnections() { | ||
function serverOnClose(server) { | ||
server.emit('error', new Error('the underlying socket closed')); | ||
for (const session of server[exports.kConns].values()) { | ||
@@ -143,0 +142,0 @@ session.destroy(new Error('the underlying socket closed')); |
@@ -52,7 +52,7 @@ /// <reference types="node" /> | ||
_windowUpdate(offset: Offset, streamID?: StreamID): void; | ||
request(options: any): Stream; | ||
request(options?: any): Stream; | ||
goaway(err: any): Promise<void>; | ||
ping(): Promise<void>; | ||
setTimeout(_msecs: number): void; | ||
close(err: any): Promise<void>; | ||
close(err?: any): Promise<void>; | ||
reset(_err: any): Promise<void>; | ||
@@ -59,0 +59,0 @@ destroy(err: any): void; |
@@ -13,2 +13,3 @@ 'use strict'; | ||
const error_1 = require("./internal/error"); | ||
const socket_1 = require("./socket"); | ||
const stream_1 = require("./stream"); | ||
@@ -128,3 +129,3 @@ const common_1 = require("./internal/common"); | ||
this[symbol_1.kUnackedPackets].push(packet); | ||
if (this[symbol_1.kUnackedPackets].length > 1000) { | ||
if (this[symbol_1.kUnackedPackets].length > 4096) { | ||
return callback(error_1.QuicError.fromError(error_1.QuicError.QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS)); | ||
@@ -134,4 +135,5 @@ } | ||
} | ||
const buf = common_1.toBuffer(packet); | ||
socket.send(buf, this[symbol_1.kState].remotePort, this[symbol_1.kState].remoteAddress, callback); | ||
socket_1.sendPacket(socket, packet, this[symbol_1.kState].remotePort, this[symbol_1.kState].remoteAddress, callback); | ||
// const buf = toBuffer(packet) | ||
// socket.send(buf, this[kState].remotePort, this[kState].remoteAddress, callback) | ||
} | ||
@@ -379,5 +381,12 @@ _trySendAckFrame() { | ||
debug(`session %s - session destroyed, error: %j`, this.id, err); | ||
if (this[symbol_1.kState].destroyed) { | ||
return; | ||
} | ||
err = error_1.QuicError.checkAny(err); | ||
if (err != null && err.isNoError) { | ||
err = null; | ||
} | ||
const socket = this[symbol_1.kSocket]; | ||
if (socket != null) { | ||
if (this.isClient && !socket[symbol_1.kState].destroyed) { | ||
if (socket[symbol_1.kState].exclusive && !socket[symbol_1.kState].destroyed) { | ||
socket.close(); | ||
@@ -389,3 +398,3 @@ socket[symbol_1.kState].destroyed = true; | ||
for (const stream of this[symbol_1.kStreams].values()) { | ||
stream.destroy(new Error('the underlying session destroyed')); | ||
stream.destroy(err); | ||
} | ||
@@ -403,3 +412,3 @@ const timer = this[symbol_1.kIntervalCheck]; | ||
this[symbol_1.kState].destroyed = true; | ||
this.emit('close'); | ||
process.nextTick(() => this.emit('close')); | ||
} | ||
@@ -509,2 +518,3 @@ return; | ||
this.lowestAcked = this.largestAcked; | ||
numbersAcked.length = 1; | ||
} | ||
@@ -511,0 +521,0 @@ else { |
/// <reference types="node" /> | ||
import { Socket as UDPSocket } from 'dgram'; | ||
import { kState } from './internal/symbol'; | ||
import { Packet } from './internal/packet'; | ||
export interface AddressInfo { | ||
@@ -13,2 +14,3 @@ address: string; | ||
export declare class SocketState { | ||
exclusive: boolean; | ||
destroyed: boolean; | ||
@@ -18,1 +20,2 @@ constructor(); | ||
export declare function createSocket(family: number): Socket; | ||
export declare function sendPacket(socket: Socket, packet: Packet, remotePort: number, remoteAddr: string, callback: (err: any) => void): void; |
@@ -8,4 +8,6 @@ 'use strict'; | ||
const symbol_1 = require("./internal/symbol"); | ||
const common_1 = require("./internal/common"); | ||
class SocketState { | ||
constructor() { | ||
this.exclusive = true; | ||
this.destroyed = false; | ||
@@ -25,2 +27,20 @@ } | ||
exports.createSocket = createSocket; | ||
const bufferPool = []; | ||
function sendPacket(socket, packet, remotePort, remoteAddr, callback) { | ||
const byteLen = packet.byteLen(); | ||
if (byteLen > 1500) { | ||
return callback(new Error('packet size too large!')); | ||
} | ||
let bufv = bufferPool.shift(); | ||
if (bufv == null) { | ||
bufv = common_1.Visitor.wrap(Buffer.alloc(1500)); // MTU | ||
} | ||
bufv.v.reset(0, 0); | ||
packet.writeTo(bufv); | ||
socket.send(bufv.slice(0, bufv.v.end), remotePort, remoteAddr, (err) => { | ||
bufferPool.push(bufv); | ||
callback(err); | ||
}); | ||
} | ||
exports.sendPacket = sendPacket; | ||
//# sourceMappingURL=socket.js.map |
@@ -16,2 +16,4 @@ /// <reference types="node" /> | ||
readonly destroyed: boolean; | ||
readonly bytesRead: number; | ||
readonly bytesWritten: number; | ||
close(err: any): Promise<any>; | ||
@@ -22,3 +24,3 @@ _handleFrame(frame: StreamFrame, rcvTime: number): void; | ||
_tryFlushCallbacks(): void; | ||
_flushData(callback: (...args: any[]) => void): void; | ||
_flushData(callback: (err: any) => void): void; | ||
_write(chunk: Buffer, encoding: string, callback: (...args: any[]) => void): void; | ||
@@ -25,0 +27,0 @@ _writev(chunks: any[], callback: (...args: any[]) => void): void; |
@@ -38,2 +38,8 @@ 'use strict'; | ||
} | ||
get bytesRead() { | ||
return this[symbol_1.kState].bytesRead; | ||
} | ||
get bytesWritten() { | ||
return this[symbol_1.kState].bytesWritten; | ||
} | ||
// close closes the stream with an error. | ||
@@ -117,6 +123,7 @@ close(err) { | ||
this[symbol_1.kState].flushing = true; | ||
this._flushData((err, shouldContinue) => { | ||
this._flushData((err) => { | ||
this[symbol_1.kState].flushing = false; | ||
// continue to send data or send FIN | ||
if (err == null && (shouldContinue || (this[symbol_1.kState].shouldFIN && !this[symbol_1.kState].localFIN))) { | ||
const shouldConsume = this[symbol_1.kState].bufferList.byteLen > 0; // should send data | ||
const shouldFIN = this[symbol_1.kState].shouldFIN && !this[symbol_1.kState].localFIN; // should send FIN | ||
if (err == null && (shouldConsume || shouldFIN)) { | ||
return this._tryFlushCallbacks(); | ||
@@ -131,21 +138,19 @@ } | ||
_flushData(callback) { | ||
const buf = this[symbol_1.kState].bufferList.read(protocol_1.MaxStreamBufferSize); | ||
if (buf == null && !this[symbol_1.kState].shouldFIN) { | ||
return callback(); | ||
const byteLen = this[symbol_1.kState].bufferList.read(this[symbol_1.kState].flushBuffer, 0); | ||
if (byteLen === 0 && !this[symbol_1.kState].shouldFIN) { | ||
return callback(null); | ||
} | ||
const offet = this[symbol_1.kState].writeOffset; | ||
if (buf != null) { | ||
this[symbol_1.kState].writeOffset = offet.nextOffset(buf.length); | ||
const buf = byteLen > 0 ? this[symbol_1.kState].flushBuffer.slice(0, byteLen) : null; | ||
const shouldFIN = this[symbol_1.kState].shouldFIN && this[symbol_1.kState].bufferList.byteLen === 0; | ||
if (byteLen > 0) { | ||
this[symbol_1.kState].writeOffset = offet.nextOffset(byteLen); | ||
this[symbol_1.kState].bytesWritten += byteLen; | ||
} | ||
const streamFrame = new frame_1.StreamFrame(this[symbol_1.kID], offet, buf, this[symbol_1.kState].shouldFIN && this[symbol_1.kState].bufferList.byteLen === 0); | ||
const streamFrame = new frame_1.StreamFrame(this[symbol_1.kID], offet, buf, shouldFIN); | ||
if (streamFrame.isFIN) { | ||
this[symbol_1.kState].localFIN = true; | ||
} | ||
debug(`stream %s - write streamFrame, isFIN: %s, offset: %d, data size: %d`, this.id, streamFrame.isFIN, streamFrame.offset.valueOf(), (buf == null ? 0 : buf.length)); | ||
this[symbol_1.kSession]._sendFrame(streamFrame, (err) => { | ||
if (err != null) { | ||
return callback(err); | ||
} | ||
callback(null, this[symbol_1.kState].bufferList.byteLen > 0); | ||
}); | ||
debug(`stream %s - write streamFrame, isFIN: %s, offset: %d, data size: %d`, this.id, streamFrame.isFIN, streamFrame.offset.valueOf(), byteLen); | ||
this[symbol_1.kSession]._sendFrame(streamFrame, callback); | ||
} | ||
@@ -184,8 +189,10 @@ _write(chunk, encoding, callback) { | ||
_read(size = 0) { | ||
const data = this[symbol_1.kState].readQueue.read(); | ||
if (data != null) { | ||
let data = this[symbol_1.kState].readQueue.read(); | ||
while (data != null) { | ||
if (this.push(data) && size > data.length) { | ||
this._read(size - data.length); | ||
return; | ||
size -= data.length; | ||
data = this[symbol_1.kState].readQueue.read(); | ||
continue; | ||
} | ||
break; | ||
} | ||
@@ -208,2 +215,6 @@ if (!this[symbol_1.kState].ended && this[symbol_1.kState].readQueue.isEnd()) { | ||
state.bufferList.reset(); | ||
err = error_1.StreamError.checkAny(err); | ||
if (err != null && err.isNoError) { | ||
err = null; | ||
} | ||
callback(err); | ||
@@ -229,2 +240,3 @@ } | ||
this.writeOffset = new protocol_1.Offset(0); | ||
this.flushBuffer = Buffer.alloc(protocol_1.MaxStreamBufferSize); | ||
// Both stream and session windows start with a default value of 16 KB | ||
@@ -281,16 +293,18 @@ this.maxIncomingByteOffset = 16 * 1024; | ||
} | ||
read(n) { | ||
read(buf, offset) { | ||
if (this.head == null) { | ||
return null; | ||
return 0; | ||
} | ||
let ret = this.head.data; | ||
if (ret.length > n) { | ||
const n = buf.length - offset; | ||
const ret = this.head.data; | ||
if (ret.length >= n) { | ||
ret.copy(buf, offset, 0, n); | ||
this.head.data = ret.slice(n); | ||
ret = ret.slice(0, n); | ||
this.byteLen -= n; | ||
return ret; | ||
return n; | ||
} | ||
ret.copy(buf, offset, 0, ret.length); | ||
this._shift(); | ||
this.byteLen -= ret.length; | ||
return ret; // ret.length <= n | ||
return ret.length + this.read(buf, offset + ret.length); | ||
} | ||
@@ -297,0 +311,0 @@ } |
@@ -7,3 +7,3 @@ { | ||
], | ||
"version": "0.2.1", | ||
"version": "0.2.2", | ||
"main": "dist/index.js", | ||
@@ -25,3 +25,3 @@ "license": "MIT", | ||
"@types/node": "^9.6.5", | ||
"ilog": "^1.2.1", | ||
"ilog": "^1.2.2", | ||
"thunks": "^4.9.2", | ||
@@ -28,0 +28,0 @@ "tman": "^1.7.4", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
327834
5417