Exchange peerlists
This commit is contained in:
parent
61b830121e
commit
1091f9c3c2
4 changed files with 65 additions and 11 deletions
|
@ -34,16 +34,34 @@ class Agent {
|
|||
}
|
||||
|
||||
async init() {
|
||||
///
|
||||
// 1: Create our local environment
|
||||
///
|
||||
/** Our peer id - calculated automatically from the system's uuid */
|
||||
this.peer_id = await hostuuid(this.config.net.port);
|
||||
this.peer_name = os.hostname();
|
||||
|
||||
|
||||
///
|
||||
// 2: Create the peer server
|
||||
///
|
||||
this.server = new PeerServer(
|
||||
this.peer_id,
|
||||
await this.find_secret()
|
||||
);
|
||||
this.server.retries = this.config.net.peer_retries;
|
||||
|
||||
|
||||
///
|
||||
// 3: Attach message handling listeners
|
||||
///
|
||||
this.server.on("message-peerlist-request", this.__send_peer_list.bind(this));
|
||||
this.server.on("message-peerlist-response", this.__handle_peer_list.bind(this));
|
||||
|
||||
|
||||
///
|
||||
// 4: Start listening
|
||||
///
|
||||
l.log(`Starting peer listener....`);
|
||||
await this.server.listen(
|
||||
this.config.net.port,
|
||||
|
@ -51,6 +69,10 @@ class Agent {
|
|||
);
|
||||
l.log(`Listening on ${this.config.net.bind_address}:${this.config.net.port}`);
|
||||
|
||||
|
||||
///
|
||||
// 5: Add initial peers to kick things off
|
||||
///
|
||||
await this.server.add_peers(...this.config.peers.map(
|
||||
peer => parse_peer_name(peer)
|
||||
));
|
||||
|
@ -58,6 +80,37 @@ class Agent {
|
|||
l.log(`Added ${this.server.peers().length} / ${this.config.peers.length} initial peers`);
|
||||
if(this.config.peers.length < 1)
|
||||
l.warn(`No initial peers were specified! It's recommended that you specify at least 1 on every host.`);
|
||||
|
||||
// Ask for more peers
|
||||
await this.server.broadcast("peerlist-request", {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a list of known peers to the given peer.
|
||||
* @param {Peer} peer The peer to send the list to.
|
||||
* @return {Promise} A Promise that resolves whent he message has been sent.
|
||||
*/
|
||||
async __send_peer_list(peer, _msg) {
|
||||
l.log(`Sending peer list to ${peer.id_short}`);
|
||||
await peer.send("peerlist-response", {
|
||||
peers: this.server.peers()
|
||||
});
|
||||
}
|
||||
|
||||
async __handle_peer_list(peer, msg) {
|
||||
l.log(`Received peer list from ${peer.id_short}`);
|
||||
if(!(msg.peers instanceof Array)) {
|
||||
l.warn(`Encountered invalid peer list message from peer ${peer.id_short}.`);
|
||||
return false;
|
||||
}
|
||||
let peerids_connected = this.server.peers().map(el => el.id);
|
||||
let new_peers = await this.server.add_peers(...msg.peers
|
||||
.filter(el => !peerids_connected.includes(el.id) && el.id !== this.peer_id)
|
||||
.map(el => { return { address: el.listening_address, port: el.listening_port }; }));
|
||||
if(new_peers.length > 0)
|
||||
l.log(`Connected to ${new_peers.length} / ${msg.peers.length} peers from peerlist sent by ${peer.id_short}`);
|
||||
else
|
||||
l.log(`No new peers in peerlist sent by ${peer.id_short}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,13 +33,6 @@ class Peer extends EventEmitter {
|
|||
*/
|
||||
this.connection = connection;
|
||||
|
||||
/**
|
||||
* A list of other peers known to this peer.
|
||||
* May or may not actually be up to date.
|
||||
* @type {{address:string,port:number}[]}
|
||||
*/
|
||||
this.known_peers = [];
|
||||
|
||||
// If a message with the event name "end" is received, close our side
|
||||
// of the connection
|
||||
this.once(`message-end`, this.destroy);
|
||||
|
@ -88,7 +81,8 @@ class Peer extends EventEmitter {
|
|||
*/
|
||||
__handle_hello(msg) {
|
||||
this.id = msg.id;
|
||||
this.known_peers = msg.peers;
|
||||
this.listening_address = msg.listening_address;
|
||||
this.listening_port = msg.listening_port;
|
||||
|
||||
if(this.id === this.server.our_id) {
|
||||
l.warn(`Our id (${this.server.our_id}) is equal to that of the remote (${this.id}), killing connection`);
|
||||
|
@ -111,7 +105,8 @@ class Peer extends EventEmitter {
|
|||
async __send_hello() {
|
||||
await this.send("hello", {
|
||||
id: this.server.our_id,
|
||||
peers: this.server.peers()
|
||||
listening_address: this.server.host,
|
||||
listening_port: this.server.port
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -108,7 +108,9 @@ class PeerServer extends EventEmitter {
|
|||
return this.connected_peers.map(peer => { return {
|
||||
address: peer.address,
|
||||
port: peer.port,
|
||||
id: peer.id
|
||||
id: peer.id,
|
||||
listening_address: peer.listening_address,
|
||||
listening_port: peer.listening_port
|
||||
}}).filter(el => typeof el.address === "string" && typeof el.port === "number");
|
||||
}
|
||||
|
||||
|
@ -153,7 +155,7 @@ class PeerServer extends EventEmitter {
|
|||
), {
|
||||
retries: this.retries,
|
||||
onFailedAttempt: (error) => {
|
||||
switch(error instanceof ErrorWrapper ? error.inner_exception.code : error.code) {
|
||||
switch(error.code) {
|
||||
case "ECONNREFUSED":
|
||||
l.error(`Failed to connect to peer at ${new_peer.address}:${new_peer.port}.`);
|
||||
break;
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
"use strict";
|
||||
|
||||
class ErrorWrapper extends Error {
|
||||
get code() {
|
||||
return this.inner_exception.code;
|
||||
}
|
||||
|
||||
constructor(message, inner_exception) {
|
||||
super(message);
|
||||
this.inner_exception = inner_exception;
|
||||
|
|
Loading…
Reference in a new issue