mirror of
https://github.com/fluencelabs/js-libp2p
synced 2025-04-24 18:12:14 +00:00
Add an example of webrtc-direct (#868)
Co-authored-by: Vasco Santos <vasco.santos@moxy.studio>
This commit is contained in:
parent
a1424826e7
commit
9c67364caa
9
.github/workflows/main.yml
vendored
9
.github/workflows/main.yml
vendored
@ -92,7 +92,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: yarn
|
||||
- run: cd examples && yarn && npm run test -- echo
|
||||
- run: cd examples && yarn && npm run test -- echo
|
||||
test-libp2p-in-the-browser-example:
|
||||
needs: check
|
||||
runs-on: macos-latest
|
||||
@ -135,3 +135,10 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- run: yarn
|
||||
- run: cd examples && yarn && npm run test -- transports
|
||||
test-webrtc-direct-example:
|
||||
needs: check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: yarn
|
||||
- run: cd examples && yarn && npm run test -- webrtc-direct
|
||||
|
33
examples/webrtc-direct/README.md
Normal file
33
examples/webrtc-direct/README.md
Normal file
@ -0,0 +1,33 @@
|
||||
### Webrtc-direct example
|
||||
|
||||
An example that uses [js-libp2p-webrtc-direct](https://github.com/libp2p/js-libp2p-webrtc-direct) for connecting
|
||||
nodejs libp2p and browser libp2p clients. To run the example:
|
||||
|
||||
## 0. Run a nodejs libp2p listener
|
||||
|
||||
When in the root folder of this example, type `node listener.js` in terminal. You should see an address that listens for
|
||||
incoming connections. Below is just an example of such address. In your case the suffix hash (`peerId`) will be different.
|
||||
|
||||
```bash
|
||||
$ node listener.js
|
||||
Listening on:
|
||||
/ip4/127.0.0.1/tcp/9090/http/p2p-webrtc-direct/p2p/QmUKQCzEUhhhobcNSrXU5uzxTqbvF1BjMCGNGZzZU14Kgd
|
||||
```
|
||||
|
||||
## 1. Prepare a browser libp2p dialer
|
||||
Confirm that the above address is the same as the field `list` in `public/dialer.js`:
|
||||
```js
|
||||
peerDiscovery: {
|
||||
[Bootstrap.tag]: {
|
||||
enabled: true,
|
||||
// paste the address into `list`
|
||||
list: ['/ip4/127.0.0.1/tcp/9090/http/p2p-webrtc-direct/p2p/QmUKQCzEUhhhobcNSrXU5uzxTqbvF1BjMCGNGZzZU14Kgd']
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 2. Run a browser libp2p dialer
|
||||
When in the root folder of this example, type `npm run dev` in terminal. You should see an address where you can browse
|
||||
the running client. Open this address in your browser. In console
|
||||
logs you should see logs about successful connection with the node client. In the output of node client you should see
|
||||
a log message about successful connection as well.
|
57
examples/webrtc-direct/dialer.js
Normal file
57
examples/webrtc-direct/dialer.js
Normal file
@ -0,0 +1,57 @@
|
||||
import 'babel-polyfill'
|
||||
const Libp2p = require('libp2p')
|
||||
const WebRTCDirect = require('libp2p-webrtc-direct')
|
||||
const Mplex = require('libp2p-mplex')
|
||||
const {NOISE} = require('libp2p-noise')
|
||||
const Bootstrap = require('libp2p-bootstrap')
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
// use the same peer id as in `listener.js` to avoid copy-pasting of listener's peer id into `peerDiscovery`
|
||||
const hardcodedPeerId = '12D3KooWCuo3MdXfMgaqpLC5Houi1TRoFqgK9aoxok4NK5udMu8m'
|
||||
const libp2p = await Libp2p.create({
|
||||
modules: {
|
||||
transport: [WebRTCDirect],
|
||||
streamMuxer: [Mplex],
|
||||
connEncryption: [NOISE],
|
||||
peerDiscovery: [Bootstrap]
|
||||
},
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
[Bootstrap.tag]: {
|
||||
enabled: true,
|
||||
list: [`/ip4/127.0.0.1/tcp/9090/http/p2p-webrtc-direct/p2p/${hardcodedPeerId}`]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const status = document.getElementById('status')
|
||||
const output = document.getElementById('output')
|
||||
|
||||
output.textContent = ''
|
||||
|
||||
function log (txt) {
|
||||
console.info(txt)
|
||||
output.textContent += `${txt.trim()}\n`
|
||||
}
|
||||
|
||||
// Listen for new peers
|
||||
libp2p.on('peer:discovery', (peerId) => {
|
||||
log(`Found peer ${peerId.toB58String()}`)
|
||||
})
|
||||
|
||||
// Listen for new connections to peers
|
||||
libp2p.connectionManager.on('peer:connect', (connection) => {
|
||||
log(`Connected to ${connection.remotePeer.toB58String()}`)
|
||||
})
|
||||
|
||||
// Listen for peers disconnecting
|
||||
libp2p.connectionManager.on('peer:disconnect', (connection) => {
|
||||
log(`Disconnected from ${connection.remotePeer.toB58String()}`)
|
||||
})
|
||||
|
||||
await libp2p.start()
|
||||
status.innerText = 'libp2p started!'
|
||||
log(`libp2p id is ${libp2p.peerId.toB58String()}`)
|
||||
|
||||
})
|
17
examples/webrtc-direct/index.html
Normal file
17
examples/webrtc-direct/index.html
Normal file
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>js-libp2p parcel.js browser example</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
<h1 id="status">Starting libp2p...</h1>
|
||||
</header>
|
||||
<main>
|
||||
<pre id="output"></pre>
|
||||
</main>
|
||||
<script src="./dialer.js"></script>
|
||||
</body>
|
||||
</html>
|
44
examples/webrtc-direct/listener.js
Normal file
44
examples/webrtc-direct/listener.js
Normal file
@ -0,0 +1,44 @@
|
||||
const Libp2p = require('libp2p')
|
||||
const Bootstrap = require('libp2p-bootstrap')
|
||||
const WebRTCDirect = require('libp2p-webrtc-direct')
|
||||
const Mplex = require('libp2p-mplex')
|
||||
const {NOISE} = require('libp2p-noise')
|
||||
const PeerId = require('peer-id')
|
||||
|
||||
;(async () => {
|
||||
// hardcoded peer id to avoid copy-pasting of listener's peer id into the dialer's bootstrap list
|
||||
// generated with cmd `peer-id --type=ed25519`
|
||||
const hardcodedPeerId = await PeerId.createFromJSON({
|
||||
"id": "12D3KooWCuo3MdXfMgaqpLC5Houi1TRoFqgK9aoxok4NK5udMu8m",
|
||||
"privKey": "CAESQAG6Ld7ev6nnD0FKPs033/j0eQpjWilhxnzJ2CCTqT0+LfcWoI2Vr+zdc1vwk7XAVdyoCa2nwUR3RJebPWsF1/I=",
|
||||
"pubKey": "CAESIC33FqCNla/s3XNb8JO1wFXcqAmtp8FEd0SXmz1rBdfy"
|
||||
})
|
||||
const node = await Libp2p.create({
|
||||
peerId: hardcodedPeerId,
|
||||
addresses: {
|
||||
listen: ['/ip4/127.0.0.1/tcp/9090/http/p2p-webrtc-direct']
|
||||
},
|
||||
modules: {
|
||||
transport: [WebRTCDirect],
|
||||
streamMuxer: [Mplex],
|
||||
connEncryption: [NOISE]
|
||||
},
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
[Bootstrap.tag]: {
|
||||
enabled: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
node.connectionManager.on('peer:connect', (connection) => {
|
||||
console.info(`Connected to ${connection.remotePeer.toB58String()}!`)
|
||||
})
|
||||
|
||||
await node.start()
|
||||
|
||||
console.log('Listening on:')
|
||||
node.multiaddrs.forEach((ma) => console.log(`${ma.toString()}/p2p/${node.peerId.toB58String()}`))
|
||||
|
||||
})()
|
31
examples/webrtc-direct/package.json
Normal file
31
examples/webrtc-direct/package.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "webrtc-direct",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"description": "",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"build": "parcel build index.html",
|
||||
"start": "parcel index.html"
|
||||
},
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.8.3",
|
||||
"@babel/core": "^7.8.3",
|
||||
"babel-plugin-syntax-async-functions": "^6.13.0",
|
||||
"babel-plugin-transform-regenerator": "^6.26.0",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"parcel-bundler": "^1.12.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"libp2p": "../../",
|
||||
"libp2p-bootstrap": "^0.12.1",
|
||||
"libp2p-mplex": "^0.10.1",
|
||||
"libp2p-noise": "^2.0.1",
|
||||
"libp2p-webrtc-direct": "^0.5.0",
|
||||
"peer-id": "^0.14.3"
|
||||
},
|
||||
"browser": {
|
||||
"ipfs": "ipfs/dist/index.min.js"
|
||||
}
|
||||
}
|
93
examples/webrtc-direct/test.js
Normal file
93
examples/webrtc-direct/test.js
Normal file
@ -0,0 +1,93 @@
|
||||
'use strict'
|
||||
|
||||
const path = require('path')
|
||||
const execa = require('execa')
|
||||
const pDefer = require('p-defer')
|
||||
const uint8ArrayToString = require('uint8arrays/to-string')
|
||||
const { chromium } = require('playwright');
|
||||
|
||||
function startNode (name, args = []) {
|
||||
return execa('node', [path.join(__dirname, name), ...args], {
|
||||
cwd: path.resolve(__dirname),
|
||||
all: true
|
||||
})
|
||||
}
|
||||
|
||||
function startBrowser (name, args = []) {
|
||||
return execa('parcel', [path.join(__dirname, name), ...args], {
|
||||
preferLocal: true,
|
||||
localDir: __dirname,
|
||||
cwd: __dirname,
|
||||
all: true
|
||||
})
|
||||
}
|
||||
|
||||
async function test () {
|
||||
// Step 1, listener process
|
||||
const listenerProcReady = pDefer()
|
||||
let listenerOutput = ''
|
||||
process.stdout.write('listener.js\n')
|
||||
const listenerProc = startNode('listener.js')
|
||||
|
||||
listenerProc.all.on('data', async (data) => {
|
||||
process.stdout.write(data)
|
||||
listenerOutput += uint8ArrayToString(data)
|
||||
if (listenerOutput.includes('Listening on:') && listenerOutput.includes('12D3KooWCuo3MdXfMgaqpLC5Houi1TRoFqgK9aoxok4NK5udMu8m')) {
|
||||
listenerProcReady.resolve()
|
||||
}
|
||||
})
|
||||
|
||||
await listenerProcReady.promise
|
||||
process.stdout.write('==================================================================\n')
|
||||
|
||||
// Step 2, dialer process
|
||||
process.stdout.write('dialer.js\n')
|
||||
let dialerUrl = ''
|
||||
const dialerProc = startBrowser('index.html')
|
||||
|
||||
dialerProc.all.on('data', async (chunk) => {
|
||||
/**@type {string} */
|
||||
const out = chunk.toString()
|
||||
|
||||
if (out.includes('Server running at')) {
|
||||
dialerUrl = out.replace('Server running at ', '')
|
||||
}
|
||||
|
||||
if (out.includes('✨ Built in ')) {
|
||||
try {
|
||||
const browser = await chromium.launch();
|
||||
const page = await browser.newPage();
|
||||
await page.goto(dialerUrl);
|
||||
await page.waitForFunction(selector => document.querySelector(selector).innerText === 'libp2p started!', '#status')
|
||||
await page.waitForFunction(
|
||||
selector => {
|
||||
const text = document.querySelector(selector).innerText
|
||||
return text.includes('libp2p id is') &&
|
||||
text.includes('Found peer') &&
|
||||
text.includes('Connected to')
|
||||
},
|
||||
'#output',
|
||||
{ timeout: 10000 }
|
||||
)
|
||||
await browser.close();
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
} finally {
|
||||
dialerProc.cancel()
|
||||
listenerProc.kill()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
await Promise.all([
|
||||
listenerProc,
|
||||
dialerProc,
|
||||
]).catch((err) => {
|
||||
if (err.signal !== 'SIGTERM') {
|
||||
throw err
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = test
|
Loading…
x
Reference in New Issue
Block a user