From 21dd9ccf7ecc2a1b17482b36f2aeefe63d21c439 Mon Sep 17 00:00:00 2001 From: nvms Date: Mon, 21 Apr 2025 10:39:48 -0400 Subject: [PATCH] feat(server): assign short unique connection IDs using custom generator --- packages/mesh/src/server/connection.ts | 5 ++- packages/mesh/src/server/utils/ids.ts | 47 ++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 packages/mesh/src/server/utils/ids.ts diff --git a/packages/mesh/src/server/connection.ts b/packages/mesh/src/server/connection.ts index ad1eeaa..43328d7 100644 --- a/packages/mesh/src/server/connection.ts +++ b/packages/mesh/src/server/connection.ts @@ -10,6 +10,9 @@ import { Status } from "../common/status"; import { Latency } from "./latency"; import { Ping } from "./ping"; import type { MeshServerOptions } from "./"; +import { getCreateId } from "./utils/ids"; + +const getId = getCreateId({ init: Date.now(), len: 4 }); export class Connection extends EventEmitter { id: string; @@ -29,7 +32,7 @@ export class Connection extends EventEmitter { ) { super(); this.socket = socket; - this.id = req.headers["sec-websocket-key"]!; + this.id = getId(); this.remoteAddress = req.socket.remoteAddress!; this.connectionOptions = options; diff --git a/packages/mesh/src/server/utils/ids.ts b/packages/mesh/src/server/utils/ids.ts new file mode 100644 index 0000000..692149f --- /dev/null +++ b/packages/mesh/src/server/utils/ids.ts @@ -0,0 +1,47 @@ +import { getRandomValues } from "node:crypto"; + +const HEX: string[] = []; + +for (let i = 0; i < 256; i++) { + HEX[i] = (i + 256).toString(16).substring(1); +} + +function pad(str: string, size: number) { + const s = `000000${str}`; + return s.substring(s.length - size); +} + +const SHARD_COUNT = 32; + +export function getCreateId(opts: { init: number; len: number }) { + const len = opts.len || 16; + let str = ""; + let num = 0; + const discreteValues = 1_679_616; // Math.pow(36, 4) + let current = opts.init + Math.ceil(discreteValues / 2); + + function counter() { + if (current >= discreteValues) current = 0; + current++; + return (current - 1).toString(16); + } + + return () => { + if (!str || num === 256) { + const bytes = new Uint8Array(len); + getRandomValues(bytes); + str = Array.from(bytes, (b) => HEX[b]) + .join("") + .substring(0, len); + num = 0; + } + + const date = Date.now().toString(36); + const paddedCounter = pad(counter(), 6); + const hex = HEX[num++]!; + + const shardKey = parseInt(hex, 16) % SHARD_COUNT; + + return `conn-${date}${paddedCounter}${hex}${str}${shardKey}`; + }; +}