UNPKG

drpc

Version:
151 lines (149 loc) 4.71 kB
const net = require('net'); class TCP { split(buffer) { let tail = buffer.split('\r\n'); let head = tail.pop(); return { head: head, tail: tail }; } handshake(socket, message, server) { try { message = JSON.parse(message); if (server) { if (!(message.password && message.sname && message.password === this.password)) { throw new Error(); } if (message.sname === this.sname) { // prevent self loop throw new Error(); } if (this.list[message.sname]) { // prevent double connection throw new Error(); } socket.write(JSON.stringify({ sname: this.sname }) + '\r\n'); } else { if (!message.sname) { throw new Error(); } if (message.sname === this.sname) { // prevent self loop throw new Error(); } if (this.list[message.sname]) { // prevent double connection throw new Error(); } } socket.sname = message.sname; this.list[socket.sname] = socket; this.drpc.emit('connect', socket.sname); } catch (e) { } } close(socket) { if (socket.sname) { delete this.list[socket.sname]; this.drpc.emit('disconnect', socket.sname); } } init(drpc, port, sname, password) { this.drpc = drpc; this.port = port; this.sname = sname; this.password = password; this.list = {}; this.server = net.createServer((socket) => { let buffer = ''; socket.on('data', (chunk) => { buffer += chunk.toString(); let { head, tail } = this.split(buffer); buffer = head; for (let message of tail) { if (socket.sname) { this.drpc.emit('cast', socket.sname, message); } else { this.handshake.call(this, socket, message, true); } } }); socket.on('close', () => { this.close.call(this, socket); }); setTimeout(() => { if (!socket.sname) { socket.destroy(); } }, 5000); }); this.server.on('listening', () => { this.drpc.emit('start'); }); this.server.on('error', (error) => { this.drpc.emit('error', error); }); this.server.on('close', () => { this.drpc.emit('stop'); }); } start() { this.server.listen(this.port, '127.0.0.1'); } stop() { for (let name of Object.keys(this.list)) { this.list[name].destroy(); delete this.list[name]; } this.server.close(); } connect(host, port, password) { let socket = net.createConnection(port, host, () => { let buffer = ''; socket.on('data', (chunk) => { buffer += chunk.toString(); let { head, tail } = this.split(buffer); buffer = head; for (let message of tail) { if (socket.sname) { this.drpc.emit('cast', socket.sname, message); } else { this.handshake.call(this, socket, message, false); } } }); socket.on('close', () => { this.close.call(this, socket); }); socket.write(JSON.stringify({ password: this.password, sname: this.sname }) + '\r\n'); }); } disconnect(sname) { this.list[sname].destroy(); } broadcast(message) { for (let socket of Object.values(this.list)) { socket.write(message + '\r\n'); } } multicast(snames, message) { for (let sname of snames) { let socket = this.list[sname]; if (socket) { socket.write(message + '\r\n'); } } } unicast(sname, message) { let socket = this.list[sname]; if (socket) { socket.write(message + '\r\n'); } } } exports.TCP = TCP;