110 lines
2.6 KiB
JavaScript
110 lines
2.6 KiB
JavaScript
"use strict";
|
|
|
|
import { EventEmitter, once } from 'events';
|
|
|
|
import log from 'log'; const l = log.get("Peer");
|
|
|
|
import Connection from '../transport/Connection.mjs';
|
|
|
|
class Peer extends EventEmitter {
|
|
get address() { return this.connection.address; }
|
|
get port() { return this.connection.port; }
|
|
get remote_endpoint() {
|
|
return { address: this.address, port: this.port };
|
|
}
|
|
|
|
constructor(server, connection) {
|
|
super();
|
|
|
|
this.id = null;
|
|
|
|
/**
|
|
* The parent server this Peer is part of.
|
|
* @type {PeerServer}
|
|
*/
|
|
this.server = server;
|
|
/**
|
|
* The underlying Connection.
|
|
* @type {Connection}
|
|
*/
|
|
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 = [];
|
|
|
|
// TODO: Log when disconnected too
|
|
this.once("connect", () => {
|
|
l.log(`${this.connection.address}:${this.connection.port} connected`);
|
|
});
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* Accepts an existing connection as a new Peer.
|
|
* @param {Connection} connection The Connection to accept.
|
|
* @return {Promise<HelloMsg>} A Promise that resolves once the initial handshake is complete.
|
|
*/
|
|
async __accept(connection) {
|
|
this.connection = connection;
|
|
const [ msg ] = await once(this.connection, "message-hello");
|
|
this.__handle_hello(msg);
|
|
|
|
this.emit("connect");
|
|
}
|
|
|
|
/**
|
|
* Initiates the handshake after opening a new connection.
|
|
* @return {Promise<HelloMsg>} A Promise that resolves after the initial peer handshake is complete.
|
|
*/
|
|
async __initiate() {
|
|
await this.__send_hello();
|
|
const [ msg ] = await once(this.connection, "message-hello");
|
|
this.__handle_hello(msg);
|
|
this.emit("connect");
|
|
}
|
|
|
|
__handle_hello(msg) {
|
|
this.id = msg.id;
|
|
this.known_peers = msg.peers;
|
|
}
|
|
|
|
async __send_hello() {
|
|
await this.send("hello", {
|
|
id: this.server.our_id,
|
|
peers: this.server.peers()
|
|
});
|
|
}
|
|
|
|
async send(event_name, msg) {
|
|
await this.connection.send(event_name, msg);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
async destroy() {
|
|
await this.connection.destroy();
|
|
this.emit("destroy");
|
|
this.removeAllListeners();
|
|
}
|
|
}
|
|
|
|
Peer.Initiate = function(server, address, port) {
|
|
const conn = await Connection.Create(server.secret_join, address, port);
|
|
const peer = new Peer(server, conn);
|
|
await peer.__initiate();
|
|
return peer;
|
|
}
|
|
|
|
Peer.Accept = function(server, connection) {
|
|
const peer = new Peer(server);
|
|
await peer.__accept(connection);
|
|
|
|
return peer;
|
|
}
|
|
|
|
export default Peer;
|