mirror of
https://github.com/cerc-io/watcher-ts
synced 2024-11-19 20:36:19 +00:00
Pass initialization options when starting a peer (#328)
* Pass initialization options when starting a peer * Update config used for relay and peer nodes in watcher * Rename types * Refactor mobymask libp2p message parsing * Enable laconic debug logs in server command
This commit is contained in:
parent
6fa3ee28b5
commit
6a8b9a2385
@ -20,7 +20,7 @@ async function main (): Promise<void> {
|
||||
// https://adamcoster.com/blog/commonjs-and-esm-importexport-compatibility-examples#importing-esm-into-commonjs-cjs
|
||||
const { Peer } = await import('@cerc-io/peer');
|
||||
const peer = new Peer(argv.relayNode, true);
|
||||
await peer.init();
|
||||
await peer.init({});
|
||||
|
||||
peer.subscribeMessage((peerId: PeerId, message: string) => {
|
||||
console.log(`> ${peerId.toString()} > ${message}`);
|
||||
|
@ -28,8 +28,12 @@ import {
|
||||
P2PConfig
|
||||
} from '@cerc-io/util';
|
||||
import { TypeSource } from '@graphql-tools/utils';
|
||||
// @ts-expect-error https://github.com/microsoft/TypeScript/issues/49721#issuecomment-1319854183
|
||||
import { RelayNodeInit, PeerIdObj } from '@cerc-io/peer';
|
||||
import {
|
||||
RelayNodeInitConfig,
|
||||
PeerInitConfig,
|
||||
PeerIdObj
|
||||
// @ts-expect-error https://github.com/microsoft/TypeScript/issues/49721#issuecomment-1319854183
|
||||
} from '@cerc-io/peer';
|
||||
|
||||
import { BaseCmd } from './base';
|
||||
import { readPeerId } from './utils/index';
|
||||
@ -145,7 +149,13 @@ export class ServerCmd {
|
||||
parseLibp2pMessage?: (peerId: string, data: any) => void
|
||||
): Promise<void> {
|
||||
const { createRelayNode, Peer } = await import('@cerc-io/peer');
|
||||
const { RELAY_DEFAULT_HOST, RELAY_DEFAULT_PORT, RELAY_DEFAULT_MAX_DIAL_RETRY } = await import('@cerc-io/peer');
|
||||
const {
|
||||
RELAY_DEFAULT_HOST,
|
||||
RELAY_DEFAULT_PORT,
|
||||
RELAY_DEFAULT_MAX_DIAL_RETRY,
|
||||
RELAY_REDIAL_INTERVAL,
|
||||
PING_INTERVAL
|
||||
} = await import('@cerc-io/peer');
|
||||
|
||||
// Run the relay node if enabled
|
||||
if (p2pConfig.enableRelay) {
|
||||
@ -157,11 +167,13 @@ export class ServerCmd {
|
||||
peerIdObj = readPeerId(relayConfig.peerIdFile);
|
||||
}
|
||||
|
||||
const relayNodeInit: RelayNodeInit = {
|
||||
const relayNodeInit: RelayNodeInitConfig = {
|
||||
host: relayConfig.host ?? RELAY_DEFAULT_HOST,
|
||||
port: relayConfig.port ?? RELAY_DEFAULT_PORT,
|
||||
announceDomain: relayConfig.announce,
|
||||
relayPeers: relayConfig.relayPeers ?? [],
|
||||
pingInterval: relayConfig.pingInterval ?? PING_INTERVAL,
|
||||
redialInterval: relayConfig.redialInterval ?? RELAY_REDIAL_INTERVAL,
|
||||
maxDialRetry: relayConfig.maxDialRetry ?? RELAY_DEFAULT_MAX_DIAL_RETRY,
|
||||
peerIdObj
|
||||
};
|
||||
@ -170,10 +182,22 @@ export class ServerCmd {
|
||||
|
||||
// Run a peer node if enabled
|
||||
if (p2pConfig.enablePeer) {
|
||||
const peer = new Peer(p2pConfig.relayMultiaddr, true);
|
||||
await peer.init();
|
||||
const peerConfig = p2pConfig.peer;
|
||||
assert(peerConfig, 'Peer config not set');
|
||||
|
||||
peer.subscribeTopic(p2pConfig.pubSubTopic, (peerId, data) => {
|
||||
const peer = new Peer(peerConfig.relayMultiaddr, true);
|
||||
|
||||
const peerNodeInit: PeerInitConfig = {
|
||||
pingInterval: peerConfig.pingInterval,
|
||||
pingTimeout: peerConfig.pingTimeout,
|
||||
maxRelayConnections: peerConfig.maxRelayConnections,
|
||||
relayRedialInterval: peerConfig.relayRedialInterval,
|
||||
maxConnections: peerConfig.maxConnections,
|
||||
dialTimeout: peerConfig.dialTimeout
|
||||
};
|
||||
await peer.init(peerNodeInit);
|
||||
|
||||
peer.subscribeTopic(peerConfig.pubSubTopic, (peerId, data) => {
|
||||
if (parseLibp2pMessage) {
|
||||
parseLibp2pMessage(peerId.toString(), data);
|
||||
}
|
||||
|
@ -20,10 +20,8 @@
|
||||
maxEventsBlockRange = -1
|
||||
|
||||
[server.p2p]
|
||||
enablePeer = true
|
||||
relayMultiaddr = ''
|
||||
pubSubTopic = 'mobymask'
|
||||
enableRelay = true
|
||||
enablePeer = true
|
||||
|
||||
[server.p2p.relay]
|
||||
host = "127.0.0.1"
|
||||
@ -31,6 +29,10 @@
|
||||
relayPeers = []
|
||||
peerIdFile = ''
|
||||
|
||||
[server.p2p.peer]
|
||||
relayMultiaddr = ''
|
||||
pubSubTopic = 'mobymask'
|
||||
|
||||
[metrics]
|
||||
host = "127.0.0.1"
|
||||
port = 9000
|
||||
|
@ -9,7 +9,7 @@
|
||||
"build": "yarn clean && tsc && yarn copy-assets",
|
||||
"clean": "rm -rf ./dist",
|
||||
"copy-assets": "copyfiles -u 1 src/**/*.gql dist/",
|
||||
"server": "DEBUG=vulcanize:* YARN_CHILD_PROCESS=true node --enable-source-maps dist/server.js",
|
||||
"server": "DEBUG='vulcanize:*, laconic:*' YARN_CHILD_PROCESS=true node --enable-source-maps dist/server.js",
|
||||
"server:dev": "DEBUG=vulcanize:* YARN_CHILD_PROCESS=true ts-node src/server.ts",
|
||||
"job-runner": "DEBUG=vulcanize:* YARN_CHILD_PROCESS=true node --enable-source-maps dist/job-runner.js",
|
||||
"job-runner:dev": "DEBUG=vulcanize:* YARN_CHILD_PROCESS=true ts-node src/job-runner.ts",
|
||||
|
@ -33,55 +33,64 @@ const MESSAGE_KINDS = {
|
||||
REVOKE: 'revoke'
|
||||
};
|
||||
|
||||
function parseLibp2pMessage (peerId: string, data: any) {
|
||||
function parseLibp2pMessage (peerId: string, data: any): void {
|
||||
log('Received a message on mobymask P2P network from peer:', peerId);
|
||||
const { kind, message } = data;
|
||||
|
||||
switch (kind) {
|
||||
case MESSAGE_KINDS.INVOKE: {
|
||||
log('Signed invocations:');
|
||||
log(JSON.stringify(message, null, 2));
|
||||
|
||||
const [{ invocations: { batch: invocationsList } }] = message;
|
||||
Array.from(invocationsList).forEach((invocation: any) => {
|
||||
const txData = invocation.transaction.data;
|
||||
const decoded = contractInterface.parseTransaction({ data: txData });
|
||||
|
||||
log(`method: ${decoded.name}, value: ${decoded.args[0]}`);
|
||||
});
|
||||
|
||||
_parseInvocation(message);
|
||||
break;
|
||||
}
|
||||
|
||||
case MESSAGE_KINDS.REVOKE: {
|
||||
const { signedDelegation, signedIntendedRevocation } = message;
|
||||
log('Signed delegation:');
|
||||
log(JSON.stringify(signedDelegation, null, 2));
|
||||
log('Signed intention to revoke:');
|
||||
const stringifiedSignedIntendedRevocation = JSON.stringify(
|
||||
signedIntendedRevocation,
|
||||
(key, value) => {
|
||||
if (key === 'delegationHash' && value.type === 'Buffer') {
|
||||
// Show hex value for delegationHash instead of Buffer
|
||||
return ethers.utils.hexlify(Buffer.from(value));
|
||||
}
|
||||
|
||||
return value;
|
||||
},
|
||||
2
|
||||
);
|
||||
log(stringifiedSignedIntendedRevocation);
|
||||
|
||||
_parseRevocation(message);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
default: {
|
||||
log(`libp2p message of unknown kind ${kind}`);
|
||||
log(JSON.stringify(message, null, 2));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
log('------------------------------------------');
|
||||
}
|
||||
|
||||
function _parseInvocation (msg: any): void {
|
||||
log('Signed invocations:');
|
||||
log(JSON.stringify(msg, null, 2));
|
||||
|
||||
const [{ invocations: { batch: invocationsList } }] = msg;
|
||||
Array.from(invocationsList).forEach((invocation: any) => {
|
||||
const txData = invocation.transaction.data;
|
||||
const decoded = contractInterface.parseTransaction({ data: txData });
|
||||
|
||||
log(`method: ${decoded.name}, value: ${decoded.args[0]}`);
|
||||
});
|
||||
}
|
||||
|
||||
function _parseRevocation (msg: any): void {
|
||||
const { signedDelegation, signedIntendedRevocation } = msg;
|
||||
log('Signed delegation:');
|
||||
log(JSON.stringify(signedDelegation, null, 2));
|
||||
log('Signed intention to revoke:');
|
||||
const stringifiedSignedIntendedRevocation = JSON.stringify(
|
||||
signedIntendedRevocation,
|
||||
(key, value) => {
|
||||
if (key === 'delegationHash' && value.type === 'Buffer') {
|
||||
// Show hex value for delegationHash instead of Buffer
|
||||
return ethers.utils.hexlify(Buffer.from(value));
|
||||
}
|
||||
|
||||
return value;
|
||||
},
|
||||
2
|
||||
);
|
||||
log(stringifiedSignedIntendedRevocation);
|
||||
}
|
||||
|
||||
main().then(() => {
|
||||
log('Starting server...');
|
||||
}).catch(err => {
|
||||
|
@ -3,9 +3,9 @@ import { hideBin } from 'yargs/helpers';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
import { RelayNodeInit, createRelayNode } from '../relay.js';
|
||||
import { RelayNodeInitConfig, createRelayNode } from '../relay.js';
|
||||
import { PeerIdObj } from '../peer.js';
|
||||
import { RELAY_DEFAULT_HOST, RELAY_DEFAULT_PORT, RELAY_DEFAULT_MAX_DIAL_RETRY } from '../constants.js';
|
||||
import { RELAY_DEFAULT_HOST, RELAY_DEFAULT_PORT, RELAY_DEFAULT_MAX_DIAL_RETRY, RELAY_REDIAL_INTERVAL, PING_INTERVAL } from '../constants.js';
|
||||
|
||||
interface Arguments {
|
||||
host: string;
|
||||
@ -13,6 +13,8 @@ interface Arguments {
|
||||
announce?: string;
|
||||
peerIdFile?: string;
|
||||
relayPeers?: string;
|
||||
pingInterval: number;
|
||||
redialInterval: number;
|
||||
maxDialRetry: number;
|
||||
}
|
||||
|
||||
@ -44,13 +46,15 @@ async function main (): Promise<void> {
|
||||
relayPeersList = JSON.parse(relayPeersListObj);
|
||||
}
|
||||
|
||||
const relayNodeInit: RelayNodeInit = {
|
||||
const relayNodeInit: RelayNodeInitConfig = {
|
||||
host: argv.host,
|
||||
port: argv.port,
|
||||
peerIdObj,
|
||||
announceDomain: argv.announce,
|
||||
relayPeers: relayPeersList,
|
||||
maxDialRetry: argv.maxDialRetry,
|
||||
peerIdObj
|
||||
pingInterval: argv.pingInterval,
|
||||
redialInterval: argv.redialInterval,
|
||||
maxDialRetry: argv.maxDialRetry
|
||||
};
|
||||
await createRelayNode(relayNodeInit);
|
||||
}
|
||||
@ -86,6 +90,16 @@ function _getArgv (): Arguments {
|
||||
alias: 'r',
|
||||
describe: 'Relay peer multiaddr(s) list file path (json)'
|
||||
},
|
||||
pingInterval: {
|
||||
type: 'number',
|
||||
describe: 'Interval to check relay peer connections using ping (ms)',
|
||||
default: PING_INTERVAL
|
||||
},
|
||||
redialInterval: {
|
||||
type: 'number',
|
||||
describe: 'Redial interval to relay peer on connection failure (ms)',
|
||||
default: RELAY_REDIAL_INTERVAL
|
||||
},
|
||||
maxDialRetry: {
|
||||
type: 'number',
|
||||
describe: 'Maximum number of dial retries to be attempted to a relay peer',
|
||||
|
@ -21,16 +21,15 @@ export const RELAY_TAG = {
|
||||
value: 100
|
||||
};
|
||||
|
||||
// Interval time in ms to check connection with ping for connected peer
|
||||
// Currently only checking for relay node
|
||||
export const CONN_CHECK_INTERVAL = 10000; // 10 seconds
|
||||
// Interval in ms to check peer connections using ping
|
||||
export const PING_INTERVAL = 10000; // 10 seconds
|
||||
|
||||
// Ping timeout used to check if connection is alive
|
||||
// Should be lesser than CONN_CHECK_INTERVAL
|
||||
// Should be less than PING_INTERVAL
|
||||
export const PING_TIMEOUT = 5000; // 5 seconds
|
||||
|
||||
// Delay time in ms to redial relay node on failing to connect
|
||||
export const RELAY_REDIAL_DELAY = 5000; // 5 seconds
|
||||
// Redial interval (in ms) to relay node on connection failure
|
||||
export const RELAY_REDIAL_INTERVAL = 5000; // 5 seconds
|
||||
|
||||
// Max number of relay node connections for a peer after which it starts igoring them
|
||||
export const DEFAULT_MAX_RELAY_CONNECTIONS = 2;
|
||||
|
@ -2,7 +2,13 @@
|
||||
// Copyright 2022 Vulcanize, Inc.
|
||||
//
|
||||
|
||||
export { Peer, PeerIdObj, createPeerId } from './peer.js';
|
||||
export { RelayNodeInit, createRelayNode } from './relay.js';
|
||||
export { Peer, PeerIdObj, PeerInitConfig, createPeerId } from './peer.js';
|
||||
export { RelayNodeInitConfig, createRelayNode } from './relay.js';
|
||||
export { getPseudonymForPeerId } from './utils/index.js';
|
||||
export { RELAY_DEFAULT_HOST, RELAY_DEFAULT_PORT, RELAY_DEFAULT_MAX_DIAL_RETRY } from './constants.js';
|
||||
export {
|
||||
RELAY_DEFAULT_HOST,
|
||||
RELAY_DEFAULT_PORT,
|
||||
RELAY_REDIAL_INTERVAL,
|
||||
RELAY_DEFAULT_MAX_DIAL_RETRY,
|
||||
PING_INTERVAL
|
||||
} from './constants.js';
|
||||
|
@ -5,7 +5,7 @@
|
||||
import { Libp2p } from '@cerc-io/libp2p';
|
||||
import type { PeerId } from '@libp2p/interface-peer-id';
|
||||
|
||||
import { CONN_CHECK_INTERVAL } from './constants.js';
|
||||
import { PING_INTERVAL } from './constants.js';
|
||||
|
||||
interface PeerData {
|
||||
intervalId: NodeJS.Timer;
|
||||
@ -17,10 +17,12 @@ interface PeerData {
|
||||
*/
|
||||
export class PeerHearbeatChecker {
|
||||
_node: Libp2p;
|
||||
_pingInterval: number;
|
||||
_peerMap: Map<string, PeerData> = new Map()
|
||||
|
||||
constructor (node: Libp2p) {
|
||||
constructor (node: Libp2p, pingInterval = PING_INTERVAL) {
|
||||
this._node = node;
|
||||
this._pingInterval = pingInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -53,7 +55,7 @@ export class PeerHearbeatChecker {
|
||||
peerId,
|
||||
handlePingDisconnect
|
||||
);
|
||||
}, CONN_CHECK_INTERVAL);
|
||||
}, this._pingInterval);
|
||||
|
||||
this._peerMap.set(
|
||||
peerIdString,
|
||||
|
@ -36,7 +36,7 @@ import {
|
||||
PUBSUB_DISCOVERY_INTERVAL,
|
||||
PUBSUB_SIGNATURE_POLICY,
|
||||
RELAY_TAG,
|
||||
RELAY_REDIAL_DELAY,
|
||||
RELAY_REDIAL_INTERVAL,
|
||||
DEFAULT_MAX_RELAY_CONNECTIONS,
|
||||
PING_TIMEOUT
|
||||
} from './constants.js';
|
||||
@ -48,20 +48,35 @@ export const CHAT_PROTOCOL = '/chat/1.0.0';
|
||||
|
||||
const ERR_PEER_ALREADY_TAGGED = 'Peer already tagged';
|
||||
|
||||
export type PeerIdObj = {
|
||||
export interface PeerIdObj {
|
||||
id: string;
|
||||
privKey: string;
|
||||
pubKey: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface PeerInitConfig {
|
||||
pingInterval?: number;
|
||||
pingTimeout?: number;
|
||||
maxRelayConnections?: number;
|
||||
relayRedialInterval?: number;
|
||||
maxConnections?: number;
|
||||
minConnections?: number;
|
||||
dialTimeout?: number;
|
||||
}
|
||||
|
||||
export class Peer {
|
||||
_node?: Libp2p
|
||||
_peerHeartbeatChecker?: PeerHearbeatChecker
|
||||
_wrtcTransport: (components: WebRTCDirectComponents) => Transport
|
||||
|
||||
_relayNodeMultiaddr: Multiaddr
|
||||
_numRelayConnections = 0
|
||||
|
||||
_peerStreamMap: Map<string, Pushable<any>> = new Map()
|
||||
_pingInterval?: number
|
||||
_relayRedialInterval?: number
|
||||
_maxRelayConnections?: number
|
||||
|
||||
_peerStreamMap: Map<string, Pushable<any>> = new Map()
|
||||
_messageHandlers: Array<(peerId: PeerId, message: any) => void> = []
|
||||
_topicHandlers: Map<string, Array<(peerId: PeerId, data: any) => void>> = new Map()
|
||||
_metrics = new PrometheusMetrics()
|
||||
@ -97,10 +112,11 @@ export class Peer {
|
||||
return this._metrics;
|
||||
}
|
||||
|
||||
async init (
|
||||
peerIdObj?: PeerIdObj,
|
||||
maxRelayConnections = DEFAULT_MAX_RELAY_CONNECTIONS
|
||||
): Promise<void> {
|
||||
async init (initOptions: PeerInitConfig, peerIdObj?: PeerIdObj): Promise<void> {
|
||||
this._pingInterval = initOptions.pingInterval;
|
||||
this._relayRedialInterval = initOptions.relayRedialInterval;
|
||||
this._maxRelayConnections = initOptions.maxRelayConnections;
|
||||
|
||||
try {
|
||||
let peerId: PeerId | undefined;
|
||||
if (peerIdObj) {
|
||||
@ -134,13 +150,13 @@ export class Peer {
|
||||
connectionManager: {
|
||||
maxDialsPerPeer: MAX_CONCURRENT_DIALS_PER_PEER,
|
||||
autoDial: false,
|
||||
maxConnections: MAX_CONNECTIONS,
|
||||
minConnections: MIN_CONNECTIONS,
|
||||
dialTimeout: DIAL_TIMEOUT,
|
||||
maxConnections: initOptions.maxConnections ?? MAX_CONNECTIONS,
|
||||
minConnections: initOptions.minConnections ?? MIN_CONNECTIONS,
|
||||
dialTimeout: initOptions.dialTimeout ?? DIAL_TIMEOUT,
|
||||
keepMultipleConnections: true // Set true to get connections with multiple multiaddr
|
||||
},
|
||||
ping: {
|
||||
timeout: PING_TIMEOUT
|
||||
timeout: initOptions.pingTimeout ?? PING_TIMEOUT
|
||||
},
|
||||
metrics: () => this._metrics
|
||||
});
|
||||
@ -150,10 +166,10 @@ export class Peer {
|
||||
}
|
||||
|
||||
console.log('libp2p node created', this._node);
|
||||
this._peerHeartbeatChecker = new PeerHearbeatChecker(this._node);
|
||||
this._peerHeartbeatChecker = new PeerHearbeatChecker(this._node, this._pingInterval);
|
||||
|
||||
// Dial to the HOP enabled primary relay node
|
||||
await this._dialRelay();
|
||||
await this._dialRelay(this._relayRedialInterval);
|
||||
|
||||
// Listen for change in stored multiaddrs
|
||||
this._node.peerStore.addEventListener('change:multiaddrs', (evt) => {
|
||||
@ -178,13 +194,13 @@ export class Peer {
|
||||
// Listen for peers discovery
|
||||
this._node.addEventListener('peer:discovery', (evt) => {
|
||||
// console.log('event peer:discovery', evt);
|
||||
this._handleDiscovery(evt.detail, maxRelayConnections);
|
||||
this._handleDiscovery(evt.detail, this._maxRelayConnections);
|
||||
});
|
||||
|
||||
// Listen for peers connection
|
||||
this._node.addEventListener('peer:connect', async (evt) => {
|
||||
console.log('event peer:connect', evt);
|
||||
await this._handleConnect(evt.detail, maxRelayConnections);
|
||||
await this._handleConnect(evt.detail, this._maxRelayConnections);
|
||||
});
|
||||
|
||||
// Listen for peers disconnecting
|
||||
@ -320,7 +336,7 @@ export class Peer {
|
||||
}
|
||||
}
|
||||
|
||||
async _dialRelay (): Promise<void> {
|
||||
async _dialRelay (redialInterval = RELAY_REDIAL_INTERVAL): Promise<void> {
|
||||
assert(this._node);
|
||||
const relayMultiaddr = this._relayNodeMultiaddr;
|
||||
console.log('Dialling primary relay node');
|
||||
@ -329,7 +345,7 @@ export class Peer {
|
||||
this._node,
|
||||
relayMultiaddr,
|
||||
{
|
||||
redialDelay: RELAY_REDIAL_DELAY,
|
||||
redialInterval: redialInterval,
|
||||
maxRetry: Infinity
|
||||
}
|
||||
);
|
||||
@ -352,7 +368,7 @@ export class Peer {
|
||||
});
|
||||
}
|
||||
|
||||
_handleDiscovery (peer: PeerInfo, maxRelayConnections: number): void {
|
||||
_handleDiscovery (peer: PeerInfo, maxRelayConnections = DEFAULT_MAX_RELAY_CONNECTIONS): void {
|
||||
// Check connected peers as they are discovered repeatedly.
|
||||
if (!this._node?.getPeers().some(remotePeerId => remotePeerId.toString() === peer.id.toString())) {
|
||||
let isRelayPeer = false;
|
||||
@ -374,7 +390,7 @@ export class Peer {
|
||||
}
|
||||
}
|
||||
|
||||
async _handleConnect (connection: Connection, maxRelayConnections: number): Promise<void> {
|
||||
async _handleConnect (connection: Connection, maxRelayConnections = DEFAULT_MAX_RELAY_CONNECTIONS): Promise<void> {
|
||||
assert(this._node);
|
||||
const remotePeerId = connection.remotePeer;
|
||||
const remotePeerIdString = connection.remotePeer.toString();
|
||||
@ -474,7 +490,7 @@ export class Peer {
|
||||
|
||||
if (disconnectedPeerId.toString() === this._relayNodeMultiaddr?.getPeerId()) {
|
||||
// Reconnect to primary relay node if disconnected
|
||||
await this._dialRelay();
|
||||
await this._dialRelay(this._relayRedialInterval);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,23 +16,25 @@ import { multiaddr } from '@multiformats/multiaddr';
|
||||
import type { PeerId } from '@libp2p/interface-peer-id';
|
||||
import { createFromJSON } from '@libp2p/peer-id-factory';
|
||||
|
||||
import { HOP_TIMEOUT, PUBSUB_DISCOVERY_INTERVAL, PUBSUB_SIGNATURE_POLICY, WEBRTC_PORT_RANGE, RELAY_REDIAL_DELAY } from './constants.js';
|
||||
import { HOP_TIMEOUT, PUBSUB_DISCOVERY_INTERVAL, PUBSUB_SIGNATURE_POLICY, WEBRTC_PORT_RANGE } from './constants.js';
|
||||
import { PeerHearbeatChecker } from './peer-heartbeat-checker.js';
|
||||
import { dialWithRetry } from './utils/index.js';
|
||||
import { PeerIdObj } from './peer.js';
|
||||
|
||||
const log = debug('laconic:relay');
|
||||
|
||||
export interface RelayNodeInit {
|
||||
export interface RelayNodeInitConfig {
|
||||
host: string;
|
||||
port: number;
|
||||
peerIdObj?: PeerIdObj;
|
||||
announceDomain?: string;
|
||||
relayPeers: string[];
|
||||
pingInterval: number;
|
||||
redialInterval: number;
|
||||
maxDialRetry: number;
|
||||
peerIdObj?: PeerIdObj;
|
||||
}
|
||||
|
||||
export async function createRelayNode (init: RelayNodeInit): Promise<Libp2p> {
|
||||
export async function createRelayNode (init: RelayNodeInitConfig): Promise<Libp2p> {
|
||||
const listenMultiaddrs = [`/ip4/${init.host}/tcp/${init.port}/http/p2p-webrtc-direct`];
|
||||
const announceMultiaddrs = [];
|
||||
|
||||
@ -83,7 +85,7 @@ export async function createRelayNode (init: RelayNodeInit): Promise<Libp2p> {
|
||||
}
|
||||
});
|
||||
|
||||
const peerHeartbeatChecker = new PeerHearbeatChecker(node);
|
||||
const peerHeartbeatChecker = new PeerHearbeatChecker(node, init.pingInterval);
|
||||
|
||||
console.log(`Relay node started with id ${node.peerId.toString()}`);
|
||||
console.log('Listening on:');
|
||||
@ -123,7 +125,7 @@ export async function createRelayNode (init: RelayNodeInit): Promise<Libp2p> {
|
||||
node,
|
||||
remoteAddr,
|
||||
{
|
||||
redialDelay: RELAY_REDIAL_DELAY,
|
||||
redialInterval: init.redialInterval,
|
||||
maxRetry: init.maxDialRetry
|
||||
}
|
||||
).catch((error: Error) => console.log(error.message));
|
||||
@ -132,20 +134,20 @@ export async function createRelayNode (init: RelayNodeInit): Promise<Libp2p> {
|
||||
|
||||
if (init.relayPeers.length) {
|
||||
console.log('Dialling relay peers');
|
||||
await _dialRelayPeers(node, init.relayPeers, init.maxDialRetry);
|
||||
await _dialRelayPeers(node, init.relayPeers, init.maxDialRetry, init.redialInterval);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
async function _dialRelayPeers (node: Libp2p, relayPeersList: string[], maxDialRetry: number): Promise<void> {
|
||||
async function _dialRelayPeers (node: Libp2p, relayPeersList: string[], maxDialRetry: number, redialInterval: number): Promise<void> {
|
||||
relayPeersList.forEach(async (relayPeer) => {
|
||||
const relayMultiaddr = multiaddr(relayPeer);
|
||||
await dialWithRetry(
|
||||
node,
|
||||
relayMultiaddr,
|
||||
{
|
||||
redialDelay: RELAY_REDIAL_DELAY,
|
||||
redialInterval,
|
||||
maxRetry: maxDialRetry
|
||||
}
|
||||
).catch((error: Error) => console.log(error.message));
|
||||
|
@ -7,12 +7,12 @@ import { Multiaddr } from '@multiformats/multiaddr';
|
||||
import { uniqueNamesGenerator, adjectives, colors, names } from 'unique-names-generator';
|
||||
|
||||
interface DialWithRetryOptions {
|
||||
redialDelay: number
|
||||
redialInterval: number
|
||||
maxRetry: number
|
||||
}
|
||||
|
||||
const DEFAULT_DIAL_RETRY_OPTIONS: DialWithRetryOptions = {
|
||||
redialDelay: 5000, // ms
|
||||
redialInterval: 5000, // ms
|
||||
maxRetry: 5
|
||||
};
|
||||
|
||||
@ -24,7 +24,7 @@ const DEFAULT_DIAL_RETRY_OPTIONS: DialWithRetryOptions = {
|
||||
* @param options
|
||||
*/
|
||||
export const dialWithRetry = async (node: Libp2p, multiaddr: Multiaddr, options: Partial<DialWithRetryOptions>) => {
|
||||
const { redialDelay, maxRetry } = {
|
||||
const { redialInterval, maxRetry } = {
|
||||
...DEFAULT_DIAL_RETRY_OPTIONS,
|
||||
...options
|
||||
};
|
||||
@ -38,11 +38,11 @@ export const dialWithRetry = async (node: Libp2p, multiaddr: Multiaddr, options:
|
||||
return connection;
|
||||
} catch (err) {
|
||||
console.log(`Could not dial node ${multiaddr.toString()}`, err);
|
||||
console.log(`Retrying after ${redialDelay}ms`);
|
||||
console.log(`Retrying after ${redialInterval}ms`);
|
||||
|
||||
// TODO: Use wait method from util package.
|
||||
// Issue using util package in react app.
|
||||
await new Promise(resolve => setTimeout(resolve, redialDelay));
|
||||
await new Promise(resolve => setTimeout(resolve, redialInterval));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,19 +44,52 @@ export interface RelayConfig {
|
||||
// Port to start listening on
|
||||
port?: number;
|
||||
|
||||
// Domain name to be used in the announce address
|
||||
announce?: string;
|
||||
|
||||
// Relay peer id file path (json)
|
||||
peerIdFile?: string;
|
||||
|
||||
// Domain name to be used in the announce address
|
||||
announce?: string;
|
||||
|
||||
// Relay peer multiaddr(s) list
|
||||
relayPeers?: string[];
|
||||
|
||||
// Interval in ms to check relay peer connections using ping
|
||||
pingInterval?: number;
|
||||
|
||||
// Redial interval in ms on connection failure
|
||||
redialInterval?: number;
|
||||
|
||||
// Max number of dial retries to be attempted to a relay peer
|
||||
maxDialRetry?: number;
|
||||
}
|
||||
|
||||
// Peer config
|
||||
export interface PeerConfig {
|
||||
// Multiaddr of the primary relay node for this peer
|
||||
relayMultiaddr: string;
|
||||
|
||||
// Pubsub topic to subscribe this peer to
|
||||
pubSubTopic: string;
|
||||
|
||||
// Interval (ms) to check relay peer connections using ping
|
||||
pingInterval?: number;
|
||||
|
||||
// Ping timeout (ms) used to check if connection is alive
|
||||
pingTimeout?: number;
|
||||
|
||||
// Max number of relay node connections for a peer
|
||||
maxRelayConnections?: number;
|
||||
|
||||
// Redial interval (ms) to relay node on connection failure
|
||||
relayRedialInterval?: number;
|
||||
|
||||
// Max number of connections for a peer
|
||||
maxConnections?: number;
|
||||
|
||||
// Timeout (ms) for dial to peers
|
||||
dialTimeout?: number;
|
||||
}
|
||||
|
||||
// P2P config
|
||||
export interface P2PConfig {
|
||||
// Enable relay node
|
||||
@ -65,12 +98,7 @@ export interface P2PConfig {
|
||||
|
||||
// Enable peer node
|
||||
enablePeer: boolean;
|
||||
|
||||
// Multiaddr of the primary relay node for this peer
|
||||
relayMultiaddr: string;
|
||||
|
||||
// Pubsub topic to subscribe this peer to
|
||||
pubSubTopic: string;
|
||||
peer: PeerConfig;
|
||||
}
|
||||
|
||||
export interface ServerConfig {
|
||||
|
Loading…
Reference in New Issue
Block a user