ntrnetwork
Version:
Transledger peer to peer wire communication
170 lines (154 loc) • 6.3 kB
JavaScript
// LIBRARIES IMPORTS
// =====================================================================
const DPT = require('./dpt');
const RLPx = require('./rlpx');
const _util = require('./util');
const NTR = require('./interblockchain');
//const LRUCache = require('lru-cache');
const assert = require('assert');
const { randomBytes } = require('crypto');
//const rlp = require('rlp-encoding');
const nodes = require('../src/environment').peers;
const environment = require('../src/environment');
const getPeerAddr = (peer) => `${peer._socket.remoteAddress}:${peer._socket.remotePort}`;
//const getPeerIP = (peer) => `${peer._socket.remoteAddress}`;
const debug = process.env.MONITOR || require('./environment').debug.monitor;
// EXPORT STATUS OBJECT
// ======================================================================
const status = {
networkId: 1,
networkName: "interblockchain",
Note:"test in progress",
nodeID: environment.nodeID
}
// GLOBALS INITIALIZATION
// ======================================================================
const PRIVATE_KEY = randomBytes(32);
const REMOTE_CLIENTID_FILTER = ['interblockchain'];
// DPT INSTANCE CREATION
// =====================================================================
// We create a Distributed Peer Table (DPT)
// and set an error handler. The table is refreshed
// every 30 seconds
const dpt = new DPT(PRIVATE_KEY, {
refreshInterval: 180000,
endpoint: {
address: '0.0.0.0',
udpPort: null,
tcpPort: null
}
})
dpt.on('error', (err) => {
if (err.message.match(/Timeout/)) {
debug ? console.error(`${Date().toString().substring(0, 24)} monitor: DPT error: ${err}`) : null;
} else {
console.error(`${Date().toString().substring(0, 24)} monitor: DPT error: ${err}`);
}
});
dpt.server.monitor = true;
// RLPX INSTANCE CREATION
// ============================================================================
// We create a RLPX object and an error handler.
// The RLPX protocol is based on the Kamdelia protocol.
// This instance uses a DLT table and the interblockchain
// protocol. We set the limit to 7 peers
const rlpx = new RLPx(PRIVATE_KEY, {
dpt: dpt,
maxPeers: environment.maxPeers,
capabilities: [
NTR.ntr
],
remoteClientIdFilter: REMOTE_CLIENTID_FILTER,
listenPort: null
})
rlpx.on('error', (err) => {
if (err.message.match(/Timeout|valid tag/)) {
debug ? console.error(`${Date().toString().substring(0, 24)} monitor: RLPx error: ${err.stack || err}`) : null;
} else {
console.error(`${Date().toString().substring(0, 24)} monitor: RLPx error: ${err.stack || err}`);
}
});
rlpx.on('close', (reason) => {
a = reason;
});
rlpx.monitor = true;
// Node listening comands
dpt.bind(environment.port, '0.0.0.0');
rlpx.listen(environment.port, '0.0.0.0');
console.log (`server version: ${environment.version} with nodeID: ${environment.nodeID} listening to socket on port 20399`);
// CONNECT TO BOOTSTRAP NODES
// ===============================================================================
// the bootstrap nodes are declared in the environment/index.js file
// Each bootstrap node is declared as an object contained into an container object.
// Initially, that collection of bootstrap node objects is scanned to connect
// the present node to the network.
setTimeout( () => {
let BOOTNODES = [];
/* To be deleted
const BOOTNODES = nodes.filter((node) => {
return node.channelID === rlpx.channelID;
}).map((node) => {
return {
address: node.ip,
udpPort: node.port,
tcpPort: node.port
}
});
*/
nodes.forEach( (node) => {
BOOTNODES.push({
channelID: node.channelID,
address: node.ip,
udpPort: node.port,
tcpPort: node.port
})
});
for (let bootnode of BOOTNODES) {
dpt.bootstrap(bootnode).catch((err) => {
if (err.message.match(/Timeout|valid tag/))
console.error(`${Date().toString().substring(0, 24)} monitor: DPT bootstrap ${err}`);
else
console.error(`${Date().toString().substring(0, 24)} monitor: DPT bootstrap ${err.stack || err}`);
})
}
},500);
// RLPX ERROR HANDLING
// ===========================================================================
// rlpx errors are bubbled up to these error handlers
// When a node is disconnected, an event is fired and bubbled up to
// the event handler.
rlpx.on('peer:removed', (peer, reasonCode, disconnectWe) => {
const who = disconnectWe ? 'we disconnect' : 'peer disconnect';
const total = rlpx.getPeers().length;
console.log(`${Date().toString().substring(0, 24)} monitor: Remove peer: ${getPeerAddr(peer)} - ${who}, reason: ${peer.getDisconnectPrefix(reasonCode)} (${String(reasonCode)}) (total: ${total})`);
})
rlpx.on('peer:error', (peer, err) => {
if (err.code === 'ECONNRESET') return
if (err instanceof assert.AssertionError) {
const peerId = peer.getId()
if (peerId !== null)
dpt.banPeer(peerId, 5000);
debug ? console.error(`${Date().toString().substring(0, 24)} monitor: Peer error (${getPeerAddr(peer)}): ${err.message}`) : null;
return
}
console.error(`${Date().toString().substring(0, 24)} monitor: Peer error (${getPeerAddr(peer)}): ${err.stack || err}`);
});
// DPT STATUS
// =============================================================================
setInterval( () => {
const peersCount = dpt.getPeers().length;
const openSlots = rlpx._getOpenSlots();
const queueLength = rlpx._peersQueue.length;
const queueLength2 = rlpx._peersQueue.filter((o) => o.ts <= Date.now()).length;
//console.log(`${Date().toString().substring(0, 24)} monitor: Total nodes in DPT: ${peersCount}, open slots: ${openSlots}, queue: ${queueLength} / ${queueLength2}`);
},180000);
// EXPORTS FROM THIS LIBRARY
// ================================================================================
exports.DPT = DPT;
exports.RLPx = RLPx;
exports._util = _util;
exports.NTR = NTR;
exports.rlpx = rlpx;
exports.dpt = dpt;
exports.MESSAGE_CODES = NTR.MESSAGE_CODES;
exports.status = status;