forked from libp2p/js-libp2p-webrtc
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into feat/64/export-metrics-reland
- Loading branch information
Showing
30 changed files
with
1,431 additions
and
551 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# js-libp2p-webrtc Browser to Browser | ||
|
||
This example leverages the [vite bundler](https://vitejs.dev/) to compile and serve the libp2p code in the browser. You can use other bundlers such as Webpack, but we will not be covering them here. | ||
|
||
## Build the `@libp2p/webrtc` package | ||
|
||
Build the `@libp2p/webrtc` package by calling `npm i && npm run build` in the repository root. | ||
|
||
## Running the Relay Server | ||
|
||
For browsers to communicate, we first need to run the LibP2P relay server: | ||
|
||
```shell | ||
npm run relay | ||
``` | ||
|
||
Copy one of the multiaddresses in the output. | ||
|
||
## Running the Example | ||
|
||
In a separate console tab, install dependencies and start the Vite server: | ||
|
||
```shell | ||
npm i && npm run start | ||
``` | ||
|
||
The browser window will automatically open. Let's call this `Browser A`. | ||
Using the copied multiaddress from the Go or NodeJS relay server, paste it into the `Remote MultiAddress` input and click the `Connect` button. | ||
`Browser A` is now connected to the relay server. | ||
Copy the multiaddress located after the `Listening on` message. | ||
|
||
Now open a second browser with the url `http://localhost:5173/`. Let's call this `Browser B`. | ||
Using the copied multiaddress from `Listening on` section in `Browser A`, paste it into the `Remote MultiAddress` input and click the `Connect` button. | ||
`Browser B` is now connected to `Browser A`. | ||
Copy the multiaddress located after the `Listening on` message. | ||
|
||
Using the copied multiaddress from `Listening on` section in `Browser B`, paste it into the `Remote MultiAddress` input in `Browser A` and click the `Connect` button. | ||
`Browser A` is now connected to `Browser B`. | ||
|
||
The peers are now connected to each other. Enter a message and click the `Send` button in either/both browsers and see the echo'd messages. | ||
|
||
The output should look like: | ||
|
||
`Browser A` | ||
```text | ||
Dialing '/ip4/127.0.0.1/tcp/57708/ws/p2p/12D3KooWRqAUEzPwKMoGstpfJVqr3aoinwKVPu4DLo9nQncbnuLk' | ||
Listening on /ip4/127.0.0.1/tcp/57708/ws/p2p/12D3KooWRqAUEzPwKMoGstpfJVqr3aoinwKVPu4DLo9nQncbnuLk/p2p-circuit/p2p/12D3KooW9wFiWFELqGJTbzEwtByXsPiHJdHB8n7Kin71VMYyERmC/p2p-webrtc-direct/p2p/12D3KooW9wFiWFELqGJTbzEwtByXsPiHJdHB8n7Kin71VMYyERmC | ||
Dialing '/ip4/127.0.0.1/tcp/57708/ws/p2p/12D3KooWRqAUEzPwKMoGstpfJVqr3aoinwKVPu4DLo9nQncbnuLk/p2p-circuit/p2p/12D3KooWBZyVLJfQkofqLK4op9TPkHuUumCZt1ybQrPvNm7TVQV9/p2p-webrtc-direct/p2p/12D3KooWBZyVLJfQkofqLK4op9TPkHuUumCZt1ybQrPvNm7TVQV9' | ||
Sending message 'helloa' | ||
Received message 'helloa' | ||
Received message 'hellob' | ||
``` | ||
|
||
`Browser B` | ||
```text | ||
Dialing '/ip4/127.0.0.1/tcp/57708/ws/p2p/12D3KooWRqAUEzPwKMoGstpfJVqr3aoinwKVPu4DLo9nQncbnuLk/p2p-circuit/p2p/12D3KooW9wFiWFELqGJTbzEwtByXsPiHJdHB8n7Kin71VMYyERmC/p2p-webrtc-direct/p2p/12D3KooW9wFiWFELqGJTbzEwtByXsPiHJdHB8n7Kin71VMYyERmC' | ||
Listening on /ip4/127.0.0.1/tcp/57708/ws/p2p/12D3KooWRqAUEzPwKMoGstpfJVqr3aoinwKVPu4DLo9nQncbnuLk/p2p-circuit/p2p/12D3KooWBZyVLJfQkofqLK4op9TPkHuUumCZt1ybQrPvNm7TVQV9/p2p-webrtc-direct/p2p/12D3KooWBZyVLJfQkofqLK4op9TPkHuUumCZt1ybQrPvNm7TVQV9 | ||
Received message 'helloa' | ||
Sending message 'hellob' | ||
Received message 'hellob' | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>js-libp2p WebRTC</title> | ||
<style> | ||
label, | ||
button { | ||
display: block; | ||
font-weight: bold; | ||
margin: 5px 0; | ||
} | ||
div { | ||
margin-bottom: 20px; | ||
} | ||
#send-section { | ||
display: none; | ||
} | ||
input[type="text"] { | ||
width: 800px; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<div id="app"> | ||
<div> | ||
<label for="peer">Remote MultiAddress:</label> | ||
<input type="text" id="peer" /> | ||
<button id="connect">Connect</button> | ||
</div> | ||
<div id="send-section"> | ||
<label for="message">Message:</label> | ||
<input type="text" id="message" value="hello" /> | ||
<button id="send">Send</button> | ||
</div> | ||
<div id="connectionsWrapper"> | ||
<h3> Active Connections: </h3> | ||
<ul id="connections"></ul> | ||
</div> | ||
<div id="connected_peer"></div> | ||
<div id="output"></div> | ||
</div> | ||
<script type="module" src="./index.js"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
import { multiaddr, protocols } from "@multiformats/multiaddr" | ||
import { pipe } from "it-pipe" | ||
import { fromString, toString } from "uint8arrays" | ||
import { webRTC } from "js-libp2p-webrtc" | ||
import { webSockets } from "@libp2p/websockets" | ||
import * as filters from "@libp2p/websockets/filters" | ||
import { pushable } from "it-pushable" | ||
import { mplex } from "@libp2p/mplex" | ||
import { createLibp2p } from "libp2p" | ||
import { circuitRelayTransport } from 'libp2p/circuit-relay' | ||
import { noise } from "@chainsafe/libp2p-noise" | ||
|
||
let webrtcDirectAddress | ||
|
||
const CIRCUIT_RELAY_CODE = 290 | ||
const WEBRTC_CODE = 281 | ||
|
||
const output = document.getElementById("output") | ||
const sendSection = document.getElementById("send-section") | ||
const peer = document.getElementById("peer") | ||
const appendOutput = (line) => { | ||
const div = document.createElement("div") | ||
div.appendChild(document.createTextNode(line)) | ||
output.append(div) | ||
} | ||
const clean = (line) => line.replaceAll("\n", "") | ||
const sender = pushable() | ||
|
||
const node = await createLibp2p({ | ||
transports: [ | ||
webSockets({ | ||
filter: filters.all, | ||
}), | ||
webRTC({}), | ||
circuitRelayTransport({ | ||
discoverRelays: 1, | ||
}), | ||
], | ||
connectionEncryption: [noise()], | ||
streamMuxers: [mplex()], | ||
}) | ||
|
||
await node.start() | ||
|
||
// handle the echo protocol | ||
await node.handle("/echo/1.0.0", ({ stream }) => { | ||
console.log("incoming stream") | ||
pipe( | ||
stream, | ||
async function* (source) { | ||
for await (const buf of source) { | ||
const incoming = toString(buf.subarray()) | ||
appendOutput(`Received message '${clean(incoming)}'`) | ||
yield buf | ||
} | ||
}, | ||
stream | ||
) | ||
}) | ||
|
||
function updateConnList() { | ||
// Update connections list | ||
const connListEls = node.getConnections() | ||
.map((connection) => { return connection.remoteAddr.toString() }) | ||
.map((addr) => { | ||
const el = document.createElement("li") | ||
el.textContent = addr | ||
return el | ||
}) | ||
document.getElementById("connections").replaceChildren(...connListEls) | ||
} | ||
|
||
node.addEventListener("peer:connect", (event) => { | ||
updateConnList() | ||
}) | ||
node.addEventListener("peer:disconnect", (event) => { | ||
updateConnList() | ||
}) | ||
|
||
node.peerStore.addEventListener("change:multiaddrs", (event) => { | ||
const { peerId } = event.detail | ||
|
||
if (node.getMultiaddrs().length === 0 || !node.peerId.equals(peerId)) { | ||
return | ||
} | ||
|
||
node.getMultiaddrs().forEach((ma) => { | ||
if (ma.protoCodes().includes(CIRCUIT_RELAY_CODE)) { | ||
if (ma.protos().pop()?.name === 'p2p') { | ||
ma = ma.decapsulateCode(protocols('p2p').code) | ||
} | ||
const newWebrtcDirectAddress = multiaddr(ma.toString() + '/webrtc/p2p/' + node.peerId) | ||
|
||
const webrtcAddrString = newWebrtcDirectAddress.toString() | ||
|
||
// only update if the address is new | ||
if (newWebrtcDirectAddress?.toString() !== webrtcDirectAddress?.toString()) { | ||
appendOutput(`Listening on '${webrtcAddrString}'`) | ||
sendSection.style.display = "block" | ||
webrtcDirectAddress = newWebrtcDirectAddress | ||
connected_peer.innerText = webrtcDirectAddress | ||
} | ||
} | ||
}) | ||
}) | ||
|
||
const isWebrtc = (ma) => { | ||
return ma.protoCodes().includes(WEBRTC_CODE) | ||
} | ||
|
||
window.connect.onclick = async () => { | ||
const ma = multiaddr(window.peer.value) | ||
appendOutput(`Dialing '${ma}'`) | ||
const connection = await node.dial(ma) | ||
|
||
if (!isWebrtc(ma)) { | ||
return | ||
} | ||
|
||
const outgoing_stream = await connection.newStream(["/echo/1.0.0"]) | ||
|
||
pipe(sender, outgoing_stream, async (src) => { | ||
for await (const buf of src) { | ||
const response = toString(buf.subarray()) | ||
appendOutput(`Received message '${clean(response)}'`) | ||
} | ||
}) | ||
} | ||
|
||
window.send.onclick = async () => { | ||
const message = `${window.message.value}\n` | ||
appendOutput(`Sending message '${clean(message)}'`) | ||
sender.push(fromString(message)) | ||
} |
Oops, something went wrong.