UNPKG

@u4/adbkit

Version:

A Typescript client for the Android Debug Bridge.

103 lines 3.91 kB
import { Buffer } from 'node:buffer'; import { setImmediate } from "node:timers"; import EventEmitter from 'node:events'; import Packet from './packet.js'; import Utils from '../utils.js'; export class ChecksumError extends Error { constructor(packet) { super(); this.packet = packet; Object.setPrototypeOf(this, ChecksumError.prototype); this.name = 'ChecksumError'; this.message = 'Checksum mismatch'; Error.captureStackTrace(this, PacketReader.ChecksumError); } } export class MagicError extends Error { constructor(packet) { super(); this.packet = packet; Object.setPrototypeOf(this, MagicError.prototype); this.name = 'MagicError'; this.message = 'Magic value mismatch'; Error.captureStackTrace(this, PacketReader.MagicError); } } class PacketReader extends EventEmitter { constructor(stream) { super(); this.stream = stream; this.inBody = false; this.on = (event, listener) => super.on(event, listener); this.off = (event, listener) => super.off(event, listener); this.once = (event, listener) => super.once(event, listener); this.emit = (event, ...args) => super.emit(event, ...args); this.stream.on('readable', this._tryRead.bind(this)); this.stream.on('error', (err) => { this.emit('error', err); }); this.stream.on('end', () => { this.emit('end'); }); setImmediate(this._tryRead.bind(this)); } _tryRead() { while (this._appendChunk()) { while (this.buffer) { if (this.inBody) { if (!this.packet) { throw Error('invalid stat packet is missing'); } if (!(this.buffer.length >= this.packet.length)) { break; } this.packet.data = this._consume(this.packet.length); if (!this.packet.verifyChecksum()) { this.emit('error', new PacketReader.ChecksumError(this.packet)); return; } this.emit('packet', this.packet); this.inBody = false; } else { if (!(this.buffer.length >= 24)) { break; } const header = this._consume(24); this.packet = new Packet(header.readUInt32LE(0), header.readUInt32LE(4), header.readUInt32LE(8), header.readUInt32LE(12), header.readUInt32LE(16), header.readUInt32LE(20), Buffer.alloc(0)); if (!this.packet.verifyMagic()) { this.emit('error', new PacketReader.MagicError(this.packet)); return; } if (this.packet.length === 0) { this.emit('packet', this.packet); } else { this.inBody = true; } } } } } _appendChunk() { const chunk = this.stream.read(); if (chunk) { if (this.buffer) { return (this.buffer = Utils.concatBuffer([this.buffer, chunk])); } else { return (this.buffer = chunk); } } else { return null; } } _consume(length) { if (!this.buffer) return Buffer.from([]); const chunk = this.buffer.slice(0, length); this.buffer = length === this.buffer.length ? undefined : this.buffer.slice(length); return chunk; } } PacketReader.ChecksumError = ChecksumError; PacketReader.MagicError = MagicError; export default PacketReader; //# sourceMappingURL=packetreader.js.map