"use strict"; import { EventEmitter, once } 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. */ 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} 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; } async __send_hello() { await this.connection.send("hello", { id: this.server.our_id, peers: this.server.peers() }); } /////////////////////////////////////////////////////////////////////////// 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;