@aegis-fluxion/core 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1200 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +179 -0
- package/dist/index.d.ts +179 -0
- package/dist/index.js +1193 -0
- package/dist/index.js.map +1 -0
- package/package.json +45 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["createECDH","createHash","randomBytes","createCipheriv","createDecipheriv","WebSocketServer","WebSocket","randomUUID"],"mappings":"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","file":"index.cjs","sourcesContent":["import {\r\n createCipheriv,\r\n createDecipheriv,\r\n createECDH,\r\n createHash,\r\n randomBytes,\r\n randomUUID\r\n} from \"node:crypto\";\r\nimport type { ECDH } from \"node:crypto\";\r\nimport type { IncomingMessage } from \"node:http\";\r\nimport WebSocket, { WebSocketServer } from \"ws\";\r\nimport type {\r\n ClientOptions,\r\n RawData,\r\n ServerOptions as WebSocketServerOptions\r\n} from \"ws\";\r\n\r\nconst DEFAULT_CLOSE_CODE = 1000;\r\nconst DEFAULT_CLOSE_REASON = \"\";\r\nconst INTERNAL_HANDSHAKE_EVENT = \"__handshake\";\r\nconst READY_EVENT = \"ready\";\r\nconst HANDSHAKE_CURVE = \"prime256v1\";\r\nconst ENCRYPTION_ALGORITHM = \"aes-256-gcm\";\r\nconst GCM_IV_LENGTH = 12;\r\nconst GCM_AUTH_TAG_LENGTH = 16;\r\nconst ENCRYPTION_KEY_LENGTH = 32;\r\nconst ENCRYPTED_PACKET_VERSION = 1;\r\nconst ENCRYPTED_PACKET_PREFIX_LENGTH = 1 + GCM_IV_LENGTH + GCM_AUTH_TAG_LENGTH;\r\nconst DEFAULT_HEARTBEAT_INTERVAL_MS = 15_000;\r\nconst DEFAULT_HEARTBEAT_TIMEOUT_MS = 15_000;\r\nconst DEFAULT_RECONNECT_INITIAL_DELAY_MS = 250;\r\nconst DEFAULT_RECONNECT_MAX_DELAY_MS = 10_000;\r\nconst DEFAULT_RECONNECT_FACTOR = 2;\r\nconst DEFAULT_RECONNECT_JITTER_RATIO = 0.2;\r\n\r\ninterface HandshakePayload {\r\n publicKey: string;\r\n}\r\n\r\ninterface ServerHandshakeState {\r\n ecdh: ECDH;\r\n localPublicKey: string;\r\n isReady: boolean;\r\n}\r\n\r\ninterface ClientHandshakeState {\r\n ecdh: ECDH;\r\n localPublicKey: string;\r\n isReady: boolean;\r\n sharedSecret: Buffer | null;\r\n encryptionKey: Buffer | null;\r\n}\r\n\r\ninterface EncryptedPacketParts {\r\n iv: Buffer;\r\n authTag: Buffer;\r\n ciphertext: Buffer;\r\n}\r\n\r\nexport interface SecureEnvelope<TData = unknown> {\r\n event: string;\r\n data: TData;\r\n}\r\n\r\nexport interface SecureServerHeartbeatOptions {\r\n enabled?: boolean;\r\n intervalMs?: number;\r\n timeoutMs?: number;\r\n}\r\n\r\nexport interface SecureServerOptions extends WebSocketServerOptions {\r\n heartbeat?: SecureServerHeartbeatOptions;\r\n}\r\n\r\nexport interface SecureClientReconnectOptions {\r\n enabled?: boolean;\r\n initialDelayMs?: number;\r\n maxDelayMs?: number;\r\n factor?: number;\r\n jitterRatio?: number;\r\n maxAttempts?: number | null;\r\n}\r\n\r\nexport interface SecureClientOptions {\r\n protocols?: string | string[];\r\n wsOptions?: ClientOptions;\r\n autoConnect?: boolean;\r\n reconnect?: boolean | SecureClientReconnectOptions;\r\n}\r\n\r\nexport interface SecureServerClient {\r\n id: string;\r\n socket: WebSocket;\r\n request: IncomingMessage;\r\n join: (room: string) => boolean;\r\n leave: (room: string) => boolean;\r\n leaveAll: () => number;\r\n}\r\n\r\nexport interface SecureServerRoomOperator {\r\n emit: (event: string, data: unknown) => SecureServer;\r\n}\r\n\r\nexport type SecureErrorHandler = (error: Error) => void;\r\n\r\nexport type SecureServerEventHandler = (\r\n data: unknown,\r\n client: SecureServerClient\r\n) => void;\r\n\r\nexport type SecureServerConnectionHandler = (\r\n client: SecureServerClient\r\n) => void;\r\n\r\nexport type SecureServerDisconnectHandler = (\r\n client: SecureServerClient,\r\n code: number,\r\n reason: string\r\n) => void;\r\n\r\nexport type SecureServerReadyHandler = (client: SecureServerClient) => void;\r\n\r\nexport type SecureClientEventHandler = (data: unknown) => void;\r\n\r\nexport type SecureClientConnectHandler = () => void;\r\n\r\nexport type SecureClientDisconnectHandler = (\r\n code: number,\r\n reason: string\r\n) => void;\r\n\r\nexport type SecureClientReadyHandler = () => void;\r\n\r\nexport type SecureServerLifecycleEvent =\r\n | \"connection\"\r\n | \"disconnect\"\r\n | \"ready\"\r\n | \"error\";\r\n\r\nexport type SecureClientLifecycleEvent =\r\n | \"connect\"\r\n | \"disconnect\"\r\n | \"ready\"\r\n | \"error\";\r\n\r\nexport interface SecureServerEventMap {\r\n connection: SecureServerConnectionHandler;\r\n disconnect: SecureServerDisconnectHandler;\r\n ready: SecureServerReadyHandler;\r\n error: SecureErrorHandler;\r\n}\r\n\r\nexport interface SecureClientEventMap {\r\n connect: SecureClientConnectHandler;\r\n disconnect: SecureClientDisconnectHandler;\r\n ready: SecureClientReadyHandler;\r\n error: SecureErrorHandler;\r\n}\r\n\r\nfunction normalizeToError(error: unknown, fallbackMessage: string): Error {\r\n if (error instanceof Error) {\r\n return error;\r\n }\r\n\r\n if (typeof error === \"string\" && error.trim().length > 0) {\r\n return new Error(error);\r\n }\r\n\r\n return new Error(fallbackMessage);\r\n}\r\n\r\nfunction decodeRawData(rawData: RawData): string {\r\n if (typeof rawData === \"string\") {\r\n return rawData;\r\n }\r\n\r\n if (rawData instanceof ArrayBuffer) {\r\n return Buffer.from(rawData).toString(\"utf8\");\r\n }\r\n\r\n if (Array.isArray(rawData)) {\r\n return Buffer.concat(rawData).toString(\"utf8\");\r\n }\r\n\r\n return rawData.toString(\"utf8\");\r\n}\r\n\r\nfunction rawDataToBuffer(rawData: RawData): Buffer {\r\n if (typeof rawData === \"string\") {\r\n return Buffer.from(rawData, \"utf8\");\r\n }\r\n\r\n if (rawData instanceof ArrayBuffer) {\r\n return Buffer.from(rawData);\r\n }\r\n\r\n if (Array.isArray(rawData)) {\r\n return Buffer.concat(rawData);\r\n }\r\n\r\n return Buffer.from(rawData);\r\n}\r\n\r\nfunction serializeEnvelope(event: string, data: unknown): string {\r\n const envelope: SecureEnvelope = { event, data };\r\n return JSON.stringify(envelope);\r\n}\r\n\r\nfunction parseEnvelope(rawData: RawData): SecureEnvelope {\r\n const decoded = decodeRawData(rawData);\r\n const parsed = JSON.parse(decoded) as Partial<SecureEnvelope>;\r\n\r\n if (\r\n typeof parsed !== \"object\" ||\r\n parsed === null ||\r\n typeof parsed.event !== \"string\"\r\n ) {\r\n throw new Error(\"Invalid message format. Expected { event: string, data: unknown }.\");\r\n }\r\n\r\n return {\r\n event: parsed.event,\r\n data: parsed.data\r\n };\r\n}\r\n\r\nfunction parseEnvelopeFromText(decodedPayload: string): SecureEnvelope {\r\n const parsed = JSON.parse(decodedPayload) as Partial<SecureEnvelope>;\r\n\r\n if (\r\n typeof parsed !== \"object\" ||\r\n parsed === null ||\r\n typeof parsed.event !== \"string\"\r\n ) {\r\n throw new Error(\"Invalid message format. Expected { event: string, data: unknown }.\");\r\n }\r\n\r\n return {\r\n event: parsed.event,\r\n data: parsed.data\r\n };\r\n}\r\n\r\nfunction decodeCloseReason(reason: Buffer): string {\r\n return reason.toString(\"utf8\");\r\n}\r\n\r\nfunction isReservedEmitEvent(event: string): boolean {\r\n return event === INTERNAL_HANDSHAKE_EVENT || event === READY_EVENT;\r\n}\r\n\r\nfunction createEphemeralHandshakeState(): { ecdh: ECDH; localPublicKey: string } {\r\n const ecdh = createECDH(HANDSHAKE_CURVE);\r\n ecdh.generateKeys();\r\n\r\n return {\r\n ecdh,\r\n localPublicKey: ecdh.getPublicKey(\"base64\")\r\n };\r\n}\r\n\r\nfunction parseHandshakePayload(data: unknown): HandshakePayload {\r\n if (typeof data !== \"object\" || data === null) {\r\n throw new Error(\"Invalid handshake payload format.\");\r\n }\r\n\r\n const payload = data as Partial<HandshakePayload>;\r\n\r\n if (typeof payload.publicKey !== \"string\" || payload.publicKey.length === 0) {\r\n throw new Error(\"Handshake payload must include a non-empty public key.\");\r\n }\r\n\r\n return {\r\n publicKey: payload.publicKey\r\n };\r\n}\r\n\r\nfunction deriveEncryptionKey(sharedSecret: Buffer): Buffer {\r\n const derivedKey = createHash(\"sha256\").update(sharedSecret).digest();\r\n\r\n if (derivedKey.length !== ENCRYPTION_KEY_LENGTH) {\r\n throw new Error(\"Failed to derive a valid AES-256 key.\");\r\n }\r\n\r\n return derivedKey;\r\n}\r\n\r\nfunction encryptSerializedEnvelope(serializedEnvelope: string, encryptionKey: Buffer): Buffer {\r\n const iv = randomBytes(GCM_IV_LENGTH);\r\n const cipher = createCipheriv(ENCRYPTION_ALGORITHM, encryptionKey, iv);\r\n const ciphertext = Buffer.concat([\r\n cipher.update(serializedEnvelope, \"utf8\"),\r\n cipher.final()\r\n ]);\r\n const authTag = cipher.getAuthTag();\r\n\r\n return Buffer.concat([\r\n Buffer.from([ENCRYPTED_PACKET_VERSION]),\r\n iv,\r\n authTag,\r\n ciphertext\r\n ]);\r\n}\r\n\r\nfunction parseEncryptedPacket(rawData: RawData): EncryptedPacketParts {\r\n const packetBuffer = rawDataToBuffer(rawData);\r\n\r\n if (packetBuffer.length <= ENCRYPTED_PACKET_PREFIX_LENGTH) {\r\n throw new Error(\"Encrypted packet is too short.\");\r\n }\r\n\r\n const version = packetBuffer.readUInt8(0);\r\n\r\n if (version !== ENCRYPTED_PACKET_VERSION) {\r\n throw new Error(\"Unsupported encrypted packet version.\");\r\n }\r\n\r\n const ivStart = 1;\r\n const ivEnd = ivStart + GCM_IV_LENGTH;\r\n const authTagStart = ivEnd;\r\n const authTagEnd = authTagStart + GCM_AUTH_TAG_LENGTH;\r\n\r\n const iv = packetBuffer.subarray(ivStart, ivEnd);\r\n const authTag = packetBuffer.subarray(authTagStart, authTagEnd);\r\n const ciphertext = packetBuffer.subarray(authTagEnd);\r\n\r\n if (ciphertext.length === 0) {\r\n throw new Error(\"Encrypted payload is empty.\");\r\n }\r\n\r\n return {\r\n iv,\r\n authTag,\r\n ciphertext\r\n };\r\n}\r\n\r\nfunction decryptSerializedEnvelope(rawData: RawData, encryptionKey: Buffer): string {\r\n const encryptedPacket = parseEncryptedPacket(rawData);\r\n const decipher = createDecipheriv(\r\n ENCRYPTION_ALGORITHM,\r\n encryptionKey,\r\n encryptedPacket.iv\r\n );\r\n\r\n decipher.setAuthTag(encryptedPacket.authTag);\r\n\r\n const plaintext = Buffer.concat([\r\n decipher.update(encryptedPacket.ciphertext),\r\n decipher.final()\r\n ]);\r\n\r\n return plaintext.toString(\"utf8\");\r\n}\r\n\r\nexport class SecureServer {\r\n private readonly socketServer: WebSocketServer;\r\n\r\n private readonly heartbeatConfig: Required<SecureServerHeartbeatOptions>;\r\n\r\n private heartbeatIntervalHandle: ReturnType<typeof setInterval> | null = null;\r\n\r\n private readonly clientsById = new Map<string, SecureServerClient>();\r\n\r\n private readonly clientIdBySocket = new Map<WebSocket, string>();\r\n\r\n private readonly customEventHandlers = new Map<string, Set<SecureServerEventHandler>>();\r\n\r\n private readonly connectionHandlers = new Set<SecureServerConnectionHandler>();\r\n\r\n private readonly disconnectHandlers = new Set<SecureServerDisconnectHandler>();\r\n\r\n private readonly readyHandlers = new Set<SecureServerReadyHandler>();\r\n\r\n private readonly errorHandlers = new Set<SecureErrorHandler>();\r\n\r\n private readonly handshakeStateBySocket = new WeakMap<WebSocket, ServerHandshakeState>();\r\n\r\n private readonly sharedSecretBySocket = new WeakMap<WebSocket, Buffer>();\r\n\r\n private readonly encryptionKeyBySocket = new WeakMap<WebSocket, Buffer>();\r\n\r\n private readonly pendingPayloadsBySocket = new WeakMap<WebSocket, SecureEnvelope[]>();\r\n\r\n private readonly heartbeatStateBySocket = new WeakMap<\r\n WebSocket,\r\n { awaitingPong: boolean; lastPingAt: number }\r\n >();\r\n\r\n private readonly roomMembersByName = new Map<string, Set<string>>();\r\n\r\n private readonly roomNamesByClientId = new Map<string, Set<string>>();\r\n\r\n public constructor(options: SecureServerOptions) {\r\n const { heartbeat, ...socketServerOptions } = options;\r\n\r\n this.heartbeatConfig = this.resolveHeartbeatConfig(heartbeat);\r\n this.socketServer = new WebSocketServer(socketServerOptions);\r\n this.bindSocketServerEvents();\r\n this.startHeartbeatLoop();\r\n }\r\n\r\n public get clientCount(): number {\r\n return this.clientsById.size;\r\n }\r\n\r\n public get clients(): ReadonlyMap<string, SecureServerClient> {\r\n return this.clientsById;\r\n }\r\n\r\n public on(event: \"connection\", handler: SecureServerConnectionHandler): this;\r\n public on(event: \"disconnect\", handler: SecureServerDisconnectHandler): this;\r\n public on(event: \"ready\", handler: SecureServerReadyHandler): this;\r\n public on(event: \"error\", handler: SecureErrorHandler): this;\r\n public on(event: string, handler: SecureServerEventHandler): this;\r\n public on(event: string, handler: unknown): this {\r\n try {\r\n if (event === \"connection\") {\r\n this.connectionHandlers.add(handler as SecureServerConnectionHandler);\r\n return this;\r\n }\r\n\r\n if (event === \"disconnect\") {\r\n this.disconnectHandlers.add(handler as SecureServerDisconnectHandler);\r\n return this;\r\n }\r\n\r\n if (event === READY_EVENT) {\r\n this.readyHandlers.add(handler as SecureServerReadyHandler);\r\n return this;\r\n }\r\n\r\n if (event === \"error\") {\r\n this.errorHandlers.add(handler as SecureErrorHandler);\r\n return this;\r\n }\r\n\r\n if (event === INTERNAL_HANDSHAKE_EVENT) {\r\n throw new Error(`The event \"${INTERNAL_HANDSHAKE_EVENT}\" is reserved for internal use.`);\r\n }\r\n\r\n const typedHandler = handler as SecureServerEventHandler;\r\n const listeners = this.customEventHandlers.get(event) ?? new Set<SecureServerEventHandler>();\r\n listeners.add(typedHandler);\r\n this.customEventHandlers.set(event, listeners);\r\n } catch (error) {\r\n this.notifyError(\r\n normalizeToError(error, \"Failed to register server event handler.\")\r\n );\r\n }\r\n\r\n return this;\r\n }\r\n\r\n public off(event: \"connection\", handler: SecureServerConnectionHandler): this;\r\n public off(event: \"disconnect\", handler: SecureServerDisconnectHandler): this;\r\n public off(event: \"ready\", handler: SecureServerReadyHandler): this;\r\n public off(event: \"error\", handler: SecureErrorHandler): this;\r\n public off(event: string, handler: SecureServerEventHandler): this;\r\n public off(event: string, handler: unknown): this {\r\n try {\r\n if (event === \"connection\") {\r\n this.connectionHandlers.delete(handler as SecureServerConnectionHandler);\r\n return this;\r\n }\r\n\r\n if (event === \"disconnect\") {\r\n this.disconnectHandlers.delete(handler as SecureServerDisconnectHandler);\r\n return this;\r\n }\r\n\r\n if (event === READY_EVENT) {\r\n this.readyHandlers.delete(handler as SecureServerReadyHandler);\r\n return this;\r\n }\r\n\r\n if (event === \"error\") {\r\n this.errorHandlers.delete(handler as SecureErrorHandler);\r\n return this;\r\n }\r\n\r\n if (event === INTERNAL_HANDSHAKE_EVENT) {\r\n return this;\r\n }\r\n\r\n const listeners = this.customEventHandlers.get(event);\r\n\r\n if (!listeners) {\r\n return this;\r\n }\r\n\r\n listeners.delete(handler as SecureServerEventHandler);\r\n\r\n if (listeners.size === 0) {\r\n this.customEventHandlers.delete(event);\r\n }\r\n } catch (error) {\r\n this.notifyError(\r\n normalizeToError(error, \"Failed to remove server event handler.\")\r\n );\r\n }\r\n\r\n return this;\r\n }\r\n\r\n public emit(event: string, data: unknown): this {\r\n try {\r\n if (isReservedEmitEvent(event)) {\r\n throw new Error(`The event \"${event}\" is reserved and cannot be emitted manually.`);\r\n }\r\n\r\n const envelope: SecureEnvelope = { event, data };\r\n\r\n for (const client of this.clientsById.values()) {\r\n this.sendOrQueuePayload(client.socket, envelope);\r\n }\r\n } catch (error) {\r\n this.notifyError(normalizeToError(error, \"Failed to emit server event.\"));\r\n }\r\n\r\n return this;\r\n }\r\n\r\n public emitTo(clientId: string, event: string, data: unknown): boolean {\r\n try {\r\n if (isReservedEmitEvent(event)) {\r\n throw new Error(`The event \"${event}\" is reserved and cannot be emitted manually.`);\r\n }\r\n\r\n const client = this.clientsById.get(clientId);\r\n\r\n if (!client) {\r\n throw new Error(`Client with id ${clientId} was not found.`);\r\n }\r\n\r\n this.sendOrQueuePayload(client.socket, { event, data });\r\n return true;\r\n } catch (error) {\r\n this.notifyError(normalizeToError(error, \"Failed to emit event to client.\"));\r\n return false;\r\n }\r\n }\r\n\r\n public to(room: string): SecureServerRoomOperator {\r\n const normalizedRoom = this.normalizeRoomName(room);\r\n\r\n return {\r\n emit: (event: string, data: unknown): SecureServer => {\r\n try {\r\n this.emitToRoom(normalizedRoom, event, data);\r\n } catch (error) {\r\n this.notifyError(\r\n normalizeToError(error, `Failed to emit event to room ${normalizedRoom}.`)\r\n );\r\n }\r\n\r\n return this;\r\n }\r\n };\r\n }\r\n\r\n public close(\r\n code: number = DEFAULT_CLOSE_CODE,\r\n reason: string = DEFAULT_CLOSE_REASON\r\n ): void {\r\n try {\r\n this.stopHeartbeatLoop();\r\n\r\n for (const client of this.clientsById.values()) {\r\n if (\r\n client.socket.readyState === WebSocket.OPEN ||\r\n client.socket.readyState === WebSocket.CONNECTING\r\n ) {\r\n client.socket.close(code, reason);\r\n }\r\n }\r\n\r\n this.socketServer.close();\r\n } catch (error) {\r\n this.notifyError(normalizeToError(error, \"Failed to close server.\"));\r\n }\r\n }\r\n\r\n private resolveHeartbeatConfig(\r\n heartbeatOptions: SecureServerHeartbeatOptions | undefined\r\n ): Required<SecureServerHeartbeatOptions> {\r\n const intervalMs = heartbeatOptions?.intervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS;\r\n const timeoutMs = heartbeatOptions?.timeoutMs ?? DEFAULT_HEARTBEAT_TIMEOUT_MS;\r\n\r\n if (!Number.isFinite(intervalMs) || intervalMs <= 0) {\r\n throw new Error(\"Server heartbeat intervalMs must be a positive number.\");\r\n }\r\n\r\n if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {\r\n throw new Error(\"Server heartbeat timeoutMs must be a positive number.\");\r\n }\r\n\r\n return {\r\n enabled: heartbeatOptions?.enabled ?? true,\r\n intervalMs,\r\n timeoutMs\r\n };\r\n }\r\n\r\n private startHeartbeatLoop(): void {\r\n if (!this.heartbeatConfig.enabled || this.heartbeatIntervalHandle) {\r\n return;\r\n }\r\n\r\n this.heartbeatIntervalHandle = setInterval(() => {\r\n this.performHeartbeatSweep();\r\n }, this.heartbeatConfig.intervalMs);\r\n\r\n this.heartbeatIntervalHandle.unref?.();\r\n }\r\n\r\n private stopHeartbeatLoop(): void {\r\n if (!this.heartbeatIntervalHandle) {\r\n return;\r\n }\r\n\r\n clearInterval(this.heartbeatIntervalHandle);\r\n this.heartbeatIntervalHandle = null;\r\n }\r\n\r\n private performHeartbeatSweep(): void {\r\n const now = Date.now();\r\n\r\n for (const client of this.clientsById.values()) {\r\n const socket = client.socket;\r\n\r\n if (socket.readyState !== WebSocket.OPEN) {\r\n continue;\r\n }\r\n\r\n const heartbeatState = this.heartbeatStateBySocket.get(socket) ?? {\r\n awaitingPong: false,\r\n lastPingAt: 0\r\n };\r\n\r\n if (\r\n heartbeatState.awaitingPong &&\r\n now - heartbeatState.lastPingAt >= this.heartbeatConfig.timeoutMs\r\n ) {\r\n this.sharedSecretBySocket.delete(socket);\r\n this.encryptionKeyBySocket.delete(socket);\r\n this.pendingPayloadsBySocket.delete(socket);\r\n this.handshakeStateBySocket.delete(socket);\r\n this.heartbeatStateBySocket.delete(socket);\r\n socket.terminate();\r\n continue;\r\n }\r\n\r\n if (heartbeatState.awaitingPong) {\r\n continue;\r\n }\r\n\r\n heartbeatState.awaitingPong = true;\r\n heartbeatState.lastPingAt = now;\r\n this.heartbeatStateBySocket.set(socket, heartbeatState);\r\n\r\n try {\r\n socket.ping();\r\n } catch (error) {\r\n this.notifyError(\r\n normalizeToError(error, `Failed to send heartbeat ping to client ${client.id}.`)\r\n );\r\n }\r\n }\r\n }\r\n\r\n private handleHeartbeatPong(socket: WebSocket): void {\r\n const heartbeatState = this.heartbeatStateBySocket.get(socket);\r\n\r\n if (!heartbeatState) {\r\n return;\r\n }\r\n\r\n heartbeatState.awaitingPong = false;\r\n heartbeatState.lastPingAt = 0;\r\n this.heartbeatStateBySocket.set(socket, heartbeatState);\r\n }\r\n\r\n private bindSocketServerEvents(): void {\r\n this.socketServer.on(\"connection\", (socket: WebSocket, request: IncomingMessage) => {\r\n this.handleConnection(socket, request);\r\n });\r\n\r\n this.socketServer.on(\"error\", (error: Error) => {\r\n this.notifyError(normalizeToError(error, \"WebSocket server encountered an error.\"));\r\n });\r\n }\r\n\r\n private handleConnection(socket: WebSocket, request: IncomingMessage): void {\r\n try {\r\n const clientId = randomUUID();\r\n const handshakeState = this.createServerHandshakeState();\r\n const client = this.createSecureServerClient(clientId, socket, request);\r\n\r\n this.clientsById.set(clientId, client);\r\n this.clientIdBySocket.set(socket, clientId);\r\n this.handshakeStateBySocket.set(socket, handshakeState);\r\n this.pendingPayloadsBySocket.set(socket, []);\r\n this.heartbeatStateBySocket.set(socket, {\r\n awaitingPong: false,\r\n lastPingAt: 0\r\n });\r\n this.roomNamesByClientId.set(clientId, new Set<string>());\r\n\r\n socket.on(\"message\", (rawData: RawData) => {\r\n this.handleIncomingMessage(client, rawData);\r\n });\r\n\r\n socket.on(\"close\", (code: number, reason: Buffer) => {\r\n this.handleDisconnection(client, code, reason);\r\n });\r\n\r\n socket.on(\"pong\", () => {\r\n this.handleHeartbeatPong(client.socket);\r\n });\r\n\r\n socket.on(\"error\", (error: Error) => {\r\n this.notifyError(\r\n normalizeToError(\r\n error,\r\n `Client socket error detected for client ${client.id}.`\r\n )\r\n );\r\n });\r\n\r\n this.sendInternalHandshake(socket, handshakeState.localPublicKey);\r\n this.notifyConnection(client);\r\n } catch (error) {\r\n this.notifyError(normalizeToError(error, \"Failed to handle client connection.\"));\r\n }\r\n }\r\n\r\n private handleIncomingMessage(client: SecureServerClient, rawData: RawData): void {\r\n try {\r\n let envelope: SecureEnvelope | null = null;\r\n\r\n try {\r\n envelope = parseEnvelope(rawData);\r\n } catch {\r\n envelope = null;\r\n }\r\n\r\n if (envelope?.event === INTERNAL_HANDSHAKE_EVENT) {\r\n this.handleInternalHandshake(client, envelope.data);\r\n return;\r\n }\r\n\r\n if (envelope !== null) {\r\n this.notifyError(\r\n new Error(\r\n `Plaintext event \"${envelope.event}\" was rejected for client ${client.id}.`\r\n )\r\n );\r\n return;\r\n }\r\n\r\n if (!this.isClientHandshakeReady(client.socket)) {\r\n this.notifyError(\r\n new Error(`Encrypted payload was received before handshake completion for client ${client.id}.`)\r\n );\r\n return;\r\n }\r\n\r\n const encryptionKey = this.encryptionKeyBySocket.get(client.socket);\r\n\r\n if (!encryptionKey) {\r\n this.notifyError(new Error(`Missing encryption key for client ${client.id}.`));\r\n return;\r\n }\r\n\r\n let decryptedPayload: string;\r\n\r\n try {\r\n decryptedPayload = decryptSerializedEnvelope(rawData, encryptionKey);\r\n } catch {\r\n console.warn(\"Tampered data detected and dropped\");\r\n return;\r\n }\r\n\r\n const decryptedEnvelope = parseEnvelopeFromText(decryptedPayload);\r\n this.dispatchCustomEvent(decryptedEnvelope.event, decryptedEnvelope.data, client);\r\n } catch (error) {\r\n this.notifyError(normalizeToError(error, \"Failed to process incoming server message.\"));\r\n }\r\n }\r\n\r\n private handleDisconnection(client: SecureServerClient, code: number, reason: Buffer): void {\r\n try {\r\n client.leaveAll();\r\n this.clientsById.delete(client.id);\r\n this.clientIdBySocket.delete(client.socket);\r\n this.handshakeStateBySocket.delete(client.socket);\r\n this.sharedSecretBySocket.delete(client.socket);\r\n this.encryptionKeyBySocket.delete(client.socket);\r\n this.pendingPayloadsBySocket.delete(client.socket);\r\n this.heartbeatStateBySocket.delete(client.socket);\r\n\r\n const decodedReason = decodeCloseReason(reason);\r\n\r\n for (const handler of this.disconnectHandlers) {\r\n try {\r\n handler(client, code, decodedReason);\r\n } catch (handlerError) {\r\n this.notifyError(\r\n normalizeToError(\r\n handlerError,\r\n `Disconnect handler failed for client ${client.id}.`\r\n )\r\n );\r\n }\r\n }\r\n } catch (error) {\r\n this.notifyError(normalizeToError(error, \"Failed to process client disconnection.\"));\r\n }\r\n }\r\n\r\n private dispatchCustomEvent(\r\n event: string,\r\n data: unknown,\r\n client: SecureServerClient\r\n ): void {\r\n const handlers = this.customEventHandlers.get(event);\r\n\r\n if (!handlers || handlers.size === 0) {\r\n return;\r\n }\r\n\r\n for (const handler of handlers) {\r\n try {\r\n handler(data, client);\r\n } catch (error) {\r\n this.notifyError(\r\n normalizeToError(\r\n error,\r\n `Server event handler failed for event ${event}.`\r\n )\r\n );\r\n }\r\n }\r\n }\r\n\r\n private sendRaw(socket: WebSocket, payload: string): void {\r\n try {\r\n if (socket.readyState !== WebSocket.OPEN) {\r\n return;\r\n }\r\n\r\n socket.send(payload);\r\n } catch (error) {\r\n this.notifyError(normalizeToError(error, \"Failed to send server payload.\"));\r\n }\r\n }\r\n\r\n private sendEncryptedEnvelope(socket: WebSocket, envelope: SecureEnvelope): void {\r\n try {\r\n if (socket.readyState !== WebSocket.OPEN) {\r\n return;\r\n }\r\n\r\n const encryptionKey = this.encryptionKeyBySocket.get(socket);\r\n\r\n if (!encryptionKey) {\r\n throw new Error(\"Missing encryption key for connected socket.\");\r\n }\r\n\r\n const encryptedPayload = encryptSerializedEnvelope(\r\n serializeEnvelope(envelope.event, envelope.data),\r\n encryptionKey\r\n );\r\n\r\n socket.send(encryptedPayload);\r\n } catch (error) {\r\n this.notifyError(normalizeToError(error, \"Failed to send encrypted server payload.\"));\r\n }\r\n }\r\n\r\n private notifyConnection(client: SecureServerClient): void {\r\n for (const handler of this.connectionHandlers) {\r\n try {\r\n handler(client);\r\n } catch (error) {\r\n this.notifyError(\r\n normalizeToError(error, `Connection handler failed for client ${client.id}.`)\r\n );\r\n }\r\n }\r\n }\r\n\r\n private notifyReady(client: SecureServerClient): void {\r\n for (const handler of this.readyHandlers) {\r\n try {\r\n handler(client);\r\n } catch (error) {\r\n this.notifyError(\r\n normalizeToError(error, `Ready handler failed for client ${client.id}.`)\r\n );\r\n }\r\n }\r\n }\r\n\r\n private notifyError(error: Error): void {\r\n if (this.errorHandlers.size === 0) {\r\n return;\r\n }\r\n\r\n for (const handler of this.errorHandlers) {\r\n try {\r\n handler(error);\r\n } catch {\r\n // Error handlers should not throw into the event loop.\r\n }\r\n }\r\n }\r\n\r\n private createServerHandshakeState(): ServerHandshakeState {\r\n const { ecdh, localPublicKey } = createEphemeralHandshakeState();\r\n\r\n return {\r\n ecdh,\r\n localPublicKey,\r\n isReady: false\r\n };\r\n }\r\n\r\n private sendInternalHandshake(socket: WebSocket, localPublicKey: string): void {\r\n this.sendRaw(\r\n socket,\r\n serializeEnvelope(INTERNAL_HANDSHAKE_EVENT, {\r\n publicKey: localPublicKey\r\n })\r\n );\r\n }\r\n\r\n private handleInternalHandshake(client: SecureServerClient, data: unknown): void {\r\n try {\r\n const payload = parseHandshakePayload(data);\r\n const handshakeState = this.handshakeStateBySocket.get(client.socket);\r\n\r\n if (!handshakeState) {\r\n throw new Error(`Missing handshake state for client ${client.id}.`);\r\n }\r\n\r\n if (handshakeState.isReady) {\r\n return;\r\n }\r\n\r\n const remotePublicKey = Buffer.from(payload.publicKey, \"base64\");\r\n const sharedSecret = handshakeState.ecdh.computeSecret(remotePublicKey);\r\n const encryptionKey = deriveEncryptionKey(sharedSecret);\r\n\r\n this.sharedSecretBySocket.set(client.socket, sharedSecret);\r\n this.encryptionKeyBySocket.set(client.socket, encryptionKey);\r\n handshakeState.isReady = true;\r\n\r\n this.flushQueuedPayloads(client.socket);\r\n this.notifyReady(client);\r\n } catch (error) {\r\n this.notifyError(normalizeToError(error, \"Failed to complete server handshake.\"));\r\n }\r\n }\r\n\r\n private isClientHandshakeReady(socket: WebSocket): boolean {\r\n return this.handshakeStateBySocket.get(socket)?.isReady ?? false;\r\n }\r\n\r\n private sendOrQueuePayload(socket: WebSocket, envelope: SecureEnvelope): void {\r\n if (!this.isClientHandshakeReady(socket)) {\r\n this.queuePayload(socket, envelope);\r\n return;\r\n }\r\n\r\n this.sendEncryptedEnvelope(socket, envelope);\r\n }\r\n\r\n private queuePayload(socket: WebSocket, envelope: SecureEnvelope): void {\r\n const pendingPayloads = this.pendingPayloadsBySocket.get(socket) ?? [];\r\n pendingPayloads.push(envelope);\r\n this.pendingPayloadsBySocket.set(socket, pendingPayloads);\r\n }\r\n\r\n private flushQueuedPayloads(socket: WebSocket): void {\r\n const pendingPayloads = this.pendingPayloadsBySocket.get(socket);\r\n\r\n if (!pendingPayloads || pendingPayloads.length === 0) {\r\n return;\r\n }\r\n\r\n this.pendingPayloadsBySocket.delete(socket);\r\n\r\n for (const envelope of pendingPayloads) {\r\n this.sendEncryptedEnvelope(socket, envelope);\r\n }\r\n }\r\n\r\n private createSecureServerClient(\r\n clientId: string,\r\n socket: WebSocket,\r\n request: IncomingMessage\r\n ): SecureServerClient {\r\n return {\r\n id: clientId,\r\n socket,\r\n request,\r\n join: (room: string): boolean => this.joinClientToRoom(clientId, room),\r\n leave: (room: string): boolean => this.leaveClientFromRoom(clientId, room),\r\n leaveAll: (): number => this.leaveClientFromAllRooms(clientId)\r\n };\r\n }\r\n\r\n private normalizeRoomName(room: string): string {\r\n if (typeof room !== \"string\") {\r\n throw new Error(\"Room name must be a string.\");\r\n }\r\n\r\n const normalizedRoom = room.trim();\r\n\r\n if (normalizedRoom.length === 0) {\r\n throw new Error(\"Room name cannot be empty.\");\r\n }\r\n\r\n return normalizedRoom;\r\n }\r\n\r\n private joinClientToRoom(clientId: string, room: string): boolean {\r\n const normalizedRoom = this.normalizeRoomName(room);\r\n\r\n if (!this.clientsById.has(clientId)) {\r\n return false;\r\n }\r\n\r\n const clientRooms = this.roomNamesByClientId.get(clientId) ?? new Set<string>();\r\n\r\n if (clientRooms.has(normalizedRoom)) {\r\n this.roomNamesByClientId.set(clientId, clientRooms);\r\n return false;\r\n }\r\n\r\n clientRooms.add(normalizedRoom);\r\n this.roomNamesByClientId.set(clientId, clientRooms);\r\n\r\n const roomMembers = this.roomMembersByName.get(normalizedRoom) ?? new Set<string>();\r\n roomMembers.add(clientId);\r\n this.roomMembersByName.set(normalizedRoom, roomMembers);\r\n\r\n return true;\r\n }\r\n\r\n private leaveClientFromRoom(clientId: string, room: string): boolean {\r\n const normalizedRoom = this.normalizeRoomName(room);\r\n const clientRooms = this.roomNamesByClientId.get(clientId);\r\n\r\n if (!clientRooms || !clientRooms.delete(normalizedRoom)) {\r\n return false;\r\n }\r\n\r\n if (clientRooms.size === 0) {\r\n this.roomNamesByClientId.delete(clientId);\r\n }\r\n\r\n const roomMembers = this.roomMembersByName.get(normalizedRoom);\r\n\r\n if (roomMembers) {\r\n roomMembers.delete(clientId);\r\n\r\n if (roomMembers.size === 0) {\r\n this.roomMembersByName.delete(normalizedRoom);\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n private leaveClientFromAllRooms(clientId: string): number {\r\n const clientRooms = this.roomNamesByClientId.get(clientId);\r\n\r\n if (!clientRooms || clientRooms.size === 0) {\r\n this.roomNamesByClientId.delete(clientId);\r\n return 0;\r\n }\r\n\r\n const roomNames = [...clientRooms];\r\n this.roomNamesByClientId.delete(clientId);\r\n\r\n for (const roomName of roomNames) {\r\n const roomMembers = this.roomMembersByName.get(roomName);\r\n\r\n if (!roomMembers) {\r\n continue;\r\n }\r\n\r\n roomMembers.delete(clientId);\r\n\r\n if (roomMembers.size === 0) {\r\n this.roomMembersByName.delete(roomName);\r\n }\r\n }\r\n\r\n return roomNames.length;\r\n }\r\n\r\n private emitToRoom(room: string, event: string, data: unknown): void {\r\n if (isReservedEmitEvent(event)) {\r\n throw new Error(`The event \"${event}\" is reserved and cannot be emitted manually.`);\r\n }\r\n\r\n const roomMembers = this.roomMembersByName.get(room);\r\n\r\n if (!roomMembers || roomMembers.size === 0) {\r\n return;\r\n }\r\n\r\n const envelope: SecureEnvelope = { event, data };\r\n\r\n for (const clientId of roomMembers) {\r\n const client = this.clientsById.get(clientId);\r\n\r\n if (!client) {\r\n continue;\r\n }\r\n\r\n this.sendOrQueuePayload(client.socket, envelope);\r\n }\r\n }\r\n}\r\n\r\nexport class SecureClient {\r\n private socket: WebSocket | null = null;\r\n\r\n private readonly reconnectConfig: Required<SecureClientReconnectOptions>;\r\n\r\n private reconnectAttemptCount = 0;\r\n\r\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\r\n\r\n private isManualDisconnectRequested = false;\r\n\r\n private readonly customEventHandlers = new Map<string, Set<SecureClientEventHandler>>();\r\n\r\n private readonly connectHandlers = new Set<SecureClientConnectHandler>();\r\n\r\n private readonly disconnectHandlers = new Set<SecureClientDisconnectHandler>();\r\n\r\n private readonly readyHandlers = new Set<SecureClientReadyHandler>();\r\n\r\n private readonly errorHandlers = new Set<SecureErrorHandler>();\r\n\r\n private handshakeState: ClientHandshakeState | null = null;\r\n\r\n private pendingPayloadQueue: SecureEnvelope[] = [];\r\n\r\n public constructor(\r\n private readonly url: string,\r\n private readonly options: SecureClientOptions = {}\r\n ) {\r\n this.reconnectConfig = this.resolveReconnectConfig(this.options.reconnect);\r\n\r\n if (this.options.autoConnect ?? true) {\r\n this.connect();\r\n }\r\n }\r\n\r\n public get readyState(): number | null {\r\n return this.socket?.readyState ?? null;\r\n }\r\n\r\n public isConnected(): boolean {\r\n return this.socket?.readyState === WebSocket.OPEN;\r\n }\r\n\r\n public connect(): void {\r\n try {\r\n if (\r\n this.socket &&\r\n (this.socket.readyState === WebSocket.OPEN ||\r\n this.socket.readyState === WebSocket.CONNECTING)\r\n ) {\r\n return;\r\n }\r\n\r\n this.clearReconnectTimer();\r\n this.isManualDisconnectRequested = false;\r\n\r\n const socket = this.createSocket();\r\n this.socket = socket;\r\n this.handshakeState = this.createClientHandshakeState();\r\n this.pendingPayloadQueue = [];\r\n this.bindSocketEvents(socket);\r\n } catch (error) {\r\n this.notifyError(normalizeToError(error, \"Failed to connect client.\"));\r\n\r\n if (!this.isManualDisconnectRequested) {\r\n this.scheduleReconnect();\r\n }\r\n }\r\n }\r\n\r\n public disconnect(\r\n code: number = DEFAULT_CLOSE_CODE,\r\n reason: string = DEFAULT_CLOSE_REASON\r\n ): void {\r\n try {\r\n this.isManualDisconnectRequested = true;\r\n this.clearReconnectTimer();\r\n\r\n if (!this.socket) {\r\n return;\r\n }\r\n\r\n if (\r\n this.socket.readyState === WebSocket.CLOSING ||\r\n this.socket.readyState === WebSocket.CLOSED\r\n ) {\r\n return;\r\n }\r\n\r\n this.socket.close(code, reason);\r\n } catch (error) {\r\n this.notifyError(normalizeToError(error, \"Failed to disconnect client.\"));\r\n }\r\n }\r\n\r\n public on(event: \"connect\", handler: SecureClientConnectHandler): this;\r\n public on(event: \"disconnect\", handler: SecureClientDisconnectHandler): this;\r\n public on(event: \"ready\", handler: SecureClientReadyHandler): this;\r\n public on(event: \"error\", handler: SecureErrorHandler): this;\r\n public on(event: string, handler: SecureClientEventHandler): this;\r\n public on(event: string, handler: unknown): this {\r\n try {\r\n if (event === \"connect\") {\r\n this.connectHandlers.add(handler as SecureClientConnectHandler);\r\n return this;\r\n }\r\n\r\n if (event === \"disconnect\") {\r\n this.disconnectHandlers.add(handler as SecureClientDisconnectHandler);\r\n return this;\r\n }\r\n\r\n if (event === READY_EVENT) {\r\n this.readyHandlers.add(handler as SecureClientReadyHandler);\r\n return this;\r\n }\r\n\r\n if (event === \"error\") {\r\n this.errorHandlers.add(handler as SecureErrorHandler);\r\n return this;\r\n }\r\n\r\n if (event === INTERNAL_HANDSHAKE_EVENT) {\r\n throw new Error(`The event \"${INTERNAL_HANDSHAKE_EVENT}\" is reserved for internal use.`);\r\n }\r\n\r\n const typedHandler = handler as SecureClientEventHandler;\r\n const listeners = this.customEventHandlers.get(event) ?? new Set<SecureClientEventHandler>();\r\n listeners.add(typedHandler);\r\n this.customEventHandlers.set(event, listeners);\r\n } catch (error) {\r\n this.notifyError(\r\n normalizeToError(error, \"Failed to register client event handler.\")\r\n );\r\n }\r\n\r\n return this;\r\n }\r\n\r\n public off(event: \"connect\", handler: SecureClientConnectHandler): this;\r\n public off(event: \"disconnect\", handler: SecureClientDisconnectHandler): this;\r\n public off(event: \"ready\", handler: SecureClientReadyHandler): this;\r\n public off(event: \"error\", handler: SecureErrorHandler): this;\r\n public off(event: string, handler: SecureClientEventHandler): this;\r\n public off(event: string, handler: unknown): this {\r\n try {\r\n if (event === \"connect\") {\r\n this.connectHandlers.delete(handler as SecureClientConnectHandler);\r\n return this;\r\n }\r\n\r\n if (event === \"disconnect\") {\r\n this.disconnectHandlers.delete(handler as SecureClientDisconnectHandler);\r\n return this;\r\n }\r\n\r\n if (event === READY_EVENT) {\r\n this.readyHandlers.delete(handler as SecureClientReadyHandler);\r\n return this;\r\n }\r\n\r\n if (event === \"error\") {\r\n this.errorHandlers.delete(handler as SecureErrorHandler);\r\n return this;\r\n }\r\n\r\n if (event === INTERNAL_HANDSHAKE_EVENT) {\r\n return this;\r\n }\r\n\r\n const listeners = this.customEventHandlers.get(event);\r\n\r\n if (!listeners) {\r\n return this;\r\n }\r\n\r\n listeners.delete(handler as SecureClientEventHandler);\r\n\r\n if (listeners.size === 0) {\r\n this.customEventHandlers.delete(event);\r\n }\r\n } catch (error) {\r\n this.notifyError(\r\n normalizeToError(error, \"Failed to remove client event handler.\")\r\n );\r\n }\r\n\r\n return this;\r\n }\r\n\r\n public emit(event: string, data: unknown): boolean {\r\n try {\r\n if (isReservedEmitEvent(event)) {\r\n throw new Error(`The event \"${event}\" is reserved and cannot be emitted manually.`);\r\n }\r\n\r\n if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {\r\n throw new Error(\"Client socket is not connected.\");\r\n }\r\n\r\n const envelope: SecureEnvelope = { event, data };\r\n\r\n if (!this.isHandshakeReady()) {\r\n this.pendingPayloadQueue.push(envelope);\r\n return true;\r\n }\r\n\r\n this.sendEncryptedEnvelope(envelope);\r\n return true;\r\n } catch (error) {\r\n this.notifyError(normalizeToError(error, \"Failed to emit client event.\"));\r\n return false;\r\n }\r\n }\r\n\r\n private resolveReconnectConfig(\r\n reconnectOptions: boolean | SecureClientReconnectOptions | undefined\r\n ): Required<SecureClientReconnectOptions> {\r\n if (typeof reconnectOptions === \"boolean\") {\r\n return {\r\n enabled: reconnectOptions,\r\n initialDelayMs: DEFAULT_RECONNECT_INITIAL_DELAY_MS,\r\n maxDelayMs: DEFAULT_RECONNECT_MAX_DELAY_MS,\r\n factor: DEFAULT_RECONNECT_FACTOR,\r\n jitterRatio: DEFAULT_RECONNECT_JITTER_RATIO,\r\n maxAttempts: null\r\n };\r\n }\r\n\r\n const initialDelayMs = reconnectOptions?.initialDelayMs ?? DEFAULT_RECONNECT_INITIAL_DELAY_MS;\r\n const maxDelayMs = reconnectOptions?.maxDelayMs ?? DEFAULT_RECONNECT_MAX_DELAY_MS;\r\n const factor = reconnectOptions?.factor ?? DEFAULT_RECONNECT_FACTOR;\r\n const jitterRatio = reconnectOptions?.jitterRatio ?? DEFAULT_RECONNECT_JITTER_RATIO;\r\n const maxAttempts = reconnectOptions?.maxAttempts ?? null;\r\n\r\n if (!Number.isFinite(initialDelayMs) || initialDelayMs < 0) {\r\n throw new Error(\"Client reconnect initialDelayMs must be a non-negative number.\");\r\n }\r\n\r\n if (!Number.isFinite(maxDelayMs) || maxDelayMs < 0) {\r\n throw new Error(\"Client reconnect maxDelayMs must be a non-negative number.\");\r\n }\r\n\r\n if (maxDelayMs < initialDelayMs) {\r\n throw new Error(\"Client reconnect maxDelayMs must be greater than or equal to initialDelayMs.\");\r\n }\r\n\r\n if (!Number.isFinite(factor) || factor < 1) {\r\n throw new Error(\"Client reconnect factor must be greater than or equal to 1.\");\r\n }\r\n\r\n if (!Number.isFinite(jitterRatio) || jitterRatio < 0 || jitterRatio > 1) {\r\n throw new Error(\"Client reconnect jitterRatio must be between 0 and 1.\");\r\n }\r\n\r\n if (\r\n maxAttempts !== null &&\r\n (!Number.isInteger(maxAttempts) || maxAttempts < 0)\r\n ) {\r\n throw new Error(\"Client reconnect maxAttempts must be a non-negative integer or null.\");\r\n }\r\n\r\n return {\r\n enabled: reconnectOptions?.enabled ?? true,\r\n initialDelayMs,\r\n maxDelayMs,\r\n factor,\r\n jitterRatio,\r\n maxAttempts\r\n };\r\n }\r\n\r\n private scheduleReconnect(): void {\r\n if (!this.reconnectConfig.enabled || this.reconnectTimer) {\r\n return;\r\n }\r\n\r\n if (\r\n this.reconnectConfig.maxAttempts !== null &&\r\n this.reconnectAttemptCount >= this.reconnectConfig.maxAttempts\r\n ) {\r\n return;\r\n }\r\n\r\n this.reconnectAttemptCount += 1;\r\n const delayMs = this.computeReconnectDelay(this.reconnectAttemptCount);\r\n\r\n this.reconnectTimer = setTimeout(() => {\r\n this.reconnectTimer = null;\r\n this.connect();\r\n }, delayMs);\r\n\r\n this.reconnectTimer.unref?.();\r\n }\r\n\r\n private computeReconnectDelay(attemptNumber: number): number {\r\n const exponentialDelay = Math.min(\r\n this.reconnectConfig.maxDelayMs,\r\n this.reconnectConfig.initialDelayMs *\r\n Math.pow(this.reconnectConfig.factor, Math.max(0, attemptNumber - 1))\r\n );\r\n\r\n if (this.reconnectConfig.jitterRatio === 0 || exponentialDelay === 0) {\r\n return Math.round(exponentialDelay);\r\n }\r\n\r\n const jitterDelta = exponentialDelay * this.reconnectConfig.jitterRatio;\r\n const jitterOffset = (Math.random() * 2 - 1) * jitterDelta;\r\n\r\n return Math.max(0, Math.round(exponentialDelay + jitterOffset));\r\n }\r\n\r\n private clearReconnectTimer(): void {\r\n if (!this.reconnectTimer) {\r\n return;\r\n }\r\n\r\n clearTimeout(this.reconnectTimer);\r\n this.reconnectTimer = null;\r\n }\r\n\r\n private createSocket(): WebSocket {\r\n if (this.options.protocols !== undefined) {\r\n return new WebSocket(this.url, this.options.protocols, this.options.wsOptions);\r\n }\r\n\r\n if (this.options.wsOptions !== undefined) {\r\n return new WebSocket(this.url, this.options.wsOptions);\r\n }\r\n\r\n return new WebSocket(this.url);\r\n }\r\n\r\n private bindSocketEvents(socket: WebSocket): void {\r\n socket.on(\"open\", () => {\r\n this.clearReconnectTimer();\r\n this.reconnectAttemptCount = 0;\r\n this.sendInternalHandshake();\r\n this.notifyConnect();\r\n });\r\n\r\n socket.on(\"message\", (rawData: RawData) => {\r\n this.handleIncomingMessage(rawData);\r\n });\r\n\r\n socket.on(\"close\", (code: number, reason: Buffer) => {\r\n this.handleDisconnect(code, reason);\r\n });\r\n\r\n socket.on(\"error\", (error: Error) => {\r\n this.notifyError(normalizeToError(error, \"Client socket encountered an error.\"));\r\n });\r\n }\r\n\r\n private handleIncomingMessage(rawData: RawData): void {\r\n try {\r\n let envelope: SecureEnvelope | null = null;\r\n\r\n try {\r\n envelope = parseEnvelope(rawData);\r\n } catch {\r\n envelope = null;\r\n }\r\n\r\n if (envelope?.event === INTERNAL_HANDSHAKE_EVENT) {\r\n this.handleInternalHandshake(envelope.data);\r\n return;\r\n }\r\n\r\n if (envelope !== null) {\r\n this.notifyError(\r\n new Error(`Plaintext event \"${envelope.event}\" was rejected on client.`)\r\n );\r\n return;\r\n }\r\n\r\n if (!this.isHandshakeReady()) {\r\n this.notifyError(new Error(\"Encrypted payload was received before handshake completion.\"));\r\n return;\r\n }\r\n\r\n const encryptionKey = this.handshakeState?.encryptionKey;\r\n\r\n if (!encryptionKey) {\r\n this.notifyError(new Error(\"Missing encryption key for client payload decryption.\"));\r\n return;\r\n }\r\n\r\n let decryptedPayload: string;\r\n\r\n try {\r\n decryptedPayload = decryptSerializedEnvelope(rawData, encryptionKey);\r\n } catch {\r\n console.warn(\"Tampered data detected and dropped\");\r\n return;\r\n }\r\n\r\n const decryptedEnvelope = parseEnvelopeFromText(decryptedPayload);\r\n this.dispatchCustomEvent(decryptedEnvelope.event, decryptedEnvelope.data);\r\n } catch (error) {\r\n this.notifyError(normalizeToError(error, \"Failed to process incoming client message.\"));\r\n }\r\n }\r\n\r\n private handleDisconnect(code: number, reason: Buffer): void {\r\n try {\r\n this.socket = null;\r\n this.handshakeState = null;\r\n this.pendingPayloadQueue = [];\r\n const decodedReason = decodeCloseReason(reason);\r\n\r\n for (const handler of this.disconnectHandlers) {\r\n try {\r\n handler(code, decodedReason);\r\n } catch (handlerError) {\r\n this.notifyError(\r\n normalizeToError(handlerError, \"Client disconnect handler failed.\")\r\n );\r\n }\r\n }\r\n\r\n if (!this.isManualDisconnectRequested) {\r\n this.scheduleReconnect();\r\n }\r\n\r\n this.isManualDisconnectRequested = false;\r\n } catch (error) {\r\n this.notifyError(normalizeToError(error, \"Failed to handle client disconnect.\"));\r\n }\r\n }\r\n\r\n private dispatchCustomEvent(event: string, data: unknown): void {\r\n const handlers = this.customEventHandlers.get(event);\r\n\r\n if (!handlers || handlers.size === 0) {\r\n return;\r\n }\r\n\r\n for (const handler of handlers) {\r\n try {\r\n handler(data);\r\n } catch (error) {\r\n this.notifyError(\r\n normalizeToError(error, `Client event handler failed for event ${event}.`)\r\n );\r\n }\r\n }\r\n }\r\n\r\n private notifyConnect(): void {\r\n for (const handler of this.connectHandlers) {\r\n try {\r\n handler();\r\n } catch (error) {\r\n this.notifyError(normalizeToError(error, \"Client connect handler failed.\"));\r\n }\r\n }\r\n }\r\n\r\n private notifyReady(): void {\r\n for (const handler of this.readyHandlers) {\r\n try {\r\n handler();\r\n } catch (error) {\r\n this.notifyError(normalizeToError(error, \"Client ready handler failed.\"));\r\n }\r\n }\r\n }\r\n\r\n private notifyError(error: Error): void {\r\n if (this.errorHandlers.size === 0) {\r\n return;\r\n }\r\n\r\n for (const handler of this.errorHandlers) {\r\n try {\r\n handler(error);\r\n } catch {\r\n // Error handlers should not throw into the event loop.\r\n }\r\n }\r\n }\r\n\r\n private sendEncryptedEnvelope(envelope: SecureEnvelope): void {\r\n try {\r\n if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {\r\n throw new Error(\"Client socket is not connected.\");\r\n }\r\n\r\n const encryptionKey = this.handshakeState?.encryptionKey;\r\n\r\n if (!encryptionKey) {\r\n throw new Error(\"Missing encryption key for client payload encryption.\");\r\n }\r\n\r\n const encryptedPayload = encryptSerializedEnvelope(\r\n serializeEnvelope(envelope.event, envelope.data),\r\n encryptionKey\r\n );\r\n\r\n this.socket.send(encryptedPayload);\r\n } catch (error) {\r\n this.notifyError(normalizeToError(error, \"Failed to send encrypted client payload.\"));\r\n }\r\n }\r\n\r\n private createClientHandshakeState(): ClientHandshakeState {\r\n const { ecdh, localPublicKey } = createEphemeralHandshakeState();\r\n\r\n return {\r\n ecdh,\r\n localPublicKey,\r\n isReady: false,\r\n sharedSecret: null,\r\n encryptionKey: null\r\n };\r\n }\r\n\r\n private sendInternalHandshake(): void {\r\n try {\r\n if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {\r\n return;\r\n }\r\n\r\n if (!this.handshakeState) {\r\n throw new Error(\"Missing client handshake state.\");\r\n }\r\n\r\n this.socket.send(\r\n serializeEnvelope(INTERNAL_HANDSHAKE_EVENT, {\r\n publicKey: this.handshakeState.localPublicKey\r\n })\r\n );\r\n } catch (error) {\r\n this.notifyError(normalizeToError(error, \"Failed to send client handshake payload.\"));\r\n }\r\n }\r\n\r\n private handleInternalHandshake(data: unknown): void {\r\n try {\r\n const payload = parseHandshakePayload(data);\r\n\r\n if (!this.handshakeState) {\r\n throw new Error(\"Missing client handshake state.\");\r\n }\r\n\r\n if (this.handshakeState.isReady) {\r\n return;\r\n }\r\n\r\n const remotePublicKey = Buffer.from(payload.publicKey, \"base64\");\r\n const sharedSecret = this.handshakeState.ecdh.computeSecret(remotePublicKey);\r\n\r\n this.handshakeState.sharedSecret = sharedSecret;\r\n this.handshakeState.encryptionKey = deriveEncryptionKey(sharedSecret);\r\n this.handshakeState.isReady = true;\r\n\r\n this.flushPendingPayloadQueue();\r\n this.notifyReady();\r\n } catch (error) {\r\n this.notifyError(normalizeToError(error, \"Failed to complete client handshake.\"));\r\n }\r\n }\r\n\r\n private isHandshakeReady(): boolean {\r\n return this.handshakeState?.isReady ?? false;\r\n }\r\n\r\n private flushPendingPayloadQueue(): void {\r\n if (!this.socket || this.socket.readyState !== WebSocket.OPEN || !this.isHandshakeReady()) {\r\n return;\r\n }\r\n\r\n const pendingPayloads = this.pendingPayloadQueue;\r\n this.pendingPayloadQueue = [];\r\n\r\n for (const envelope of pendingPayloads) {\r\n this.sendEncryptedEnvelope(envelope);\r\n }\r\n }\r\n}\r\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { IncomingMessage } from 'node:http';
|
|
2
|
+
import WebSocket, { ClientOptions, ServerOptions } from 'ws';
|
|
3
|
+
|
|
4
|
+
interface SecureEnvelope<TData = unknown> {
|
|
5
|
+
event: string;
|
|
6
|
+
data: TData;
|
|
7
|
+
}
|
|
8
|
+
interface SecureServerHeartbeatOptions {
|
|
9
|
+
enabled?: boolean;
|
|
10
|
+
intervalMs?: number;
|
|
11
|
+
timeoutMs?: number;
|
|
12
|
+
}
|
|
13
|
+
interface SecureServerOptions extends ServerOptions {
|
|
14
|
+
heartbeat?: SecureServerHeartbeatOptions;
|
|
15
|
+
}
|
|
16
|
+
interface SecureClientReconnectOptions {
|
|
17
|
+
enabled?: boolean;
|
|
18
|
+
initialDelayMs?: number;
|
|
19
|
+
maxDelayMs?: number;
|
|
20
|
+
factor?: number;
|
|
21
|
+
jitterRatio?: number;
|
|
22
|
+
maxAttempts?: number | null;
|
|
23
|
+
}
|
|
24
|
+
interface SecureClientOptions {
|
|
25
|
+
protocols?: string | string[];
|
|
26
|
+
wsOptions?: ClientOptions;
|
|
27
|
+
autoConnect?: boolean;
|
|
28
|
+
reconnect?: boolean | SecureClientReconnectOptions;
|
|
29
|
+
}
|
|
30
|
+
interface SecureServerClient {
|
|
31
|
+
id: string;
|
|
32
|
+
socket: WebSocket;
|
|
33
|
+
request: IncomingMessage;
|
|
34
|
+
join: (room: string) => boolean;
|
|
35
|
+
leave: (room: string) => boolean;
|
|
36
|
+
leaveAll: () => number;
|
|
37
|
+
}
|
|
38
|
+
interface SecureServerRoomOperator {
|
|
39
|
+
emit: (event: string, data: unknown) => SecureServer;
|
|
40
|
+
}
|
|
41
|
+
type SecureErrorHandler = (error: Error) => void;
|
|
42
|
+
type SecureServerEventHandler = (data: unknown, client: SecureServerClient) => void;
|
|
43
|
+
type SecureServerConnectionHandler = (client: SecureServerClient) => void;
|
|
44
|
+
type SecureServerDisconnectHandler = (client: SecureServerClient, code: number, reason: string) => void;
|
|
45
|
+
type SecureServerReadyHandler = (client: SecureServerClient) => void;
|
|
46
|
+
type SecureClientEventHandler = (data: unknown) => void;
|
|
47
|
+
type SecureClientConnectHandler = () => void;
|
|
48
|
+
type SecureClientDisconnectHandler = (code: number, reason: string) => void;
|
|
49
|
+
type SecureClientReadyHandler = () => void;
|
|
50
|
+
type SecureServerLifecycleEvent = "connection" | "disconnect" | "ready" | "error";
|
|
51
|
+
type SecureClientLifecycleEvent = "connect" | "disconnect" | "ready" | "error";
|
|
52
|
+
interface SecureServerEventMap {
|
|
53
|
+
connection: SecureServerConnectionHandler;
|
|
54
|
+
disconnect: SecureServerDisconnectHandler;
|
|
55
|
+
ready: SecureServerReadyHandler;
|
|
56
|
+
error: SecureErrorHandler;
|
|
57
|
+
}
|
|
58
|
+
interface SecureClientEventMap {
|
|
59
|
+
connect: SecureClientConnectHandler;
|
|
60
|
+
disconnect: SecureClientDisconnectHandler;
|
|
61
|
+
ready: SecureClientReadyHandler;
|
|
62
|
+
error: SecureErrorHandler;
|
|
63
|
+
}
|
|
64
|
+
declare class SecureServer {
|
|
65
|
+
private readonly socketServer;
|
|
66
|
+
private readonly heartbeatConfig;
|
|
67
|
+
private heartbeatIntervalHandle;
|
|
68
|
+
private readonly clientsById;
|
|
69
|
+
private readonly clientIdBySocket;
|
|
70
|
+
private readonly customEventHandlers;
|
|
71
|
+
private readonly connectionHandlers;
|
|
72
|
+
private readonly disconnectHandlers;
|
|
73
|
+
private readonly readyHandlers;
|
|
74
|
+
private readonly errorHandlers;
|
|
75
|
+
private readonly handshakeStateBySocket;
|
|
76
|
+
private readonly sharedSecretBySocket;
|
|
77
|
+
private readonly encryptionKeyBySocket;
|
|
78
|
+
private readonly pendingPayloadsBySocket;
|
|
79
|
+
private readonly heartbeatStateBySocket;
|
|
80
|
+
private readonly roomMembersByName;
|
|
81
|
+
private readonly roomNamesByClientId;
|
|
82
|
+
constructor(options: SecureServerOptions);
|
|
83
|
+
get clientCount(): number;
|
|
84
|
+
get clients(): ReadonlyMap<string, SecureServerClient>;
|
|
85
|
+
on(event: "connection", handler: SecureServerConnectionHandler): this;
|
|
86
|
+
on(event: "disconnect", handler: SecureServerDisconnectHandler): this;
|
|
87
|
+
on(event: "ready", handler: SecureServerReadyHandler): this;
|
|
88
|
+
on(event: "error", handler: SecureErrorHandler): this;
|
|
89
|
+
on(event: string, handler: SecureServerEventHandler): this;
|
|
90
|
+
off(event: "connection", handler: SecureServerConnectionHandler): this;
|
|
91
|
+
off(event: "disconnect", handler: SecureServerDisconnectHandler): this;
|
|
92
|
+
off(event: "ready", handler: SecureServerReadyHandler): this;
|
|
93
|
+
off(event: "error", handler: SecureErrorHandler): this;
|
|
94
|
+
off(event: string, handler: SecureServerEventHandler): this;
|
|
95
|
+
emit(event: string, data: unknown): this;
|
|
96
|
+
emitTo(clientId: string, event: string, data: unknown): boolean;
|
|
97
|
+
to(room: string): SecureServerRoomOperator;
|
|
98
|
+
close(code?: number, reason?: string): void;
|
|
99
|
+
private resolveHeartbeatConfig;
|
|
100
|
+
private startHeartbeatLoop;
|
|
101
|
+
private stopHeartbeatLoop;
|
|
102
|
+
private performHeartbeatSweep;
|
|
103
|
+
private handleHeartbeatPong;
|
|
104
|
+
private bindSocketServerEvents;
|
|
105
|
+
private handleConnection;
|
|
106
|
+
private handleIncomingMessage;
|
|
107
|
+
private handleDisconnection;
|
|
108
|
+
private dispatchCustomEvent;
|
|
109
|
+
private sendRaw;
|
|
110
|
+
private sendEncryptedEnvelope;
|
|
111
|
+
private notifyConnection;
|
|
112
|
+
private notifyReady;
|
|
113
|
+
private notifyError;
|
|
114
|
+
private createServerHandshakeState;
|
|
115
|
+
private sendInternalHandshake;
|
|
116
|
+
private handleInternalHandshake;
|
|
117
|
+
private isClientHandshakeReady;
|
|
118
|
+
private sendOrQueuePayload;
|
|
119
|
+
private queuePayload;
|
|
120
|
+
private flushQueuedPayloads;
|
|
121
|
+
private createSecureServerClient;
|
|
122
|
+
private normalizeRoomName;
|
|
123
|
+
private joinClientToRoom;
|
|
124
|
+
private leaveClientFromRoom;
|
|
125
|
+
private leaveClientFromAllRooms;
|
|
126
|
+
private emitToRoom;
|
|
127
|
+
}
|
|
128
|
+
declare class SecureClient {
|
|
129
|
+
private readonly url;
|
|
130
|
+
private readonly options;
|
|
131
|
+
private socket;
|
|
132
|
+
private readonly reconnectConfig;
|
|
133
|
+
private reconnectAttemptCount;
|
|
134
|
+
private reconnectTimer;
|
|
135
|
+
private isManualDisconnectRequested;
|
|
136
|
+
private readonly customEventHandlers;
|
|
137
|
+
private readonly connectHandlers;
|
|
138
|
+
private readonly disconnectHandlers;
|
|
139
|
+
private readonly readyHandlers;
|
|
140
|
+
private readonly errorHandlers;
|
|
141
|
+
private handshakeState;
|
|
142
|
+
private pendingPayloadQueue;
|
|
143
|
+
constructor(url: string, options?: SecureClientOptions);
|
|
144
|
+
get readyState(): number | null;
|
|
145
|
+
isConnected(): boolean;
|
|
146
|
+
connect(): void;
|
|
147
|
+
disconnect(code?: number, reason?: string): void;
|
|
148
|
+
on(event: "connect", handler: SecureClientConnectHandler): this;
|
|
149
|
+
on(event: "disconnect", handler: SecureClientDisconnectHandler): this;
|
|
150
|
+
on(event: "ready", handler: SecureClientReadyHandler): this;
|
|
151
|
+
on(event: "error", handler: SecureErrorHandler): this;
|
|
152
|
+
on(event: string, handler: SecureClientEventHandler): this;
|
|
153
|
+
off(event: "connect", handler: SecureClientConnectHandler): this;
|
|
154
|
+
off(event: "disconnect", handler: SecureClientDisconnectHandler): this;
|
|
155
|
+
off(event: "ready", handler: SecureClientReadyHandler): this;
|
|
156
|
+
off(event: "error", handler: SecureErrorHandler): this;
|
|
157
|
+
off(event: string, handler: SecureClientEventHandler): this;
|
|
158
|
+
emit(event: string, data: unknown): boolean;
|
|
159
|
+
private resolveReconnectConfig;
|
|
160
|
+
private scheduleReconnect;
|
|
161
|
+
private computeReconnectDelay;
|
|
162
|
+
private clearReconnectTimer;
|
|
163
|
+
private createSocket;
|
|
164
|
+
private bindSocketEvents;
|
|
165
|
+
private handleIncomingMessage;
|
|
166
|
+
private handleDisconnect;
|
|
167
|
+
private dispatchCustomEvent;
|
|
168
|
+
private notifyConnect;
|
|
169
|
+
private notifyReady;
|
|
170
|
+
private notifyError;
|
|
171
|
+
private sendEncryptedEnvelope;
|
|
172
|
+
private createClientHandshakeState;
|
|
173
|
+
private sendInternalHandshake;
|
|
174
|
+
private handleInternalHandshake;
|
|
175
|
+
private isHandshakeReady;
|
|
176
|
+
private flushPendingPayloadQueue;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export { SecureClient, type SecureClientConnectHandler, type SecureClientDisconnectHandler, type SecureClientEventHandler, type SecureClientEventMap, type SecureClientLifecycleEvent, type SecureClientOptions, type SecureClientReadyHandler, type SecureClientReconnectOptions, type SecureEnvelope, type SecureErrorHandler, SecureServer, type SecureServerClient, type SecureServerConnectionHandler, type SecureServerDisconnectHandler, type SecureServerEventHandler, type SecureServerEventMap, type SecureServerHeartbeatOptions, type SecureServerLifecycleEvent, type SecureServerOptions, type SecureServerReadyHandler, type SecureServerRoomOperator };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { IncomingMessage } from 'node:http';
|
|
2
|
+
import WebSocket, { ClientOptions, ServerOptions } from 'ws';
|
|
3
|
+
|
|
4
|
+
interface SecureEnvelope<TData = unknown> {
|
|
5
|
+
event: string;
|
|
6
|
+
data: TData;
|
|
7
|
+
}
|
|
8
|
+
interface SecureServerHeartbeatOptions {
|
|
9
|
+
enabled?: boolean;
|
|
10
|
+
intervalMs?: number;
|
|
11
|
+
timeoutMs?: number;
|
|
12
|
+
}
|
|
13
|
+
interface SecureServerOptions extends ServerOptions {
|
|
14
|
+
heartbeat?: SecureServerHeartbeatOptions;
|
|
15
|
+
}
|
|
16
|
+
interface SecureClientReconnectOptions {
|
|
17
|
+
enabled?: boolean;
|
|
18
|
+
initialDelayMs?: number;
|
|
19
|
+
maxDelayMs?: number;
|
|
20
|
+
factor?: number;
|
|
21
|
+
jitterRatio?: number;
|
|
22
|
+
maxAttempts?: number | null;
|
|
23
|
+
}
|
|
24
|
+
interface SecureClientOptions {
|
|
25
|
+
protocols?: string | string[];
|
|
26
|
+
wsOptions?: ClientOptions;
|
|
27
|
+
autoConnect?: boolean;
|
|
28
|
+
reconnect?: boolean | SecureClientReconnectOptions;
|
|
29
|
+
}
|
|
30
|
+
interface SecureServerClient {
|
|
31
|
+
id: string;
|
|
32
|
+
socket: WebSocket;
|
|
33
|
+
request: IncomingMessage;
|
|
34
|
+
join: (room: string) => boolean;
|
|
35
|
+
leave: (room: string) => boolean;
|
|
36
|
+
leaveAll: () => number;
|
|
37
|
+
}
|
|
38
|
+
interface SecureServerRoomOperator {
|
|
39
|
+
emit: (event: string, data: unknown) => SecureServer;
|
|
40
|
+
}
|
|
41
|
+
type SecureErrorHandler = (error: Error) => void;
|
|
42
|
+
type SecureServerEventHandler = (data: unknown, client: SecureServerClient) => void;
|
|
43
|
+
type SecureServerConnectionHandler = (client: SecureServerClient) => void;
|
|
44
|
+
type SecureServerDisconnectHandler = (client: SecureServerClient, code: number, reason: string) => void;
|
|
45
|
+
type SecureServerReadyHandler = (client: SecureServerClient) => void;
|
|
46
|
+
type SecureClientEventHandler = (data: unknown) => void;
|
|
47
|
+
type SecureClientConnectHandler = () => void;
|
|
48
|
+
type SecureClientDisconnectHandler = (code: number, reason: string) => void;
|
|
49
|
+
type SecureClientReadyHandler = () => void;
|
|
50
|
+
type SecureServerLifecycleEvent = "connection" | "disconnect" | "ready" | "error";
|
|
51
|
+
type SecureClientLifecycleEvent = "connect" | "disconnect" | "ready" | "error";
|
|
52
|
+
interface SecureServerEventMap {
|
|
53
|
+
connection: SecureServerConnectionHandler;
|
|
54
|
+
disconnect: SecureServerDisconnectHandler;
|
|
55
|
+
ready: SecureServerReadyHandler;
|
|
56
|
+
error: SecureErrorHandler;
|
|
57
|
+
}
|
|
58
|
+
interface SecureClientEventMap {
|
|
59
|
+
connect: SecureClientConnectHandler;
|
|
60
|
+
disconnect: SecureClientDisconnectHandler;
|
|
61
|
+
ready: SecureClientReadyHandler;
|
|
62
|
+
error: SecureErrorHandler;
|
|
63
|
+
}
|
|
64
|
+
declare class SecureServer {
|
|
65
|
+
private readonly socketServer;
|
|
66
|
+
private readonly heartbeatConfig;
|
|
67
|
+
private heartbeatIntervalHandle;
|
|
68
|
+
private readonly clientsById;
|
|
69
|
+
private readonly clientIdBySocket;
|
|
70
|
+
private readonly customEventHandlers;
|
|
71
|
+
private readonly connectionHandlers;
|
|
72
|
+
private readonly disconnectHandlers;
|
|
73
|
+
private readonly readyHandlers;
|
|
74
|
+
private readonly errorHandlers;
|
|
75
|
+
private readonly handshakeStateBySocket;
|
|
76
|
+
private readonly sharedSecretBySocket;
|
|
77
|
+
private readonly encryptionKeyBySocket;
|
|
78
|
+
private readonly pendingPayloadsBySocket;
|
|
79
|
+
private readonly heartbeatStateBySocket;
|
|
80
|
+
private readonly roomMembersByName;
|
|
81
|
+
private readonly roomNamesByClientId;
|
|
82
|
+
constructor(options: SecureServerOptions);
|
|
83
|
+
get clientCount(): number;
|
|
84
|
+
get clients(): ReadonlyMap<string, SecureServerClient>;
|
|
85
|
+
on(event: "connection", handler: SecureServerConnectionHandler): this;
|
|
86
|
+
on(event: "disconnect", handler: SecureServerDisconnectHandler): this;
|
|
87
|
+
on(event: "ready", handler: SecureServerReadyHandler): this;
|
|
88
|
+
on(event: "error", handler: SecureErrorHandler): this;
|
|
89
|
+
on(event: string, handler: SecureServerEventHandler): this;
|
|
90
|
+
off(event: "connection", handler: SecureServerConnectionHandler): this;
|
|
91
|
+
off(event: "disconnect", handler: SecureServerDisconnectHandler): this;
|
|
92
|
+
off(event: "ready", handler: SecureServerReadyHandler): this;
|
|
93
|
+
off(event: "error", handler: SecureErrorHandler): this;
|
|
94
|
+
off(event: string, handler: SecureServerEventHandler): this;
|
|
95
|
+
emit(event: string, data: unknown): this;
|
|
96
|
+
emitTo(clientId: string, event: string, data: unknown): boolean;
|
|
97
|
+
to(room: string): SecureServerRoomOperator;
|
|
98
|
+
close(code?: number, reason?: string): void;
|
|
99
|
+
private resolveHeartbeatConfig;
|
|
100
|
+
private startHeartbeatLoop;
|
|
101
|
+
private stopHeartbeatLoop;
|
|
102
|
+
private performHeartbeatSweep;
|
|
103
|
+
private handleHeartbeatPong;
|
|
104
|
+
private bindSocketServerEvents;
|
|
105
|
+
private handleConnection;
|
|
106
|
+
private handleIncomingMessage;
|
|
107
|
+
private handleDisconnection;
|
|
108
|
+
private dispatchCustomEvent;
|
|
109
|
+
private sendRaw;
|
|
110
|
+
private sendEncryptedEnvelope;
|
|
111
|
+
private notifyConnection;
|
|
112
|
+
private notifyReady;
|
|
113
|
+
private notifyError;
|
|
114
|
+
private createServerHandshakeState;
|
|
115
|
+
private sendInternalHandshake;
|
|
116
|
+
private handleInternalHandshake;
|
|
117
|
+
private isClientHandshakeReady;
|
|
118
|
+
private sendOrQueuePayload;
|
|
119
|
+
private queuePayload;
|
|
120
|
+
private flushQueuedPayloads;
|
|
121
|
+
private createSecureServerClient;
|
|
122
|
+
private normalizeRoomName;
|
|
123
|
+
private joinClientToRoom;
|
|
124
|
+
private leaveClientFromRoom;
|
|
125
|
+
private leaveClientFromAllRooms;
|
|
126
|
+
private emitToRoom;
|
|
127
|
+
}
|
|
128
|
+
declare class SecureClient {
|
|
129
|
+
private readonly url;
|
|
130
|
+
private readonly options;
|
|
131
|
+
private socket;
|
|
132
|
+
private readonly reconnectConfig;
|
|
133
|
+
private reconnectAttemptCount;
|
|
134
|
+
private reconnectTimer;
|
|
135
|
+
private isManualDisconnectRequested;
|
|
136
|
+
private readonly customEventHandlers;
|
|
137
|
+
private readonly connectHandlers;
|
|
138
|
+
private readonly disconnectHandlers;
|
|
139
|
+
private readonly readyHandlers;
|
|
140
|
+
private readonly errorHandlers;
|
|
141
|
+
private handshakeState;
|
|
142
|
+
private pendingPayloadQueue;
|
|
143
|
+
constructor(url: string, options?: SecureClientOptions);
|
|
144
|
+
get readyState(): number | null;
|
|
145
|
+
isConnected(): boolean;
|
|
146
|
+
connect(): void;
|
|
147
|
+
disconnect(code?: number, reason?: string): void;
|
|
148
|
+
on(event: "connect", handler: SecureClientConnectHandler): this;
|
|
149
|
+
on(event: "disconnect", handler: SecureClientDisconnectHandler): this;
|
|
150
|
+
on(event: "ready", handler: SecureClientReadyHandler): this;
|
|
151
|
+
on(event: "error", handler: SecureErrorHandler): this;
|
|
152
|
+
on(event: string, handler: SecureClientEventHandler): this;
|
|
153
|
+
off(event: "connect", handler: SecureClientConnectHandler): this;
|
|
154
|
+
off(event: "disconnect", handler: SecureClientDisconnectHandler): this;
|
|
155
|
+
off(event: "ready", handler: SecureClientReadyHandler): this;
|
|
156
|
+
off(event: "error", handler: SecureErrorHandler): this;
|
|
157
|
+
off(event: string, handler: SecureClientEventHandler): this;
|
|
158
|
+
emit(event: string, data: unknown): boolean;
|
|
159
|
+
private resolveReconnectConfig;
|
|
160
|
+
private scheduleReconnect;
|
|
161
|
+
private computeReconnectDelay;
|
|
162
|
+
private clearReconnectTimer;
|
|
163
|
+
private createSocket;
|
|
164
|
+
private bindSocketEvents;
|
|
165
|
+
private handleIncomingMessage;
|
|
166
|
+
private handleDisconnect;
|
|
167
|
+
private dispatchCustomEvent;
|
|
168
|
+
private notifyConnect;
|
|
169
|
+
private notifyReady;
|
|
170
|
+
private notifyError;
|
|
171
|
+
private sendEncryptedEnvelope;
|
|
172
|
+
private createClientHandshakeState;
|
|
173
|
+
private sendInternalHandshake;
|
|
174
|
+
private handleInternalHandshake;
|
|
175
|
+
private isHandshakeReady;
|
|
176
|
+
private flushPendingPayloadQueue;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export { SecureClient, type SecureClientConnectHandler, type SecureClientDisconnectHandler, type SecureClientEventHandler, type SecureClientEventMap, type SecureClientLifecycleEvent, type SecureClientOptions, type SecureClientReadyHandler, type SecureClientReconnectOptions, type SecureEnvelope, type SecureErrorHandler, SecureServer, type SecureServerClient, type SecureServerConnectionHandler, type SecureServerDisconnectHandler, type SecureServerEventHandler, type SecureServerEventMap, type SecureServerHeartbeatOptions, type SecureServerLifecycleEvent, type SecureServerOptions, type SecureServerReadyHandler, type SecureServerRoomOperator };
|