var net = require("net"); class RPCConn { constructor(ip, port) { this.ready = false; this._callbacks = {}; this._onready = []; this._listeners = {}; this._id = 1; this.sock = new net.Socket(); this.sock.connect(port, ip, () => { console.log("Connected to RPC server "+ip+":"+port+"."); this.ready = true; this._onready.forEach(x => x()); }); var onjson = json => { var obj; try { obj = JSON.parse(json); } catch (err) { console.log("Failed to parse JSON: '"+json+"'"); return; } if (obj.id == null) { var listeners = this._listeners[obj.method]; if (listeners) listeners.forEach(l => l(obj.params)); if (!listeners || listeners.length === 0) console.log("Received method '"+obj.method+"', but no listeners."); return; } var cb = this._callbacks[obj.id]; if (!cb) return console.log("Warning: received unknown ID "+obj.id); cb(obj.error, obj.result); } //Digest JSON lines as they come, but only if they're a whole line var currdata = ""; this.sock.on("data", d => { currdata += d.toString(); var start = 0; for (var i = 0; i < currdata.length; ++i) { if (currdata[i] === "\n") { var s = currdata.substring(start, i); start = i + 1; onjson(s); } } currdata = currdata.substring(start); }); } wait() { return new Promise((resolve, reject) => { if (this.ready) return resolve(); this._onready.push(resolve); }); } call(name, ...params) { return new Promise((resolve, reject) => { var json = JSON.stringify({ id: this._id, method: name, params: params }); this._callbacks[this._id] = (err, res) => { if (err) reject(err); else resolve(res); } this.sock.write(json+"\n"); this._id += 1; }); } on(name, fn) { this._listeners[name] = this._listeners[name] || []; this._listeners[name].push(fn); } } module.exports = RPCConn;