Use webrtc-direct transport with pubsub based discovery

This commit is contained in:
Prathamesh Musale 2023-01-03 16:05:05 +05:30
parent 461610f023
commit 1acba76522
10 changed files with 77 additions and 152 deletions

View File

@ -17,30 +17,20 @@ A basic CLI to pass messages between peers using `stdin`/`stdout`
yarn build
```
* (Optional) Run a local signalling server:
```bash
# In packages/peer
yarn signal-server
```
* (Optional) Run a local relay node:
```bash
# In packages/peer
yarn relay-node --signal-server [SIGNAL_SERVER_URL]
yarn relay-node
```
* `signal-server`: multiaddr of a signalling server (default: local signalling server multiaddr)
* Start the node:
```bash
# In packages/cli
yarn chat --signal-server [SIGNAL_SERVER_URL] --relay-node [RELAY_NODE_URL]
yarn chat --relay-node <RELAY_NODE_URL>
```
* `signal-server`: multiaddr of a signalling server (default: local signalling server multiaddr)
* `relay-node`: multiaddr of a hop enabled relay node
* The process starts reading from `stdin` and outputs messages from others peers to `stdout`.

View File

@ -10,20 +10,16 @@ import yargs from 'yargs';
import { PeerId } from '@libp2p/interface-peer-id';
interface Arguments {
signalServer: string;
relayNode: string;
}
async function main (): Promise<void> {
const argv: Arguments = _getArgv();
if (!argv.signalServer) {
console.log('Using the default signalling server URL');
}
// 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(true);
await peer.init(argv.signalServer, argv.relayNode);
await peer.init(argv.relayNode);
peer.subscribeMessage((peerId: PeerId, message: string) => {
console.log(`> ${peerId.toString()} > ${message}`);
@ -47,13 +43,10 @@ function _getArgv (): any {
return yargs(hideBin(process.argv)).parserConfiguration({
'parse-numbers': false
}).options({
signalServer: {
type: 'string',
describe: 'Signalling server URL'
},
relayNode: {
type: 'string',
describe: 'Relay node URL'
describe: 'Relay node URL',
demandOption: true
}
}).argv;
}

View File

@ -1,2 +1 @@
REACT_APP_SIGNAL_SERVER=/ip4/127.0.0.1/tcp/13579/ws/p2p-webrtc-star/
REACT_APP_RELAY_NODE=

View File

@ -19,27 +19,17 @@ This project was bootstrapped with [Create React App](https://github.com/faceboo
yarn build
```
* (Optional) Run a local signalling server:
```bash
# In packages/peer
yarn signal-server
```
* (Optional) Run a local relay node:
```bash
# In packages/peer
yarn relay-node --signal-server [SIGNAL_SERVER_URL]
yarn relay-node
```
* `signal-server`: multiaddr of a signalling server (default: local signalling server multiaddr)
* Set the signalling server and relay node multiaddrs in the [env](./.env) file:
* Set the relay node multiaddr in the [env](./.env) file:
```
REACT_APP_SIGNAL_SERVER=/ip4/127.0.0.1/tcp/13579/ws/p2p-webrtc-star/
REACT_APP_RELAY_NODE=/ip4/127.0.0.1/tcp/13579/wss/p2p-webrtc-star/p2p/12D3KooWRzH3ZRFP6RDbs2EKA8jSrD4Y6VYtLnCRMj3mYCiMHCJP
REACT_APP_RELAY_NODE=/ip4/0.0.0.0/tcp/9090/http/p2p-webrtc-direct/p2p/12D3KooWFn2tjcv1ciot6sXJDiCdxXAPh37pzxjBC1UmCkbP3QBo
```
* Start the react app in development mode:

View File

@ -14,8 +14,14 @@ function App() {
useEffect(() => {
(async () => {
if (peer) {
await peer.init(process.env.REACT_APP_SIGNAL_SERVER, process.env.REACT_APP_RELAY_NODE)
console.log(`Peer ID is ${peer.peerId!.toString()}`);
const relayNode = process.env.REACT_APP_RELAY_NODE;
if (!relayNode) {
console.log('REACT_APP_RELAY_NODE not set')
return;
}
await peer.init(relayNode)
console.log(`Peer ID: ${peer.peerId!.toString()}`);
peer.subscribeMessage((peerId, message) => {
console.log(`${peerId.toString()} > ${message}`)

View File

@ -22,7 +22,6 @@
"build": "tsc",
"lint": "eslint .",
"dev": "node dist/index.js",
"signal-server": "webrtc-star --port=13579 --host=0.0.0.0",
"relay-node": "node dist/relay.js"
},
"dependencies": {
@ -30,8 +29,8 @@
"@libp2p/bootstrap": "^5.0.2",
"@libp2p/floodsub": "^5.0.0",
"@libp2p/mplex": "^7.1.1",
"@libp2p/webrtc-direct": "^4.0.2",
"@libp2p/pubsub-peer-discovery": "^7.0.1",
"@libp2p/webrtc-star": "^5.0.3",
"@libp2p/websockets": "^5.0.2",
"@multiformats/multiaddr": "^11.1.4",
"assert": "^2.0.0",

View File

@ -3,3 +3,4 @@
//
export const PUBSUB_DISCOVERY_INTERVAL = 10000;
export const RELAY_NODE_LISTEN_ADDRESS = '/ip4/0.0.0.0/tcp/9090/http/p2p-webrtc-direct';

View File

@ -13,9 +13,10 @@ import { pushable, Pushable } from 'it-pushable';
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string';
import { toString as uint8ArrayToString } from 'uint8arrays/to-string';
import { webRTCStar, WebRTCStarTuple } from '@libp2p/webrtc-star';
import { webRTCDirect } from '@libp2p/webrtc-direct';
import { noise } from '@chainsafe/libp2p-noise';
import { mplex } from '@libp2p/mplex';
import type { Transport } from '@libp2p/interface-transport';
import type { Stream as P2PStream, Connection } from '@libp2p/interface-connection';
import type { PeerInfo } from '@libp2p/interface-peer-info';
import { PeerId } from '@libp2p/interface-peer-id';
@ -23,14 +24,12 @@ import { multiaddr, Multiaddr } from '@multiformats/multiaddr';
import { bootstrap } from '@libp2p/bootstrap';
import { floodsub } from '@libp2p/floodsub';
import { pubsubPeerDiscovery } from '@libp2p/pubsub-peer-discovery';
import { PUBSUB_DISCOVERY_INTERVAL } from './constants.js';
export const PROTOCOL = '/chat/1.0.0';
export const DEFAULT_SIGNAL_SERVER_URL = '/ip4/127.0.0.1/tcp/13579/wss/p2p-webrtc-star';
export class Peer {
_node?: Libp2p
_wrtcStar: WebRTCStarTuple
_wrtcTransport: () => Transport
_relayNodeMultiaddr?: Multiaddr
_remotePeerIds: PeerId[] = []
@ -40,9 +39,9 @@ export class Peer {
constructor (nodejs?: boolean) {
// Instantiation in nodejs.
if (nodejs) {
this._wrtcStar = webRTCStar({ wrtc });
this._wrtcTransport = webRTCDirect({ wrtc });
} else {
this._wrtcStar = webRTCStar();
this._wrtcTransport = webRTCDirect();
}
}
@ -50,38 +49,22 @@ export class Peer {
return this._node?.peerId;
}
async init (signalServerURL = DEFAULT_SIGNAL_SERVER_URL, relayNodeURL?: string): Promise<void> {
let peerDiscovery: any;
if (relayNodeURL) {
this._relayNodeMultiaddr = multiaddr(relayNodeURL);
console.log(`Bootstrapping with relay node ${this._relayNodeMultiaddr.toString()}`);
peerDiscovery = [
bootstrap({
list: [this._relayNodeMultiaddr.toString()]
}),
pubsubPeerDiscovery({
interval: PUBSUB_DISCOVERY_INTERVAL
})
];
} else {
peerDiscovery = [this._wrtcStar.discovery];
}
async init (relayNodeURL: string): Promise<void> {
this._relayNodeMultiaddr = multiaddr(relayNodeURL);
console.log(`Bootstrapping with relay node ${this._relayNodeMultiaddr.toString()}`);
const peerDiscovery = [
bootstrap({
list: [this._relayNodeMultiaddr.toString()]
}),
// Add pubsub discovery; relay server acts as a peer discovery source
pubsubPeerDiscovery({
interval: 1000
})
];
this._node = await createLibp2p({
addresses: {
// Add the signaling server address, along with our PeerId to our multiaddrs list
// libp2p will automatically attempt to dial to the signaling server so that it can
// receive inbound connections from other peers
listen: [
// Public signal servers
// '/dns4/wrtc-star1.par.dwebops.pub/tcp/443/wss/p2p-webrtc-star',
// '/dns4/wrtc-star2.sjc.dwebops.pub/tcp/443/wss/p2p-webrtc-star'
signalServerURL
]
},
transports: [
this._wrtcStar.transport
],
transports: [this._wrtcTransport],
connectionEncryption: [noise()],
streamMuxers: [mplex()],
pubsub: floodsub(),
@ -137,6 +120,7 @@ export class Peer {
async close (): Promise<void> {
assert(this._node);
this._node.peerStore.removeEventListener('change:multiaddrs');
this._node.removeEventListener('peer:discovery');
this._node.connectionManager.removeEventListener('peer:connect');
this._node.connectionManager.removeEventListener('peer:disconnect');
@ -189,20 +173,20 @@ export class Peer {
async _connectPeer (peer: PeerInfo): Promise<void> {
assert(this._node);
assert(this._relayNodeMultiaddr);
console.log(`Dialling peer ${peer.id.toString()}`);
// Check if discovered the relay node
if (this._relayNodeMultiaddr) {
const relayMultiaddr = this._relayNodeMultiaddr;
const relayNodePeerId = relayMultiaddr.getPeerId();
const relayMultiaddr = this._relayNodeMultiaddr;
const relayNodePeerId = relayMultiaddr.getPeerId();
if (relayNodePeerId && relayNodePeerId === peer.id.toString()) {
console.log(`Dialling relay peer ${peer.id.toString()} using multiaddr ${relayMultiaddr.toString()}`);
await this._node.dial(relayMultiaddr).catch(err => {
console.log(`Could not dial relay ${relayMultiaddr.toString()}`, err);
});
if (relayNodePeerId && relayNodePeerId === peer.id.toString()) {
console.log(`Dialling relay peer ${peer.id.toString()} using multiaddr ${relayMultiaddr.toString()}`);
await this._node.dial(relayMultiaddr).catch(err => {
console.log(`Could not dial relay ${relayMultiaddr.toString()}`, err);
});
return;
}
return;
}
// Dial them when we discover them

View File

@ -4,38 +4,21 @@
import { createLibp2p } from 'libp2p';
import wrtc from 'wrtc';
import { hideBin } from 'yargs/helpers';
import yargs from 'yargs';
import { noise } from '@chainsafe/libp2p-noise';
import { mplex } from '@libp2p/mplex';
import { webRTCStar, WebRTCStarTuple } from '@libp2p/webrtc-star';
import { webRTCDirect } from '@libp2p/webrtc-direct';
import { floodsub } from '@libp2p/floodsub';
import { pubsubPeerDiscovery } from '@libp2p/pubsub-peer-discovery';
import { DEFAULT_SIGNAL_SERVER_URL } from './index.js';
import { PUBSUB_DISCOVERY_INTERVAL } from './constants.js';
interface Arguments {
signalServer: string;
}
import { PUBSUB_DISCOVERY_INTERVAL, RELAY_NODE_LISTEN_ADDRESS } from './constants.js';
async function main (): Promise<void> {
const argv: Arguments = _getArgv();
if (!argv.signalServer) {
console.log('Using the default signalling server URL');
}
const wrtcStar: WebRTCStarTuple = webRTCStar({ wrtc });
const node = await createLibp2p({
addresses: {
listen: [
argv.signalServer || DEFAULT_SIGNAL_SERVER_URL
]
listen: [RELAY_NODE_LISTEN_ADDRESS]
},
transports: [
wrtcStar.transport
],
transports: [webRTCDirect({ wrtc })],
connectionEncryption: [noise()],
streamMuxers: [mplex()],
pubsub: floodsub(),
@ -60,21 +43,6 @@ async function main (): Promise<void> {
node.getMultiaddrs().forEach((ma) => console.log(ma.toString()));
}
function _getArgv (): any {
return yargs(hideBin(process.argv)).parserConfiguration({
'parse-numbers': false
}).options({
signalServer: {
type: 'string',
describe: 'Signalling server URL'
},
relayNode: {
type: 'string',
describe: 'Relay node URL'
}
}).argv;
}
main().catch(err => {
console.log(err);
});

View File

@ -4245,7 +4245,7 @@
uint8arraylist "^2.0.0"
uint8arrays "^4.0.2"
"@libp2p/peer-id@^1.0.0", "@libp2p/peer-id@^1.1.0", "@libp2p/peer-id@^1.1.13", "@libp2p/peer-id@^1.1.15", "@libp2p/peer-id@^1.1.8", "@libp2p/peer-id@^1.1.9":
"@libp2p/peer-id@^1.0.0", "@libp2p/peer-id@^1.1.0", "@libp2p/peer-id@^1.1.13", "@libp2p/peer-id@^1.1.15", "@libp2p/peer-id@^1.1.8":
version "1.1.18"
resolved "https://registry.npmjs.org/@libp2p/peer-id/-/peer-id-1.1.18.tgz"
integrity sha512-Zh3gzbrQZKDMLpoJAJB8gdGtyYFSBKV0dU5vflQ18/7MJDJmjsgKO+sJTYi72yN5sWREs1eGKMhxLo+N1ust5w==
@ -4367,7 +4367,7 @@
dependencies:
"@libp2p/interface-metrics" "^4.0.0"
"@libp2p/utils@^3.0.0", "@libp2p/utils@^3.0.1", "@libp2p/utils@^3.0.2":
"@libp2p/utils@^3.0.0", "@libp2p/utils@^3.0.2":
version "3.0.4"
resolved "https://registry.npmjs.org/@libp2p/utils/-/utils-3.0.4.tgz"
integrity sha512-EWJNJtlop2ylmGE1BNiMA0u4eTLKoY0LbZ/DOvSDs9VlGSLua9J+LUjp6XV8lazGv7l1rOLiU+1hP5fcmg1+eg==
@ -4384,6 +4384,27 @@
private-ip "^3.0.0"
uint8arraylist "^2.3.2"
"@libp2p/webrtc-direct@^4.0.2":
version "4.0.2"
resolved "https://registry.yarnpkg.com/@libp2p/webrtc-direct/-/webrtc-direct-4.0.2.tgz#2227746279950f3586d5f823edc865c673a31897"
integrity sha512-mnGBsxECXdsx6UyIbxjEEGM+9FkyfamcInALjpuW+34KNlF/OlLCJV+PBOxDQK9NSGIoVDSJ8VwYItn5MU51Fg==
dependencies:
"@libp2p/interface-transport" "^2.0.0"
"@libp2p/interfaces" "^3.0.3"
"@libp2p/logger" "^2.0.1"
"@libp2p/utils" "^3.0.2"
"@libp2p/webrtc-peer" "^2.0.0"
"@multiformats/mafmt" "^11.0.3"
"@multiformats/multiaddr" "^11.0.0"
abortable-iterator "^4.0.2"
err-code "^3.0.0"
multiformats "^10.0.0"
native-fetch "^4.0.2"
p-event "^5.0.1"
uint8arrays "^4.0.2"
undici "^5.2.0"
wherearewe "^2.0.1"
"@libp2p/webrtc-peer@^2.0.0":
version "2.0.2"
resolved "https://registry.npmjs.org/@libp2p/webrtc-peer/-/webrtc-peer-2.0.2.tgz"
@ -4424,32 +4445,6 @@
socket.io "^4.1.2"
socket.io-client "^4.1.2"
"@libp2p/webrtc-star@^5.0.3":
version "5.0.3"
resolved "https://registry.npmjs.org/@libp2p/webrtc-star/-/webrtc-star-5.0.3.tgz"
integrity sha512-tGH72ARnuHaj5FlLMrdU4B2PIZMgUKdS40YqlIu5w9zo4csZ8n07oRHt0B+gRnahLd8wY80uiS6CnmTC5c0skg==
dependencies:
"@libp2p/interface-connection" "^3.0.1"
"@libp2p/interface-peer-discovery" "^1.0.0"
"@libp2p/interface-peer-id" "^1.0.2"
"@libp2p/interface-transport" "^2.0.0"
"@libp2p/interfaces" "^3.0.2"
"@libp2p/logger" "^2.0.0"
"@libp2p/peer-id" "^1.1.9"
"@libp2p/utils" "^3.0.1"
"@libp2p/webrtc-peer" "^2.0.0"
"@libp2p/webrtc-star-protocol" "^2.0.0"
"@multiformats/mafmt" "^11.0.2"
"@multiformats/multiaddr" "^11.0.0"
abortable-iterator "^4.0.2"
delay "^5.0.0"
err-code "^3.0.1"
iso-random-stream "^2.0.2"
multiformats "^10.0.0"
p-defer "^4.0.0"
socket.io-client "^4.1.2"
uint8arrays "^4.0.2"
"@libp2p/websockets@^5.0.2":
version "5.0.2"
resolved "https://registry.npmjs.org/@libp2p/websockets/-/websockets-5.0.2.tgz"
@ -10702,7 +10697,7 @@ err-code@^2.0.2:
resolved "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz"
integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==
err-code@^3.0.1:
err-code@^3.0.0, err-code@^3.0.1:
version "3.0.1"
resolved "https://registry.npmjs.org/err-code/-/err-code-3.0.1.tgz"
integrity sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==
@ -22788,7 +22783,7 @@ underscore@1.9.1:
resolved "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz"
integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==
undici@^5.12.0:
undici@^5.12.0, undici@^5.2.0:
version "5.14.0"
resolved "https://registry.npmjs.org/undici/-/undici-5.14.0.tgz"
integrity sha512-yJlHYw6yXPPsuOH0x2Ib1Km61vu4hLiRRQoafs+WUgX1vO64vgnxiCEN9dpIrhZyHFsai3F0AEj4P9zy19enEQ==