systemquery/src/lib/agent/Peer.mjs

85 lines
2 KiB
JavaScript
Raw Normal View History

"use strict";
import { EventEmitter } from 'events';
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;
// Fetch the remote's id
}
/**
* Accepts an existing connection as a new Peer.
* @param {Connection} connection The Connection to accept.
* @return {Promise} A Promise that resolves once the initial handshake is complete.
*/
__accept(connection) {
return new Promise((resolve, reject) => {
this.connection = connection;
this.connection.on("message-request-id", (msg) => {
this.connection.id = msg.my_id;
this.connection.send("id", { my_id: this.server.our_id })
.then(resolve, reject);
});
});
}
/**
* Initiates the handshake after opening a new connection.
* @return {Promise} A Promise that resolves after the initial peer handshake is complete.
*/
__initiate() {
return new Promise((resolve, reject) => {
this.connection.send("request-id", { my_id: this.server.our_id })
.then(() => {
this.connection.once("message-id", (msg) => {
this.id = msg.my_id;
this.emit("connect");
resolve();
});
}, reject);
});
}
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();
}
Peer.Accept = function(server, connection) {
const peer = new Peer(server);
await peer.__accept(connection);
}
export default Peer;