diff --git a/example/example.js b/example/example.js index ce4af09..3177e55 100644 --- a/example/example.js +++ b/example/example.js @@ -8,7 +8,10 @@ const wormhole = new Wormhole({ urls: [ '/hello' ], httpServer }); wormhole.on('connect', ({ socket, accept, reject }) => { accept(); - socket.sendText('hello'); + const buf = Buffer.from([0x41, 0x41, 0x41, 0x41]); + console.log(buf); + socket.send(buf); + socket.on('text', console.log); }); httpServer.listen(8080); \ No newline at end of file diff --git a/lib/Parser.js b/lib/Parser.js index 43da7a4..174b3b3 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -46,6 +46,8 @@ WebsocketFrame.prototype.toBuffer = function() { this.MASK && packet.push(this.MaskingKey); packet.push(this.PayloadData); + console.log(packet); + return Buffer.concat(packet); }; diff --git a/lib/Socket.js b/lib/Socket.js index 0bd1c49..75675ca 100644 --- a/lib/Socket.js +++ b/lib/Socket.js @@ -1,29 +1,49 @@ +const EventEmitter = require('events'); + const constants = require("./constants"); const parser = require('./Parser'); -class Socket { +class Socket extends EventEmitter { constructor({ initialState='CONNECTING', socket }) { + super(); + this._state = initialState; this._socket = socket; this._accepted = false; this._fateDecided = false; // Wether the decision to accept or reject the socket was made this._socket.on('data', (e) => { - if (this._state !== constants.states.OPEN) return; + if (!this._isConnected()) return; - this._decodePayload(e.buffer); + const packet = this._decodePayload(e.buffer); + if (packet.Opcode === constants.opcodes.TEXT_FRAME) { + this.emit('text', packet); + } else if (packet.Opcode === constants.opcodes.BINARY_FRAME) { + this.emit('binary', packet); + } }); } } -Socket.prototype.sendText = function(text) { +Socket.prototype.send = function(payload) { + if (typeof payload === 'string') { + this._sendBuffer(Buffer.from(payload)); + } else if (payload instanceof Buffer) { + this._sendBuffer(payload); + } else { + throw new Error(`Unsupported type ${typeof payload}, supported types are: string, Buffer`); + } +}; + +Socket.prototype._sendBuffer = function(buffer) { const frame = new parser.WebsocketFrame(); frame.FIN = 1; frame.RSVx = 0; frame.Opcode = 0x01; frame.MASK = 0; - const length = text.length; + const length = buffer.byteLength; + console.log(length); if (length > 125) { frame.PayloadLen = 126; } else if (length >= 65536) { @@ -32,13 +52,13 @@ Socket.prototype.sendText = function(text) { frame.PayloadLen = length; } frame.PayloadLenEx = length; - frame.PayloadData = Buffer.from(text); + frame.PayloadData = buffer; this._socket.write(frame.toBuffer()); }; Socket.prototype._decodePayload = function(payload) { - console.log(parser.parseWebsocketFrame(new DataView(payload))); + return parser.parseWebsocketFrame(new DataView(payload)); }; Socket.prototype._setConnectionState = function(state) { @@ -52,4 +72,8 @@ Socket.prototype._setAccepted = function(state) { this._accepted = state; }; +Socket.prototype._isConnected = function() { + return (this._fateDecided && this._isConnected && this._accepted === true); +} + module.exports = Socket; \ No newline at end of file diff --git a/lib/constants.js b/lib/constants.js index c4d135b..feff026 100644 --- a/lib/constants.js +++ b/lib/constants.js @@ -7,5 +7,9 @@ module.exports = { OPEN: 'OPEN', CLOSING: 'CLOSING', CLOSED: 'CLOSED' + }, + opcodes: { + 'TEXT_FRAME': 0x01, + 'BINARY_FRAME': 0x02 } } \ No newline at end of file