This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const http = require('node:http'); | |
const crypto = require('node:crypto'); | |
const { setTimeout: sleep } = require('node:timers/promises'); | |
const { EventEmitter } = require('node:events'); | |
class WebSocketServer extends EventEmitter { | |
constructor(options = {}) { | |
super(); | |
this.clients = new Set(); | |
this.port = options.port || 8080; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const PORT = 4000; | |
const server = new WebSocketServer({ port: PORT }); | |
server.on('data', async (message, reply) => { | |
if (!message) return; | |
const data = JSON.parse(message); | |
const { method, args = [] } = data; | |
const handler = api[method]; | |
if (!handler) return reply({ error: 'Not Found' }); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const api = { | |
auth: async (login, password) => { | |
await sleep(300); // simulate asynchronous call | |
if (login === 'admin' && password === 'secret') { | |
return { | |
token: crypto.randomBytes(20).toString('hex') | |
}; | |
} | |
return { |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const PORT = 4000. | |
const server = new WebSocketServer({ port: PORT }); | |
server.on('headers', ({ headers }) => console.log(headers)); | |
server.on('data', (message, reply) => { | |
if (!message) return; | |
const data = JSON.parse(message); | |
return reply({ pong: data }); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
socket.on('data', (buffer) => | |
this.emit( | |
'data', | |
this.parseFrame(buffer), | |
(data) => socket.write(this.createFrame(data)) | |
) | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
createFrame(data) { | |
const payload = JSON.stringify(data); | |
const payloadByteLength = Buffer.byteLength(payload); | |
let payloadBytesOffset = 2; | |
let payloadLength = payloadByteLength; | |
if (payloadByteLength > 65535) { // length value cannot fit in 2 bytes | |
payloadBytesOffset += 8; | |
payloadLength = 127; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const PORT = 4000. | |
const server = new WebSocketServer({ port: PORT }); | |
server.on('data', (message) => { | |
if (!message) return; | |
const data = JSON.parse(message); | |
console.log('Message received:', data); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
this._server.on('upgrade', (req, socket) => | |
// ...request upgrade logic... | |
socket.on('data', (buffer) => | |
this.emit('data', this.parseFrame(buffer)) | |
); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
_unmask(payload, maskingKey) { | |
const result = Buffer.alloc(payload.byteLength); | |
for (let i = 0; i < payload.byteLength; ++i) { | |
const j = i % 4; | |
const maskingKeyByteShift = j === 3 ? 0 : (3 - j) << 3; | |
const maskingKeyByte = (maskingKeyByteShift === 0 ? maskingKey : maskingKey >>> maskingKeyByteShift) & 0b11111111; | |
const transformedByte = maskingKeyByte ^ payload.readUInt8(i); | |
result.writeUInt8(transformedByte, i); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
parseFrame(buffer) { | |
// ... first and second byte processing ... | |
const isMasked = Boolean((secondByte >>> 7) & 0b00000001); // get first bit of a second byte | |
if (isMasked) { | |
const maskingKey = buffer.readUInt32BE(offset); // read 4-byte (32-bit) masking key | |
offset += 4; | |
const payload = buffer.subarray(offset); | |
const result = this._unmask(payload, maskingKey); |
NewerOlder