Newer
Older
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity.
//
// SPDX-License-Identifier: BSD-3-Clause
import EventEmitter from 'eventemitter3';
import net from 'net';
import Pino from '../utils/pino';
const pino = Pino();
/*
* IpcChannel to send messages to and receive messages from the node via ipc.
*
* Usage:
* ipcChannel.init('path/to/ipc');
* ipcChannel.send('{"jsonrpc":"2.0", ...}')
* ipcChannel.on('message', x => { console.log(x) });
*/
class IpcChannel extends EventEmitter {
_queued = [];
init (path) {
return new Promise((resolve, reject) => {
const socket = net.createConnection(path);
socket.on('connect', () => {
pino.info('Connected to IPC socket.');
this._socket = socket;
this._sendQueued();
resolve(true);
});
// We get data from the socket by chunks, and 1 chunk !== 1 Rpc message
// Sometimes 1 chunk is multiple messages, sometimes we get partial
// messages.
// https://github.com/paritytech/fether/issues/562
// The last element in a '\n'-separate chunk. Will be `""` if the
// last element was a correctly-formed message, or will hold the
// ill-formed message otherwise.
let lastData = '';
// If the last data was truncated, then we concatenate to the new data
// we just received
const data = `${lastData}${data_.toString()}`;
// All messages are separated by a '\n'
const messages = data.split(/\n/);
lastData = messages.pop(); // Will hold "" or an ill-formed JSONRPC message
messages.forEach(data => {
this.emit('message', data);
});
});
socket.on('error', err => {
pino.error('Error connecting to IPC socket.', err);
reject(err);
});
});
}
send (message) {
if (this._socket) this._socket.write(message + '\r\n');
else this._queued.push(message);
}
_sendQueued () {
this._queued.forEach(message => this.send(message));
}
}
export default new IpcChannel();