UNPKG

@2003scape/rsc-client

Version:
286 lines (225 loc) 7.29 kB
const Long = require('long'); function toCharArray(s) { const a = new Uint16Array(s.length); for (let i = 0; i < s.length; i += 1) { a[i] = s.charCodeAt(i); } return a; } class PacketStream { constructor(socket) { this.socket = socket; this.closed = false; this.closing = false; this.delay = 0; this.isaacIncoming = null; this.isaacOutgoing = null; this.length = 0; this.maxReadTries = 0; this.packet8Check = 8; this.packetData = null; this.packetEnd = 3; this.packetMaxLength = 5000; this.packetStart = 0; this.readTries = 0; this.socketException = false; this.socketExceptionMessage = ''; } // TODO toggle ISAAC /*seedIsaac(seed) { //this.isaacIncoming = new ISAAC(seed); //this.isaacOutgoing = new ISAAC(seed); }*/ async readBytes(len, buff) { await this.readStreamBytes(len, 0, buff); } async readPacket(buff) { try { this.readTries++; if (this.maxReadTries > 0 && this.readTries > this.maxReadTries) { this.socketException = true; this.socketExceptionMessage = 'time-out'; this.maxReadTries += this.maxReadTries; return 0; } if (this.length === 0 && this.availableStream() >= 2) { this.length = await this.readStream(); if (this.length >= 160) { this.length = (this.length - 160) * 256 + (await this.readStream()); } } if (this.length > 0 && this.availableStream() >= this.length) { if (this.length >= 160) { await this.readBytes(this.length, buff); } else { buff[this.length - 1] = (await this.readStream()) & 0xff; if (this.length > 1) { await this.readBytes(this.length - 1, buff); } } let i = this.length; this.length = 0; this.readTries = 0; return i; } } catch (e) { this.socketException = true; this.socketExceptionMessage = e.message; } return 0; } hasPacket() { return this.packetStart > 0; } writePacket(i) { if (this.socketException) { this.packetStart = 0; this.packetEnd = 3; this.socketException = false; throw new Error(this.socketExceptionMessage); } this.delay++; if (this.delay < i) { return; } if (this.packetStart > 0) { this.delay = 0; this.writeStreamBytes(this.packetData, 0, this.packetStart); } this.packetStart = 0; this.packetEnd = 3; } sendPacket() { if (this.isaacOutgoing !== null) { let i = this.packetData[this.packetStart + 2] & 0xff; this.packetData[this.packetStart + 2] = (i + this.isaacOutgoing.getNextValue()) & 0xff; } // what the fuck is this even for? legacy? if (this.packet8Check !== 8) { this.packetEnd++; } const length = this.packetEnd - this.packetStart - 2; if (length >= 160) { this.packetData[this.packetStart] = (160 + ((length / 256) | 0)) & 0xff; this.packetData[this.packetStart + 1] = length & 0xff; } else { this.packetData[this.packetStart] = length & 0xff; this.packetEnd--; this.packetData[this.packetStart + 1] = this.packetData[ this.packetEnd ]; } // this seems largely useless and doesn't appear to do anything if (this.packetMaxLength <= 10000) { let k = this.packetData[this.packetStart + 2] & 0xff; PacketStream.anIntArray537[k]++; PacketStream.anIntArray541[k] += this.packetEnd - this.packetStart; } this.packetStart = this.packetEnd; } putBytes(src, srcPos, len) { for (let k = 0; k < len; k++) { this.packetData[this.packetEnd++] = src[srcPos + k] & 0xff; } } putLong(l) { this.putInt(l.shiftRight(32).toInt()); this.putInt(l.toInt()); } newPacket(opcode) { if (this.packetStart > (((this.packetMaxLength * 4) / 5) | 0)) { try { this.writePacket(0); } catch (e) { this.socketException = true; this.socketExceptionMessage = e.message; } } if (this.packetData === null) { this.packetData = new Int8Array(this.packetMaxLength); } this.packetData[this.packetStart + 2] = opcode & 0xff; this.packetData[this.packetStart + 3] = 0; this.packetEnd = this.packetStart + 3; this.packet8Check = 8; } async getLong() { let l = await this.getShort(); let l1 = await this.getShort(); let l2 = await this.getShort(); let l3 = await this.getShort(); return Long.fromInt(l) .shiftLeft(48) .add(Long.fromInt(l1).shiftLeft(32)) .add(l2 << 16) .add(l3); } putShort(i) { this.packetData[this.packetEnd++] = (i >> 8) & 0xff; this.packetData[this.packetEnd++] = i & 0xff; } putInt(i) { this.packetData[this.packetEnd++] = (i >> 24) & 0xff; this.packetData[this.packetEnd++] = (i >> 16) & 0xff; this.packetData[this.packetEnd++] = (i >> 8) & 0xff; this.packetData[this.packetEnd++] = i & 0xff; } async getShort() { let i = await this.getByte(); let j = await this.getByte(); return i * 256 + j; } putString(s) { this.putBytes(toCharArray(s), 0, s.length); } putByte(i) { this.packetData[this.packetEnd++] = i & 0xff; } isaacCommand(i) { // TODO toggle ISAA //return i - isaacIncoming.getNextValue() & 0xff; return i; } async getByte() { return (await this.readStream()) & 0xff; } flushPacket() { this.sendPacket(); this.writePacket(0); } closeStream() { this.closing = true; this.socket.close(); this.closed = true; } async readStream() { if (this.closing) { return 0; } return await this.socket.read(); } availableStream() { if (this.closing) { return 0; } return this.socket.available(); } async readStreamBytes(len, off, buff) { if (this.closing) { return; } await this.socket.readBytes(buff, off, len); } writeStreamBytes(buff, off, len) { if (this.closing) { return; } this.socket.write(buff, off, len); } } PacketStream.anIntArray537 = new Int32Array(256); PacketStream.anIntArray541 = new Int32Array(256); module.exports = PacketStream;