diff --git a/src/DumbClient.ts b/src/DumbClient.ts
new file mode 100644
index 0000000..4b905b6
--- /dev/null
+++ b/src/DumbClient.ts
@@ -0,0 +1,71 @@
+/*
+ * node-subdata-2 - SubData 2 wrapper for Node.js
+ * Copyright (C) 2022 LogN
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+import SafeEventEmitter from "./lib/SafeEventEmitter";
+import Packet from "./Packet";
+import type Shell from "./shell";
+import { ShellEvents } from "./shell";
+
+/** A list of possible events for a {@link DumbClient} */
+export enum DumbClientEvents {
+ /** A new packet is received */
+ Packet = "packet",
+ /** The connection is closing */
+ Close = "close"
+}
+
+export type DumbClientEventArguments = {
+ [DumbClientEvents.Packet]: [Packet];
+ [DumbClientEvents.Close]: [];
+};
+
+/**
+ * Represents a SubData 2 client that does not perform any protocol
+ * handshake or states, and leaves it up to the user. You probably
+ * don't want to use this.
+ */
+export default class DumbClient extends SafeEventEmitter {
+ private _shell: Shell;
+
+ /**
+ * Create a new DumbClient.
+ * @param shell The {@link Shell} to use
+ */
+ public constructor(shell: Shell) {
+ super();
+ this._shell = shell;
+ this._shell.on(ShellEvents.Close, () => {
+ this.emit(DumbClientEvents.Close);
+ });
+ this._shell.on(ShellEvents.Packet, (_size, data) => {
+ this.emit(DumbClientEvents.Packet, new Packet(data));
+ });
+ }
+
+ /**
+ * Terminate the TCP level of the connection. This does not send the disconnect packets.
+ */
+ public close() {
+ this._shell.close();
+ }
+
+ /** Send a {@link Packet} over the stream. */
+ public send(data: Packet) {
+ this._shell.send(data.toRaw());
+ }
+}
diff --git a/src/Packet.ts b/src/Packet.ts
new file mode 100644
index 0000000..d4544e2
--- /dev/null
+++ b/src/Packet.ts
@@ -0,0 +1,44 @@
+/*
+ * node-subdata-2 - SubData 2 wrapper for Node.js
+ * Copyright (C) 2022 LogN
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+/** Describes a SubData 2 packet. */
+export default class Packet {
+ /** This packet's identification number */
+ public id: number;
+ /** The rest of the packet's InputStream */
+ public data: Buffer;
+
+ /**
+ * Create a new Packet.
+ * @param raw The raw packet data including the ID as the first two bytes
+ */
+ public constructor(raw: Buffer) {
+ this.id = parseInt(raw.subarray(0, 2).toString("hex"), 16);
+ this.data = raw.subarray(2);
+ }
+
+ /** Convert this Packet to raw network data */
+ public toRaw() {
+ return Buffer.concat([Buffer.from([this.id >> 8, this.id & 0xff]), this.data]);
+ }
+
+ /** Make a new Packet given an ID and data. */
+ public static fromID(id: number, data: Buffer) {
+ return new Packet(Buffer.concat([Buffer.from([id >> 8, id & 0xff]), data]));
+ }
+}
diff --git a/src/index.ts b/src/index.ts
index 69022c1..8ea2344 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -16,6 +16,7 @@
* along with this program. If not, see .
*/
+import DumbClient, { DumbClientEventArguments, DumbClientEvents } from "./DumbClient";
import SafeEventEmitter from "./lib/SafeEventEmitter.js";
import { bytes, kb, mb } from "./lib/sizeHelpers.js";
import Shell, { ShellEventArguments, ShellEvents } from "./shell/";
@@ -34,6 +35,9 @@ export {
DirectStream,
DirectStreamEventArguments,
DirectStreamEvents,
+ DumbClient,
+ DumbClientEventArguments,
+ DumbClientEvents,
IOProvider,
IOProviderEventArguments,
IOProviderEvents,
diff --git a/src/shell/index.ts b/src/shell/index.ts
index ba2c65c..103eecf 100644
--- a/src/shell/index.ts
+++ b/src/shell/index.ts
@@ -62,4 +62,9 @@ export default class Shell extends SafeEventEmitter {
public send(data: Buffer): void {
this._stream.writePacket(this._algorithm.encode(data));
}
+
+ /** Close the underlying connection. */
+ public close(): void {
+ this._stream.close();
+ }
}