import { MAX_DATA_LENGTH } from "../common"; import { numberToUint16BE } from "../utilities/number"; import { SmartBuffer } from "../utilities/smart-buffer"; export interface IncomingPacket { messageType: number; senderId: number; data: Uint8Array; } export interface OutgoingPacket { messageType: Uint8Array; data?: Uint8Array; } /** * Create an outgoing packet ready-to-send over a WebSocket in line with the BENNC basic message strucure specification. * @param outgoingPacket The message type and data to send. * @returns A buffer containing the ready-to-send packet. */ export function packOutgoingPacket(outgoingPacket: OutgoingPacket): Uint8Array { // Default to empty data if not provided const data = outgoingPacket.data ?? new Uint8Array(0); // Verify that the data does not exceed the maximum data length. if (data.length > MAX_DATA_LENGTH) { throw RangeError( `Specified data of length ${data.length} exceeds max data length ${MAX_DATA_LENGTH}.`, ); } // Prepare the outgoing packet. const buffer = new SmartBuffer(); buffer.writeBytes(outgoingPacket.messageType); buffer.writeBytes(numberToUint16BE(data.length)); buffer.writeBytes(data); return buffer.data; } /** * Unpack an incoming packet coming from a WebSocket in line with the BENNC basic message strucure specification. * @param incomingPacket The incoming buffer from a WebSocket to unpack. * @returns The unpacked data. */ export function unpackIncomingPacket( incomingPacket: ArrayBuffer, ): IncomingPacket { const buffer = SmartBuffer.from(incomingPacket); const messageType = buffer.readUInt16(); const senderId = buffer.readUInt32(); const length = buffer.readUInt16(); const data = buffer.readBytes(length); return { messageType: messageType, senderId: senderId, data: data, }; }