UNPKG

@hazae41/kcp

Version:

Zero-copy KCP protocol for the web

95 lines (91 loc) 3.6 kB
'use strict'; var binary = require('@hazae41/binary'); var cursor = require('@hazae41/cursor'); var index = require('../console/index.cjs'); var segment = require('./segment.cjs'); class ExpectedKcpSegmentError extends Error { #class = ExpectedKcpSegmentError; name = this.#class.name; constructor() { super(`Expected a KCP segment`); } } class UnknownKcpCommandError extends Error { #class = UnknownKcpCommandError; name = this.#class.name; constructor() { super(`Unknown KCP command`); } } class SecretKcpReader { parent; #buffer = new Map(); constructor(parent) { this.parent = parent; } async onWrite(chunk) { const cursor$1 = new cursor.Cursor(chunk.bytes); while (cursor$1.remaining) await this.#onSegment(binary.Readable.readOrRollbackAndThrow(segment.KcpSegment, cursor$1)); return; } async #onSegment(segment$1) { if (segment$1.conversation !== this.parent.conversation) return; if (segment$1.command === segment.KcpSegment.commands.push) return await this.#onPushSegment(segment$1); if (segment$1.command === segment.KcpSegment.commands.ack) return await this.#onAckSegment(segment$1); if (segment$1.command === segment.KcpSegment.commands.wask) return await this.#onWaskSegment(segment$1); throw new UnknownKcpCommandError(); } async #onPushSegment(segment$1) { const conversation = this.parent.conversation; const command = segment.KcpSegment.commands.ack; const timestamp = segment$1.timestamp; const serial = segment$1.serial; const unackSerial = this.parent.recvCounter; const fragment = new binary.Empty(); const ack = segment.KcpSegment.empty({ conversation, command, timestamp, serial, unackSerial, fragment }); this.parent.output.enqueue(ack); if (segment$1.serial < this.parent.recvCounter) { index.Console.debug(`Received previous KCP segment`); return; } if (segment$1.serial > this.parent.recvCounter) { index.Console.debug(`Received next KCP segment`); this.#buffer.set(segment$1.serial, segment$1); return; } this.parent.input.enqueue(segment$1.fragment); this.parent.recvCounter++; let next; while (next = this.#buffer.get(this.parent.recvCounter)) { index.Console.debug(`Unblocked next KCP segment`); this.parent.input.enqueue(next.fragment); this.#buffer.delete(this.parent.recvCounter); this.parent.recvCounter++; } } async #onAckSegment(segment) { const future = this.parent.resolveOnAckBySerial.get(segment.serial); if (future == null) return; this.parent.resolveOnAckBySerial.delete(segment.serial); future.resolve(); } async #onWaskSegment(segment$1) { const conversation = this.parent.conversation; const command = segment.KcpSegment.commands.wins; const serial = 0; const unackSerial = this.parent.recvCounter; const fragment = new binary.Empty(); const wins = segment.KcpSegment.empty({ conversation, command, serial, unackSerial, fragment }); this.parent.output.enqueue(wins); } } exports.ExpectedKcpSegmentError = ExpectedKcpSegmentError; exports.SecretKcpReader = SecretKcpReader; exports.UnknownKcpCommandError = UnknownKcpCommandError; //# sourceMappingURL=reader.cjs.map