UNPKG

node-jet

Version:

Jet Realtime Message Bus for the Web. Daemon and Peer implementation.

120 lines (119 loc) 3.65 kB
/* istanbul ignore file */ import { Socket, connect } from 'net'; import { EventEmitter } from './index.js'; /** * Class Message socket */ export class MessageSocket extends EventEmitter { last = Buffer.alloc(0); len = -1; socket; constructor(port, ip = '') { super(); if (port instanceof Socket) { this.socket = port; } else { this.socket = connect(port, ip); this.socket.on('connect', () => { this.emit('open'); }); } this.socket.on('data', (buf) => { let bigBuf = Buffer.concat([this.last, buf]); while (true) { if (this.len < 0) { if (bigBuf.length < 4) { this.last = bigBuf; return; } else { this.len = bigBuf.readUInt32BE(0); bigBuf = bigBuf.subarray(4); } } if (this.len > 0) { if (bigBuf.length < this.len) { this.last = bigBuf; return; } else { this.emit('message', bigBuf.toString(undefined, 0, this.len)); bigBuf = bigBuf.subarray(this.len); this.len = -1; } } } }); this.socket.setNoDelay(true); this.socket.setKeepAlive(true); this.socket.once('close', () => { this.emit('close'); }); this.socket.once('error', (e) => { this.emit('error', e); }); } /** * Send. */ send(msg) { const utf8Length = Buffer.byteLength(msg, 'utf8'); const buf = Buffer.alloc(4 + utf8Length); buf.writeUInt32BE(utf8Length, 0); buf.write(msg, 4); process.nextTick(() => { this.socket.write(buf); this.emit('sent', msg); }); } /** * Close. */ close() { this.socket.end(); } /** * addEventListener method needed for MessageSocket to be used in the browser. * It is a wrapper for plain EventEmitter events like ms.on('...', callback). * * npm module 'ws' also comes with this method. * See https://github.com/websockets/ws/blob/master/lib/WebSocket.js#L410 * That way we can use node-jet with via browserify inside the browser. */ addEventListener(method, listener) { const onMessage = (data) => { listener.call(this, new MessageEvent('data', { data })); }; const onClose = (code, message) => { listener.call(this, new CloseEvent(code, message)); }; const onError = (event) => { listener.call(this, event); }; const onOpen = () => { listener.call(this, new Event('open')); }; if (typeof listener === 'function') { let cb; switch (method) { case 'message': cb = onMessage; break; case 'close': cb = onClose; break; case 'error': cb = onError; break; case 'open': cb = onOpen; break; default: cb = listener; } this.on(method, cb); } } } export default MessageSocket;