Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
ca7c9bf
initial transport
ckousik Jul 8, 2022
8412622
Implement webrtc transport
ckousik Jul 12, 2022
a90bb53
update interfaces
ckousik Jul 12, 2022
f642485
cleanup
ckousik Jul 12, 2022
18d3baa
create a negotiated datachannel on the listener
ckousik Jul 12, 2022
c2de6cf
Use uuid as ufrag instead of DTLS fingerprint
ckousik Jul 12, 2022
a5a9e6b
address review
ckousik Jul 25, 2022
a0c0a8a
read/write deadlines
ckousik Jul 25, 2022
121fc9a
fix streams
ckousik Jul 25, 2022
853f90a
change privkey algorithm to ecdsa p224
ckousik Jul 25, 2022
7a1bf7f
switch to updated multiformats
ckousik Jul 27, 2022
f161056
change mtu
ckousik Jul 29, 2022
82b4fff
use noise prologue mechanism
ckousik Aug 15, 2022
bc879d4
debug
ckousik Aug 15, 2022
c0b2a84
fix staticcheck
ckousik Aug 15, 2022
d6cd3a3
log
ckousik Aug 15, 2022
9b55ae4
change multibase to b58btc
ckousik Aug 16, 2022
5ef0b92
fix tests on non-linux systems
ckousik Aug 16, 2022
382bb88
fix windows
ckousik Aug 16, 2022
3f16cf5
fix dialer ip in linux
ckousik Aug 16, 2022
2bdc93c
fix race condition in accepting streams
ckousik Aug 26, 2022
17e16d1
use message callback instead of detached data channels
ckousik Sep 6, 2022
e7f3d9e
resets
ckousik Sep 6, 2022
2c506c6
fix libp2p core
ckousik Sep 6, 2022
0cd637e
fix imports
ckousik Sep 6, 2022
5b6a345
update protobuf
ckousik Sep 6, 2022
0896819
fix atomics
ckousik Sep 6, 2022
15eae54
fix main
ckousik Sep 8, 2022
1fd841d
fix
ckousik Sep 9, 2022
e4143f7
bind webrtc example to correct interface
ckousik Sep 9, 2022
8d194a2
match webrtc listener ufrag pwd to spec
ckousik Sep 12, 2022
f3ef762
make fixes
ckousik Sep 13, 2022
00770d0
remove example
ckousik Sep 13, 2022
12732c2
fix dtls failure test
ckousik Sep 13, 2022
7b6db78
cleanup datachannels
ckousik Sep 13, 2022
bac8ff4
fix deadline tests running until timeout
ckousik Sep 13, 2022
cff28c1
fix error condition
ckousik Sep 13, 2022
8103da3
lagging listener
ckousik Sep 14, 2022
37e5686
cleanup dialer and listener
ckousik Sep 14, 2022
700949e
cleanup
ckousik Sep 14, 2022
3aaed7c
fmt listener.go
ckousik Sep 14, 2022
56d7ca0
add logging to tests
ckousik Sep 14, 2022
1e0375f
add logging to tests
ckousik Sep 14, 2022
54f9535
use backpressure in sctp layer
ckousik Oct 9, 2022
559c292
go mod tidy
ckousik Oct 9, 2022
894e6a8
reset?
ckousik Oct 9, 2022
6c3bf8a
state transitions
ckousik Oct 12, 2022
6a01cfe
Attempting to include webrtc in example
plauche Oct 12, 2022
8c61bae
'correct' import url
plauche Oct 12, 2022
58be936
updated example
plauche Oct 13, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/webrtc-echo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
echo
52 changes: 52 additions & 0 deletions examples/webrtc-echo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Echo client/server with libp2p

This is an example that quickly shows how to use the `go-libp2p` stack, including Host/Basichost, Network/Swarm, Streams, Peerstores and Multiaddresses.

This example can be started in either listen mode, or dial mode.

In listen mode, it will sit and wait for incoming connections on the `/echo/1.0.0` protocol. Whenever it receives a stream, it will write the message `"Hello, world!"` over the stream and close it.

In dial mode, the node will start up, connect to the given address, open a stream to the target peer, and read a message on the protocol `/echo/1.0.0`.

## Build

From the `go-libp2p/examples` directory run the following:

```
> cd echo/
> go build
```

## Usage

```
> ./echo -l 10000
2017/03/15 14:11:32 I am /ip4/127.0.0.1/tcp/10000/p2p/QmYo41GybvrXk8y8Xnm1P7pfA4YEXCpfnLyzgRPnNbG35e
2017/03/15 14:11:32 Now run "./echo -l 10001 -d /ip4/127.0.0.1/tcp/10000/p2p/QmYo41GybvrXk8y8Xnm1P7pfA4YEXCpfnLyzgRPnNbG35e" on a different terminal
2017/03/15 14:11:32 listening for connections
```

The listener libp2p host will print its `Multiaddress`, which indicates how it can be reached (ip4+tcp) and its randomly generated ID (`QmYo41Gyb...`)

Now, launch another node that talks to the listener:

```
> ./echo -l 10001 -d /ip4/127.0.0.1/tcp/10000/p2p/QmYo41GybvrXk8y8Xnm1P7pfA4YEXCpfnLyzgRPnNbG35e
```

The new node with send the message `"Hello, world!"` to the listener, which will in turn echo it over the stream and close it. The listener logs the message, and the sender logs the response.

## Details

The `makeBasicHost()` function creates a [go-libp2p-basichost](https://godoc.org/github.com/libp2p/go-libp2p/p2p/host/basic) object. `basichost` objects wrap [go-libp2p swarms](https://godoc.org/github.com/libp2p/go-libp2p-swarm#Swarm) and should be used preferentially. A [go-libp2p-swarm Network](https://godoc.org/github.com/libp2p/go-libp2p-swarm#Network) is a `swarm` which complies to the [go-libp2p-net Network interface](https://godoc.org/github.com/libp2p/go-libp2p-net#Network) and takes care of maintaining streams, connections, multiplexing different protocols on them, handling incoming connections etc.

In order to create the swarm (and a `basichost`), the example needs:

- An [ipfs-procotol ID](https://godoc.org/github.com/libp2p/go-libp2p-peer#ID) like `QmNtX1cvrm2K6mQmMEaMxAuB4rTexhd87vpYVot4sEZzxc`. The example autogenerates a key pair on every run and uses an ID extracted from the public key (the hash of the public key). When using `-insecure`, it leaves the connection unencrypted (otherwise, it uses the key pair to encrypt communications).
- A [Multiaddress](https://godoc.org/github.com/multiformats/go-multiaddr), which indicates how to reach this peer. There can be several of them (using different protocols or locations for example). Example: `/ip4/127.0.0.1/tcp/1234`.
- A [go-libp2p-peerstore](https://godoc.org/github.com/libp2p/go-libp2p-peerstore), which is used as an address book which matches node IDs to the multiaddresses through which they can be contacted. This peerstore gets autopopulated when manually opening a connection (with [`Connect()`](https://godoc.org/github.com/libp2p/go-libp2p/p2p/host/basic#BasicHost.Connect). Alternatively, we can manually [`AddAddr()`](https://godoc.org/github.com/libp2p/go-libp2p-peerstore#AddrManager.AddAddr) as in the example.

A `basichost` can now open streams (bi-directional channel between two peers) using [NewStream](https://godoc.org/github.com/libp2p/go-libp2p/p2p/host/basic#BasicHost.NewStream) and use them to send and receive data tagged with a `Protocol.ID` (a string). The host can also listen for incoming connections for a given
`Protocol` with [`SetStreamHandle()`](https://godoc.org/github.com/libp2p/go-libp2p/p2p/host/basic#BasicHost.SetStreamHandler).

The example makes use of all of this to enable communication between a listener and a sender using protocol `/echo/1.0.0` (which could be any other thing).
140 changes: 140 additions & 0 deletions examples/webrtc-echo/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package main

import (
"bufio"
"fmt"
"log"
"net"
"os"
"os/signal"
"syscall"

"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p/core/host"
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
webrtc "github.com/libp2p/go-libp2p/p2p/transport/webrtc"
)

var listenerIp = net.IPv4(0, 0, 0, 0)

func init() {
ifaces, err := net.Interfaces()
if err != nil {
return
}
for _, iface := range ifaces {
if iface.Flags&net.FlagUp == 0 {
continue
}
addrs, err := iface.Addrs()
if err != nil {
return
}
for _, addr := range addrs {
// bind to private non-loopback ip
if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && ipnet.IP.IsPrivate() {
if ipnet.IP.To4() != nil {
listenerIp = ipnet.IP.To4()
return
}
}
}
}
}

func echoHandler(stream network.Stream) {
for {
reader := bufio.NewReader(stream)
str, err := reader.ReadString('\n')
if err != nil {
return
}
log.Printf("echo: %s", str)
_, err = stream.Write([]byte(str))
if err != nil {
return
}

}
}

func main() {
host := createHost()
host.SetStreamHandler("/echo/1.0.0", echoHandler)
defer host.Close()
remoteInfo := peer.AddrInfo{
ID: host.ID(),
Addrs: host.Network().ListenAddresses(),
}

remoteAddrs, _ := peer.AddrInfoToP2pAddrs(&remoteInfo)
fmt.Println("p2p addr: ", remoteAddrs[0])

fmt.Println("press Ctrl+C to quit")
ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT)
<-ch
}

func createHost() host.Host {
h, err := libp2p.New(
libp2p.Transport(webrtc.New),
libp2p.ListenAddrStrings(
fmt.Sprintf("/ip4/%s/udp/0/webrtc", listenerIp),
),
libp2p.DisableRelay(),
libp2p.Ping(true),
)
if err != nil {
panic(err)
}

return h
}

// func dialHost(ctx context.Context, server host.Host) {
// client, err := libp2p.New(
// libp2p.Transport(webrtc.New),
// libp2p.DisableRelay(),
// libp2p.Ping(true),
// )
// if err != nil {
// panic(err)
// }

// if err = server.ID().Validate(); err != nil {
// panic(err)
// }

// remoteInfo := peer.AddrInfo{
// ID: server.ID(),
// Addrs: server.Network().ListenAddresses(),
// }

// remoteAddrs, err := peer.AddrInfoToP2pAddrs(&remoteInfo)
// fmt.Println("p2p addr: ", remoteAddrs)

// fmt.Println("=========================== connecting ==============================")
// err = client.Connect(context.Background(), remoteInfo)
// if err != nil {
// panic(err)
// }
// fmt.Println("============================ connected ==============================")

// resultChan := ping.Ping(ctx, server, server.ID())

// for i := 0; i < 5; i++ {
// select {
// case <-ctx.Done():
// case result := <-resultChan:
// if result.Error != nil {
// fmt.Println("ping error", result.Error)
// } else {
// fmt.Println("pinged", remoteInfo.Addrs, " in ", result.RTT)
// }
// }

// }

// }
58 changes: 58 additions & 0 deletions examples/webrtc-echo/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package main

import (
"context"
"log"
"testing"

"github.com/libp2p/go-libp2p/examples/testutils"
)

func TestMain(t *testing.T) {
var h testutils.LogHarness
h.Expect("listening for connections")
h.Expect("sender opening stream")
h.Expect("sender saying hello")
h.Expect("listener received new stream")
h.Expect("read: Hello, world!")
h.Expect(`read reply: "Hello, world!\n"`)

h.Run(t, func() {
// Create a context that will stop the hosts when the tests end
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

// Get a tcp port for the listener
lport, err := testutils.FindFreePort(t, "", 5)
if err != nil {
log.Println(err)
return
}

// Get a tcp port for the sender
sport, err := testutils.FindFreePort(t, "", 5)
if err != nil {
log.Println(err)
return
}

// Make listener
lh, err := makeBasicHost(lport, true, 1)
if err != nil {
log.Println(err)
return
}

startListener(ctx, lh, lport, true)

// Make sender
listenAddr := getHostAddress(lh)
sh, err := makeBasicHost(sport, true, 2)
if err != nil {
log.Println(err)
return
}

runSender(ctx, sh, listenAddr)
})
}
Binary file added examples/webrtc-echo/webrtc-echo
Binary file not shown.
34 changes: 26 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/gogo/protobuf v1.3.2
github.com/golang/mock v1.6.0
github.com/google/gopacket v1.1.19
github.com/google/uuid v1.3.0
github.com/gorilla/websocket v1.5.0
github.com/hashicorp/golang-lru v0.5.4
github.com/ipfs/go-cid v0.3.2
Expand Down Expand Up @@ -47,41 +48,48 @@ require (
github.com/multiformats/go-multistream v0.3.3
github.com/multiformats/go-varint v0.0.6
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58
github.com/pion/datachannel v1.5.2
github.com/pion/dtls/v2 v2.1.5
github.com/pion/ice/v2 v2.2.6
github.com/pion/logging v0.2.2
github.com/pion/stun v0.3.5
github.com/pion/transport v0.13.1
github.com/pion/webrtc/v3 v3.1.43
github.com/prometheus/client_golang v1.13.0
github.com/raulk/go-watchdog v1.3.0
github.com/stretchr/testify v1.8.0
go.opencensus.io v0.23.0
go.uber.org/goleak v1.1.12
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90
golang.org/x/sync v0.0.0-20220907140024-f12130a52804
golang.org/x/sys v0.0.0-20220913175220-63ea55921009
)

require (
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash v1.1.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/containerd/cgroups v1.0.4 // indirect
github.com/coreos/go-systemd/v22 v22.4.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgraph-io/badger v1.6.2 // indirect
github.com/dgraph-io/ristretto v0.0.2 // indirect
github.com/dgraph-io/ristretto v0.1.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/elastic/gosigar v0.14.2 // indirect
github.com/francoispqt/gojay v1.2.13 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/golang/glog v1.0.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/huin/goupnp v1.0.3 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/goprocess v0.1.4 // indirect
github.com/klauspost/cpuid/v2 v2.1.1 // indirect
github.com/koron/go-ssdp v0.0.3 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/libp2p/go-cidranger v1.1.0 // indirect
github.com/marten-seemann/qpack v0.2.1 // indirect
github.com/marten-seemann/qtls-go1-18 v0.1.2 // indirect
Expand All @@ -95,14 +103,24 @@ require (
github.com/nxadm/tail v1.4.8 // indirect
github.com/onsi/ginkgo v1.16.5 // indirect
github.com/opencontainers/runtime-spec v1.0.2 // indirect
github.com/pion/interceptor v0.1.12 // indirect
github.com/pion/mdns v0.0.5 // indirect
github.com/pion/randutil v0.1.0 // indirect
github.com/pion/rtcp v1.2.10 // indirect
github.com/pion/rtp v1.7.13 // indirect
github.com/pion/sctp v1.8.2 // indirect
github.com/pion/sdp/v3 v3.0.6 // indirect
github.com/pion/srtp/v2 v2.0.10 // indirect
github.com/pion/turn/v2 v2.0.8 // indirect
github.com/pion/udp v0.1.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/syndtr/goleveldb v1.0.0 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.23.0 // indirect
Expand Down
Loading