(opcode: number, payload: Buffer)
| 91 | } |
| 92 | |
| 93 | private writeFrame(opcode: number, payload: Buffer): void { |
| 94 | if (this.socket.destroyed) return; |
| 95 | |
| 96 | // Server-to-client frames are NOT masked (per RFC 6455 §5.1) |
| 97 | const length = payload.length; |
| 98 | let header: Buffer; |
| 99 | |
| 100 | if (length < 126) { |
| 101 | header = Buffer.alloc(2); |
| 102 | header[0] = 0x80 | opcode; // FIN + opcode |
| 103 | header[1] = length; |
| 104 | } else if (length < 65536) { |
| 105 | header = Buffer.alloc(4); |
| 106 | header[0] = 0x80 | opcode; |
| 107 | header[1] = 126; |
| 108 | header.writeUInt16BE(length, 2); |
| 109 | } else { |
| 110 | header = Buffer.alloc(10); |
| 111 | header[0] = 0x80 | opcode; |
| 112 | header[1] = 127; |
| 113 | header.writeUInt32BE(0, 2); |
| 114 | header.writeUInt32BE(length, 6); |
| 115 | } |
| 116 | |
| 117 | try { |
| 118 | this.socket.write(Buffer.concat([header, payload])); |
| 119 | } catch (err: unknown) { |
| 120 | // Expected when socket is destroyed between our check and write. |
| 121 | // Log unexpected errors so they don't vanish silently. |
| 122 | if (!this.socket.destroyed) { |
| 123 | const msg = err instanceof Error ? err.message : String(err); |
| 124 | console.error(`[LLMock] Unexpected writeFrame error: ${msg}`); |
| 125 | } |
| 126 | } |
| 127 | } |
| 128 | |
| 129 | private parseFrames(): void { |
| 130 | while (this.buffer.length >= 2 && !this.closed) { |
no test coverage detected