UNPKG

rescript

Version:
93 lines (86 loc) 2.77 kB
var crypto = require("crypto"); var KEY_SUFFIX = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; function hashWebSocketKey(key) { var sha1 = crypto.createHash("sha1"); sha1.update(key + KEY_SUFFIX, "ascii"); return sha1.digest("base64"); } /** * Limitations: the current implementation does not * care about what the client send: * - we don't know `ws.close` only know `socket.closed` which is later so it has a latency * - ping pong protocol */ // http://tools.ietf.org/html/rfc6455#section-5.2 var opcodes = { TEXT: 1, BINARY: 2, CLOSE: 8, PING: 9, PONG: 10 }; /** * * @param {number} opcode * @param {Buffer} payload */ function encodeMessage(opcode, payload) { var buf; // Buffer type var b1 = 0x80 | opcode; // always send message as one frame (fin) // second byte: maks and length part 1 // followed by 0, 2, or 8 additional bytes of continued length var b2 = 0; // server does not mask frames var length = payload.length; if (length < 126) { buf = Buffer.allocUnsafe(payload.length + 2 + 0); // zero extra bytes b2 |= length; buf.writeUInt8(b1, 0); buf.writeUInt8(b2, 1); payload.copy(buf, 2); } else if (length < (1 << 16)) { buf = Buffer.allocUnsafe(payload.length + 2 + 2); // two bytes extra b2 |= 126; buf.writeUInt8(b1, 0); buf.writeUInt8(b2, 1); // add two byte length buf.writeUInt16BE(length, 2); payload.copy(buf, 4); } else { buf = Buffer.allocUnsafe(payload.length + 2 + 8); // eight bytes extra b2 |= 127; buf.writeUInt8(b1, 0); buf.writeUInt8(b2, 1); // add eight byte length // note: this implementation cannot handle lengths greater than 2^32 // the 32 bit length is prefixed with 0x0000 buf.writeUInt32BE(0, 2); buf.writeUInt32BE(length, 6); payload.copy(buf, 10); } return buf; }; var upgradeHeader = 'HTTP/1.1 101 Web Socket Protocol Handshake\r\nUpgrade: WebSocket\r\nConnection: Upgrade\r\nsec-websocket-accept: ' class MiniWebSocket { constructor(req, socket, upgradeHead) { this.socket = socket; this.closed = false; var self = this; var key = hashWebSocketKey(req.headers["sec-websocket-key"]) // http://tools.ietf.org/html/rfc6455#section-4.2.2 socket.write( upgradeHeader + key + '\r\n\r\n'); socket.on("close", function (hadError) { if (!self.closed) { self.closed = true; } }); }; sendText(obj) { this.socket.write(encodeMessage(opcodes.TEXT,Buffer.from(obj, "utf8"))) }; } exports.MiniWebSocket = MiniWebSocket