'use strict'; const common = require('../common.js'); const crypto = require('crypto'); const http = require('http'); const GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'; const configs = { size: [64, 16 * 1024, 128 * 1024, 1024 * 1024], useBinary: ['true', 'false'], roundtrips: [5000, 1000, 100], }; const bench = common.createBenchmark(main, configs); function createFrame(data, opcode) { let infoLength = 2; let payloadLength = data.length; if (payloadLength >= 65536) { infoLength += 8; payloadLength = 127; } else if (payloadLength > 125) { infoLength += 2; payloadLength = 126; } const info = Buffer.alloc(infoLength); info[0] = opcode | 0x80; info[1] = payloadLength; if (payloadLength === 126) { info.writeUInt16BE(data.length, 2); } else if (payloadLength === 127) { info[2] = info[3] = 0; info.writeUIntBE(data.length, 4, 6); } return Buffer.concat([info, data]); } function main(conf) { const frame = createFrame(Buffer.alloc(conf.size).fill('.'), conf.useBinary === 'true' ? 2 : 1); const server = http.createServer(); server.on('upgrade', (req, socket) => { const key = crypto .createHash('sha1') .update(req.headers['sec-websocket-key'] + GUID) .digest('base64'); let bytesReceived = 0; let roundtrip = 0; socket.on('data', function onData(chunk) { bytesReceived += chunk.length; if (bytesReceived === frame.length + 4) { // +4 for the mask. // Message completely received. bytesReceived = 0; if (++roundtrip === conf.roundtrips) { socket.removeListener('data', onData); socket.resume(); socket.end(); server.close(); bench.end(conf.roundtrips); } else { socket.write(frame); } } }); socket.write( [ 'HTTP/1.1 101 Switching Protocols', 'Upgrade: websocket', 'Connection: Upgrade', `Sec-WebSocket-Accept: ${key}`, '\r\n', ].join('\r\n'), ); socket.write(frame); }); server.listen(0, () => { const ws = new WebSocket(`ws://localhost:${server.address().port}`); ws.addEventListener('open', () => { bench.start(); }); ws.addEventListener('message', (event) => { ws.send(event.data); }); }); }