Skip to content

Commit

Permalink
Merge branch 'main' into feat/64/export-metrics-reland
Browse files Browse the repository at this point in the history
  • Loading branch information
maschad committed Apr 23, 2023
2 parents f4a4bd1 + ffaab58 commit 835efc4
Show file tree
Hide file tree
Showing 30 changed files with 1,431 additions and 551 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ jobs:
matrix:
project:
- browser-to-server
- browser-to-browser
defaults:
run:
working-directory: examples/${{ matrix.project }}
Expand All @@ -30,7 +31,7 @@ jobs:
node-version: lts/*
- uses: actions/setup-go@v3
with:
go-version: '>=1.19.0'
go-version: '1.19'
- name: Install dependencies
run: npm install
working-directory: .
Expand All @@ -44,4 +45,4 @@ jobs:
- name: Run tests
run: npm run test
env:
CI: true
CI: true
65 changes: 65 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,68 @@
## [1.1.6](https://github.com/libp2p/js-libp2p-webrtc/compare/v1.1.5...v1.1.6) (2023-04-21)


### Bug Fixes

* readme: Remove confusing section ([#122](https://github.com/libp2p/js-libp2p-webrtc/issues/122)) ([dc78154](https://github.com/libp2p/js-libp2p-webrtc/commit/dc781543b8175c6c40c6745029a4ba53587aef29))

## [1.1.5](https://github.com/libp2p/js-libp2p-webrtc/compare/v1.1.4...v1.1.5) (2023-04-13)


### Dependencies

* bump it-pipe from 2.0.5 to 3.0.1 ([#111](https://github.com/libp2p/js-libp2p-webrtc/issues/111)) ([7e593a3](https://github.com/libp2p/js-libp2p-webrtc/commit/7e593a34b44b7a2cf4758df2218b3ba9ebacfce9))
* bump protons-runtime from 4.0.2 to 5.0.0 ([#117](https://github.com/libp2p/js-libp2p-webrtc/issues/117)) ([87cbb19](https://github.com/libp2p/js-libp2p-webrtc/commit/87cbb193e2a45642333498d9317ab17eb527d34d))
* **dev:** bump protons from 6.1.3 to 7.0.2 ([#119](https://github.com/libp2p/js-libp2p-webrtc/issues/119)) ([fd20f4f](https://github.com/libp2p/js-libp2p-webrtc/commit/fd20f4f7a182a8edca5a511fe747885d24a60652))

## [1.1.4](https://github.com/libp2p/js-libp2p-webrtc/compare/v1.1.3...v1.1.4) (2023-04-13)


### Dependencies

* Update multiaddr to 12.1.1 and multiformats 11.0.2 ([#123](https://github.com/libp2p/js-libp2p-webrtc/issues/123)) ([e069784](https://github.com/libp2p/js-libp2p-webrtc/commit/e069784229f2495b3cebc2c2a85969f23f0e7acf))

## [1.1.3](https://github.com/libp2p/js-libp2p-webrtc/compare/v1.1.2...v1.1.3) (2023-04-12)


### Dependencies

* bump @libp2p/interface-connection from 3.1.1 to 4.0.0 ([#124](https://github.com/libp2p/js-libp2p-webrtc/issues/124)) ([4146761](https://github.com/libp2p/js-libp2p-webrtc/commit/4146761226118268d510c8834f894083ba5408d3))

## [1.1.2](https://github.com/libp2p/js-libp2p-webrtc/compare/v1.1.1...v1.1.2) (2023-04-11)


### Bug Fixes

* update multiaddr in webrtc connection to include webRTC ([#121](https://github.com/libp2p/js-libp2p-webrtc/issues/121)) ([6ea04db](https://github.com/libp2p/js-libp2p-webrtc/commit/6ea04db9800259963affcb3101ea542de79271c0))

## [1.1.1](https://github.com/libp2p/js-libp2p-webrtc/compare/v1.1.0...v1.1.1) (2023-04-10)


### Dependencies

* bump it-pb-stream from 2.0.4 to 3.2.1 ([#118](https://github.com/libp2p/js-libp2p-webrtc/issues/118)) ([7e2ac67](https://github.com/libp2p/js-libp2p-webrtc/commit/7e2ac6795ea096b3cf5dc2c4077f6f39821e0502))

## [1.1.0](https://github.com/libp2p/js-libp2p-webrtc/compare/v1.0.5...v1.1.0) (2023-04-07)


### Features

* Browser to Browser ([#90](https://github.com/libp2p/js-libp2p-webrtc/issues/90)) ([add5c46](https://github.com/libp2p/js-libp2p-webrtc/commit/add5c467a2d02058933e6e11751af0c850568eaf))

## [1.0.5](https://github.com/libp2p/js-libp2p-webrtc/compare/v1.0.4...v1.0.5) (2023-03-30)


### Bug Fixes

* correction package.json exports types path ([#103](https://github.com/libp2p/js-libp2p-webrtc/issues/103)) ([c78851f](https://github.com/libp2p/js-libp2p-webrtc/commit/c78851fe71f6a6ca79a146a7022e818378ea6721))


### Trivial Changes

* replace err-code with CodeError ([#82](https://github.com/libp2p/js-libp2p-webrtc/issues/82)) ([cfa6494](https://github.com/libp2p/js-libp2p-webrtc/commit/cfa6494c43c4edb977e70abe81a260bf0e03de73))
* Update .github/workflows/semantic-pull-request.yml [skip ci] ([f0ae5e7](https://github.com/libp2p/js-libp2p-webrtc/commit/f0ae5e78a0469bd1129d7b242e4fb41f0b2ed49e))
* Update .github/workflows/semantic-pull-request.yml [skip ci] ([4c8806c](https://github.com/libp2p/js-libp2p-webrtc/commit/4c8806c6d2a1a8eff48f0e2248203d48bd84c065))

## [1.0.4](https://github.com/libp2p/js-libp2p-webrtc/compare/v1.0.3...v1.0.4) (2023-02-22)


Expand Down
28 changes: 4 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,30 +75,10 @@ Examples can be found in the [examples folder](examples/README.md).

![https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-transport](https://raw.githubusercontent.com/libp2p/js-libp2p-interfaces/master/packages/interface-transport/img/badge.png)

Browsers can only `dial`, so `listen` is not supported.

```js
interface Transport {
[Symbol.toStringTag]: string
[symbol]: true
dial: (ma: Multiaddr, options: DialOptions) => Promise<Connection>
createListener: (options: CreateListenerOptions) => Listener
filter: MultiaddrFilter
}

class WebRTCTransport implements Transport {

async dial (ma: Multiaddr, options: WebRTCDialOptions): Promise<Connection> {
const rawConn = await this._connect(ma, options)
log(`dialing address - ${ma.toString()}`)
return rawConn
}

createListener (options: CreateListenerOptions): Listener {
throw unimplemented('WebRTCTransport.createListener')
}
}
```
Browsers can usually only `dial`, but `listen` is supported in the WebRTC
transport when paired with another listener like CircuitV2, where you listen on
a relayed connection. Take a look at [index.js](examples/browser-to-browser/index.js) for
an example.

### Connection

Expand Down
61 changes: 61 additions & 0 deletions examples/browser-to-browser/README.md
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'
```
46 changes: 46 additions & 0 deletions examples/browser-to-browser/index.html
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>
134 changes: 134 additions & 0 deletions examples/browser-to-browser/index.js
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))
}
Loading

0 comments on commit 835efc4

Please sign in to comment.