From a93bfc182fef7645014163e480524dd7bb89a3ea Mon Sep 17 00:00:00 2001 From: Jack Hadrill Date: Tue, 1 Feb 2022 02:12:49 +0000 Subject: [PATCH] Initial progress --- package-lock.json | 36 ++++++++++++-- package.json | 10 ++-- src/bennc.ts | 18 ++++++- src/buffer-reader.ts | 37 ++++++++++++++ src/common.ts | 4 ++ src/index.ts | 1 + src/structures/server.ts | 16 +++++++ tests/bennc.test.ts | 5 -- tests/buffer-reader.test.ts | 96 +++++++++++++++++++++++++++++++++++++ tsconfig.eslint.json | 1 - 10 files changed, 209 insertions(+), 15 deletions(-) create mode 100644 src/buffer-reader.ts create mode 100644 src/common.ts create mode 100644 src/structures/server.ts delete mode 100644 tests/bennc.test.ts create mode 100644 tests/buffer-reader.test.ts diff --git a/package-lock.json b/package-lock.json index 06d2fdb..f5b90e3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,10 @@ "name": "bennc-js", "version": "1.0.0", "license": "ISC", + "dependencies": { + "@types/websocket": "^1.0.5", + "romulus-js": "git+https://git.jacknet.io/TerribleCodeClub/romulus-js.git" + }, "devDependencies": { "@types/jest": "^27.4.0", "jest": "^27.4.7", @@ -1078,8 +1082,7 @@ "node_modules/@types/node": { "version": "17.0.13", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.13.tgz", - "integrity": "sha512-Y86MAxASe25hNzlDbsviXl8jQHb0RDvKt4c40ZJQ1Don0AAL0STLZSs4N+6gLEO55pedy7r2cLwS+ZDxPm/2Bw==", - "dev": true + "integrity": "sha512-Y86MAxASe25hNzlDbsviXl8jQHb0RDvKt4c40ZJQ1Don0AAL0STLZSs4N+6gLEO55pedy7r2cLwS+ZDxPm/2Bw==" }, "node_modules/@types/prettier": { "version": "2.4.3", @@ -1093,6 +1096,14 @@ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, + "node_modules/@types/websocket": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/websocket/-/websocket-1.0.5.tgz", + "integrity": "sha512-NbsqiNX9CnEfC1Z0Vf4mE1SgAJ07JnRYcNex7AJ9zAVzmiGHmjKFEk7O4TJIsgv2B1sLEb6owKFZrACwdYngsQ==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/yargs": { "version": "16.0.4", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", @@ -5398,6 +5409,12 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/romulus-js": { + "version": "1.0.0", + "resolved": "git+https://git.jacknet.io/TerribleCodeClub/romulus-js.git#8718556a6f976efb0bd30571f0699e925aafda82", + "hasInstallScript": true, + "license": "ISC" + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -7212,8 +7229,7 @@ "@types/node": { "version": "17.0.13", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.13.tgz", - "integrity": "sha512-Y86MAxASe25hNzlDbsviXl8jQHb0RDvKt4c40ZJQ1Don0AAL0STLZSs4N+6gLEO55pedy7r2cLwS+ZDxPm/2Bw==", - "dev": true + "integrity": "sha512-Y86MAxASe25hNzlDbsviXl8jQHb0RDvKt4c40ZJQ1Don0AAL0STLZSs4N+6gLEO55pedy7r2cLwS+ZDxPm/2Bw==" }, "@types/prettier": { "version": "2.4.3", @@ -7227,6 +7243,14 @@ "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==", "dev": true }, + "@types/websocket": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/websocket/-/websocket-1.0.5.tgz", + "integrity": "sha512-NbsqiNX9CnEfC1Z0Vf4mE1SgAJ07JnRYcNex7AJ9zAVzmiGHmjKFEk7O4TJIsgv2B1sLEb6owKFZrACwdYngsQ==", + "requires": { + "@types/node": "*" + } + }, "@types/yargs": { "version": "16.0.4", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", @@ -10390,6 +10414,10 @@ "glob": "^7.1.3" } }, + "romulus-js": { + "version": "git+https://git.jacknet.io/TerribleCodeClub/romulus-js.git#8718556a6f976efb0bd30571f0699e925aafda82", + "from": "romulus-js@git+https://git.jacknet.io/TerribleCodeClub/romulus-js.git" + }, "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", diff --git a/package.json b/package.json index 7a64fa6..3b21e0c 100644 --- a/package.json +++ b/package.json @@ -15,16 +15,20 @@ "author": "Butlersaurus", "license": "ISC", "devDependencies": { - "typescript": "^4.5.5", - "ts-standard": "^11.0.0", + "@types/jest": "^27.4.0", "jest": "^27.4.7", "ts-jest": "^27.1.3", - "@types/jest": "^27.4.0" + "ts-standard": "^11.0.0", + "typescript": "^4.5.5" }, "jest": { "verbose": true, "transform": { "^.+\\.ts?$": "ts-jest" } + }, + "dependencies": { + "@types/websocket": "^1.0.5", + "romulus-js": "git+https://git.jacknet.io/TerribleCodeClub/romulus-js.git" } } diff --git a/src/bennc.ts b/src/bennc.ts index 6725e6f..45f0c52 100644 --- a/src/bennc.ts +++ b/src/bennc.ts @@ -1,3 +1,17 @@ -export function addNumbers (a: number, b: number): number { - return a + b +import { IMessageEvent } from 'websocket' +import { IncomingPacket } from './structures/server' + +export function connect (url: string): void { + const webSocket = new WebSocket(url) + webSocket.binaryType = 'arraybuffer' + webSocket.onopen = onOpen + webSocket.onmessage = onMessage +} + +function onOpen (): void { + console.log('Connected!') +} + +function onMessage (event: IMessageEvent): void { + console.log(new IncomingPacket(event.data as Buffer)) } diff --git a/src/buffer-reader.ts b/src/buffer-reader.ts new file mode 100644 index 0000000..5638161 --- /dev/null +++ b/src/buffer-reader.ts @@ -0,0 +1,37 @@ +import { ByteLength } from './common' + +export class BufferReader { + private readonly _data: Buffer + private _cursor: number + + constructor (data: Buffer = Buffer.from([])) { + this._data = data + this._cursor = 0 + } + + get cursor (): number { + return this._cursor + } + + set cursor (position: number) { + if (position < 0 || position > this._data.length) { + throw RangeError(`Cannot seek to ${this.cursor} of ${this._data.length} bytes.`) + } + this._cursor = position + } + + readUInt16 (): number { + this.cursor += ByteLength.UInt16 + return this._data.slice(this.cursor - ByteLength.UInt16, this.cursor).readInt16BE() + } + + readUInt32 (): number { + this.cursor += ByteLength.UInt32 + return this._data.slice(this.cursor - ByteLength.UInt32, this.cursor).readInt32BE() + } + + readBuffer (len: number): Buffer { + this.cursor += len + return this._data.slice(this.cursor - len, this.cursor) + } +} diff --git a/src/common.ts b/src/common.ts new file mode 100644 index 0000000..e5e5f1c --- /dev/null +++ b/src/common.ts @@ -0,0 +1,4 @@ +export enum ByteLength { + UInt16 = 2, + UInt32 = 4 +} diff --git a/src/index.ts b/src/index.ts index e69de29..7a89cd8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -0,0 +1 @@ +export { connect } from './bennc' diff --git a/src/structures/server.ts b/src/structures/server.ts new file mode 100644 index 0000000..28b91f1 --- /dev/null +++ b/src/structures/server.ts @@ -0,0 +1,16 @@ +import { BufferReader } from '../buffer-reader' + +export class IncomingPacket extends BufferReader { + messageType: number + senderId: number + length: number + data: Buffer + + constructor (data: Buffer) { + super() + this.messageType = this.readUInt16() + this.senderId = this.readUInt32() + this.length = this.readUInt16() + this.data = this.readBuffer(this.length) + } +} diff --git a/tests/bennc.test.ts b/tests/bennc.test.ts deleted file mode 100644 index 77001b7..0000000 --- a/tests/bennc.test.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { addNumbers } from '../src/bennc' - -test('Add two numbers', () => { - expect(addNumbers(1, 2)).toBe(3) -}) diff --git a/tests/buffer-reader.test.ts b/tests/buffer-reader.test.ts new file mode 100644 index 0000000..70ef36e --- /dev/null +++ b/tests/buffer-reader.test.ts @@ -0,0 +1,96 @@ +import { BufferReader } from '../src/buffer-reader' + +test('Read a UInt16.', () => { + // Given + const buffer = Buffer.from([0x30, 0x39]) + + // When + const smartBuffer = new BufferReader(buffer) + + // Then + expect(smartBuffer.readUInt16()).toBe(12345) +}) + +test('Read a UInt32.', () => { + // Given + const buffer = Buffer.from([0x49, 0x96, 0x02, 0xD2]) + + // When + const smartBuffer = new BufferReader(buffer) + + // Then + expect(smartBuffer.readUInt32()).toBe(1234567890) +}) + +test('Read a buffer.', () => { + // Given + const buffer = Buffer.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) + + // When + const smartBuffer = new BufferReader(buffer) + + // Then + expect(smartBuffer.readBuffer(4)).toMatchObject(Buffer.from([0, 1, 2, 3])) +}) + +test('Cursor is correctly incremented after reading a UInt16.', () => { + // Given + const buffer = Buffer.from([0x30, 0x39, 0x1A, 0x85]) + + // When + const smartBuffer = new BufferReader(buffer) + + // Then + expect(smartBuffer.readUInt16()).toBe(12345) + expect(smartBuffer.readUInt16()).toBe(6789) +}) + +test('Cursor is correctly incremented after reading a buffer.', () => { + // Given + const buffer = Buffer.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) + + // When + const smartBuffer = new BufferReader(buffer) + + // Then + expect(smartBuffer.readBuffer(4)).toMatchObject(Buffer.from([0, 1, 2, 3])) + expect(smartBuffer.readBuffer(4)).toMatchObject(Buffer.from([4, 5, 6, 7])) +}) + +test('Cursor is correctly incremented after reading a UInt32.', () => { + // Given + const buffer = Buffer.from([0x49, 0x96, 0x02, 0xD2, 0x3A, 0xDE, 0x68, 0xB1]) + + // When + const smartBuffer = new BufferReader(buffer) + + // Then + expect(smartBuffer.readUInt32()).toBe(1234567890) + expect(smartBuffer.readUInt32()).toBe(987654321) +}) + +test('Seek to position below 0 throws range error.', () => { + // Given + const buffer = Buffer.from([]) + + // When + const smartBuffer = new BufferReader(buffer) + + // Then + expect(() => { + smartBuffer.cursor = -1 + }).toThrow(RangeError) +}) + +test('Seek beyond buffer throws range error.', () => { + // Given + const buffer = Buffer.from([0, 1, 2, 3]) + + // When + const smartBuffer = new BufferReader(buffer) + + // Then + expect(() => { + smartBuffer.cursor = 5 + }).toThrow(RangeError) +}) diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json index 4430ff4..21c332e 100644 --- a/tsconfig.eslint.json +++ b/tsconfig.eslint.json @@ -1,5 +1,4 @@ { "extends": "./tsconfig.json", - // "include": ["src", "tests"], "exclude": [] } \ No newline at end of file