chia-network-scanner
Version:
Scans the Chia network for active full nodes
132 lines • 5.52 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.PeerConnection = void 0;
const log_1 = require("./log");
const MessageChannel_1 = require("./MessageChannel");
const encoder_1 = require("./encoder");
class PeerConnection {
constructor({ networkId, protocolVersion, softwareVersion, nodeType, hostname, port, connectionTimeout, cert, key }) {
this.messageHandlers = new Map();
this.messageChannel = new MessageChannel_1.MessageChannel({
networkId,
protocolVersion,
softwareVersion,
nodeType,
hostname,
port,
connectionTimeout,
onMessage: data => this.onMessage(data),
cert,
key
});
}
async connect() {
return new Promise(async (resolve, reject) => {
const timeout = setTimeout(() => reject(new Error('Failed to connect to peer within 2 seconds')), 2000);
try {
await this.messageChannel.connect();
// Connected within timeout
clearTimeout(timeout);
resolve();
}
catch (err) {
clearTimeout(timeout);
reject(err);
}
});
}
/**
* Chia application level handshake required before using the peer protocol.
*/
async handshake() {
const { hostname, port, connectionTimeout, networkId, protocolVersion, softwareVersion, nodeType } = this.messageChannel;
return new Promise(async (resolve, reject) => {
const timeout = setTimeout(() => reject(new Error(`${hostname}:${port} did not respond to handshake within ${(connectionTimeout / 1000).toFixed(2)} seconds. Bailing.`)), connectionTimeout);
// Handle handshake response messages
const handshakeResponse = [
this.expectMessage(encoder_1.ProtocolMessageTypes.handshake),
this.expectMessage(encoder_1.ProtocolMessageTypes.handshake_ack)
];
// Initiate handshake
this.sendMessage(encoder_1.ProtocolMessageTypes.handshake, {
network_id: networkId,
protocol_version: protocolVersion,
software_version: softwareVersion,
server_port: port,
node_type: nodeType
});
try {
// Wait for handshake response
await Promise.race(handshakeResponse);
}
catch (err) {
return reject(err);
}
// Handshake completed within timeout
clearTimeout(timeout);
// We can now use the peer protocol
resolve(this);
});
}
sendMessage(messageType, data) {
const message = encoder_1.encodeMessage(messageType, data);
log_1.log.info(`Sending ${messageType} message`);
this.messageChannel.sendMessage(message);
}
/**
* Get the peers of this peer.
*/
getPeers() {
const { hostname, port, connectionTimeout } = this.messageChannel;
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => reject(new Error(`${hostname}:${port} did not respond after ${(connectionTimeout / 1000).toFixed(2)} seconds. Bailing.`)), connectionTimeout);
this.addMessageHandler(encoder_1.ProtocolMessageTypes.respond_peers, (respondPeers) => {
clearTimeout(timeout);
resolve(respondPeers.peer_list);
});
this.sendMessage(encoder_1.ProtocolMessageTypes.request_peers, {});
});
}
close() {
return this.messageChannel.close();
}
addMessageHandler(messageType, handler) {
log_1.log.debug(`Adding message handler for ${messageType} messages`);
this.messageHandlers.set(messageType, handler);
}
onMessage(data) {
try {
const messageType = data[0];
log_1.log.info(`Received message of type ${messageType}`);
const message = encoder_1.decodeMessage(data);
log_1.log.info(`Decoded message to ${JSON.stringify(message)}`);
const handler = this.messageHandlers.get(messageType);
if (handler) {
return handler(message);
}
log_1.log.warn(`No handler for ${messageType} message. Discarding it.`);
}
catch (err) {
// Anybody could send any old rubbish down the wire and we don't want that to crash our process
log_1.log.error(err, 'Error handling inbound message');
log_1.log.warn(`Hex of message that could not be decoded: ${data.toString('hex')}`);
}
}
/**
* Expects a message of a messageType to be received within a timeout.
*
* @param messageType expected
*/
expectMessage(messageType) {
const { hostname, port, connectionTimeout } = this.messageChannel;
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => reject(new Error(`${hostname}:${port} did not receive ${messageType} message within ${(connectionTimeout / 1000).toFixed(2)} seconds. Bailing.`)), connectionTimeout);
this.addMessageHandler(messageType, () => {
clearTimeout(timeout);
resolve();
});
});
}
}
exports.PeerConnection = PeerConnection;
//# sourceMappingURL=PeerConnection.js.map