Skip to content

Commit

Permalink
feat: using relay server instead of direct connection
Browse files Browse the repository at this point in the history
Signed-off-by: Minh Huy Tran <[email protected]>
  • Loading branch information
NhoxxKienn committed May 6, 2024
1 parent a2bfb47 commit af21343
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 47 deletions.
37 changes: 35 additions & 2 deletions p2p/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,23 @@ import (
"context"
"crypto/sha256"
"math/rand"
"net"

"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/peer"
ma "github.com/multiformats/go-multiaddr"
"github.com/pkg/errors"
"perun.network/go-perun/wire"
)

const relayID = "QmVCPfUMr98PaaM8qbAQBgJ9jqc7XHpGp7AsyragdFDmgm"

// Account represents a libp2p wire account.
type Account struct {
host.Host
relayAddr string
privateKey crypto.PrivKey
}

Expand All @@ -41,6 +47,29 @@ func (acc *Account) Sign(data []byte) ([]byte, error) {

// NewRandomAccount generates a new random account.
func NewRandomAccount(rng *rand.Rand) *Account {
id, err := peer.Decode(relayID)
if err != nil {
err = errors.WithMessage(err, "decoding peer id of relay server")
return nil
}

// Get the IP address of the relay server.
ip, err := net.LookupIP("relay.perun.network")
if err != nil {
panic(errors.WithMessage(err, "looking up IP address of relay.perun.network"))
}
relayAddr := "/ip4/" + ip[0].String() + "/tcp/5574"

relayMultiaddr, err := ma.NewMultiaddr(relayAddr)
if err != nil {
panic(errors.WithMessage(err, "parsing relay multiadress"))
}

relayInfo := peer.AddrInfo{
ID: id,
Addrs: []ma.Multiaddr{relayMultiaddr},
}

// Creates a new RSA key pair for this host.
prvKey, _, err := crypto.GenerateKeyPairWithReader(crypto.RSA, 2048, rng)
if err != nil {
Expand All @@ -53,10 +82,14 @@ func NewRandomAccount(rng *rand.Rand) *Account {
client, err := libp2p.New(
context.Background(),
libp2p.Identity(prvKey),
libp2p.EnableRelay(),
)

if err != nil {
panic(err)
}
return &Account{client, prvKey}

if err := client.Connect(context.Background(), relayInfo); err != nil {
panic(errors.WithMessage(err, "connecting to the relay server"))
}
return &Account{client, relayAddr, prvKey}
}
26 changes: 3 additions & 23 deletions p2p/bus.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
package p2p

import (
"github.com/libp2p/go-libp2p-core/host"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/multiformats/go-multiaddr"
"github.com/pkg/errors"
"perun.network/go-perun/wire/net"
perunio "perun.network/go-perun/wire/perunio/serializer"
)
Expand All @@ -14,30 +10,14 @@ type Net struct {
*net.Bus
*Listener
*Dialer
MultiAddr string
PeerID string
}

// NewP2PBus creates a dialer, listener, and a bus for the given account `acc`
// and includes them in the returned P2P Net.
func NewP2PBus(acc *Account) (*Net, error) {
listener := NewP2PListener(acc)
dialer := NewP2PDialer(acc)
dialer := NewP2PDialer(acc, relayID, acc.relayAddr)
bus := net.NewBus(acc, dialer, perunio.Serializer())

multiAddr, err := getHostMA(acc)
if err != nil {
return nil, err
}

return &Net{Bus: bus, Dialer: dialer, Listener: listener, MultiAddr: multiAddr.String()}, nil
}

// getHostMA returns the first multiaddress of the given host.
func getHostMA(host host.Host) (multiaddr.Multiaddr, error) {
peerInfo := peer.AddrInfo{
ID: host.ID(),
Addrs: host.Addrs(),
}
addrs, err := peer.AddrInfoToP2pAddrs(&peerInfo)
return addrs[0], errors.Wrap(err, "converting peer info to multiaddress")
return &Net{Bus: bus, Dialer: dialer, Listener: listener, PeerID: acc.ID().String()}, nil
}
40 changes: 25 additions & 15 deletions p2p/dialer.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,33 +15,43 @@ import (

// Dialer is a dialer for p2p connections.
type Dialer struct {
mutex sync.RWMutex // Protects peers.
peers map[wire.AddrKey]string
host host.Host
closer pkgsync.Closer
mutex sync.RWMutex // Protects peers.
peers map[wire.AddrKey]string
host host.Host
relayID string
relayAddr string
closer pkgsync.Closer
}

// NewP2PDialer creates a new dialer for the given account.
func NewP2PDialer(acc *Account) *Dialer {
func NewP2PDialer(acc *Account, relayID string, relayAddr string) *Dialer {
return &Dialer{
host: acc,
peers: make(map[wire.AddrKey]string),
host: acc,
relayID: relayID,
relayAddr: relayAddr,
peers: make(map[wire.AddrKey]string),
}
}

// Dial implements Dialer.Dial().
func (d *Dialer) Dial(ctx context.Context, addr wire.Address, serializer wire.EnvelopeSerializer) (wirenet.Conn, error) {
peerMA, ok := d.get(wire.Key(addr))
peerID, ok := d.get(wire.Key(addr))
if !ok {
return nil, errors.New("peer not found")
}

_peerMA, err := ma.NewMultiaddr(peerMA)
_peerID, err := peer.Decode(peerID)
if err != nil {
return nil, errors.Wrap(err, "peer ID is not valid")
}

fullAddr := d.relayAddr + "/p2p/" + d.relayID + "/p2p-circuit/p2p/" + _peerID.String()
peerMultiAddr, err := ma.NewMultiaddr(fullAddr)
if err != nil {
return nil, errors.Wrap(err, "failed to parse multiaddress of peer")
}

peerAddrInfo, err := peer.AddrInfoFromP2pAddr(_peerMA)
peerAddrInfo, err := peer.AddrInfoFromP2pAddr(peerMultiAddr)
if err != nil {
return nil, errors.Wrap(err, "converting peer multiaddress to address info")
}
Expand All @@ -57,12 +67,12 @@ func (d *Dialer) Dial(ctx context.Context, addr wire.Address, serializer wire.En
return wirenet.NewIoConn(s, serializer), nil
}

// Register registers a p2p multiaddress for a peer wire address.
func (d *Dialer) Register(addr wire.Address, p2pAddress string) {
// Register registers a p2p peer id for a peer wire address.
func (d *Dialer) Register(addr wire.Address, peerID string) {
d.mutex.Lock()
defer d.mutex.Unlock()

d.peers[wire.Key(addr)] = p2pAddress
d.peers[wire.Key(addr)] = peerID
}

// Close closes the dialer by closing the underlying libp2p host.
Expand All @@ -74,9 +84,9 @@ func (d *Dialer) Close() error {
}

// get returns the p2p multiaddress for the given address if registered.
func (d *Dialer) get(addr wire.AddrKey) (p2pAddress string, ok bool) {
func (d *Dialer) get(addr wire.AddrKey) (peerID string, ok bool) {
d.mutex.RLock()
defer d.mutex.RUnlock()
p2pAddress, ok = d.peers[addr]
peerID, ok = d.peers[addr]
return
}
13 changes: 6 additions & 7 deletions p2p/dialer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
func TestNewDialer(t *testing.T) {
h := getHost(t)

d := NewP2PDialer(h)
d := NewP2PDialer(h, relayID, h.relayAddr)
assert.NotNil(t, d)
d.Close()
}
Expand All @@ -28,7 +28,7 @@ func TestDialer_Register(t *testing.T) {
addr := NewRandomAddress(rng)
key := wire.Key(addr)
h := getHost(t)
d := NewP2PDialer(h)
d := NewP2PDialer(h, relayID, h.relayAddr)
defer d.Close()

_, ok := d.get(key)
Expand All @@ -47,15 +47,14 @@ func TestDialer_Dial(t *testing.T) {

lHost := getHost(t)
lAddr := lHost.Address()
lP2PAddr, err := getHostMA(lHost)
require.NoError(t, err)
lpeerID := lHost.ID()
listener := NewP2PListener(lHost)
defer listener.Close()

dHost := getHost(t)
dAddr := dHost.Address()
dialer := NewP2PDialer(dHost)
dialer.Register(lAddr, lP2PAddr.String())
dialer := NewP2PDialer(dHost, relayID, dHost.relayAddr)
dialer.Register(lAddr, lpeerID.String())
defer dialer.Close()

t.Run("happy", func(t *testing.T) {
Expand Down Expand Up @@ -122,7 +121,7 @@ func TestDialer_Dial(t *testing.T) {
func TestDialer_Close(t *testing.T) {
t.Run("double close", func(t *testing.T) {
h := getHost(t)
d := NewP2PDialer(h)
d := NewP2PDialer(h, relayID, h.relayAddr)

assert.NoError(t, d.Close(), "first close must not return error")
assert.Error(t, d.Close(), "second close must result in error")
Expand Down

0 comments on commit af21343

Please sign in to comment.